diff --git a/THIRD-PARTY-NOTICES b/THIRD-PARTY-NOTICES
index a6470f40de..d1bf499032 100644
--- a/THIRD-PARTY-NOTICES
+++ b/THIRD-PARTY-NOTICES
@@ -35,3 +35,52 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+License notice for IIS-Common
+------------------------------------
+
+MIT License
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE
+
+License notice for IIS-Setup
+------------------------------------
+
+MIT License
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMPackageResolver/ANCMPackageResolver.csproj b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMPackageResolver/ANCMPackageResolver.csproj
new file mode 100644
index 0000000000..e09c9574bb
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMPackageResolver/ANCMPackageResolver.csproj
@@ -0,0 +1,26 @@
+
+
+ netstandard1.0
+ true
+ true
+ $(RepositoryRoot).deps\ANCM
+
+
+
+
+
+
+
+
+
+ $(RepositoryRoot).deps\ANCM;
+
+
+ $(RestoreSources);
+ https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json;
+ https://api.nuget.org/v3/index.json;
+ https://dotnet.myget.org/F/dotnet-core/api/v3/index.json;
+
+
+
+
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/Directory.Build.props b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/Directory.Build.props
new file mode 100644
index 0000000000..2f47372910
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/Directory.Build.props
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+ $(_TwoDigitYear)$(_ThreeDigitDayOfYear)
+ $(PRODUCT_MAJOR)
+ $(PRODUCT_MINOR)
+ $(BUILD_MAJOR)
+ $(BUILD_MINOR)
+ BLDVERMAJOR=$(BLDVERMAJOR);BLDVERMINOR=$(BLDVERMINOR);BLDNUMMAJOR=$(BLDNUMMAJOR);BLDNUMMINOR=$(BLDNUMMINOR);$(DefineConstants)
+
+
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.cpp
new file mode 100644
index 0000000000..48d826f720
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.cpp
@@ -0,0 +1,184 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+#include
+
+DECLARE_DEBUG_PRINT_OBJECT( "proxyCA.dll" );
+
+HINSTANCE g_hinst;
+
+BOOL WINAPI
+DllMain(
+ HINSTANCE hModule,
+ DWORD dwReason,
+ LPVOID lpReserved
+ )
+{
+ UNREFERENCED_PARAMETER( lpReserved );
+ switch( dwReason )
+ {
+ case DLL_PROCESS_ATTACH:
+ CREATE_DEBUG_PRINT_OBJECT;
+ DisableThreadLibraryCalls( hModule );
+ g_hinst = hModule;
+ break;
+
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+
+ return TRUE;
+}
+
+
+struct COMPRESSION_MIME_TYPE
+{
+ PCWSTR pszMimeType;
+ BOOL fEnabled;
+};
+
+COMPRESSION_MIME_TYPE gMimeTypes[] =
+ { { L"text/event-stream", FALSE} };
+
+UINT
+WINAPI
+RegisterANCMCompressionCA(
+ IN MSIHANDLE
+ )
+{
+ HRESULT hr = S_OK;
+ DWORD i;
+ VARIANT varName;
+ IAppHostWritableAdminManager * pAdminMgr = NULL;
+ IAppHostElement * pHttpCompressionSection = NULL;
+ IAppHostElement * pDynamicCompressionElement = NULL;
+ IAppHostElementCollection * pMimeTypeCollection = NULL;
+ IAppHostElement * pMimeTypeElement = NULL;
+
+ VariantInit(&varName);
+
+ hr = CoCreateInstance(__uuidof(AppHostWritableAdminManager),
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ __uuidof(IAppHostWritableAdminManager),
+ (VOID **)&pAdminMgr);
+ if (FAILED(hr))
+ {
+ goto exit;
+ }
+
+ hr = pAdminMgr->GetAdminSection(L"system.webServer/httpCompression",
+ L"MACHINE/WEBROOT/APPHOST",
+ &pHttpCompressionSection);
+ if (FAILED(hr))
+ {
+ goto exit;
+ }
+
+ hr = pHttpCompressionSection->GetElementByName(L"dynamicTypes",
+ &pDynamicCompressionElement);
+ if (FAILED(hr))
+ {
+ goto exit;
+ }
+
+ hr = pDynamicCompressionElement->get_Collection(&pMimeTypeCollection);
+ if (FAILED(hr))
+ {
+ goto exit;
+ }
+
+ hr = pMimeTypeCollection->get_Count(&i);
+ if (FAILED(hr) || i == 0)
+ {
+ // failure or DynamicCmpression is not enabled
+ goto exit;
+ }
+
+ for (i=0; i<_countof(gMimeTypes); i++)
+ {
+ hr = pMimeTypeCollection->CreateNewElement(L"add",
+ &pMimeTypeElement);
+ if (FAILED(hr))
+ {
+ goto exit;
+ }
+
+ hr = VariantAssign(&varName,
+ gMimeTypes[i].pszMimeType);
+ if (FAILED(hr))
+ {
+ goto exit;
+ }
+
+ hr = SetElementProperty(pMimeTypeElement,
+ L"mimeType",
+ &varName);
+ if (FAILED(hr))
+ {
+ goto exit;
+ }
+ VariantClear(&varName);
+
+ varName.vt = VT_BOOL;
+ varName.boolVal = gMimeTypes[i].fEnabled ? VARIANT_TRUE : VARIANT_FALSE;
+
+ hr = SetElementProperty(pMimeTypeElement,
+ L"enabled",
+ &varName);
+ if (FAILED(hr))
+ {
+ goto exit;
+ }
+ VariantClear(&varName);
+
+ hr = pMimeTypeCollection->AddElement(pMimeTypeElement);
+ if (FAILED(hr) &&
+ hr != HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS))
+ {
+ goto exit;
+ }
+
+ pMimeTypeElement->Release();
+ pMimeTypeElement = NULL;
+ }
+
+ hr = pAdminMgr->CommitChanges();
+
+ exit:
+
+ VariantClear(&varName);
+
+ if (pMimeTypeElement != NULL)
+ {
+ pMimeTypeElement->Release();
+ pMimeTypeElement = NULL;
+ }
+
+ if (pMimeTypeCollection != NULL)
+ {
+ pMimeTypeCollection->Release();
+ pMimeTypeCollection = NULL;
+ }
+
+ if (pDynamicCompressionElement != NULL)
+ {
+ pDynamicCompressionElement->Release();
+ pDynamicCompressionElement = NULL;
+ }
+
+ if (pHttpCompressionSection != NULL)
+ {
+ pHttpCompressionSection->Release();
+ pHttpCompressionSection = NULL;
+ }
+
+ if (pAdminMgr != NULL)
+ {
+ pAdminMgr->Release();
+ pAdminMgr = NULL;
+ }
+
+ return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_SUCCESS;
+}
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.def b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.def
new file mode 100644
index 0000000000..3518cde35f
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.def
@@ -0,0 +1,23 @@
+LIBRARY aspnetcoreCA
+
+EXPORTS
+
+ ; IIS Common Config custom actions
+
+ IISScheduleInstallCA
+ IISScheduleUninstallCA
+ IISExecuteCA
+ IISBeginTransactionCA
+ IISRollbackTransactionCA
+ IISCommitTransactionCA
+
+ CheckForSharedConfigurationCA
+
+ ScheduleInstallWindowsHotfixCA
+ ExecuteInstallWindowsHotfixCA
+ ExecuteCleanUpWindowsHotfixCA
+ ScheduleRebootIfRequiredCA
+
+ RegisterANCMCompressionCA
+
+ CheckForServicesRunningCA
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.rc b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.rc
new file mode 100644
index 0000000000..8f05349435
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.rc
@@ -0,0 +1,10 @@
+#define VER_FILETYPE VFT_DLL
+#define RC_VERSION_INTERNAL_NAME "aspnetcoreCA\0"
+#define RC_VERSION_ORIGINAL_FILE_NAME "aspnetcoreCA.dll\0"
+#define RC_VERSION_FILE_DESCRIPTION "IIS AspNet Core Support Module Custom Action DLL\0"
+#define PRODUCT_MAJOR 7
+#define PRODUCT_MINOR 1
+#define BUILD_MAJOR 1972
+#define BUILD_MINOR 0
+
+#include
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.vcxproj b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.vcxproj
new file mode 100644
index 0000000000..9d621fb37b
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.vcxproj
@@ -0,0 +1,98 @@
+
+
+
+
+ $(MSBuildThisFileDirectory)..\
+
+
+
+ <_IIS-SetupExportsPath>$(ANCM-Setup)IIS-Setup\build\exports.props
+
+
+
+
+
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 15.0
+ {7C27E72F-54D0-4820-8CFA-5E4BE640974B}
+ aspnetcoreca
+ aspnetcoreCA
+
+
+
+ DynamicLibrary
+ v141
+ Unicode
+
+
+ true
+
+
+
+ $(IIS-Common)version;$(IIS-Common)Include;$(IIS-Setup)iisca\lib;$(WIX)sdk\$(WixPlatformToolset)\inc;$(AdditionalIncludeDirectories)
+
+
+
+ true
+ $(AdditionalIncludeDirectories)
+
+
+ httpapi.lib;shlwapi.lib;ahadmin.lib;xmllite.lib;msi.lib;Version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ aspnetcoreCA.def
+ $(OutDir)$(TargetName).lib
+ /NODEFAULTLIB:MSVCRT %(AdditionalOptions)
+
+
+
+
+
+
+
+
+
+
+
+ $(IIS-Common)version
+
+
+
+
+ {7324770c-0871-4d73-be3d-5e2f3e9e1b1e}
+
+
+ {b54a8f61-60de-4ad9-87ca-d102f230678e}
+
+
+
+
+
+
+ This project is trying to import a missing file: {0}.
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/avoid_restart.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/avoid_restart.cpp
new file mode 100644
index 0000000000..b0e4753c44
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/avoid_restart.cpp
@@ -0,0 +1,244 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+#include
+#include
+
+HRESULT
+GetServiceCurrentState(
+ __in LPCWSTR pszServiceName,
+ __out SERVICE_STATUS * pServiceStatus
+)
+{
+ HRESULT hr = S_OK;
+ SC_HANDLE hServiceControlManager = NULL;
+ SC_HANDLE hService = NULL;
+
+ hServiceControlManager = OpenSCManager( NULL, // Local machine
+ NULL,
+ STANDARD_RIGHTS_READ );
+ if ( hServiceControlManager == NULL )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ DBGERROR_HR(hr);
+ goto Finished;
+ }
+
+ hService = OpenService( hServiceControlManager,
+ pszServiceName,
+ SERVICE_QUERY_STATUS );
+ if ( hService == NULL )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ DBGERROR_HR(hr);
+ goto Finished;
+ }
+
+ if ( !QueryServiceStatus( hService,
+ pServiceStatus ) )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ DBGERROR_HR(hr);
+ goto Finished;
+ }
+
+Finished:
+
+ if ( hService != NULL )
+ {
+ CloseServiceHandle( hService );
+ hService = NULL;
+ }
+
+ if ( hServiceControlManager != NULL )
+ {
+ CloseServiceHandle( hService );
+ hService = NULL;
+ }
+
+ return hr;
+}
+
+BOOL
+IsServiceRunning(
+ const SERVICE_STATUS & ServiceStatus
+)
+{
+ switch( ServiceStatus.dwCurrentState )
+ {
+ case SERVICE_RUNNING:
+ case SERVICE_START_PENDING:
+ case SERVICE_CONTINUE_PENDING:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+HRESULT
+IsQfeInstalled(
+ __in LPCWSTR pszQfeName,
+ __out BOOL * pfIsInstalled
+)
+{
+ HRESULT hr = S_OK;
+ CComPtr< IWbemLocator > pLocator;
+ CComPtr< IWbemServices > pService;
+ CComPtr< IEnumWbemClassObject > pEnumerator;
+ ULONG Count = 0;
+ CComPtr< IWbemClassObject > pProcessor;
+ CComBSTR bstrNamespace;
+ CComBSTR bstrQueryLanguage;
+ CComBSTR bstrQuery;
+
+ if ( FAILED( hr = bstrNamespace.Append( L"root\\CIMV2", 10 ) ) ||
+ FAILED( hr = bstrQueryLanguage.Append( L"WQL", 3 ) ) ||
+ FAILED( hr = bstrQuery.Append( L"SELECT HotFixID FROM Win32_QuickFixEngineering WHERE HotFixID='" ) ) ||
+ FAILED( hr = bstrQuery.Append( pszQfeName ) ) ||
+ FAILED( hr = bstrQuery.Append( L"'", 1 ) ) )
+ {
+ goto Finished;
+ }
+
+ hr = CoCreateInstance( __uuidof(WbemAdministrativeLocator),
+ NULL, // pUnkOuter
+ CLSCTX_INPROC_SERVER,
+ __uuidof(IWbemLocator),
+ reinterpret_cast< void** >( &pLocator ) );
+ if ( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+
+ hr = pLocator->ConnectServer( bstrNamespace,
+ NULL, // strUser
+ NULL, // strPassword
+ NULL, // strLocale
+ WBEM_FLAG_CONNECT_USE_MAX_WAIT,
+ NULL, // strAuthority
+ NULL, // pCtx
+ &pService );
+ if ( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+
+ //
+ // Set the proxy so that impersonation of the client occurs.
+ //
+ hr = CoSetProxyBlanket( pService,
+ RPC_C_AUTHN_DEFAULT,
+ RPC_C_AUTHZ_NONE,
+ NULL,
+ RPC_C_AUTHN_LEVEL_CONNECT,
+ RPC_C_IMP_LEVEL_IMPERSONATE,
+ NULL,
+ EOAC_NONE);
+ if ( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+
+ hr = pService->ExecQuery( bstrQueryLanguage,
+ bstrQuery,
+ WBEM_FLAG_FORWARD_ONLY,
+ NULL,
+ &pEnumerator );
+ if ( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+
+ hr = pEnumerator->Next( WBEM_INFINITE,
+ 1L,
+ &pProcessor,
+ &Count );
+ if ( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+
+ *pfIsInstalled = Count > 0;
+
+Finished:
+
+ return hr;
+}
+
+UINT
+WINAPI
+CheckForServicesRunningCA(
+ MSIHANDLE hInstall
+)
+{
+ HRESULT hr = S_OK;
+ BOOL fIsServiceRunning = FALSE;
+ SERVICE_STATUS ServiceStatus;
+ LPCWSTR rgServiceNames[] = { L"WAS", L"WMSVC" };
+
+ IISLogInitialize(hInstall, UNITEXT(__FUNCTION__));
+
+ //
+ // Check if any pService is running.
+ //
+ for( DWORD Index = 0; Index < _countof( rgServiceNames ); Index ++ )
+ {
+ hr = GetServiceCurrentState( rgServiceNames[Index],
+ &ServiceStatus );
+ if ( hr == HRESULT_FROM_WIN32( ERROR_SERVICE_DOES_NOT_EXIST ) )
+ {
+ hr = S_OK;
+ }
+ else if ( FAILED( hr ) )
+ {
+ IISLogWrite(SETUP_LOG_SEVERITY_ERROR,
+ L"Failed to query the state of the service '%s' hr=0x%x",
+ rgServiceNames[Index],
+ hr );
+ DBGERROR_HR(hr);
+ goto Finished;
+ }
+ else
+ {
+ fIsServiceRunning = IsServiceRunning( ServiceStatus );
+ if ( fIsServiceRunning )
+ {
+ break;
+ }
+ }
+ }
+
+ if ( fIsServiceRunning )
+ {
+ BOOL fQfeInstalled = FALSE;
+
+ hr = IsQfeInstalled( L"KB954438",
+ &fQfeInstalled );
+ if ( FAILED( hr ) )
+ {
+ IISLogWrite(SETUP_LOG_SEVERITY_ERROR,
+ L"Failed to query the hotfix 'KB949172' information hr=0x%x",
+ hr );
+ DBGERROR_HR(hr);
+ goto Finished;
+ }
+
+ if ( fQfeInstalled )
+ {
+ //
+ // hotfix is already installed.
+ //
+ goto Finished;
+ }
+
+ IISLogClose();
+ return LogMsiCustomActionError( hInstall, 30003 );
+ }
+
+Finished:
+
+ IISLogClose();
+
+ // TODO Wire up when Rollback CA's are wired up
+ return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_SUCCESS;
+}
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/Directory.Build.props b/src/Installers/Windows/AspNetCoreModule-Setup/Directory.Build.props
new file mode 100644
index 0000000000..63b61c1a81
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/Directory.Build.props
@@ -0,0 +1,35 @@
+
+
+
+
+
+ $(RepositoryRoot)src\Installers\Windows\AspNetCoreModule-Setup\
+ $(AspNetCoreSetupRoot)IIS-Setup\
+ $(IIS-Setup)IIS-Common\
+
+ CustomAction=$(AspNetCoreSetupRoot)CustomAction\bin\$(Configuration)\$(Platform)\aspnetcoreca.dll
+
+ $(RepositoryRoot).deps\ANCM\Microsoft.AspNetCore.AspNetCoreModule\$(MicrosoftAspNetCoreAspNetCoreModulePackageVersion)\
+ $(RepositoryRoot).deps\ANCM\Microsoft.AspNetCore.AspNetCoreModuleV2\$(MicrosoftAspNetCoreAspNetCoreModuleV2PackageVersion)\
+
+ $(PreBuiltANCMSchema)contentFiles\any\any\
+ $(PreBuiltANCMV2Schema)contentFiles\any\any\
+
+ 2.0.0
+ ANCMOutOfProcessHandlerVersion=$(ANCMOutOfProcessHandlerVersion);$(DefineConstants)
+ PreBuiltANCMRoot=$(PreBuiltANCMRoot);PreBuiltANCMV2Root=$(PreBuiltANCMV2Root);$(DefineConstants)
+ $(CustomActionVariable);PreBuiltANCMSchema=$(PreBuiltANCMSchema);PreBuiltANCMV2Schema=$(PreBuiltANCMV2Schema);$(DefineConstants)
+
+ <_TwoDigitYear>$([MSBuild]::Subtract($([System.DateTime]::UtcNow.Year), 2000))
+ <_ThreeDigitDayOfYear>$([System.DateTime]::UtcNow.DayOfYear.ToString().PadLeft(3, '0'))
+
+
+ $(_TwoDigitYear)$(_ThreeDigitDayOfYear)
+ $(PRODUCT_MAJOR)
+ $(PRODUCT_MINOR)
+ $(BUILD_MAJOR)
+ $(BUILD_MINOR)
+ BLDVERMAJOR=$(BLDVERMAJOR);BLDVERMINOR=$(BLDVERMINOR);BLDNUMMAJOR=$(BLDNUMMAJOR);BLDNUMMINOR=$(BLDNUMMINOR);$(DefineConstants)
+
+
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Common.sln b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Common.sln
new file mode 100644
index 0000000000..5b48ec6769
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Common.sln
@@ -0,0 +1,41 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27120.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CommonLib", "lib\CommonLib.vcxproj", "{B54A8F61-60DE-4AD9-87CA-D102F230678E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reftrace", "reftrace\reftrace.vcxproj", "{A2599642-CBE5-4230-8511-3DC2D81874BE}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x64.ActiveCfg = Debug|x64
+ {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x64.Build.0 = Debug|x64
+ {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x86.ActiveCfg = Debug|Win32
+ {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x86.Build.0 = Debug|Win32
+ {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x64.ActiveCfg = Release|x64
+ {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x64.Build.0 = Release|x64
+ {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x86.ActiveCfg = Release|Win32
+ {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x86.Build.0 = Release|Win32
+ {A2599642-CBE5-4230-8511-3DC2D81874BE}.Debug|x64.ActiveCfg = Debug|x64
+ {A2599642-CBE5-4230-8511-3DC2D81874BE}.Debug|x64.Build.0 = Debug|x64
+ {A2599642-CBE5-4230-8511-3DC2D81874BE}.Debug|x86.ActiveCfg = Debug|Win32
+ {A2599642-CBE5-4230-8511-3DC2D81874BE}.Debug|x86.Build.0 = Debug|Win32
+ {A2599642-CBE5-4230-8511-3DC2D81874BE}.Release|x64.ActiveCfg = Release|x64
+ {A2599642-CBE5-4230-8511-3DC2D81874BE}.Release|x64.Build.0 = Release|x64
+ {A2599642-CBE5-4230-8511-3DC2D81874BE}.Release|x86.ActiveCfg = Release|Win32
+ {A2599642-CBE5-4230-8511-3DC2D81874BE}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {81F5A61A-A12A-4F53-B0F9-C0E541CA6567}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/acache.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/acache.h
new file mode 100644
index 0000000000..83e39fd7ff
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/acache.h
@@ -0,0 +1,116 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#pragma once
+
+#include "percpu.h"
+
+
+class ALLOC_CACHE_HANDLER
+{
+public:
+
+ ALLOC_CACHE_HANDLER(
+ VOID
+ );
+
+ ~ALLOC_CACHE_HANDLER(
+ VOID
+ );
+
+ HRESULT
+ Initialize(
+ DWORD cbSize,
+ LONG nThreshold
+ );
+
+ LPVOID
+ Alloc(
+ VOID
+ );
+
+ VOID
+ Free(
+ __in LPVOID pMemory
+ );
+
+
+private:
+
+ VOID
+ CleanupLookaside(
+ VOID
+ );
+
+ DWORD
+ QueryDepthForAllSLists(
+ VOID
+ );
+
+ LONG m_nThreshold;
+ DWORD m_cbSize;
+
+ PER_CPU * m_pFreeLists;
+
+ //
+ // Total heap allocations done over the lifetime.
+ // Note that this is not interlocked, it is just a hint for debugging.
+ //
+ volatile LONG m_nTotal;
+
+ LONG m_nFillPattern;
+
+public:
+
+ static
+ HRESULT
+ StaticInitialize(
+ VOID
+ );
+
+ static
+ VOID
+ StaticTerminate(
+ VOID
+ );
+
+ static
+ BOOL
+ IsPageheapEnabled();
+
+private:
+
+ static LONG sm_nFillPattern;
+ static HANDLE sm_hHeap;
+};
+
+
+// You can use ALLOC_CACHE_HANDLER as a per-class allocator
+// in your C++ classes. Add the following to your class definition:
+//
+// protected:
+// static ALLOC_CACHE_HANDLER* sm_palloc;
+// public:
+// static void* operator new(size_t s)
+// {
+// IRTLASSERT(s == sizeof(C));
+// IRTLASSERT(sm_palloc != NULL);
+// return sm_palloc->Alloc();
+// }
+// static void operator delete(void* pv)
+// {
+// IRTLASSERT(pv != NULL);
+// if (sm_palloc != NULL)
+// sm_palloc->Free(pv);
+// }
+//
+// Obviously, you must initialize sm_palloc before you can allocate
+// any objects of this class.
+//
+// Note that if you derive a class from this base class, the derived class
+// must also provide its own operator new and operator delete. If not, the
+// base class's allocator will be called, but the size of the derived
+// object will almost certainly be larger than that of the base object.
+// Furthermore, the allocator will not be used for arrays of objects
+// (override operator new[] and operator delete[]), but this is a
+// harder problem since the allocator works with one fixed size.
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ahutil.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ahutil.h
new file mode 100644
index 0000000000..a39c09bb73
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ahutil.h
@@ -0,0 +1,264 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#pragma once
+
+HRESULT
+SetElementProperty(
+ IN IAppHostElement * pElement,
+ IN CONST WCHAR * szPropName,
+ IN CONST VARIANT * varPropValue
+ );
+
+HRESULT
+SetElementStringProperty(
+ IN IAppHostElement * pElement,
+ IN CONST WCHAR * szPropName,
+ IN CONST WCHAR * szPropValue
+ );
+
+HRESULT
+GetElementStringProperty(
+ IN IAppHostElement * pElement,
+ IN CONST WCHAR * szPropName,
+ OUT BSTR * pbstrPropValue
+ );
+
+HRESULT
+GetElementStringProperty(
+ IN IAppHostElement * pElement,
+ IN CONST WCHAR * szPropName,
+ OUT STRU * pstrPropValue
+ );
+
+HRESULT
+GetElementBoolProperty(
+ IN IAppHostElement * pElement,
+ IN LPCWSTR pszPropertyName,
+ OUT BOOL * pBool
+ );
+
+HRESULT
+GetElementBoolProperty(
+ IN IAppHostElement * pElement,
+ IN LPCWSTR pszPropertyName,
+ OUT bool * pBool
+ );
+
+HRESULT
+GetElementChildByName(
+ IN IAppHostElement * pElement,
+ IN LPCWSTR pszElementName,
+ OUT IAppHostElement ** ppChildElement
+ );
+
+HRESULT
+GetElementDWORDProperty(
+ IN IAppHostElement * pElement,
+ IN LPCWSTR pszPropertyName,
+ OUT DWORD * pdwValue
+ );
+
+HRESULT
+GetElementINTProperty(
+ IN IAppHostElement * pElement,
+ IN LPCWSTR pszPropertyName,
+ OUT INT * pintValue
+ );
+
+HRESULT
+GetElementLONGLONGProperty(
+ IN IAppHostElement * pElement,
+ IN LPCWSTR pszPropertyName,
+ OUT LONGLONG * pllValue
+);
+
+
+HRESULT
+GetElementRawTimeSpanProperty(
+ IN IAppHostElement * pElement,
+ IN LPCWSTR pszPropertyName,
+ OUT ULONGLONG * pulonglong
+ );
+
+#define FIND_ELEMENT_CASE_SENSITIVE 0x00000000
+#define FIND_ELEMENT_CASE_INSENSITIVE 0x00000001
+
+HRESULT
+DeleteElementFromCollection(
+ IAppHostElementCollection *pCollection,
+ CONST WCHAR * szKeyName,
+ CONST WCHAR * szKeyValue,
+ ULONG BehaviorFlags,
+ BOOL * pfDeleted
+ );
+
+HRESULT
+DeleteAllElementsFromCollection(
+ IAppHostElementCollection *pCollection,
+ CONST WCHAR * szKeyName,
+ CONST WCHAR * szKeyValue,
+ ULONG BehaviorFlags,
+ UINT * pNumDeleted
+ );
+
+HRESULT
+FindElementInCollection(
+ IAppHostElementCollection *pCollection,
+ CONST WCHAR * szKeyName,
+ CONST WCHAR * szKeyValue,
+ ULONG BehaviorFlags,
+ OUT ULONG * pIndex
+ );
+
+HRESULT
+VariantAssign(
+ IN OUT VARIANT * pv,
+ IN CONST WCHAR * sz
+ );
+
+HRESULT
+GetLocationFromFile(
+ IN IAppHostAdminManager * pAdminMgr,
+ IN CONST WCHAR * szConfigPath,
+ IN CONST WCHAR * szLocationPath,
+ OUT IAppHostConfigLocation ** ppLocation,
+ OUT BOOL * pFound
+ );
+
+HRESULT
+GetSectionFromLocation(
+ IN IAppHostConfigLocation * pLocation,
+ IN CONST WCHAR * szSectionName,
+ OUT IAppHostElement ** ppSectionElement,
+ OUT BOOL * pFound
+ );
+
+HRESULT
+GetAdminElement(
+ IN IAppHostAdminManager * pAdminMgr,
+ IN CONST WCHAR * szConfigPath,
+ IN CONST WCHAR * szElementName,
+ OUT IAppHostElement ** pElement
+ );
+
+HRESULT
+ClearAdminElement(
+ IN IAppHostAdminManager * pAdminMgr,
+ IN CONST WCHAR * szConfigPath,
+ IN CONST WCHAR * szElementName
+ );
+
+HRESULT
+ClearElementFromAllSites(
+ IN IAppHostAdminManager * pAdminMgr,
+ IN CONST WCHAR * szConfigPath,
+ IN CONST WCHAR * szElementName
+ );
+
+HRESULT
+ClearElementFromAllLocations(
+ IN IAppHostAdminManager * pAdminMgr,
+ IN CONST WCHAR * szConfigPath,
+ IN CONST WCHAR * szElementName
+ );
+
+HRESULT
+ClearLocationElements(
+ IN IAppHostConfigLocation * pLocation,
+ IN CONST WCHAR * szElementName
+ );
+
+HRESULT
+CompareElementName(
+ IN IAppHostElement * pElement,
+ IN CONST WCHAR * szNameToMatch,
+ OUT BOOL * pMatched
+ );
+
+HRESULT
+ClearChildElementsByName(
+ IN IAppHostChildElementCollection * pCollection,
+ IN CONST WCHAR * szElementName,
+ OUT BOOL * pFound
+ );
+
+HRESULT
+GetSitesCollection(
+ IN IAppHostAdminManager * pAdminMgr,
+ IN CONST WCHAR * szConfigPath,
+ OUT IAppHostElementCollection ** pSitesCollection
+ );
+
+HRESULT
+GetLocationCollection(
+ IN IAppHostAdminManager * pAdminMgr,
+ IN CONST WCHAR * szConfigPath,
+ OUT IAppHostConfigLocationCollection ** pLocationCollection
+ );
+
+struct ENUM_INDEX
+{
+ VARIANT Index;
+ ULONG Count;
+};
+
+HRESULT
+FindFirstElement(
+ IN IAppHostElementCollection * pCollection,
+ OUT ENUM_INDEX * pIndex,
+ OUT IAppHostElement ** pElement
+ );
+
+HRESULT
+FindNextElement(
+ IN IAppHostElementCollection * pCollection,
+ IN OUT ENUM_INDEX * pIndex,
+ OUT IAppHostElement ** pElement
+ );
+
+HRESULT
+FindFirstChildElement(
+ IN IAppHostChildElementCollection * pCollection,
+ OUT ENUM_INDEX * pIndex,
+ OUT IAppHostElement ** pElement
+ );
+
+HRESULT
+FindNextChildElement(
+ IN IAppHostChildElementCollection * pCollection,
+ IN OUT ENUM_INDEX * pIndex,
+ OUT IAppHostElement ** pElement
+ );
+
+HRESULT
+FindFirstLocation(
+ IN IAppHostConfigLocationCollection * pCollection,
+ OUT ENUM_INDEX * pIndex,
+ OUT IAppHostConfigLocation ** pLocation
+ );
+
+HRESULT
+FindNextLocation(
+ IN IAppHostConfigLocationCollection * pCollection,
+ IN OUT ENUM_INDEX * pIndex,
+ OUT IAppHostConfigLocation ** pLocation
+ );
+
+HRESULT
+FindFirstLocationElement(
+ IN IAppHostConfigLocation * pLocation,
+ OUT ENUM_INDEX * pIndex,
+ OUT IAppHostElement ** pElement
+ );
+
+HRESULT
+FindNextLocationElement(
+ IN IAppHostConfigLocation * pLocation,
+ IN OUT ENUM_INDEX * pIndex,
+ OUT IAppHostElement ** pElement
+ );
+
+HRESULT GetSharedConfigEnabled(
+ BOOL * pfIsSharedConfig
+);
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/base64.hxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/base64.hxx
new file mode 100644
index 0000000000..871c7e8e0f
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/base64.hxx
@@ -0,0 +1,42 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef _BASE64_HXX_
+#define _BASE64_HXX_
+
+DWORD
+Base64Encode(
+ __in_bcount( cbDecodedBufferSize ) VOID * pDecodedBuffer,
+ IN DWORD cbDecodedBufferSize,
+ __out_ecount_opt( cchEncodedStringSize ) PWSTR pszEncodedString,
+ IN DWORD cchEncodedStringSize,
+ __out_opt DWORD * pcchEncoded
+ );
+
+DWORD
+Base64Decode(
+ __in PCWSTR pszEncodedString,
+ __out_opt VOID * pDecodeBuffer,
+ __in DWORD cbDecodeBufferSize,
+ __out_opt DWORD * pcbDecoded
+ );
+
+DWORD
+Base64Encode(
+ __in_bcount( cbDecodedBufferSize ) VOID * pDecodedBuffer,
+ IN DWORD cbDecodedBufferSize,
+ __out_ecount_opt( cchEncodedStringSize ) PSTR pszEncodedString,
+ IN DWORD cchEncodedStringSize,
+ __out_opt DWORD * pcchEncoded
+ );
+
+DWORD
+Base64Decode(
+ __in PCSTR pszEncodedString,
+ __out_opt VOID * pDecodeBuffer,
+ __in DWORD cbDecodeBufferSize,
+ __out_opt DWORD * pcbDecoded
+ );
+
+#endif // _BASE64_HXX_
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/buffer.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/buffer.h
new file mode 100644
index 0000000000..63e567be4d
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/buffer.h
@@ -0,0 +1,271 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#pragma once
+
+#include
+
+
+//
+// BUFFER_T class shouldn't be used directly. Use BUFFER specialization class instead.
+// The only BUFFER_T partners are STRU and STRA classes.
+// BUFFER_T cannot hold other but primitive types since it doesn't call
+// constructor and destructor.
+//
+// Note: Size is in bytes.
+//
+template
+class BUFFER_T
+{
+public:
+
+ BUFFER_T()
+ : m_cbBuffer( sizeof(m_rgBuffer) ),
+ m_fHeapAllocated( false ),
+ m_pBuffer(m_rgBuffer)
+ /*++
+ Description:
+
+ Default constructor where the inline buffer is used.
+
+ Arguments:
+
+ None.
+
+ Returns:
+
+ None.
+
+ --*/
+ {
+ }
+
+ BUFFER_T(
+ __inout_bcount(cbInit) T* pbInit,
+ __in DWORD cbInit
+ ) : m_pBuffer( pbInit ),
+ m_cbBuffer( cbInit ),
+ m_fHeapAllocated( false )
+ /*++
+ Description:
+
+ Instantiate BUFFER, initially using pbInit as buffer
+ This is useful for stack-buffers and inline-buffer class members
+ (see STACK_BUFFER and INLINE_BUFFER_INIT below)
+
+ BUFFER does not free pbInit.
+
+ Arguments:
+
+ pbInit - Initial buffer to use.
+ cbInit - Size of pbInit in bytes (not in elements).
+
+ Returns:
+
+ None.
+
+ --*/
+ {
+ _ASSERTE( NULL != pbInit );
+ _ASSERTE( cbInit > 0 );
+ }
+
+ ~BUFFER_T()
+ {
+ if( IsHeapAllocated() )
+ {
+ _ASSERTE( NULL != m_pBuffer );
+ HeapFree( GetProcessHeap(), 0, m_pBuffer );
+ m_pBuffer = NULL;
+ m_cbBuffer = 0;
+ m_fHeapAllocated = false;
+ }
+ }
+
+ T*
+ QueryPtr(
+ VOID
+ ) const
+ {
+ //
+ // Return pointer to data buffer.
+ //
+ return m_pBuffer;
+ }
+
+ DWORD
+ QuerySize(
+ VOID
+ ) const
+ {
+ //
+ // Return number of bytes.
+ //
+ return m_cbBuffer;
+ }
+
+ __success(return == true)
+ bool
+ Resize(
+ const SIZE_T cbNewSize,
+ const bool fZeroMemoryBeyondOldSize = false
+ )
+ /*++
+ Description:
+
+ Resizes the buffer.
+
+ Arguments:
+
+ cbNewSize - Size in bytes to grow to.
+ fZeroMemoryBeyondOldSize
+ - Whether to zero the region of memory of the
+ new buffer beyond the original size.
+
+ Returns:
+
+ TRUE on success, FALSE on failure.
+
+ --*/
+ {
+ PVOID pNewMem;
+
+ if ( cbNewSize <= m_cbBuffer )
+ {
+ return true;
+ }
+
+ if ( cbNewSize > MAXDWORD )
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return false;
+ }
+
+ DWORD dwHeapAllocFlags = fZeroMemoryBeyondOldSize ? HEAP_ZERO_MEMORY : 0;
+
+ if( IsHeapAllocated() )
+ {
+ pNewMem = HeapReAlloc( GetProcessHeap(), dwHeapAllocFlags, m_pBuffer, cbNewSize );
+ }
+ else
+ {
+ pNewMem = HeapAlloc( GetProcessHeap(), dwHeapAllocFlags, cbNewSize );
+ }
+
+ if( pNewMem == NULL )
+ {
+ SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ return false;
+ }
+
+ if( !IsHeapAllocated() )
+ {
+ //
+ // First time this block is allocated. Copy over old contents.
+ //
+ memcpy_s( pNewMem, static_cast(cbNewSize), m_pBuffer, m_cbBuffer );
+ m_fHeapAllocated = true;
+ }
+
+ m_pBuffer = reinterpret_cast(pNewMem);
+ m_cbBuffer = static_cast(cbNewSize);
+
+ _ASSERTE( m_pBuffer != NULL );
+
+ return true;
+ }
+
+private:
+
+ bool
+ IsHeapAllocated(
+ VOID
+ ) const
+ {
+ return m_fHeapAllocated;
+ }
+
+ //
+ // The default inline buffer.
+ // This member should be at the beginning for alignment purposes.
+ //
+ T m_rgBuffer[LENGTH];
+
+ //
+ // Is m_pBuffer dynamically allocated?
+ //
+ bool m_fHeapAllocated;
+
+ //
+ // Size of the buffer as requested by client in bytes.
+ //
+ DWORD m_cbBuffer;
+
+ //
+ // Pointer to buffer.
+ //
+ __field_bcount_full(m_cbBuffer)
+ T* m_pBuffer;
+};
+
+//
+// Resizes the buffer by 2 if the ideal size is bigger
+// than the buffer length. That give us lg(n) allocations.
+//
+// Use template inferring like:
+//
+// BUFFER buff;
+// hr = ResizeBufferByTwo(buff, 100);
+//
+template
+HRESULT
+ResizeBufferByTwo(
+ BUFFER_T& Buffer,
+ SIZE_T cbIdealSize,
+ bool fZeroMemoryBeyondOldSize = false
+)
+{
+ if (cbIdealSize > Buffer.QuerySize())
+ {
+ if (!Buffer.Resize(max(cbIdealSize, static_cast(Buffer.QuerySize() * 2)),
+ fZeroMemoryBeyondOldSize))
+ {
+ return E_OUTOFMEMORY;
+ }
+ }
+ return S_OK;
+}
+
+
+//
+//
+// Lots of code uses BUFFER class to store a bunch of different
+// structures, so m_rgBuffer needs to be 8 byte aligned when it is used
+// as an opaque buffer.
+//
+#define INLINED_BUFFER_LEN 32
+typedef BUFFER_T BUFFER;
+
+//
+// Assumption of macros below for pointer alignment purposes
+//
+C_ASSERT( sizeof(VOID*) <= sizeof(ULONGLONG) );
+
+//
+// Declare a BUFFER that will use stack memory of
+// bytes. If the buffer overflows then a heap buffer will be allocated.
+//
+#define STACK_BUFFER( _name, _size ) \
+ ULONGLONG __aqw##_name[ ( ( (_size) + sizeof(ULONGLONG) - 1 ) / sizeof(ULONGLONG) ) ]; \
+ BUFFER _name( (BYTE*)__aqw##_name, sizeof(__aqw##_name) )
+
+//
+// Macros for declaring and initializing a BUFFER that will use inline memory
+// of bytes as a member of an object.
+//
+#define INLINE_BUFFER( _name, _size ) \
+ ULONGLONG __aqw##_name[ ( ( (_size) + sizeof(ULONGLONG) - 1 ) / sizeof(ULONGLONG) ) ]; \
+ BUFFER _name;
+
+#define INLINE_BUFFER_INIT( _name ) \
+ _name( (BYTE*)__aqw##_name, sizeof( __aqw##_name ) )
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/datetime.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/datetime.h
new file mode 100644
index 0000000000..82ac441abd
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/datetime.h
@@ -0,0 +1,14 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef _DATETIME_H_
+#define _DATETIME_H_
+
+BOOL
+StringTimeToFileTime(
+ PCSTR pszTime,
+ ULONGLONG * pulTime
+);
+
+#endif
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/dbgutil.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/dbgutil.h
new file mode 100644
index 0000000000..9a33cca394
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/dbgutil.h
@@ -0,0 +1,102 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef _DBGUTIL_H_
+#define _DBGUTIL_H_
+
+#include
+
+//
+// TODO
+// Using _CrtDbg implementation. If hooking is desired
+// wrappers should be provided here so that we can reimplement
+// if neecessary.
+//
+// IF_DEBUG/DEBUG FLAGS
+//
+// registry configuration
+//
+
+//
+// Debug error levels for DEBUG_FLAGS_VAR.
+//
+
+#define DEBUG_FLAG_INFO 0x00000001
+#define DEBUG_FLAG_WARN 0x00000002
+#define DEBUG_FLAG_ERROR 0x00000004
+
+//
+// Predefined error level values. These are backwards from the
+// windows definitions.
+//
+
+#define DEBUG_FLAGS_INFO (DEBUG_FLAG_ERROR | DEBUG_FLAG_WARN | DEBUG_FLAG_INFO)
+#define DEBUG_FLAGS_WARN (DEBUG_FLAG_ERROR | DEBUG_FLAG_WARN)
+#define DEBUG_FLAGS_ERROR (DEBUG_FLAG_ERROR)
+#define DEBUG_FLAGS_ANY (DEBUG_FLAG_INFO | DEBUG_FLAG_WARN | DEBUG_FLAG_ERROR)
+
+//
+// Global variables to control tracing. Generally per module
+//
+
+#ifndef DEBUG_FLAGS_VAR
+#define DEBUG_FLAGS_VAR g_dwDebugFlags
+#endif
+
+#ifndef DEBUG_LABEL_VAR
+#define DEBUG_LABEL_VAR g_szDebugLabel
+#endif
+
+extern PCSTR DEBUG_LABEL_VAR;
+extern DWORD DEBUG_FLAGS_VAR;
+
+//
+// Module should make this declaration globally.
+//
+
+#define DECLARE_DEBUG_PRINT_OBJECT( _pszLabel_ ) \
+ PCSTR DEBUG_LABEL_VAR = _pszLabel_; \
+ DWORD DEBUG_FLAGS_VAR = DEBUG_FLAGS_ANY; \
+
+#define DECLARE_DEBUG_PRINT_OBJECT2( _pszLabel_, _dwLevel_ ) \
+ PCSTR DEBUG_LABEL_VAR = _pszLabel_; \
+ DWORD DEBUG_FLAGS_VAR = _dwLevel_; \
+
+//
+// This doesn't do anything now. Should be safe to call in dll main.
+//
+
+#define CREATE_DEBUG_PRINT_OBJECT
+
+//
+// Trace macros
+//
+
+#define DBG_CONTEXT _CRT_WARN, __FILE__, __LINE__, DEBUG_LABEL_VAR
+
+#ifdef DEBUG
+#define DBGINFO(args) \
+ {if( DEBUG_FLAGS_VAR & DEBUG_FLAG_INFO ) { _CrtDbgReport args; }}
+#define DBGWARN(args) \
+ {if( DEBUG_FLAGS_VAR & DEBUG_FLAG_WARN ) { _CrtDbgReport args; }}
+#define DBGERROR(args) \
+ {if( DEBUG_FLAGS_VAR & DEBUG_FLAG_ERROR ) { _CrtDbgReport args; }}
+#else
+#define DBGINFO
+#define DBGWARN
+#define DBGERROR
+#endif
+
+#define DBGPRINTF DBGINFO
+
+//
+// Simple error traces
+//
+
+#define DBGERROR_HR( _hr_ ) \
+ DBGERROR(( DBG_CONTEXT, "hr=0x%x\n", _hr_ ))
+
+#define DBGERROR_STATUS( _status_ ) \
+ DBGERROR(( DBG_CONTEXT, "status=%d\n", _status_ ))
+
+#endif
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/debugutil.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/debugutil.h
new file mode 100644
index 0000000000..39033973ce
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/debugutil.h
@@ -0,0 +1,124 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#pragma once
+
+#define DEBUG_FLAG_INFO 0x00000001
+#define DEBUG_FLAG_WARN 0x00000002
+#define DEBUG_FLAG_ERROR 0x00000004
+
+//
+// Predefined error level values. These are backwards from the
+// windows definitions.
+//
+
+#define DEBUG_FLAGS_INFO (DEBUG_FLAG_ERROR | DEBUG_FLAG_WARN | DEBUG_FLAG_INFO)
+#define DEBUG_FLAGS_WARN (DEBUG_FLAG_ERROR | DEBUG_FLAG_WARN)
+#define DEBUG_FLAGS_ERROR (DEBUG_FLAG_ERROR)
+#define DEBUG_FLAGS_ANY (DEBUG_FLAG_INFO | DEBUG_FLAG_WARN | DEBUG_FLAG_ERROR)
+
+#define DEBUG_FLAGS_REGISTRY_LOCATION_A "DebugFlags"
+
+extern DWORD g_dwDebugFlags;
+
+static
+BOOL
+IfDebug(
+ DWORD dwFlag
+ )
+{
+ return ( dwFlag & g_dwDebugFlags );
+}
+
+static
+VOID
+DebugPrint(
+ DWORD dwFlag,
+ LPCSTR szString
+ )
+{
+ STBUFF strOutput;
+ HRESULT hr;
+
+ if ( IfDebug( dwFlag ) )
+ {
+ hr = strOutput.Printf( "[dipmodule.dll] %s\r\n",
+ szString );
+
+ if ( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+
+ OutputDebugStringA( strOutput.QueryStr() );
+ }
+
+Finished:
+
+ return;
+}
+
+static
+VOID
+DebugPrintf(
+DWORD dwFlag,
+LPCSTR szFormat,
+...
+)
+{
+ STBUFF strCooked;
+ STBUFF strOutput;
+ va_list args;
+ HRESULT hr;
+
+ if ( IfDebug( dwFlag ) )
+ {
+ va_start( args, szFormat );
+
+ hr = strCooked.Vsprintf( (LPSTR)szFormat, args );
+
+ va_end( args );
+
+ if ( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+
+ DebugPrint( dwFlag, strCooked.QueryStr() );
+ }
+
+Finished:
+
+ return;
+}
+
+static void ReadDebugFlagFromRegistryKey(const char* pszRegKey, IN DWORD dwDefault)
+{
+ HKEY hkey = NULL;
+ g_dwDebugFlags = dwDefault;
+ DWORD dwType;
+ DWORD dwBuffer;
+ DWORD cbBuffer = sizeof(dwBuffer);
+
+ DWORD dwError = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
+ pszRegKey,
+ 0,
+ KEY_READ,
+ &hkey);
+ if ( dwError == NO_ERROR && hkey != NULL)
+ {
+ dwError = RegQueryValueExA( hkey,
+ DEBUG_FLAGS_REGISTRY_LOCATION_A,
+ NULL,
+ &dwType,
+ (LPBYTE)&dwBuffer,
+ &cbBuffer );
+ if( ( dwError == NO_ERROR ) && ( dwType == REG_DWORD ) )
+ {
+ g_dwDebugFlags = dwBuffer;
+ }
+ RegCloseKey( hkey);
+ hkey = NULL;
+ }
+}
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashfn.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashfn.h
new file mode 100644
index 0000000000..a86b0a1358
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashfn.h
@@ -0,0 +1,325 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef __HASHFN_H__
+#define __HASHFN_H__
+
+
+// Produce a scrambled, randomish number in the range 0 to RANDOM_PRIME-1.
+// Applying this to the results of the other hash functions is likely to
+// produce a much better distribution, especially for the identity hash
+// functions such as Hash(char c), where records will tend to cluster at
+// the low end of the hashtable otherwise. LKRhash applies this internally
+// to all hash signatures for exactly this reason.
+
+inline DWORD
+HashScramble(DWORD dwHash)
+{
+ // Here are 10 primes slightly greater than 10^9
+ // 1000000007, 1000000009, 1000000021, 1000000033, 1000000087,
+ // 1000000093, 1000000097, 1000000103, 1000000123, 1000000181.
+
+ // default value for "scrambling constant"
+ const DWORD RANDOM_CONSTANT = 314159269UL;
+ // large prime number, also used for scrambling
+ const DWORD RANDOM_PRIME = 1000000007UL;
+
+ return (RANDOM_CONSTANT * dwHash) % RANDOM_PRIME ;
+}
+
+
+// Faster scrambling function suggested by Eric Jacobsen
+
+inline DWORD
+HashRandomizeBits(DWORD dw)
+{
+ return (((dw * 1103515245 + 12345) >> 16)
+ | ((dw * 69069 + 1) & 0xffff0000));
+}
+
+
+// Small prime number used as a multiplier in the supplied hash functions
+const DWORD HASH_MULTIPLIER = 101;
+
+#undef HASH_SHIFT_MULTIPLY
+
+#ifdef HASH_SHIFT_MULTIPLY
+# define HASH_MULTIPLY(dw) (((dw) << 7) - (dw))
+#else
+# define HASH_MULTIPLY(dw) ((dw) * HASH_MULTIPLIER)
+#endif
+
+// Fast, simple hash function that tends to give a good distribution.
+// Apply HashScramble to the result if you're using this for something
+// other than LKRhash.
+
+inline DWORD
+HashString(
+ const char* psz,
+ DWORD dwHash = 0)
+{
+ // force compiler to use unsigned arithmetic
+ const unsigned char* upsz = (const unsigned char*) psz;
+
+ for ( ; *upsz; ++upsz)
+ dwHash = HASH_MULTIPLY(dwHash) + *upsz;
+
+ return dwHash;
+}
+
+inline DWORD
+HashString(
+ __in_ecount(cch) const char* psz,
+ __in DWORD cch,
+ __in DWORD dwHash
+)
+{
+ // force compiler to use unsigned arithmetic
+ const unsigned char* upsz = (const unsigned char*) psz;
+
+ for (DWORD Index = 0;
+ Index < cch;
+ ++Index, ++upsz)
+ {
+ dwHash = HASH_MULTIPLY(dwHash) + *upsz;
+ }
+
+ return dwHash;
+}
+
+
+// Unicode version of above
+
+inline DWORD
+HashString(
+ const wchar_t* pwsz,
+ DWORD dwHash = 0)
+{
+ for ( ; *pwsz; ++pwsz)
+ dwHash = HASH_MULTIPLY(dwHash) + *pwsz;
+
+ return dwHash;
+}
+
+// Based on length of the string instead of null-terminating character
+
+inline DWORD
+HashString(
+ __in_ecount(cch) const wchar_t* pwsz,
+ __in DWORD cch,
+ __in DWORD dwHash
+)
+{
+ for (DWORD Index = 0;
+ Index < cch;
+ ++Index, ++pwsz)
+ {
+ dwHash = HASH_MULTIPLY(dwHash) + *pwsz;
+ }
+
+ return dwHash;
+}
+
+
+// Quick-'n'-dirty case-insensitive string hash function.
+// Make sure that you follow up with _stricmp or _mbsicmp. You should
+// also cache the length of strings and check those first. Caching
+// an uppercase version of a string can help too.
+// Again, apply HashScramble to the result if using with something other
+// than LKRhash.
+// Note: this is not really adequate for MBCS strings.
+
+inline DWORD
+HashStringNoCase(
+ const char* psz,
+ DWORD dwHash = 0)
+{
+ const unsigned char* upsz = (const unsigned char*) psz;
+
+ for ( ; *upsz; ++upsz)
+ dwHash = HASH_MULTIPLY(dwHash)
+ + (*upsz & 0xDF); // strip off lowercase bit
+
+ return dwHash;
+}
+
+inline DWORD
+HashStringNoCase(
+ __in_ecount(cch)
+ const char* psz,
+ SIZE_T cch,
+ DWORD dwHash)
+{
+ const unsigned char* upsz = (const unsigned char*) psz;
+
+ for (SIZE_T Index = 0;
+ Index < cch;
+ ++Index, ++upsz)
+ {
+ dwHash = HASH_MULTIPLY(dwHash)
+ + (*upsz & 0xDF); // strip off lowercase bit
+ }
+ return dwHash;
+}
+
+
+// Unicode version of above
+
+inline DWORD
+HashStringNoCase(
+ const wchar_t* pwsz,
+ DWORD dwHash = 0)
+{
+ for ( ; *pwsz; ++pwsz)
+ dwHash = HASH_MULTIPLY(dwHash) + (*pwsz & 0xFFDF);
+
+ return dwHash;
+}
+
+// Unicode version of above with length
+
+inline DWORD
+HashStringNoCase(
+ __in_ecount(cch)
+ const wchar_t* pwsz,
+ SIZE_T cch,
+ DWORD dwHash)
+{
+ for (SIZE_T Index = 0;
+ Index < cch;
+ ++Index, ++pwsz)
+ {
+ dwHash = HASH_MULTIPLY(dwHash) + (*pwsz & 0xFFDF);
+ }
+ return dwHash;
+}
+
+
+// HashBlob returns the hash of a blob of arbitrary binary data.
+//
+// Warning: HashBlob is generally not the right way to hash a class object.
+// Consider:
+// class CFoo {
+// public:
+// char m_ch;
+// double m_d;
+// char* m_psz;
+// };
+//
+// inline DWORD Hash(const CFoo& rFoo)
+// { return HashBlob(&rFoo, sizeof(CFoo)); }
+//
+// This is the wrong way to hash a CFoo for two reasons: (a) there will be
+// a 7-byte gap between m_ch and m_d imposed by the alignment restrictions
+// of doubles, which will be filled with random data (usually non-zero for
+// stack variables), and (b) it hashes the address (rather than the
+// contents) of the string m_psz. Similarly,
+//
+// bool operator==(const CFoo& rFoo1, const CFoo& rFoo2)
+// { return memcmp(&rFoo1, &rFoo2, sizeof(CFoo)) == 0; }
+//
+// does the wrong thing. Much better to do this:
+//
+// DWORD Hash(const CFoo& rFoo)
+// {
+// return HashString(rFoo.m_psz,
+// HASH_MULTIPLIER * Hash(rFoo.m_ch)
+// + Hash(rFoo.m_d));
+// }
+//
+// Again, apply HashScramble if using with something other than LKRhash.
+
+inline DWORD
+HashBlob(
+ const void* pv,
+ size_t cb,
+ DWORD dwHash = 0)
+{
+ const BYTE * pb = static_cast(pv);
+
+ while (cb-- > 0)
+ dwHash = HASH_MULTIPLY(dwHash) + *pb++;
+
+ return dwHash;
+}
+
+
+
+//
+// Overloaded hash functions for all the major builtin types.
+// Again, apply HashScramble to result if using with something other than
+// LKRhash.
+//
+
+inline DWORD Hash(const char* psz)
+{ return HashString(psz); }
+
+inline DWORD Hash(const unsigned char* pusz)
+{ return HashString(reinterpret_cast(pusz)); }
+
+inline DWORD Hash(const signed char* pssz)
+{ return HashString(reinterpret_cast(pssz)); }
+
+inline DWORD Hash(const wchar_t* pwsz)
+{ return HashString(pwsz); }
+
+inline DWORD
+Hash(
+ const GUID* pguid,
+ DWORD dwHash = 0)
+{
+
+ return * reinterpret_cast(const_cast(pguid)) + dwHash;
+}
+
+// Identity hash functions: scalar values map to themselves
+inline DWORD Hash(char c)
+{ return c; }
+
+inline DWORD Hash(unsigned char uc)
+{ return uc; }
+
+inline DWORD Hash(signed char sc)
+{ return sc; }
+
+inline DWORD Hash(short sh)
+{ return sh; }
+
+inline DWORD Hash(unsigned short ush)
+{ return ush; }
+
+inline DWORD Hash(int i)
+{ return i; }
+
+inline DWORD Hash(unsigned int u)
+{ return u; }
+
+inline DWORD Hash(long l)
+{ return l; }
+
+inline DWORD Hash(unsigned long ul)
+{ return ul; }
+
+inline DWORD Hash(float f)
+{
+ // be careful of rounding errors when computing keys
+ union {
+ float f;
+ DWORD dw;
+ } u;
+ u.f = f;
+ return u.dw;
+}
+
+inline DWORD Hash(double dbl)
+{
+ // be careful of rounding errors when computing keys
+ union {
+ double dbl;
+ DWORD dw[2];
+ } u;
+ u.dbl = dbl;
+ return u.dw[0] * HASH_MULTIPLIER + u.dw[1];
+}
+
+#endif // __HASHFN_H__
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashtable.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashtable.h
new file mode 100644
index 0000000000..9a299ca1af
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashtable.h
@@ -0,0 +1,666 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#pragma once
+
+#include
+#include "rwlock.h"
+#include "prime.h"
+
+template
+class HASH_NODE
+{
+ template
+ friend class HASH_TABLE;
+
+ HASH_NODE(
+ _Record * pRecord,
+ DWORD dwHash
+ ) : _pNext (NULL),
+ _pRecord (pRecord),
+ _dwHash (dwHash)
+ {}
+
+ ~HASH_NODE()
+ {
+ _ASSERTE(_pRecord == NULL);
+ }
+
+ private:
+ // Next node in the hash table look-aside
+ HASH_NODE<_Record> *_pNext;
+
+ // actual record
+ _Record * _pRecord;
+
+ // hash value
+ DWORD _dwHash;
+};
+
+template
+class HASH_TABLE
+{
+protected:
+ typedef BOOL
+ (PFN_DELETE_IF)(
+ _Record * pRecord,
+ PVOID pvContext
+ );
+
+ typedef VOID
+ (PFN_APPLY)(
+ _Record * pRecord,
+ PVOID pvContext
+ );
+
+public:
+ HASH_TABLE(
+ VOID
+ )
+ : _ppBuckets( NULL ),
+ _nBuckets( 0 ),
+ _nItems( 0 )
+ {
+ }
+
+ virtual
+ ~HASH_TABLE();
+
+ virtual
+ VOID
+ ReferenceRecord(
+ _Record * pRecord
+ ) = 0;
+
+ virtual
+ VOID
+ DereferenceRecord(
+ _Record * pRecord
+ ) = 0;
+
+ virtual
+ _Key
+ ExtractKey(
+ _Record * pRecord
+ ) = 0;
+
+ virtual
+ DWORD
+ CalcKeyHash(
+ _Key key
+ ) = 0;
+
+ virtual
+ BOOL
+ EqualKeys(
+ _Key key1,
+ _Key key2
+ ) = 0;
+
+ DWORD
+ Count(
+ VOID
+ ) const;
+
+ bool
+ IsInitialized(
+ VOID
+ ) const;
+
+ virtual
+ VOID
+ Clear();
+
+ HRESULT
+ Initialize(
+ DWORD nBucketSize
+ );
+
+ virtual
+ VOID
+ FindKey(
+ _Key key,
+ _Record ** ppRecord
+ );
+
+ virtual
+ HRESULT
+ InsertRecord(
+ _Record * pRecord
+ );
+
+ virtual
+ VOID
+ DeleteKey(
+ _Key key
+ );
+
+ virtual
+ VOID
+ DeleteIf(
+ PFN_DELETE_IF pfnDeleteIf,
+ PVOID pvContext
+ );
+
+ VOID
+ Apply(
+ PFN_APPLY pfnApply,
+ PVOID pvContext
+ );
+
+private:
+
+ __success(*ppNode != NULL && return != FALSE)
+ BOOL
+ FindNodeInternal(
+ _Key key,
+ DWORD dwHash,
+ __deref_out
+ HASH_NODE<_Record> ** ppNode,
+ __deref_opt_out
+ HASH_NODE<_Record> *** pppPreviousNodeNextPointer = NULL
+ );
+
+ VOID
+ DeleteNode(
+ HASH_NODE<_Record> * pNode
+ )
+ {
+ if (pNode->_pRecord != NULL)
+ {
+ DereferenceRecord(pNode->_pRecord);
+ pNode->_pRecord = NULL;
+ }
+
+ delete pNode;
+ }
+
+ VOID
+ RehashTableIfNeeded(
+ VOID
+ );
+
+ HASH_NODE<_Record> ** _ppBuckets;
+ DWORD _nBuckets;
+ DWORD _nItems;
+ //
+ // Allow to use lock object in const methods.
+ //
+ mutable
+ CWSDRWLock _tableLock;
+};
+
+template
+HRESULT
+HASH_TABLE<_Record,_Key>::Initialize(
+ DWORD nBuckets
+)
+{
+ HRESULT hr = S_OK;
+
+ if ( nBuckets == 0 )
+ {
+ hr = E_INVALIDARG;
+ goto Failed;
+ }
+
+ if (nBuckets >= MAXDWORD/sizeof(HASH_NODE<_Record> *))
+ {
+ hr = E_INVALIDARG;
+ goto Failed;
+ }
+
+ _ASSERTE(_ppBuckets == NULL );
+ if ( _ppBuckets != NULL )
+ {
+ hr = E_INVALIDARG;
+ goto Failed;
+ }
+
+ hr = _tableLock.Init();
+ if ( FAILED( hr ) )
+ {
+ goto Failed;
+ }
+
+ _ppBuckets = (HASH_NODE<_Record> **)HeapAlloc(
+ GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ nBuckets*sizeof(HASH_NODE<_Record> *));
+ if (_ppBuckets == NULL)
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
+ goto Failed;
+ }
+ _nBuckets = nBuckets;
+
+ return S_OK;
+
+Failed:
+
+ if (_ppBuckets)
+ {
+ HeapFree(GetProcessHeap(),
+ 0,
+ _ppBuckets);
+ _ppBuckets = NULL;
+ }
+
+ return hr;
+}
+
+
+template
+HASH_TABLE<_Record,_Key>::~HASH_TABLE()
+{
+ if (_ppBuckets == NULL)
+ {
+ return;
+ }
+
+ _ASSERTE(_nItems == 0);
+
+ HeapFree(GetProcessHeap(),
+ 0,
+ _ppBuckets);
+ _ppBuckets = NULL;
+ _nBuckets = 0;
+}
+
+template< class _Record, class _Key>
+DWORD
+HASH_TABLE<_Record,_Key>::Count() const
+{
+ return _nItems;
+}
+
+template< class _Record, class _Key>
+bool
+HASH_TABLE<_Record,_Key>::IsInitialized(
+ VOID
+) const
+{
+ return _ppBuckets != NULL;
+}
+
+
+template
+VOID
+HASH_TABLE<_Record,_Key>::Clear()
+{
+ HASH_NODE<_Record> *pCurrent;
+ HASH_NODE<_Record> *pNext;
+
+ // This is here in the off cases where someone instantiates a hashtable
+ // and then does an automatic "clear" before its destruction WITHOUT
+ // ever initializing it.
+ if ( ! _tableLock.QueryInited() )
+ {
+ return;
+ }
+
+ _tableLock.ExclusiveAcquire();
+
+ for (DWORD i=0; i<_nBuckets; i++)
+ {
+ pCurrent = _ppBuckets[i];
+ _ppBuckets[i] = NULL;
+ while (pCurrent != NULL)
+ {
+ pNext = pCurrent->_pNext;
+ DeleteNode(pCurrent);
+ pCurrent = pNext;
+ }
+ }
+
+ _nItems = 0;
+ _tableLock.ExclusiveRelease();
+}
+
+template
+__success(*ppNode != NULL && return != FALSE)
+BOOL
+HASH_TABLE<_Record,_Key>::FindNodeInternal(
+ _Key key,
+ DWORD dwHash,
+ __deref_out
+ HASH_NODE<_Record> ** ppNode,
+ __deref_opt_out
+ HASH_NODE<_Record> *** pppPreviousNodeNextPointer
+)
+/*++
+ Return value indicates whether the item is found
+ key, dwHash - key and hash for the node to find
+ ppNode - on successful return, the node found, on failed return, the first
+ node with hash value greater than the node to be found
+ pppPreviousNodeNextPointer - the pointer to previous node's _pNext
+
+ This routine may be called under either read or write lock
+--*/
+{
+ HASH_NODE<_Record> **ppPreviousNodeNextPointer;
+ HASH_NODE<_Record> *pNode;
+ BOOL fFound = FALSE;
+
+ ppPreviousNodeNextPointer = _ppBuckets + (dwHash % _nBuckets);
+ pNode = *ppPreviousNodeNextPointer;
+ while (pNode != NULL)
+ {
+ if (pNode->_dwHash == dwHash)
+ {
+ if (EqualKeys(key,
+ ExtractKey(pNode->_pRecord)))
+ {
+ fFound = TRUE;
+ break;
+ }
+ }
+ else if (pNode->_dwHash > dwHash)
+ {
+ break;
+ }
+
+ ppPreviousNodeNextPointer = &(pNode->_pNext);
+ pNode = *ppPreviousNodeNextPointer;
+ }
+
+ __analysis_assume( (pNode == NULL && fFound == FALSE) ||
+ (pNode != NULL && fFound == TRUE ) );
+ *ppNode = pNode;
+ if (pppPreviousNodeNextPointer != NULL)
+ {
+ *pppPreviousNodeNextPointer = ppPreviousNodeNextPointer;
+ }
+ return fFound;
+}
+
+template
+VOID
+HASH_TABLE<_Record,_Key>::FindKey(
+ _Key key,
+ _Record ** ppRecord
+)
+{
+ HASH_NODE<_Record> *pNode;
+
+ *ppRecord = NULL;
+
+ DWORD dwHash = CalcKeyHash(key);
+
+ _tableLock.SharedAcquire();
+
+ if (FindNodeInternal(key, dwHash, &pNode) &&
+ pNode->_pRecord != NULL)
+ {
+ ReferenceRecord(pNode->_pRecord);
+ *ppRecord = pNode->_pRecord;
+ }
+
+ _tableLock.SharedRelease();
+}
+
+template
+HRESULT
+HASH_TABLE<_Record,_Key>::InsertRecord(
+ _Record * pRecord
+)
+/*++
+ This method inserts a node for this record and also empty nodes for paths
+ in the heirarchy leading upto this path
+
+ The insert is done under only a read-lock - this is possible by keeping
+ the hashes in a bucket in increasing order and using interlocked operations
+ to actually insert the item in the hash-bucket lookaside list and the parent
+ children list
+
+ Returns HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) if the record already exists.
+ Never leak this error to the end user because "*file* already exists" may be confusing.
+--*/
+{
+ BOOL fLocked = FALSE;
+ _Key key = ExtractKey(pRecord);
+ DWORD dwHash = CalcKeyHash(key);
+ HRESULT hr = S_OK;
+ HASH_NODE<_Record> * pNewNode;
+ HASH_NODE<_Record> * pNextNode;
+ HASH_NODE<_Record> ** ppPreviousNodeNextPointer;
+
+ //
+ // Ownership of pRecord is not transferred to pNewNode yet, so remember
+ // to either set it to null before deleting pNewNode or add an extra
+ // reference later - this is to make sure we do not do an extra ref/deref
+ // which users may view as getting flushed out of the hash-table
+ //
+ pNewNode = new HASH_NODE<_Record>(pRecord, dwHash);
+ if (pNewNode == NULL)
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
+ goto Finished;
+ }
+
+ _tableLock.SharedAcquire();
+ fLocked = TRUE;
+
+ do
+ {
+ //
+ // Find the right place to add this node
+ //
+ if (FindNodeInternal(key, dwHash, &pNextNode, &ppPreviousNodeNextPointer))
+ {
+ //
+ // If node already there, return error
+ //
+ pNewNode->_pRecord = NULL;
+ DeleteNode(pNewNode);
+
+ //
+ // We should never leak this error to the end user
+ // because "file already exists" may be confusing.
+ //
+ hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
+ goto Finished;
+ }
+
+ //
+ // If another node got inserted in between, we will have to retry
+ //
+ pNewNode->_pNext = pNextNode;
+ } while (InterlockedCompareExchangePointer((PVOID *)ppPreviousNodeNextPointer,
+ pNewNode,
+ pNextNode) != pNextNode);
+ // pass ownership of pRecord now
+ if (pRecord != NULL)
+ {
+ ReferenceRecord(pRecord);
+ pRecord = NULL;
+ }
+ InterlockedIncrement((LONG *)&_nItems);
+
+Finished:
+
+ if (fLocked)
+ {
+ _tableLock.SharedRelease();
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ RehashTableIfNeeded();
+ }
+
+ return hr;
+}
+
+template
+VOID
+HASH_TABLE<_Record,_Key>::DeleteKey(
+ _Key key
+)
+{
+ HASH_NODE<_Record> *pNode;
+ HASH_NODE<_Record> **ppPreviousNodeNextPointer;
+
+ DWORD dwHash = CalcKeyHash(key);
+
+ _tableLock.ExclusiveAcquire();
+
+ if (FindNodeInternal(key, dwHash, &pNode, &ppPreviousNodeNextPointer))
+ {
+ *ppPreviousNodeNextPointer = pNode->_pNext;
+ DeleteNode(pNode);
+ _nItems--;
+ }
+
+ _tableLock.ExclusiveRelease();
+}
+
+template
+VOID
+HASH_TABLE<_Record,_Key>::DeleteIf(
+ PFN_DELETE_IF pfnDeleteIf,
+ PVOID pvContext
+)
+{
+ HASH_NODE<_Record> *pNode;
+ HASH_NODE<_Record> **ppPreviousNodeNextPointer;
+
+ _tableLock.ExclusiveAcquire();
+
+ for (DWORD i=0; i<_nBuckets; i++)
+ {
+ ppPreviousNodeNextPointer = _ppBuckets + i;
+ pNode = *ppPreviousNodeNextPointer;
+ while (pNode != NULL)
+ {
+ //
+ // Non empty nodes deleted based on DeleteIf, empty nodes deleted
+ // if they have no children
+ //
+ if (pfnDeleteIf(pNode->_pRecord, pvContext))
+ {
+ *ppPreviousNodeNextPointer = pNode->_pNext;
+ DeleteNode(pNode);
+ _nItems--;
+ }
+ else
+ {
+ ppPreviousNodeNextPointer = &pNode->_pNext;
+ }
+
+ pNode = *ppPreviousNodeNextPointer;
+ }
+ }
+
+ _tableLock.ExclusiveRelease();
+}
+
+template
+VOID
+HASH_TABLE<_Record,_Key>::Apply(
+ PFN_APPLY pfnApply,
+ PVOID pvContext
+)
+{
+ HASH_NODE<_Record> *pNode;
+
+ _tableLock.SharedAcquire();
+
+ for (DWORD i=0; i<_nBuckets; i++)
+ {
+ pNode = _ppBuckets[i];
+ while (pNode != NULL)
+ {
+ if (pNode->_pRecord != NULL)
+ {
+ pfnApply(pNode->_pRecord, pvContext);
+ }
+
+ pNode = pNode->_pNext;
+ }
+ }
+
+ _tableLock.SharedRelease();
+}
+
+template
+VOID
+HASH_TABLE<_Record,_Key>::RehashTableIfNeeded(
+ VOID
+)
+{
+ HASH_NODE<_Record> **ppBuckets;
+ DWORD nBuckets;
+ HASH_NODE<_Record> *pNode;
+ HASH_NODE<_Record> *pNextNode;
+ HASH_NODE<_Record> **ppNextPointer;
+ HASH_NODE<_Record> *pNewNextNode;
+ DWORD nNewBuckets;
+
+ //
+ // If number of items has become too many, we will double the hash table
+ // size (we never reduce it however)
+ //
+ if (_nItems <= PRIME::GetPrime(2*_nBuckets))
+ {
+ return;
+ }
+
+ _tableLock.ExclusiveAcquire();
+
+ nNewBuckets = PRIME::GetPrime(2*_nBuckets);
+
+ if (_nItems <= nNewBuckets)
+ {
+ goto Finished;
+ }
+
+ nBuckets = nNewBuckets;
+ if (nBuckets >= 0xffffffff/sizeof(HASH_NODE<_Record> *))
+ {
+ goto Finished;
+ }
+ ppBuckets = (HASH_NODE<_Record> **)HeapAlloc(
+ GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ nBuckets*sizeof(HASH_NODE<_Record> *));
+ if (ppBuckets == NULL)
+ {
+ goto Finished;
+ }
+
+ //
+ // Take out nodes from the old hash table and insert in the new one, make
+ // sure to keep the hashes in increasing order
+ //
+ for (DWORD i=0; i<_nBuckets; i++)
+ {
+ pNode = _ppBuckets[i];
+ while (pNode != NULL)
+ {
+ pNextNode = pNode->_pNext;
+
+ ppNextPointer = ppBuckets + (pNode->_dwHash % nBuckets);
+ pNewNextNode = *ppNextPointer;
+ while (pNewNextNode != NULL &&
+ pNewNextNode->_dwHash <= pNode->_dwHash)
+ {
+ ppNextPointer = &pNewNextNode->_pNext;
+ pNewNextNode = pNewNextNode->_pNext;
+ }
+ pNode->_pNext = pNewNextNode;
+ *ppNextPointer = pNode;
+
+ pNode = pNextNode;
+ }
+ }
+
+ HeapFree(GetProcessHeap(), 0, _ppBuckets);
+ _ppBuckets = ppBuckets;
+ _nBuckets = nBuckets;
+ ppBuckets = NULL;
+
+Finished:
+
+ _tableLock.ExclusiveRelease();
+}
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/http_xp.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/http_xp.h
new file mode 100644
index 0000000000..400d8ec855
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/http_xp.h
@@ -0,0 +1,2797 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef __HTTP_H__
+#define __HTTP_H__
+
+#pragma once
+
+#if _WIN32_WINNT >= 0x0501
+
+//
+// HTTPAPI is available on
+//
+// a) WinXP SP2 and higher
+// b) Windows 2003 and higher
+// c) Vista and higher.
+//
+
+
+
+
+#include
+#include
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+
+//
+// Flags for HttpInitialize() and HttpTerminate().
+//
+
+//
+// HTTP_INITIALIZE_SERVER - Initializes the HTTP API layer and driver for
+// applications using server APIs.
+//
+// HTTP_INITIALIZE_CONFIG - Initializes the HTTP API layer and driver for
+// applications using HTTP configuration APIs.
+//
+//
+// Notes -
+//
+// 1. These flags can be used in combination.
+//
+// 2. HttpTerminate() must be called for each call to HttpInitialize() made
+// with each flag set when invoking HttpInitialize. For example, one
+// could make two calls to HttpInitialize() setting HTTP_INITIALIZE_SERVER
+// the first time and HTTP_INITIALIZE_CONFIG the second time. One call
+// to HttpTerminate() with both flags set suffices to clean up both
+// calls to HttpInitialize().
+//
+
+#define HTTP_INITIALIZE_SERVER 0x00000001
+#define HTTP_INITIALIZE_CONFIG 0x00000002
+
+#if _WIN32_WINNT <= 0x0501
+#define BUILD_IIS_FOR_XP 1
+#endif
+
+#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP
+
+//
+// Following section defines the properties supported by the
+// server side HTTP API.
+//
+
+typedef enum _HTTP_SERVER_PROPERTY
+{
+ //
+ // Used for enabling server side authentication.
+ //
+
+ HttpServerAuthenticationProperty,
+
+ //
+ // Used for enabling logging.
+ //
+
+ HttpServerLoggingProperty,
+
+ //
+ // Used for setting QoS properties.
+ //
+
+ HttpServerQosProperty,
+
+ //
+ // Used for configuring timeouts.
+ //
+
+ HttpServerTimeoutsProperty,
+
+ //
+ // Used for limiting request queue lengths.
+ //
+
+ HttpServerQueueLengthProperty,
+
+ //
+ // Used for manipulating the state.
+ //
+
+ HttpServerStateProperty,
+
+ //
+ // Used for modifying the verbosity level of 503 type responses
+ // generated by server side API.
+ //
+
+ HttpServer503VerbosityProperty,
+
+ //
+ // Used for manipulating Url Group to Request Queue association.
+ //
+
+ HttpServerBindingProperty,
+
+ //
+ // Extended authentication property.
+ //
+
+ HttpServerExtendedAuthenticationProperty,
+
+ //
+ // Listening endpoint property.
+ //
+
+ HttpServerListenEndpointProperty
+
+ //
+ // Authentication channel binding property
+ //
+
+#endif
+#if _WIN32_WINNT >= _WIN32_WINNT_WIN7 || BUILD_IIS_FOR_XP
+
+ ,HttpServerChannelBindProperty
+
+ //
+ // IP Protection level policy for a Url Group.
+ //
+
+ ,HttpServerProtectionLevelProperty
+#endif
+#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP
+
+
+} HTTP_SERVER_PROPERTY, *PHTTP_SERVER_PROPERTY;
+
+
+#define HTTP_MAX_SERVER_QUEUE_LENGTH 0x7FFFFFFF
+#define HTTP_MIN_SERVER_QUEUE_LENGTH 1
+
+//
+// Generic property flags. Each structure defining a property info typically
+// contain an element of this type.
+//
+
+typedef struct _HTTP_PROPERTY_FLAGS
+{
+ ULONG Present:1;
+
+} HTTP_PROPERTY_FLAGS, *PHTTP_PROPERTY_FLAGS;
+
+//
+// Enabled state.
+//
+
+typedef enum _HTTP_ENABLED_STATE
+{
+ HttpEnabledStateActive,
+ HttpEnabledStateInactive,
+
+} HTTP_ENABLED_STATE, *PHTTP_ENABLED_STATE;
+
+
+typedef struct _HTTP_STATE_INFO
+{
+ HTTP_PROPERTY_FLAGS Flags;
+ HTTP_ENABLED_STATE State;
+
+} HTTP_STATE_INFO, *PHTTP_STATE_INFO;
+
+//
+// Defines the verbosity level for a request queue which will be used
+// when sending "503 - Service Unavailable" type error responses. Note that
+// this setting only affects the error responses generated internally
+// by HTTPAPI.
+//
+
+typedef enum _HTTP_503_RESPONSE_VERBOSITY
+{
+ //
+ // Instead of sending a 503 response, the connection will be reset.
+ // This is the default behavior.
+ //
+ Http503ResponseVerbosityBasic,
+
+ //
+ // Will send a 503 w/ a generic reason phrase.
+ //
+ Http503ResponseVerbosityLimited,
+
+ //
+ // Will send a 503 w/ a detailed reason phrase.
+ //
+ Http503ResponseVerbosityFull
+
+} HTTP_503_RESPONSE_VERBOSITY, *PHTTP_503_RESPONSE_VERBOSITY;
+
+//
+// Network QoS related.
+//
+
+typedef enum _HTTP_QOS_SETTING_TYPE
+{
+ HttpQosSettingTypeBandwidth,
+ HttpQosSettingTypeConnectionLimit,
+ HttpQosSettingTypeFlowRate
+
+} HTTP_QOS_SETTING_TYPE, *PHTTP_QOS_SETTING_TYPE;
+
+typedef struct _HTTP_QOS_SETTING_INFO
+{
+ HTTP_QOS_SETTING_TYPE QosType;
+ PVOID QosSetting;
+} HTTP_QOS_SETTING_INFO, *PHTTP_QOS_SETTING_INFO;
+
+typedef struct _HTTP_CONNECTION_LIMIT_INFO
+{
+ HTTP_PROPERTY_FLAGS Flags;
+ ULONG MaxConnections;
+
+} HTTP_CONNECTION_LIMIT_INFO, *PHTTP_CONNECTION_LIMIT_INFO;
+
+typedef struct _HTTP_BANDWIDTH_LIMIT_INFO
+{
+ HTTP_PROPERTY_FLAGS Flags;
+ ULONG MaxBandwidth;
+
+} HTTP_BANDWIDTH_LIMIT_INFO, *PHTTP_BANDWIDTH_LIMIT_INFO;
+
+typedef struct _HTTP_FLOWRATE_INFO
+{
+ HTTP_PROPERTY_FLAGS Flags;
+ ULONG MaxBandwidth;
+ ULONG MaxPeakBandwidth;
+ ULONG BurstSize;
+
+} HTTP_FLOWRATE_INFO, *PHTTP_FLOWRATE_INFO;
+
+//
+// Bandwidth throttling limit can not be set lower than the following
+// number. The value is in bytes/sec.
+//
+
+#define HTTP_MIN_ALLOWED_BANDWIDTH_THROTTLING_RATE ((ULONG)1024)
+
+//
+// Distinguished value for bandwidth, connection limits and logging rollover
+// size indicating "no limit".
+//
+
+#define HTTP_LIMIT_INFINITE ((ULONG)-1)
+
+//
+// Timeout information.
+//
+
+//
+// For manipulating global timeout settings.
+// These timers run when connection does not belong to any application.
+// Value zero is not allowed for driver wide timeout settings.
+//
+
+typedef enum _HTTP_SERVICE_CONFIG_TIMEOUT_KEY
+{
+ IdleConnectionTimeout = 0,
+ HeaderWaitTimeout
+
+} HTTP_SERVICE_CONFIG_TIMEOUT_KEY, *PHTTP_SERVICE_CONFIG_TIMEOUT_KEY;
+
+typedef USHORT HTTP_SERVICE_CONFIG_TIMEOUT_PARAM,
+ *PHTTP_SERVICE_CONFIG_TIMEOUT_PARAM;
+
+//
+// To set a timeout value use the set structure. To query/delete use the key
+// directly. When you query a timeout value the output buffer must be exactly
+// the sizeof param.
+//
+
+typedef struct _HTTP_SERVICE_CONFIG_TIMEOUT_SET
+{
+ HTTP_SERVICE_CONFIG_TIMEOUT_KEY KeyDesc;
+ HTTP_SERVICE_CONFIG_TIMEOUT_PARAM ParamDesc;
+
+} HTTP_SERVICE_CONFIG_TIMEOUT_SET, *PHTTP_SERVICE_CONFIG_TIMEOUT_SET;
+
+//
+// For manipulating application specific timeout settings.
+// These timers run when there's a request being processed on a connection
+// and HTTPAPI has already associated the request with an application.
+// Setting a timeout value to zero will cause HTTPAPI to revert to default.
+//
+
+typedef struct _HTTP_TIMEOUT_LIMIT_INFO
+{
+ HTTP_PROPERTY_FLAGS Flags;
+
+ //
+ // Timeouts configured in seconds.
+ //
+
+ USHORT EntityBody;
+ USHORT DrainEntityBody;
+ USHORT RequestQueue;
+
+ //
+ // Following two timeouts are only enforced after first request on
+ // connection is routed to the application. These will not manipulate
+ // the driver wide timeouts.
+ //
+
+ USHORT IdleConnection;
+ USHORT HeaderWait;
+
+ //
+ // Timeouts configured in bytes/second.
+ // This timer can be turned off by setting it to MAXULONG.
+ //
+
+ ULONG MinSendRate;
+
+} HTTP_TIMEOUT_LIMIT_INFO, *PHTTP_TIMEOUT_LIMIT_INFO;
+
+//
+// Controls whether IP-based URLs should listen on the specific IP or wildcard.
+//
+
+typedef struct _HTTP_LISTEN_ENDPOINT_INFO
+{
+ HTTP_PROPERTY_FLAGS Flags;
+
+ BOOLEAN EnableSharing;
+
+} HTTP_LISTEN_ENDPOINT_INFO, *PHTTP_LISTEN_ENDPOINT_INFO;
+
+
+typedef struct _HTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS
+{
+ USHORT DomainNameLength;
+ PWSTR DomainName;
+ USHORT RealmLength;
+ PWSTR Realm;
+} HTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS,
+ *PHTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS;
+
+typedef struct _HTTP_SERVER_AUTHENTICATION_BASIC_PARAMS
+{
+ USHORT RealmLength;
+ PWSTR Realm;
+} HTTP_SERVER_AUTHENTICATION_BASIC_PARAMS,
+ *PHTTP_SERVER_AUTHENTICATION_BASIC_PARAMS;
+
+//
+// Definitions used for setting server side authentication property.
+//
+
+#define HTTP_AUTH_ENABLE_BASIC (0x00000001)
+#define HTTP_AUTH_ENABLE_DIGEST (0x00000002)
+#define HTTP_AUTH_ENABLE_NTLM (0x00000004)
+#define HTTP_AUTH_ENABLE_NEGOTIATE (0x00000008)
+#define HTTP_AUTH_ENABLE_KERBEROS (0x00000010)
+
+#define HTTP_AUTH_ENABLE_ALL \
+ (HTTP_AUTH_ENABLE_BASIC |\
+ HTTP_AUTH_ENABLE_DIGEST |\
+ HTTP_AUTH_ENABLE_NTLM |\
+ HTTP_AUTH_ENABLE_NEGOTIATE |\
+ HTTP_AUTH_ENABLE_KERBEROS)
+
+
+C_ASSERT(HTTP_AUTH_ENABLE_NEGOTIATE > HTTP_AUTH_ENABLE_NTLM);
+C_ASSERT(HTTP_AUTH_ENABLE_NTLM > HTTP_AUTH_ENABLE_DIGEST);
+C_ASSERT(HTTP_AUTH_ENABLE_DIGEST > HTTP_AUTH_ENABLE_BASIC);
+
+#define HTTP_AUTH_EX_FLAG_ENABLE_KERBEROS_CREDENTIAL_CACHING (0x01)
+#define HTTP_AUTH_EX_FLAG_CAPTURE_CREDENTIAL (0x02)
+
+typedef struct _HTTP_SERVER_AUTHENTICATION_INFO
+{
+ HTTP_PROPERTY_FLAGS Flags;
+
+ ULONG AuthSchemes;
+
+ BOOLEAN ReceiveMutualAuth;
+ BOOLEAN ReceiveContextHandle;
+ BOOLEAN DisableNTLMCredentialCaching;
+
+ UCHAR ExFlags;
+
+ HTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS DigestParams;
+ HTTP_SERVER_AUTHENTICATION_BASIC_PARAMS BasicParams;
+
+} HTTP_SERVER_AUTHENTICATION_INFO, *PHTTP_SERVER_AUTHENTICATION_INFO;
+
+#if _WIN32_WINNT >= _WIN32_WINNT_WIN7 || BUILD_IIS_FOR_XP
+
+//
+// Definitions for setting authentication channel binding properties
+//
+
+typedef enum _HTTP_SERVICE_BINDING_TYPE
+{
+ HttpServiceBindingTypeNone = 0,
+ HttpServiceBindingTypeW,
+ HttpServiceBindingTypeA
+
+} HTTP_SERVICE_BINDING_TYPE;
+
+typedef struct _HTTP_SERVICE_BINDING_BASE
+{
+ HTTP_SERVICE_BINDING_TYPE Type;
+
+} HTTP_SERVICE_BINDING_BASE, *PHTTP_SERVICE_BINDING_BASE;
+
+typedef struct _HTTP_SERVICE_BINDING_A
+{
+ HTTP_SERVICE_BINDING_BASE Base;
+ PCHAR Buffer;
+ ULONG BufferSize;
+
+} HTTP_SERVICE_BINDING_A, *PHTTP_SERVICE_BINDING_A;
+
+typedef struct _HTTP_SERVICE_BINDING_W
+{
+ HTTP_SERVICE_BINDING_BASE Base;
+ PWCHAR Buffer;
+ ULONG BufferSize;
+
+} HTTP_SERVICE_BINDING_W, *PHTTP_SERVICE_BINDING_W;
+
+typedef enum _HTTP_AUTHENTICATION_HARDENING_LEVELS
+{
+ HttpAuthenticationHardeningLegacy = 0,
+ HttpAuthenticationHardeningMedium,
+ HttpAuthenticationHardeningStrict
+
+} HTTP_AUTHENTICATION_HARDENING_LEVELS;
+
+//
+// Channel binding token verification flags.
+//
+
+#define HTTP_CHANNEL_BIND_PROXY 0x1
+#define HTTP_CHANNEL_BIND_PROXY_COHOSTING 0x20
+
+//
+// Service bind verification flags
+//
+
+#define HTTP_CHANNEL_BIND_NO_SERVICE_NAME_CHECK 0x2
+#define HTTP_CHANNEL_BIND_DOTLESS_SERVICE 0x4
+
+//
+// Flags triggering channel bind parameters retrieval
+//
+
+#define HTTP_CHANNEL_BIND_SECURE_CHANNEL_TOKEN 0x8
+#define HTTP_CHANNEL_BIND_CLIENT_SERVICE 0x10
+
+//
+// All valid flags (mask for internal checks)
+//
+
+typedef struct _HTTP_CHANNEL_BIND_INFO
+{
+ HTTP_AUTHENTICATION_HARDENING_LEVELS Hardening;
+ ULONG Flags;
+ PHTTP_SERVICE_BINDING_BASE * ServiceNames;
+ ULONG NumberOfServiceNames;
+
+} HTTP_CHANNEL_BIND_INFO, *PHTTP_CHANNEL_BIND_INFO;
+
+typedef struct _HTTP_REQUEST_CHANNEL_BIND_STATUS
+{
+ PHTTP_SERVICE_BINDING_BASE ServiceName;
+ PUCHAR ChannelToken;
+ ULONG ChannelTokenSize;
+ ULONG Flags;
+
+} HTTP_REQUEST_CHANNEL_BIND_STATUS, *PHTTP_REQUEST_CHANNEL_BIND_STATUS;
+
+#endif
+
+//
+// Definitions used for setting logging property.
+//
+
+//
+// The known log fields recognized/supported by HTTPAPI. Following fields
+// are used for W3C logging. Subset of them are also used for error
+// logging.
+//
+
+#define HTTP_LOG_FIELD_DATE 0x00000001
+#define HTTP_LOG_FIELD_TIME 0x00000002
+#define HTTP_LOG_FIELD_CLIENT_IP 0x00000004
+#define HTTP_LOG_FIELD_USER_NAME 0x00000008
+#define HTTP_LOG_FIELD_SITE_NAME 0x00000010
+#define HTTP_LOG_FIELD_COMPUTER_NAME 0x00000020
+#define HTTP_LOG_FIELD_SERVER_IP 0x00000040
+#define HTTP_LOG_FIELD_METHOD 0x00000080
+#define HTTP_LOG_FIELD_URI_STEM 0x00000100
+#define HTTP_LOG_FIELD_URI_QUERY 0x00000200
+#define HTTP_LOG_FIELD_STATUS 0x00000400
+#define HTTP_LOG_FIELD_WIN32_STATUS 0x00000800
+#define HTTP_LOG_FIELD_BYTES_SENT 0x00001000
+#define HTTP_LOG_FIELD_BYTES_RECV 0x00002000
+#define HTTP_LOG_FIELD_TIME_TAKEN 0x00004000
+#define HTTP_LOG_FIELD_SERVER_PORT 0x00008000
+#define HTTP_LOG_FIELD_USER_AGENT 0x00010000
+#define HTTP_LOG_FIELD_COOKIE 0x00020000
+#define HTTP_LOG_FIELD_REFERER 0x00040000
+#define HTTP_LOG_FIELD_VERSION 0x00080000
+#define HTTP_LOG_FIELD_HOST 0x00100000
+#define HTTP_LOG_FIELD_SUB_STATUS 0x00200000
+
+//
+// Fields that are used only for error logging.
+//
+
+#define HTTP_LOG_FIELD_CLIENT_PORT 0x00400000
+#define HTTP_LOG_FIELD_URI 0x00800000
+#define HTTP_LOG_FIELD_SITE_ID 0x01000000
+#define HTTP_LOG_FIELD_REASON 0x02000000
+#define HTTP_LOG_FIELD_QUEUE_NAME 0x04000000
+
+//
+// Defines the logging type.
+//
+
+typedef enum _HTTP_LOGGING_TYPE
+{
+ HttpLoggingTypeW3C,
+ HttpLoggingTypeIIS,
+ HttpLoggingTypeNCSA,
+ HttpLoggingTypeRaw
+ ,HttpLoggingTypeMaximum
+
+} HTTP_LOGGING_TYPE, *PHTTP_LOGGING_TYPE;
+
+//
+// Defines the rollover type for log files.
+//
+
+typedef enum _HTTP_LOGGING_ROLLOVER_TYPE
+{
+ HttpLoggingRolloverSize,
+ HttpLoggingRolloverDaily,
+ HttpLoggingRolloverWeekly,
+ HttpLoggingRolloverMonthly,
+ HttpLoggingRolloverHourly
+
+} HTTP_LOGGING_ROLLOVER_TYPE, *PHTTP_LOGGING_ROLLOVER_TYPE;
+
+//
+// Log file rollover size can not be set lower than the following
+// limit. The value is in bytes.
+//
+
+#define HTTP_MIN_ALLOWED_LOG_FILE_ROLLOVER_SIZE ((ULONG)(1 * 1024 * 1024))
+
+//
+// Logging option flags. When used in the logging configuration alters
+// some default logging behaviour.
+//
+// HTTP_LOGGING_FLAG_LOCAL_TIME_ROLLOVER - This flag is used to change
+// the log file rollover to happen by local time based. By default
+// log file rollovers happen by GMT time.
+//
+// HTTP_LOGGING_FLAG_USE_UTF8_CONVERSION - When set the unicode fields
+// will be converted to UTF8 multibytes when writting to the log
+// files. When this flag is not present, the local code page
+// conversion happens.
+//
+// HTTP_LOGGING_FLAG_LOG_ERRORS_ONLY -
+// HTTP_LOGGING_FLAG_LOG_SUCCESS_ONLY - These two flags are used to
+// to do selective logging. If neither of them are present both
+// types of requests will be logged. Only one these flags can be
+// set at a time. They are mutually exclusive.
+//
+
+#define HTTP_LOGGING_FLAG_LOCAL_TIME_ROLLOVER (0x00000001)
+#define HTTP_LOGGING_FLAG_USE_UTF8_CONVERSION (0x00000002)
+#define HTTP_LOGGING_FLAG_LOG_ERRORS_ONLY (0x00000004)
+#define HTTP_LOGGING_FLAG_LOG_SUCCESS_ONLY (0x00000008)
+
+//
+// Configuration structure used for setting the logging property.
+//
+
+typedef struct _HTTP_LOGGING_INFO
+{
+ //
+ // Specifies whether this property exists or not.
+ //
+
+ HTTP_PROPERTY_FLAGS Flags;
+
+ //
+ // Optional logging flags.
+ //
+
+ ULONG LoggingFlags;
+
+ //
+ // Optional informatonal software directive string for W3C type logging. Not
+ // used for other types of logging. If nothing is provided here HTTPAPI will
+ // log a default string. Any arbitrary string could be used here to identify
+ // the application. Length cannot be greater than MAX_PATH. Lenght is in
+ // bytes.
+ //
+
+ PCWSTR SoftwareName;
+ USHORT SoftwareNameLength;
+
+ //
+ // Log file directory must be a fully qualified path.
+ // Length must be in number of bytes.
+ //
+
+ USHORT DirectoryNameLength;
+ PCWSTR DirectoryName;
+
+ //
+ // Specifies the format for the log files.
+ //
+
+ HTTP_LOGGING_TYPE Format;
+
+ //
+ // Bitmask value indicates which fields to be logged
+ // if the log format is set to W3C. This must be the 'bitwise or'
+ // of the HTTP_LOG_FIELD_... values.
+ //
+
+ ULONG Fields;
+
+ //
+ // Following fields are reserved they must be NULL and zero..
+ //
+
+ PVOID pExtFields;
+ USHORT NumOfExtFields;
+
+ //
+ // Reserved must be zero.
+ //
+
+ USHORT MaxRecordSize;
+
+ //
+ // Defines the rollover type for the log files.
+ //
+
+ HTTP_LOGGING_ROLLOVER_TYPE RolloverType;
+
+ //
+ // Indicates the maximum size (in bytes) after which
+ // the log files should be rolled over. A value of -1
+ // (HTTP_LIMIT_INFINITE) indicates an unlimited size.
+ // This value is discarded if rollover type is not set to
+ // HttpLoggingRolloverSize.
+ //
+
+ ULONG RolloverSize;
+
+ //
+ // Specifies the security descriptor to be applied to
+ // the log files and the sub-directories. If null we will
+ // inherit the system default. This security descriptor must
+ // be self-relative.
+ //
+
+ PSECURITY_DESCRIPTOR pSecurityDescriptor;
+
+} HTTP_LOGGING_INFO, *PHTTP_LOGGING_INFO;
+
+//
+// Binding information.
+//
+
+typedef struct _HTTP_BINDING_INFO
+{
+ HTTP_PROPERTY_FLAGS Flags;
+ HANDLE RequestQueueHandle;
+
+} HTTP_BINDING_INFO, *PHTTP_BINDING_INFO;
+
+#endif
+#if _WIN32_WINNT >= _WIN32_WINNT_WIN7 || BUILD_IIS_FOR_XP
+
+//
+// Defines the protection level types for UrlGroups.
+//
+
+typedef enum _HTTP_PROTECTION_LEVEL_TYPE
+{
+ //
+ // This option will allow edge (NAT) traversed traffic, i.e. Teredo
+ // for the UrlGroup, unless there is an admin rule that overwrites the
+ // application's intend.
+ //
+
+ HttpProtectionLevelUnrestricted,
+
+ //
+ // This setting will ensure that edge (NAT) traversed traffic
+ // will not be allowed.
+ //
+
+ HttpProtectionLevelEdgeRestricted,
+
+ //
+ // Below type is not supported by HTTP API.
+ //
+
+ HttpProtectionLevelRestricted
+
+
+} HTTP_PROTECTION_LEVEL_TYPE, *PHTTP_PROTECTION_LEVEL_TYPE;
+
+//
+// Controls whether the associated UrlGroup Namespace should receive
+// edge traversed traffic. By default this parameter is unspecified.
+//
+
+typedef struct _HTTP_PROTECTION_LEVEL_INFO
+{
+ HTTP_PROPERTY_FLAGS Flags;
+ HTTP_PROTECTION_LEVEL_TYPE Level;
+
+} HTTP_PROTECTION_LEVEL_INFO, *PHTTP_PROTECTION_LEVEL_INFO;
+
+#endif
+#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP
+
+
+//
+// Definitions for request queue manipulation.
+//
+// These flags are used with HttpCreateRequestQueue() API.
+//
+// HTTP_CREATE_REQUEST_QUEUE_FLAG_OPEN_EXISTING - To open an existing request
+// queue. The request queue name must be supplied.
+//
+// HTTP_CREATE_REQUEST_QUEUE_FLAG_CONTROLLER - Creates the request queue and
+// marks that the caller process is not willing to do send/receive (HTTP I/O)on
+// the handle directly.
+//
+
+#define HTTP_CREATE_REQUEST_QUEUE_FLAG_OPEN_EXISTING (0x00000001)
+#define HTTP_CREATE_REQUEST_QUEUE_FLAG_CONTROLLER (0x00000002)
+
+#endif // _WIN32_WINNT >= 0x0600
+
+//
+// Flags for HttpReceiveHttpRequest().
+//
+// HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY - Specifies that the caller would like
+// any available entity body to be copied along with the protocol headers.
+//
+// HTTP_RECEIVE_REQUEST_FLAG_FLUSH_BODY - Specifies that the caller would like
+// all of the entity bodies to be copied along with the protocol headers.
+//
+
+#define HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY 0x00000001
+#define HTTP_RECEIVE_REQUEST_FLAG_FLUSH_BODY 0x00000002
+
+
+#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP
+
+//
+// Flags for HttpReceiveRequestEntityBody().
+//
+// HTTP_RECEIVE_REQUEST_ENTITY_BODY_FLAG_FILL_BUFFER - Specifies that the
+// caller would like the buffer to get filled up with entity bodies unless
+// there are no more entity bodies to be copied.
+//
+
+#define HTTP_RECEIVE_REQUEST_ENTITY_BODY_FLAG_FILL_BUFFER 0x00000001
+
+#endif // _WIN32_WINNT >= 0x0600
+
+
+//
+// Flags for HttpSendHttpResponse() and HttpSendResponseEntityBody().
+//
+// HTTP_SEND_RESPONSE_FLAG_DISCONNECT - Specifies that the network connection
+// should be disconnected immediately after sending the response, overriding
+// the HTTP protocol's persistent connection features, such as
+// "Connection: keep-alive".
+//
+// HTTP_SEND_RESPONSE_FLAG_MORE_DATA - Specifies that additional entity body
+// data will be sent by the caller.
+//
+// HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA - Specifies that a caller wants the
+// response to complete as soon as possible at the cost of buffering partial
+// or the entire response.
+//
+// HTTP_SEND_RESPONSE_FLAG_ENABLE_NAGLING - Specifies that a caller wants to
+// enable the TCP nagling algorithm for this particular send.
+//
+// HTTP_SEND_RESPONSE_FLAG_PROCESS_RANGES - Specifies that for a range request
+// a full response content is passed and a caller wants HTTP API to process
+// ranges properly.
+//
+
+#define HTTP_SEND_RESPONSE_FLAG_DISCONNECT 0x00000001
+#define HTTP_SEND_RESPONSE_FLAG_MORE_DATA 0x00000002
+#define HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA 0x00000004
+#define HTTP_SEND_RESPONSE_FLAG_ENABLE_NAGLING 0x00000008
+#define HTTP_SEND_RESPONSE_FLAG_PROCESS_RANGES 0x00000020
+
+
+//
+// Flags for HttpFlushResponseCache().
+//
+// HTTP_FLUSH_RESPONSE_FLAG_RECURSIVE - Flushes the specified URL and all
+// hierarchally-related sub-URLs from the response or fragment cache.
+//
+
+#define HTTP_FLUSH_RESPONSE_FLAG_RECURSIVE 0x00000001
+
+
+//
+// Opaque identifiers for various HTTPAPI objects.
+//
+
+typedef ULONGLONG HTTP_OPAQUE_ID, *PHTTP_OPAQUE_ID;
+
+typedef HTTP_OPAQUE_ID HTTP_REQUEST_ID, *PHTTP_REQUEST_ID;
+typedef HTTP_OPAQUE_ID HTTP_CONNECTION_ID, *PHTTP_CONNECTION_ID;
+typedef HTTP_OPAQUE_ID HTTP_RAW_CONNECTION_ID, *PHTTP_RAW_CONNECTION_ID;
+
+#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP
+
+typedef HTTP_OPAQUE_ID HTTP_URL_GROUP_ID, *PHTTP_URL_GROUP_ID;
+typedef HTTP_OPAQUE_ID HTTP_SERVER_SESSION_ID, *PHTTP_SERVER_SESSION_ID;
+
+#endif // _WIN32_WINNT >= 0x0600
+
+//
+// Macros for opaque identifier manipulations.
+//
+
+#define HTTP_NULL_ID (0ui64)
+#define HTTP_IS_NULL_ID(pid) (HTTP_NULL_ID == *(pid))
+#define HTTP_SET_NULL_ID(pid) (*(pid) = HTTP_NULL_ID)
+
+//
+// This structure defines a file byte range.
+//
+// If the Length field is HTTP_BYTE_RANGE_TO_EOF then the remainder of the
+// file (everything after StartingOffset) is sent.
+//
+
+#define HTTP_BYTE_RANGE_TO_EOF ((ULONGLONG)-1)
+
+typedef struct _HTTP_BYTE_RANGE
+{
+ ULARGE_INTEGER StartingOffset;
+ ULARGE_INTEGER Length;
+
+} HTTP_BYTE_RANGE, *PHTTP_BYTE_RANGE;
+
+//
+// The type for HTTP protocol version numbers.
+//
+
+typedef struct _HTTP_VERSION
+{
+ USHORT MajorVersion;
+ USHORT MinorVersion;
+
+} HTTP_VERSION, *PHTTP_VERSION;
+
+//
+// Some useful macros for HTTP protocol version manipulation.
+//
+
+#define HTTP_VERSION_UNKNOWN { 0, 0 }
+#define HTTP_VERSION_0_9 { 0, 9 }
+#define HTTP_VERSION_1_0 { 1, 0 }
+#define HTTP_VERSION_1_1 { 1, 1 }
+
+#define HTTP_SET_VERSION(version, major, minor) \
+do { \
+ (version).MajorVersion = (major); \
+ (version).MinorVersion = (minor); \
+} while (0, 0)
+
+#define HTTP_EQUAL_VERSION(version, major, minor) \
+ ((version).MajorVersion == (major) && \
+ (version).MinorVersion == (minor))
+
+#define HTTP_GREATER_VERSION(version, major, minor) \
+ ((version).MajorVersion > (major) || \
+ ((version).MajorVersion == (major) && \
+ (version).MinorVersion > (minor)))
+
+#define HTTP_LESS_VERSION(version, major, minor) \
+ ((version).MajorVersion < (major) || \
+ ((version).MajorVersion == (major) && \
+ (version).MinorVersion < (minor)))
+
+#define HTTP_NOT_EQUAL_VERSION(version, major, minor) \
+ (!HTTP_EQUAL_VERSION(version, major, minor))
+
+#define HTTP_GREATER_EQUAL_VERSION(version, major, minor) \
+ (!HTTP_LESS_VERSION(version, major, minor))
+
+#define HTTP_LESS_EQUAL_VERSION(version, major, minor) \
+ (!HTTP_GREATER_VERSION(version, major, minor))
+
+//
+// The enum type for HTTP verbs.
+//
+
+typedef enum _HTTP_VERB
+{
+ HttpVerbUnparsed,
+ HttpVerbUnknown,
+ HttpVerbInvalid,
+ HttpVerbOPTIONS,
+ HttpVerbGET,
+ HttpVerbHEAD,
+ HttpVerbPOST,
+ HttpVerbPUT,
+ HttpVerbDELETE,
+ HttpVerbTRACE,
+ HttpVerbCONNECT,
+ HttpVerbTRACK, // used by Microsoft Cluster Server for a non-logged trace
+ HttpVerbMOVE,
+ HttpVerbCOPY,
+ HttpVerbPROPFIND,
+ HttpVerbPROPPATCH,
+ HttpVerbMKCOL,
+ HttpVerbLOCK,
+ HttpVerbUNLOCK,
+ HttpVerbSEARCH,
+
+ HttpVerbMaximum
+
+} HTTP_VERB, *PHTTP_VERB;
+
+//
+// Symbols for all HTTP/1.1 headers and other tokens. Notice request +
+// response values overlap. Make sure you know which type of header array
+// you are indexing.
+//
+// These values are used as offsets into arrays and as token values in
+// HTTP_KNOWN_HEADER arrays in HTTP_REQUEST_HEADERS and HTTP_RESPONSE_HEADERS.
+//
+// See RFC 2616, HTTP/1.1, for further explanation of most of these headers.
+//
+
+typedef enum _HTTP_HEADER_ID
+{
+ HttpHeaderCacheControl = 0, // general-header [section 4.5]
+ HttpHeaderConnection = 1, // general-header [section 4.5]
+ HttpHeaderDate = 2, // general-header [section 4.5]
+ HttpHeaderKeepAlive = 3, // general-header [not in rfc]
+ HttpHeaderPragma = 4, // general-header [section 4.5]
+ HttpHeaderTrailer = 5, // general-header [section 4.5]
+ HttpHeaderTransferEncoding = 6, // general-header [section 4.5]
+ HttpHeaderUpgrade = 7, // general-header [section 4.5]
+ HttpHeaderVia = 8, // general-header [section 4.5]
+ HttpHeaderWarning = 9, // general-header [section 4.5]
+
+ HttpHeaderAllow = 10, // entity-header [section 7.1]
+ HttpHeaderContentLength = 11, // entity-header [section 7.1]
+ HttpHeaderContentType = 12, // entity-header [section 7.1]
+ HttpHeaderContentEncoding = 13, // entity-header [section 7.1]
+ HttpHeaderContentLanguage = 14, // entity-header [section 7.1]
+ HttpHeaderContentLocation = 15, // entity-header [section 7.1]
+ HttpHeaderContentMd5 = 16, // entity-header [section 7.1]
+ HttpHeaderContentRange = 17, // entity-header [section 7.1]
+ HttpHeaderExpires = 18, // entity-header [section 7.1]
+ HttpHeaderLastModified = 19, // entity-header [section 7.1]
+
+
+ // Request Headers
+
+ HttpHeaderAccept = 20, // request-header [section 5.3]
+ HttpHeaderAcceptCharset = 21, // request-header [section 5.3]
+ HttpHeaderAcceptEncoding = 22, // request-header [section 5.3]
+ HttpHeaderAcceptLanguage = 23, // request-header [section 5.3]
+ HttpHeaderAuthorization = 24, // request-header [section 5.3]
+ HttpHeaderCookie = 25, // request-header [not in rfc]
+ HttpHeaderExpect = 26, // request-header [section 5.3]
+ HttpHeaderFrom = 27, // request-header [section 5.3]
+ HttpHeaderHost = 28, // request-header [section 5.3]
+ HttpHeaderIfMatch = 29, // request-header [section 5.3]
+
+ HttpHeaderIfModifiedSince = 30, // request-header [section 5.3]
+ HttpHeaderIfNoneMatch = 31, // request-header [section 5.3]
+ HttpHeaderIfRange = 32, // request-header [section 5.3]
+ HttpHeaderIfUnmodifiedSince = 33, // request-header [section 5.3]
+ HttpHeaderMaxForwards = 34, // request-header [section 5.3]
+ HttpHeaderProxyAuthorization = 35, // request-header [section 5.3]
+ HttpHeaderReferer = 36, // request-header [section 5.3]
+ HttpHeaderRange = 37, // request-header [section 5.3]
+ HttpHeaderTe = 38, // request-header [section 5.3]
+ HttpHeaderTranslate = 39, // request-header [webDAV, not in rfc 2518]
+
+ HttpHeaderUserAgent = 40, // request-header [section 5.3]
+
+ HttpHeaderRequestMaximum = 41,
+
+
+ // Response Headers
+
+ HttpHeaderAcceptRanges = 20, // response-header [section 6.2]
+ HttpHeaderAge = 21, // response-header [section 6.2]
+ HttpHeaderEtag = 22, // response-header [section 6.2]
+ HttpHeaderLocation = 23, // response-header [section 6.2]
+ HttpHeaderProxyAuthenticate = 24, // response-header [section 6.2]
+ HttpHeaderRetryAfter = 25, // response-header [section 6.2]
+ HttpHeaderServer = 26, // response-header [section 6.2]
+ HttpHeaderSetCookie = 27, // response-header [not in rfc]
+ HttpHeaderVary = 28, // response-header [section 6.2]
+ HttpHeaderWwwAuthenticate = 29, // response-header [section 6.2]
+
+ HttpHeaderResponseMaximum = 30,
+
+
+ HttpHeaderMaximum = 41
+
+} HTTP_HEADER_ID, *PHTTP_HEADER_ID;
+
+
+//
+// Structure defining format of a known HTTP header.
+// Name is from HTTP_HEADER_ID.
+//
+
+typedef struct _HTTP_KNOWN_HEADER
+{
+ USHORT RawValueLength; // in bytes not including the NUL
+ PCSTR pRawValue;
+
+} HTTP_KNOWN_HEADER, *PHTTP_KNOWN_HEADER;
+
+//
+// Structure defining format of an unknown header.
+//
+
+typedef struct _HTTP_UNKNOWN_HEADER
+{
+ USHORT NameLength; // in bytes not including the NUL
+ USHORT RawValueLength; // in bytes not including the NUL
+ PCSTR pName; // The header name (minus the ':' character)
+ PCSTR pRawValue; // The header value
+
+} HTTP_UNKNOWN_HEADER, *PHTTP_UNKNOWN_HEADER;
+
+#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP
+
+//
+// Log fields data structure is used for logging a request. This structure must
+// be provided along with an HttpSendHttpResponse or HttpSendResponseEntityBody
+// call that concludes the send.
+//
+
+// Base structure is for future versioning.
+
+typedef enum _HTTP_LOG_DATA_TYPE
+{
+ HttpLogDataTypeFields = 0
+
+} HTTP_LOG_DATA_TYPE, *PHTTP_LOG_DATA_TYPE;
+
+// should we DECLSPEC_ALIGN(4 or 8) == DECLSPEC_POINTERALIGN?
+typedef struct _HTTP_LOG_DATA
+{
+ HTTP_LOG_DATA_TYPE Type;
+
+} HTTP_LOG_DATA, *PHTTP_LOG_DATA;
+
+// Current log fields data structure for of type HttpLogDataTypeFields.
+
+typedef struct _HTTP_LOG_FIELDS_DATA
+{
+ HTTP_LOG_DATA Base;
+
+ USHORT UserNameLength;
+ USHORT UriStemLength;
+ USHORT ClientIpLength;
+ USHORT ServerNameLength;
+ USHORT ServiceNameLength;
+ USHORT ServerIpLength;
+ USHORT MethodLength;
+ USHORT UriQueryLength;
+ USHORT HostLength;
+ USHORT UserAgentLength;
+ USHORT CookieLength;
+ USHORT ReferrerLength;
+
+ PWCHAR UserName;
+ PWCHAR UriStem;
+ PCHAR ClientIp;
+ PCHAR ServerName;
+ PCHAR ServiceName;
+ PCHAR ServerIp;
+ PCHAR Method;
+ PCHAR UriQuery;
+ PCHAR Host;
+ PCHAR UserAgent;
+ PCHAR Cookie;
+ PCHAR Referrer;
+
+ USHORT ServerPort;
+ USHORT ProtocolStatus;
+
+ ULONG Win32Status;
+
+ HTTP_VERB MethodNum;
+
+ USHORT SubStatus;
+
+} HTTP_LOG_FIELDS_DATA, *PHTTP_LOG_FIELDS_DATA;
+
+#endif // _WIN32_WINNT >= 0x0600
+
+//
+// This enum defines a data source for a particular chunk of data.
+//
+
+typedef enum _HTTP_DATA_CHUNK_TYPE
+{
+ HttpDataChunkFromMemory,
+ HttpDataChunkFromFileHandle,
+ HttpDataChunkFromFragmentCache,
+ HttpDataChunkFromFragmentCacheEx,
+
+ HttpDataChunkMaximum
+
+} HTTP_DATA_CHUNK_TYPE, *PHTTP_DATA_CHUNK_TYPE;
+
+
+//
+// This structure describes an individual data chunk.
+//
+
+typedef struct _HTTP_DATA_CHUNK
+{
+ //
+ // The type of this data chunk.
+ //
+
+ HTTP_DATA_CHUNK_TYPE DataChunkType;
+
+ //
+ // The data chunk structures, one per supported data chunk type.
+ //
+
+ union
+ {
+ //
+ // From-memory data chunk.
+ //
+
+ struct
+ {
+ PVOID pBuffer;
+ ULONG BufferLength;
+
+ } FromMemory;
+
+ //
+ // From-file handle data chunk.
+ //
+
+ struct
+ {
+ HTTP_BYTE_RANGE ByteRange;
+ HANDLE FileHandle;
+
+ } FromFileHandle;
+
+ //
+ // From-fragment cache data chunk.
+ //
+
+ struct
+ {
+ USHORT FragmentNameLength; // in bytes not including the NUL
+ PCWSTR pFragmentName;
+
+ } FromFragmentCache;
+
+ //
+ // From-fragment cache data chunk that specifies a byte range.
+ //
+
+ struct
+ {
+ HTTP_BYTE_RANGE ByteRange;
+ PCWSTR pFragmentName; // NULL-terminated string
+
+ } FromFragmentCacheEx;
+
+ };
+
+} HTTP_DATA_CHUNK, *PHTTP_DATA_CHUNK;
+
+//
+// HTTP API doesn't support 16 bit applications.
+// Neither WIN32 nor _WIN64 was defined.
+//
+
+C_ASSERT(TYPE_ALIGNMENT(HTTP_DATA_CHUNK) == sizeof(ULONGLONG));
+
+//
+// Structure defining format of request headers.
+//
+
+typedef struct _HTTP_REQUEST_HEADERS
+{
+ //
+ // The array of unknown HTTP headers and the number of
+ // entries in the array.
+ //
+
+ USHORT UnknownHeaderCount;
+ PHTTP_UNKNOWN_HEADER pUnknownHeaders;
+
+ //
+ // Trailers - we don't use these currently, reserved for a future release
+ //
+ USHORT TrailerCount; // Reserved, must be 0
+ PHTTP_UNKNOWN_HEADER pTrailers; // Reserved, must be NULL
+
+
+ //
+ // Known headers.
+ //
+
+ HTTP_KNOWN_HEADER KnownHeaders[HttpHeaderRequestMaximum];
+
+} HTTP_REQUEST_HEADERS, *PHTTP_REQUEST_HEADERS;
+
+//
+// Structure defining format of response headers.
+//
+
+typedef struct _HTTP_RESPONSE_HEADERS
+{
+ //
+ // The array of unknown HTTP headers and the number of
+ // entries in the array.
+ //
+
+ USHORT UnknownHeaderCount;
+ PHTTP_UNKNOWN_HEADER pUnknownHeaders;
+
+ //
+ // Trailers - we don't use these currently, reserved for a future release
+ //
+ USHORT TrailerCount; // Reserved, must be 0
+ PHTTP_UNKNOWN_HEADER pTrailers; // Reserved, must be NULL
+
+ //
+ // Known headers.
+ //
+
+ HTTP_KNOWN_HEADER KnownHeaders[HttpHeaderResponseMaximum];
+
+} HTTP_RESPONSE_HEADERS, *PHTTP_RESPONSE_HEADERS;
+
+//
+// Structure defining format of transport address. Use pLocalAddress->sa_family
+// to determine whether this is an IPv4 address (AF_INET) or IPv6 (AF_INET6).
+//
+// pRemoteAddress->sa_family will be the same as pLocalAddress->sa_family.
+//
+// SOCKADDRs are always in network order, not host order.
+//
+
+typedef struct _HTTP_TRANSPORT_ADDRESS
+{
+ PSOCKADDR pRemoteAddress;
+ PSOCKADDR pLocalAddress;
+
+} HTTP_TRANSPORT_ADDRESS, *PHTTP_TRANSPORT_ADDRESS;
+
+//
+// Structure defining format of cooked URL.
+//
+
+typedef struct _HTTP_COOKED_URL
+{
+ //
+ // Pointers overlap and point into pFullUrl. NULL if not present.
+ //
+
+ USHORT FullUrlLength; // in bytes not including the NUL
+ USHORT HostLength; // in bytes (no NUL)
+ USHORT AbsPathLength; // in bytes (no NUL)
+ USHORT QueryStringLength; // in bytes (no NUL)
+
+ PCWSTR pFullUrl; // points to "http://hostname:port/abs/.../path?query"
+ PCWSTR pHost; // points to the first char in the hostname
+ PCWSTR pAbsPath; // Points to the 3rd '/' char
+ PCWSTR pQueryString; // Points to the 1st '?' char or NULL
+
+} HTTP_COOKED_URL, *PHTTP_COOKED_URL;
+
+//
+// An opaque context for URL manipulation.
+//
+
+typedef ULONGLONG HTTP_URL_CONTEXT;
+
+
+#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP
+
+//
+// Optional flags for URL manipulation functions.
+//
+// HTTP_URL_FLAG_REMOVE_ALL : When this flag is used
+// when removing a Url from a url group, regardless of
+// the passed URL, all of the Urls from the url group
+// will be removed.
+//
+
+#define HTTP_URL_FLAG_REMOVE_ALL 0x00000001
+
+
+//
+// Request Authentication related.
+//
+
+typedef enum _HTTP_AUTH_STATUS
+{
+ HttpAuthStatusSuccess,
+ HttpAuthStatusNotAuthenticated,
+ HttpAuthStatusFailure
+
+} HTTP_AUTH_STATUS, *PHTTP_AUTH_STATUS;
+
+
+typedef enum _HTTP_REQUEST_AUTH_TYPE
+{
+ HttpRequestAuthTypeNone = 0,
+ HttpRequestAuthTypeBasic,
+ HttpRequestAuthTypeDigest,
+ HttpRequestAuthTypeNTLM,
+ HttpRequestAuthTypeNegotiate,
+ HttpRequestAuthTypeKerberos
+
+
+} HTTP_REQUEST_AUTH_TYPE, *PHTTP_REQUEST_AUTH_TYPE;
+
+#endif // _WIN32_WINNT >= 0x0600
+
+//
+// SSL Client certificate information.
+//
+
+typedef struct _HTTP_SSL_CLIENT_CERT_INFO
+{
+ ULONG CertFlags;
+ ULONG CertEncodedSize;
+ PUCHAR pCertEncoded;
+ HANDLE Token;
+ BOOLEAN CertDeniedByMapper;
+
+} HTTP_SSL_CLIENT_CERT_INFO, *PHTTP_SSL_CLIENT_CERT_INFO;
+
+#if _WIN32_WINNT >= _WIN32_WINNT_WIN7 || BUILD_IIS_FOR_XP
+
+//
+// Flag to retrieve secure channel binding with HttpReceiveClientCertificate
+//
+
+#define HTTP_RECEIVE_SECURE_CHANNEL_TOKEN 0x1
+
+#endif
+
+//
+// Data computed during SSL handshake.
+//
+
+typedef struct _HTTP_SSL_INFO
+{
+ USHORT ServerCertKeySize;
+ USHORT ConnectionKeySize;
+ ULONG ServerCertIssuerSize;
+ ULONG ServerCertSubjectSize;
+
+ PCSTR pServerCertIssuer;
+ PCSTR pServerCertSubject;
+
+ PHTTP_SSL_CLIENT_CERT_INFO pClientCertInfo;
+ ULONG SslClientCertNegotiated;
+
+} HTTP_SSL_INFO, *PHTTP_SSL_INFO;
+
+
+#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP
+
+//
+// Generic request information type.
+//
+
+typedef enum _HTTP_REQUEST_INFO_TYPE
+{
+ HttpRequestInfoTypeAuth
+
+#if _WIN32_WINNT >= _WIN32_WINNT_WIN7
+ ,HttpRequestInfoTypeChannelBind
+#endif
+
+
+} HTTP_REQUEST_INFO_TYPE, *PHTTP_REQUEST_INFO_TYPE;
+
+typedef struct _HTTP_REQUEST_INFO
+{
+ HTTP_REQUEST_INFO_TYPE InfoType;
+ ULONG InfoLength;
+ PVOID pInfo;
+
+} HTTP_REQUEST_INFO, *PHTTP_REQUEST_INFO;
+
+#ifndef __SECSTATUS_DEFINED__
+typedef LONG SECURITY_STATUS;
+#define __SECSTATUS_DEFINED__
+#endif // __SECSTATUS_DEFINED__
+
+//
+// Authentication request info structure
+//
+
+#define HTTP_REQUEST_AUTH_FLAG_TOKEN_FOR_CACHED_CRED (0x00000001)
+
+typedef struct _HTTP_REQUEST_AUTH_INFO
+{
+ HTTP_AUTH_STATUS AuthStatus;
+ SECURITY_STATUS SecStatus;
+
+ ULONG Flags;
+
+ HTTP_REQUEST_AUTH_TYPE AuthType;
+
+ HANDLE AccessToken;
+ ULONG ContextAttributes;
+
+ //
+ // Optional serialized context.
+ //
+
+ ULONG PackedContextLength;
+ ULONG PackedContextType;
+ PVOID PackedContext;
+
+ //
+ // Optional mutual authentication data and its length in bytes.
+ //
+
+ ULONG MutualAuthDataLength;
+ PCHAR pMutualAuthData;
+
+ //
+ // For SSPI based schemes the package name is returned. Length does
+ // not include the terminating null and it is in bytes.
+ //
+
+ USHORT PackageNameLength;
+ PWSTR pPackageName;
+
+} HTTP_REQUEST_AUTH_INFO, *PHTTP_REQUEST_AUTH_INFO;
+
+#endif // _WIN32_WINNT >= 0x0600
+
+//
+// The structure of an HTTP request for downlevel OS
+//
+
+typedef struct _HTTP_REQUEST_V1
+{
+ //
+ // Request flags (see HTTP_REQUEST_FLAG_* definitions below).
+ //
+
+ ULONG Flags;
+
+ //
+ // An opaque request identifier. These values are used by the driver
+ // to correlate outgoing responses with incoming requests.
+ //
+
+ HTTP_CONNECTION_ID ConnectionId;
+ HTTP_REQUEST_ID RequestId;
+
+ //
+ // The context associated with the URL prefix.
+ //
+
+ HTTP_URL_CONTEXT UrlContext;
+
+ //
+ // The HTTP version number.
+ //
+
+ HTTP_VERSION Version;
+
+ //
+ // The request verb.
+ //
+
+ HTTP_VERB Verb;
+
+ //
+ // The length of the verb string if the Verb field is HttpVerbUnknown.
+ //
+
+ USHORT UnknownVerbLength; // in bytes not including the NUL
+
+ //
+ // The length of the raw (uncooked) URL
+ //
+
+ USHORT RawUrlLength; // in bytes not including the NUL
+
+ //
+ // Pointer to the verb string if the Verb field is HttpVerbUnknown.
+ //
+
+ PCSTR pUnknownVerb;
+
+ //
+ // Pointer to the raw (uncooked) URL
+ //
+
+ PCSTR pRawUrl;
+
+ //
+ // The canonicalized Unicode URL
+ //
+
+ HTTP_COOKED_URL CookedUrl;
+
+ //
+ // Local and remote transport addresses for the connection.
+ //
+
+ HTTP_TRANSPORT_ADDRESS Address;
+
+ //
+ // The request headers.
+ //
+
+ HTTP_REQUEST_HEADERS Headers;
+
+ //
+ // The total number of bytes received from network for this request.
+ //
+
+ ULONGLONG BytesReceived;
+
+ //
+ // pEntityChunks is an array of EntityChunkCount HTTP_DATA_CHUNKs. The
+ // entity body is copied only if HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY
+ // was passed to HttpReceiveHttpRequest().
+ //
+
+ USHORT EntityChunkCount;
+ PHTTP_DATA_CHUNK pEntityChunks;
+
+ //
+ // SSL connection information.
+ //
+
+ HTTP_RAW_CONNECTION_ID RawConnectionId;
+ PHTTP_SSL_INFO pSslInfo;
+
+} HTTP_REQUEST_V1, *PHTTP_REQUEST_V1;
+
+#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP
+
+// Vista
+
+//
+// Version 2.0 members are defined here
+// N.B. One must define V2 elements in two places :(
+// This is due to the fact that C++ doesn't allow anonymous
+// structure declarations and one must use structure
+// inheritance instead.
+//
+
+#ifdef __cplusplus
+
+typedef struct _HTTP_REQUEST_V2 : _HTTP_REQUEST_V1
+{
+ //
+ // Version 1.0 members are inherited
+ // Version 2.0 members are declared below
+ //
+
+ //
+ // Additional Request Informations.
+ //
+
+ USHORT RequestInfoCount;
+ PHTTP_REQUEST_INFO pRequestInfo;
+} HTTP_REQUEST_V2, *PHTTP_REQUEST_V2;
+
+#else // __cplusplus
+
+typedef struct _HTTP_REQUEST_V2
+{
+ struct _HTTP_REQUEST_V1; // Anonymous structure
+
+ //
+ // Version 2.0 members are declared below
+ //
+
+ //
+ // Additional Request Informations.
+ //
+
+ USHORT RequestInfoCount;
+ PHTTP_REQUEST_INFO pRequestInfo;
+} HTTP_REQUEST_V2, *PHTTP_REQUEST_V2;
+
+#endif // __cplusplus
+
+typedef HTTP_REQUEST_V2 HTTP_REQUEST;
+
+#else // _WIN32_WINNT >= 0x0600
+
+typedef HTTP_REQUEST_V1 HTTP_REQUEST;
+
+#endif // _WIN32_WINNT >= 0x0600
+
+typedef HTTP_REQUEST * PHTTP_REQUEST;
+
+
+//
+// Values for HTTP_REQUEST::Flags. Zero or more of these may be ORed together.
+//
+// HTTP_REQUEST_FLAG_MORE_ENTITY_BODY_EXISTS - there is more entity body
+// to be read for this request. Otherwise, there is no entity body or
+// all of the entity body was copied into pEntityChunks.
+// HTTP_REQUEST_FLAG_IP_ROUTED - This flag indicates that the request has been
+// routed based on host plus ip or ip binding.This is a hint for the application
+// to include the local ip while flushing kernel cache entries build for this
+// request if any.
+//
+
+#define HTTP_REQUEST_FLAG_MORE_ENTITY_BODY_EXISTS 0x00000001
+#define HTTP_REQUEST_FLAG_IP_ROUTED 0x00000002
+
+
+//
+// This structure describes an HTTP response.
+//
+
+typedef struct _HTTP_RESPONSE_V1
+{
+ //
+ // Response flags (see HTTP_RESPONSE_FLAG_* definitions below).
+ //
+
+ ULONG Flags;
+
+ //
+ // The raw HTTP protocol version number.
+ //
+
+ HTTP_VERSION Version;
+
+ //
+ // The HTTP status code (e.g., 200).
+ //
+
+ USHORT StatusCode;
+
+ //
+ // The HTTP reason (e.g., "OK"). This MUST not contain
+ // non-ASCII characters (i.e., all chars must be in range 0x20-0x7E).
+ //
+
+ USHORT ReasonLength; // in bytes not including the '\0'
+ PCSTR pReason;
+
+ //
+ // The response headers.
+ //
+
+ HTTP_RESPONSE_HEADERS Headers;
+
+ //
+ // pEntityChunks points to an array of EntityChunkCount HTTP_DATA_CHUNKs.
+ //
+
+ USHORT EntityChunkCount;
+ PHTTP_DATA_CHUNK pEntityChunks;
+
+} HTTP_RESPONSE_V1, *PHTTP_RESPONSE_V1;
+
+#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP
+
+//
+// Values for HTTP_RESPONSE::Flags.
+//
+// HTTP_RESPONSE_FLAG_MULTIPLE_ENCODINGS_AVAILABLE - Set this flag if encodings
+// other than identity form are available for this resource.This flag is ignored
+// if application has not asked for response to be cached. It's used as a hint
+// to the Http Server API for content negotiation used when serving from the
+// the kernel response cache.
+//
+
+#define HTTP_RESPONSE_FLAG_MULTIPLE_ENCODINGS_AVAILABLE 0x00000001
+
+
+// Vista
+
+typedef enum _HTTP_RESPONSE_INFO_TYPE
+{
+ HttpResponseInfoTypeMultipleKnownHeaders,
+ HttpResponseInfoTypeAuthenticationProperty,
+ HttpResponseInfoTypeQoSProperty
+
+#if _WIN32_WINNT >= _WIN32_WINNT_WIN7 || BUILD_IIS_FOR_XP
+ ,HttpResponseInfoTypeChannelBind
+#endif
+
+} HTTP_RESPONSE_INFO_TYPE, PHTTP_RESPONSE_INFO_TYPE;
+
+typedef struct _HTTP_RESPONSE_INFO
+{
+ HTTP_RESPONSE_INFO_TYPE Type;
+ ULONG Length;
+ PVOID pInfo;
+} HTTP_RESPONSE_INFO, *PHTTP_RESPONSE_INFO;
+
+#define HTTP_RESPONSE_INFO_FLAGS_PRESERVE_ORDER 0x00000001
+
+//
+// This structure allows the provision of providing multiple known headers.
+//
+
+typedef struct _HTTP_MULTIPLE_KNOWN_HEADERS
+{
+ //
+ // Known header id.
+ //
+
+ HTTP_HEADER_ID HeaderId;
+
+ ULONG Flags;
+
+ //
+ // Number of headers of the same category.
+ //
+
+ USHORT KnownHeaderCount;
+
+ //
+ // Array of known header structures.
+ //
+
+ PHTTP_KNOWN_HEADER KnownHeaders;
+
+} HTTP_MULTIPLE_KNOWN_HEADERS, *PHTTP_MULTIPLE_KNOWN_HEADERS;
+
+//
+// Version 2.0 members are defined here
+// N.B. One must define V2 elements in two places :(
+// This is due to the fact that C++ doesn't allow anonymous
+// structure declarations and one must use structure
+// inheritance instead.
+//
+
+#ifdef __cplusplus
+
+typedef struct _HTTP_RESPONSE_V2 : _HTTP_RESPONSE_V1
+{
+ //
+ // Version 1.0 members are inherited
+ // Version 2.0 members are declared below
+ //
+
+ USHORT ResponseInfoCount;
+ PHTTP_RESPONSE_INFO pResponseInfo;
+
+} HTTP_RESPONSE_V2, *PHTTP_RESPONSE_V2;
+
+#else // __cplusplus
+
+typedef struct _HTTP_RESPONSE_V2
+{
+ struct _HTTP_RESPONSE_V1;
+
+ //
+ // Version 2.0 members are declared below
+ //
+
+ USHORT ResponseInfoCount;
+ PHTTP_RESPONSE_INFO pResponseInfo;
+} HTTP_RESPONSE_V2, *PHTTP_RESPONSE_V2;
+
+#endif // __cplusplus
+
+typedef HTTP_RESPONSE_V2 HTTP_RESPONSE;
+
+#else // _WIN32_WINNT >= 0x0600
+
+typedef HTTP_RESPONSE_V1 HTTP_RESPONSE;
+
+#endif // _WIN32_WINNT >= 0x0600
+
+typedef HTTP_RESPONSE *PHTTP_RESPONSE;
+
+//
+// Api Version. This is used to ensure compatibility between applications and
+// httpapi.dll and http.sys.
+//
+// This must not be confused with the HTTP Protocol version.
+//
+
+typedef struct _HTTPAPI_VERSION
+{
+ USHORT HttpApiMajorVersion;
+ USHORT HttpApiMinorVersion;
+
+} HTTPAPI_VERSION, *PHTTPAPI_VERSION;
+
+
+#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP
+
+// Vista
+
+#define HTTPAPI_VERSION_2 { 2, 0 }
+
+#endif // _WIN32_WINNT >= 0x0600
+
+#define HTTPAPI_VERSION_1 { 1, 0 }
+
+#define HTTPAPI_EQUAL_VERSION(version, major, minor) \
+ ((version).HttpApiMajorVersion == (major) && \
+ (version).HttpApiMinorVersion == (minor))
+
+#define HTTPAPI_GREATER_VERSION(version, major, minor) \
+ ((version).HttpApiMajorVersion > (major) || \
+ ((version).HttpApiMajorVersion == (major) && \
+ (version).HttpApiMinorVersion > (minor)))
+
+#define HTTPAPI_LESS_VERSION(version, major, minor) \
+ ((version).HttpApiMajorVersion < (major) || \
+ ((version).HttpApiMajorVersion == (major) && \
+ (version).HttpApiMinorVersion < (minor)))
+
+#define HTTPAPI_VERSION_GREATER_OR_EQUAL( version, major, minor) \
+ (!HTTPAPI_LESS_VERSION(version, major, minor))
+
+
+//
+// Cache control.
+//
+
+//
+// This enum defines the available cache policies.
+//
+
+typedef enum _HTTP_CACHE_POLICY_TYPE
+{
+ HttpCachePolicyNocache,
+ HttpCachePolicyUserInvalidates,
+ HttpCachePolicyTimeToLive,
+
+ HttpCachePolicyMaximum
+
+} HTTP_CACHE_POLICY_TYPE, *PHTTP_CACHE_POLICY_TYPE;
+
+
+//
+// Only cache unauthorized GETs + HEADs.
+//
+
+typedef struct _HTTP_CACHE_POLICY
+{
+ HTTP_CACHE_POLICY_TYPE Policy;
+ ULONG SecondsToLive;
+
+} HTTP_CACHE_POLICY, *PHTTP_CACHE_POLICY;
+
+//
+// Enum that is used with HttpSetServiceConfiguration(),
+// HttpQueryServiceConfiguration(), and HttpDeleteServiceConfiguration() APIs.
+//
+
+typedef enum _HTTP_SERVICE_CONFIG_ID
+{
+ HttpServiceConfigIPListenList, // Set, Query & Delete.
+ HttpServiceConfigSSLCertInfo, // Set, Query & Delete.
+ HttpServiceConfigUrlAclInfo, // Set, Query & Delete.
+ HttpServiceConfigTimeout, // Set, Query & Delete.
+ HttpServiceConfigCache, // Set, Query & Delete.
+ HttpServiceConfigMax
+
+} HTTP_SERVICE_CONFIG_ID, *PHTTP_SERVICE_CONFIG_ID;
+
+//
+// Generic Query enum that can be used with HttpQueryServiceConfiguration()
+//
+
+typedef enum _HTTP_SERVICE_CONFIG_QUERY_TYPE
+{
+ HttpServiceConfigQueryExact,
+ HttpServiceConfigQueryNext,
+ HttpServiceConfigQueryMax
+
+} HTTP_SERVICE_CONFIG_QUERY_TYPE, *PHTTP_SERVICE_CONFIG_QUERY_TYPE;
+
+//
+// This data structure is used to define a key of the SSL certificate hash
+// store.
+//
+
+typedef struct _HTTP_SERVICE_CONFIG_SSL_KEY
+{
+ PSOCKADDR pIpPort;
+} HTTP_SERVICE_CONFIG_SSL_KEY, *PHTTP_SERVICE_CONFIG_SSL_KEY;
+
+//
+// This defines a record for the SSL config store.
+//
+
+typedef struct _HTTP_SERVICE_CONFIG_SSL_PARAM
+{
+ ULONG SslHashLength; // Length of the SSL hash (in bytes)
+ PVOID pSslHash; // Pointer to the SSL hash
+ GUID AppId; // A unique identifier that can be used to
+ // identify the app that has set this parameter
+
+ PWSTR pSslCertStoreName; // Store name to read the server certificate
+ // from; defaults to "MY". Certificate must be
+ // stored in the LOCAL_MACHINE context.
+
+ //
+ // The following settings are used only for client certificates
+ //
+
+ //
+ // DefaultCertCheckMode is a bit flag with the following semantics
+ // 0x1 - Client certificate will not be verified for revocation
+ // 0x2 - Only cached certificate revocation will be used.
+ // 0x4 - Enable use of the DefaultRevocationFreshnessTime setting
+ // 0x10000 - No usage check.
+
+ DWORD DefaultCertCheckMode;
+
+ //
+ // DefaultRevocationFreshnessTime (seconds) - How often to check for
+ // an updated Certificate revocation list (CRL). If this value is 0
+ // then the new CRL is updated only if the previous one expires
+ //
+
+ DWORD DefaultRevocationFreshnessTime;
+
+ //
+ // DefaultRevocationUrlRetrievalTimeout (milliseconds) - Timeout on
+ // attempt to retrieve certificate revocation list from the remote URL.
+ //
+
+ DWORD DefaultRevocationUrlRetrievalTimeout;
+
+ //
+ // pDefaultSslCtlIdentifier - Restrict the certificate issuers that you
+ // want to trust. Can be a subset of the certificate issuers that are
+ // trusted by the machine.
+ //
+
+ PWSTR pDefaultSslCtlIdentifier;
+
+ //
+ // Store name under LOCAL_MACHINE where Ctl identified by
+ // pDefaultSslCtlIdentifier is stored.
+ //
+
+ PWSTR pDefaultSslCtlStoreName;
+
+ //
+ // Default Flags - see HTTP_SERVICE_CONFIG_SSL_FLAG* below.
+ //
+
+ DWORD DefaultFlags;
+
+} HTTP_SERVICE_CONFIG_SSL_PARAM, *PHTTP_SERVICE_CONFIG_SSL_PARAM;
+
+#define HTTP_SERVICE_CONFIG_SSL_FLAG_USE_DS_MAPPER 0x00000001
+#define HTTP_SERVICE_CONFIG_SSL_FLAG_NEGOTIATE_CLIENT_CERT 0x00000002
+#if _WIN32_WINNT < 0x0600
+#define HTTP_SERVICE_CONFIG_SSL_FLAG_NO_RAW_FILTER 0x00000004
+#endif // _WIN32_WINNT < 0x0600
+
+//
+// This data structure is used by HttpSetServiceConfiguration() for the
+// config ID HttpServiceConfigSSLCertInfo. It's used to add a new record
+// to the SSL store.
+//
+
+typedef struct _HTTP_SERVICE_CONFIG_SSL_SET
+{
+ HTTP_SERVICE_CONFIG_SSL_KEY KeyDesc;
+ HTTP_SERVICE_CONFIG_SSL_PARAM ParamDesc;
+} HTTP_SERVICE_CONFIG_SSL_SET, *PHTTP_SERVICE_CONFIG_SSL_SET;
+
+//
+// This data structure is used by HttpQueryServiceConfiguration() for the
+// config ID HttpServiceConfigSSLCertInfo. It's used to query a particular
+// record from the SSL store.
+//
+// If QueryType is HttpServiceConfigQueryExact, then one particular record of
+// the type HTTP_SERVICE_CONFIG_SSL_SET is returned. If the QueryType is
+// HttpServiceConfigQueryNext, then the next instance of
+// HTTP_SERVICE_CONFIG_SSL_SET is returned. In such cases, the dwToken field
+// represents the cursor. For the first item, dwToken has to be 0.
+// For subsequent items, dwToken has to be incremented by 1,
+// until ERROR_NO_MORE_ITEMS is returned.
+//
+
+typedef struct _HTTP_SERVICE_CONFIG_SSL_QUERY
+{
+ HTTP_SERVICE_CONFIG_QUERY_TYPE QueryDesc;
+ HTTP_SERVICE_CONFIG_SSL_KEY KeyDesc;
+ DWORD dwToken;
+} HTTP_SERVICE_CONFIG_SSL_QUERY, *PHTTP_SERVICE_CONFIG_SSL_QUERY;
+
+//
+// Set/Delete IP Listen-Only List record
+//
+// Used as a parameter to both HttpSetServiceConfiguration() and
+// HttpDeleteServiceConfiguration() functions.
+//
+
+typedef struct _HTTP_SERVICE_CONFIG_IP_LISTEN_PARAM
+{
+ USHORT AddrLength;
+ PSOCKADDR pAddress;
+} HTTP_SERVICE_CONFIG_IP_LISTEN_PARAM, *PHTTP_SERVICE_CONFIG_IP_LISTEN_PARAM;
+
+//
+// Query IP Listen-Only List record.
+//
+// Parameter to HttpQueryServiceConfiguration() for the config ID
+// HttpServiceConfigIPListenList. On successful return, AddrList
+// contains an array of AddrCount elements. Caller must provide a
+// large enough buffer to hold all elements in one call.
+//
+// Caller may determine the type of each returned element by examining
+// AddrList[i].ss_family. If it's AF_INET, use ((PSOCKADDR_IN) &AddrList[i]);
+// otherwise, for AF_INET6, use ((PSOCKADDR_IN6) &AddrList[i])
+// to select the appropriate address type.
+//
+
+typedef struct _HTTP_SERVICE_CONFIG_IP_LISTEN_QUERY
+{
+ ULONG AddrCount;
+ SOCKADDR_STORAGE AddrList[ANYSIZE_ARRAY];
+} HTTP_SERVICE_CONFIG_IP_LISTEN_QUERY, *PHTTP_SERVICE_CONFIG_IP_LISTEN_QUERY;
+
+//
+// URL ACL
+//
+//
+typedef struct _HTTP_SERVICE_CONFIG_URLACL_KEY
+{
+ PWSTR pUrlPrefix;
+
+} HTTP_SERVICE_CONFIG_URLACL_KEY, *PHTTP_SERVICE_CONFIG_URLACL_KEY;
+
+//
+// This defines a record for the SSL config store.
+//
+
+typedef struct _HTTP_SERVICE_CONFIG_URLACL_PARAM
+{
+ PWSTR pStringSecurityDescriptor;
+} HTTP_SERVICE_CONFIG_URLACL_PARAM, *PHTTP_SERVICE_CONFIG_URLACL_PARAM;
+
+
+//
+// This data structure is used by HttpSetServiceConfiguration for the config ID
+// HttpServiceConfigUrlAclInfo. It is used to add a new record to the URL ACL
+// store.
+//
+
+typedef struct _HTTP_SERVICE_CONFIG_URLACL_SET
+{
+ HTTP_SERVICE_CONFIG_URLACL_KEY KeyDesc;
+ HTTP_SERVICE_CONFIG_URLACL_PARAM ParamDesc;
+} HTTP_SERVICE_CONFIG_URLACL_SET, *PHTTP_SERVICE_CONFIG_URLACL_SET;
+
+
+//
+// This data structure is used by HttpQueryServiceConfiguration() for the
+// config ID HttpServiceConfigUrlAclInfo. It's used to query a particular
+// record from the URL ACL store.
+//
+// If QueryType is HttpServiceConfigQueryExact, then one particular record of
+// the type HTTP_SERVICE_CONFIG_URLACL_SET is returned. If the QueryType is
+// HttpServiceConfigQueryNext, then the next instance of
+// HTTP_SERVICE_CONFIG_URLACL_SET is returned. In such cases, the dwToken field
+// represents the cursor. For the first item, dwToken has to be 0.
+// For subsequent items, dwToken has to be incremented by 1,
+// until ERROR_NO_MORE_ITEMS is returned.
+//
+
+typedef struct _HTTP_SERVICE_CONFIG_URLACL_QUERY
+{
+ HTTP_SERVICE_CONFIG_QUERY_TYPE QueryDesc;
+ HTTP_SERVICE_CONFIG_URLACL_KEY KeyDesc;
+ DWORD dwToken;
+} HTTP_SERVICE_CONFIG_URLACL_QUERY, *PHTTP_SERVICE_CONFIG_URLACL_QUERY;
+
+//
+// Cache Paramemers
+//
+
+//
+// For manipulating global cache parameters.
+// The parameters that can be changed or queued are per-uri cache size
+// and cached range chunk size.
+//
+
+typedef enum _HTTP_SERVICE_CONFIG_CACHE_KEY
+{
+ MaxCacheResponseSize = 0,
+ CacheRangeChunkSize
+} HTTP_SERVICE_CONFIG_CACHE_KEY, *PHTTP_SERVICE_CONFIG_CACHE_KEY;
+
+typedef ULONG HTTP_SERVICE_CONFIG_CACHE_PARAM,
+ *PHTTP_SERVICE_CONFIG_CACHE_PARAM;
+
+//
+// To set a cache parameter value use the set structure. To query use the key
+// directly. When you query a parameter value the output buffer must be exactly
+// the sizeof param.
+//
+
+typedef struct {
+ HTTP_SERVICE_CONFIG_CACHE_KEY KeyDesc;
+ HTTP_SERVICE_CONFIG_CACHE_PARAM ParamDesc;
+} HTTP_SERVICE_CONFIG_CACHE_SET, *PHTTP_SERVICE_CONFIG_CACHE_SET;
+
+
+//
+// Define our API linkage.
+//
+
+#if !defined(HTTPAPI_LINKAGE)
+#define HTTPAPI_LINKAGE DECLSPEC_IMPORT
+#endif // !HTTPAPI_LINKAGE
+
+//
+// Initialize/Terminate APIs.
+//
+
+
+// NOTE: MUST be called once before all other APIs
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpInitialize(
+ IN HTTPAPI_VERSION Version,
+ IN ULONG Flags,
+ __reserved IN OUT PVOID pReserved
+ );
+
+// NOTE: MUST be called after final API call returns.
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpTerminate(
+ IN ULONG Flags,
+ __reserved IN OUT PVOID pReserved
+ );
+
+//
+// HTTP Request Queue manipulation APIs.
+//
+// This API is maintained for backward competibility for the first
+// version of the HTTPAPI and should not be used. Instead the new
+// HttpCreateRequestQueue() API must be used.
+//
+// Use CloseHandle() to release the handles returned by
+// HttpCreateHttpHandle() API.
+//
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpCreateHttpHandle(
+ OUT PHANDLE pReqQueueHandle,
+ __reserved IN ULONG Reserved
+ );
+
+#if _WIN32_WINNT >= 0x0600
+
+//
+// Extended Request Queue manipulation APIs.
+//
+// Use HttpCloseRequestQueue() API to close the handles
+// created by the HttpCreateRequestQueue API.
+//
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpCreateRequestQueue(
+ IN HTTPAPI_VERSION Version,
+ IN PCWSTR pName OPTIONAL,
+ IN PSECURITY_ATTRIBUTES pSecurityAttributes OPTIONAL,
+ IN ULONG Flags OPTIONAL,
+ OUT PHANDLE pReqQueueHandle
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpCloseRequestQueue(
+ IN HANDLE ReqQueueHandle
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpSetRequestQueueProperty(
+ IN HANDLE Handle,
+ IN HTTP_SERVER_PROPERTY Property,
+ __in_bcount(PropertyInformationLength) IN PVOID pPropertyInformation,
+ IN ULONG PropertyInformationLength,
+ __reserved IN ULONG Reserved,
+ __reserved IN PVOID pReserved
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpQueryRequestQueueProperty(
+ IN HANDLE Handle,
+ IN HTTP_SERVER_PROPERTY Property,
+ __out_bcount_part(PropertyInformationLength, *pReturnLength)
+ OUT PVOID pPropertyInformation,
+ IN ULONG PropertyInformationLength,
+ __reserved IN ULONG Reserved,
+ __out_opt OUT PULONG pReturnLength OPTIONAL,
+ __reserved IN PVOID pReserved
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpShutdownRequestQueue(
+ IN HANDLE ReqQueueHandle
+ );
+
+#endif // _WIN32_WINNT >= 0x0600
+
+//
+// SSL APIs.
+//
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpReceiveClientCertificate(
+ IN HANDLE ReqQueueHandle,
+ IN HTTP_CONNECTION_ID ConnectionId,
+ IN ULONG Flags,
+ __out_bcount_part(SslClientCertInfoSize, *pBytesReceived)
+ OUT PHTTP_SSL_CLIENT_CERT_INFO pSslClientCertInfo,
+ IN ULONG SslClientCertInfoSize,
+ __out_opt OUT PULONG pBytesReceived OPTIONAL,
+ IN LPOVERLAPPED pOverlapped OPTIONAL
+ );
+
+#if _WIN32_WINNT >= 0x0600
+
+//
+// Server Session APIs.
+//
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpCreateServerSession(
+ IN HTTPAPI_VERSION Version,
+ OUT PHTTP_SERVER_SESSION_ID pServerSessionId,
+ __reserved IN ULONG Reserved
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpCloseServerSession(
+ IN HTTP_SERVER_SESSION_ID ServerSessionId
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpQueryServerSessionProperty(
+ IN HTTP_SERVER_SESSION_ID ServerSessionId,
+ IN HTTP_SERVER_PROPERTY Property,
+ __out_bcount_part(PropertyInformationLength, *pReturnLength)
+ OUT PVOID pPropertyInformation,
+ IN ULONG PropertyInformationLength,
+ __out_opt OUT PULONG pReturnLength OPTIONAL
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpSetServerSessionProperty(
+ IN HTTP_SERVER_SESSION_ID ServerSessionId,
+ IN HTTP_SERVER_PROPERTY Property,
+ __in_bcount(PropertyInformationLength) IN PVOID pPropertyInformation,
+ IN ULONG PropertyInformationLength
+ );
+
+#endif // _WIN32_WINNT >= 0x0600
+
+//
+// Url Configuration APIs. Can only be used for V1 request queues.
+//
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpAddUrl(
+ IN HANDLE ReqQueueHandle,
+ IN PCWSTR pFullyQualifiedUrl,
+ __reserved IN PVOID pReserved
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpRemoveUrl(
+ IN HANDLE ReqQueueHandle,
+ IN PCWSTR pFullyQualifiedUrl
+ );
+
+#if _WIN32_WINNT >= 0x0600
+
+//
+// Url Group APIs.
+//
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpCreateUrlGroup(
+ IN HTTP_SERVER_SESSION_ID ServerSessionId,
+ OUT PHTTP_URL_GROUP_ID pUrlGroupId,
+ __reserved IN ULONG Reserved
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpCloseUrlGroup(
+ IN HTTP_URL_GROUP_ID UrlGroupId
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpAddUrlToUrlGroup(
+ IN HTTP_URL_GROUP_ID UrlGroupId,
+ IN PCWSTR pFullyQualifiedUrl,
+ IN HTTP_URL_CONTEXT UrlContext OPTIONAL,
+ __reserved IN ULONG Reserved
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpRemoveUrlFromUrlGroup(
+ IN HTTP_URL_GROUP_ID UrlGroupId,
+ IN PCWSTR pFullyQualifiedUrl,
+ IN ULONG Flags
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpSetUrlGroupProperty(
+ IN HTTP_URL_GROUP_ID UrlGroupId,
+ IN HTTP_SERVER_PROPERTY Property,
+ __in_bcount(PropertyInformationLength) IN PVOID pPropertyInformation,
+ IN ULONG PropertyInformationLength
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpQueryUrlGroupProperty(
+ IN HTTP_URL_GROUP_ID UrlGroupId,
+ IN HTTP_SERVER_PROPERTY Property,
+ __out_bcount_part(PropertyInformationLength, *pReturnLength)
+ OUT PVOID pPropertyInformation,
+ IN ULONG PropertyInformationLength,
+ __out_opt OUT PULONG pReturnLength OPTIONAL
+ );
+
+#endif // _WIN32_WINNT >= 0x0600
+
+//
+// HTTP Server I/O APIs.
+//
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpReceiveHttpRequest(
+ IN HANDLE ReqQueueHandle,
+ IN HTTP_REQUEST_ID RequestId,
+ IN ULONG Flags,
+ __out_bcount_part(RequestBufferLength, *pBytesReceived)
+ OUT PHTTP_REQUEST pRequestBuffer,
+ IN ULONG RequestBufferLength,
+ __out_opt OUT PULONG pBytesReceived OPTIONAL,
+ IN LPOVERLAPPED pOverlapped OPTIONAL
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpReceiveRequestEntityBody(
+ IN HANDLE ReqQueueHandle,
+ IN HTTP_REQUEST_ID RequestId,
+ IN ULONG Flags,
+ __out_bcount_part(BufferLength, *pBytesReceived) OUT PVOID pBuffer,
+ IN ULONG BufferLength,
+ __out_opt OUT PULONG pBytesReceived OPTIONAL,
+ IN LPOVERLAPPED pOverlapped OPTIONAL
+ );
+
+#if _WIN32_WINNT >= 0x0600
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpSendHttpResponse(
+ IN HANDLE ReqQueueHandle,
+ IN HTTP_REQUEST_ID RequestId,
+ IN ULONG Flags,
+ IN PHTTP_RESPONSE pHttpResponse,
+ IN PHTTP_CACHE_POLICY pCachePolicy OPTIONAL,
+ OUT PULONG pBytesSent OPTIONAL,
+ OUT PVOID pReserved1 OPTIONAL, // must be NULL
+ IN ULONG Reserved2 OPTIONAL, // must be 0
+ IN LPOVERLAPPED pOverlapped OPTIONAL,
+ IN PHTTP_LOG_DATA pLogData OPTIONAL
+ );
+
+#else // _WIN32_WINNT >= 0x0600
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpSendHttpResponse(
+ IN HANDLE ReqQueueHandle,
+ IN HTTP_REQUEST_ID RequestId,
+ IN ULONG Flags,
+ IN PHTTP_RESPONSE pHttpResponse,
+ IN PVOID pReserved1 OPTIONAL, // must be NULL
+ OUT PULONG pBytesSent OPTIONAL,
+ OUT PVOID pReserved2 OPTIONAL, // must be NULL
+ IN ULONG Reserved3 OPTIONAL, // must be 0
+ IN LPOVERLAPPED pOverlapped OPTIONAL,
+ IN PVOID pReserved4 OPTIONAL // must be NULL
+ );
+
+#endif // _WIN32_WINNT >= 0x0600
+
+#if _WIN32_WINNT >= 0x0600
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpSendResponseEntityBody(
+ IN HANDLE ReqQueueHandle,
+ IN HTTP_REQUEST_ID RequestId,
+ IN ULONG Flags,
+ IN USHORT EntityChunkCount OPTIONAL,
+ __in_ecount_opt(EntityChunkCount)
+ IN PHTTP_DATA_CHUNK pEntityChunks OPTIONAL,
+ OUT PULONG pBytesSent OPTIONAL,
+ OUT PVOID pReserved1 OPTIONAL, // must be NULL
+ IN ULONG Reserved2 OPTIONAL, // must be 0
+ IN LPOVERLAPPED pOverlapped OPTIONAL,
+ IN PHTTP_LOG_DATA pLogData OPTIONAL
+ );
+
+#else // _WIN32_WINNT >= 0x0600
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpSendResponseEntityBody(
+ IN HANDLE ReqQueueHandle,
+ IN HTTP_REQUEST_ID RequestId,
+ IN ULONG Flags,
+ IN USHORT EntityChunkCount OPTIONAL,
+ __in_ecount_opt(EntityChunkCount)
+ IN PHTTP_DATA_CHUNK pEntityChunks OPTIONAL,
+ OUT PULONG pBytesSent OPTIONAL,
+ OUT PVOID pReserved1 OPTIONAL, // must be NULL
+ IN ULONG Reserved2 OPTIONAL, // must be 0
+ IN LPOVERLAPPED pOverlapped OPTIONAL,
+ IN PVOID pReserved3 OPTIONAL // must be NULL
+ );
+
+#endif // _WIN32_WINNT >= 0x0600
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpWaitForDisconnect(
+ IN HANDLE ReqQueueHandle,
+ IN HTTP_CONNECTION_ID ConnectionId,
+ IN LPOVERLAPPED pOverlapped OPTIONAL
+ );
+
+#if _WIN32_WINNT >= 0x0600
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpWaitForDisconnectEx(
+ IN HANDLE ReqQueueHandle,
+ IN HTTP_CONNECTION_ID ConnectionId,
+ __reserved IN ULONG Reserved OPTIONAL,
+ IN LPOVERLAPPED pOverlapped OPTIONAL
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpCancelHttpRequest(
+ IN HANDLE ReqQueueHandle,
+ IN HTTP_REQUEST_ID RequestId,
+ IN LPOVERLAPPED pOverlapped OPTIONAL
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpWaitForDemandStart(
+ IN HANDLE ReqQueueHandle,
+ IN LPOVERLAPPED pOverlapped OPTIONAL
+ );
+
+
+#endif // _WIN32_WINNT >= 0x0600
+
+//
+// Cache manipulation APIs.
+//
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpFlushResponseCache(
+ IN HANDLE ReqQueueHandle,
+ IN PCWSTR pUrlPrefix,
+ IN ULONG Flags,
+ IN LPOVERLAPPED pOverlapped OPTIONAL
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpAddFragmentToCache(
+ IN HANDLE ReqQueueHandle,
+ IN PCWSTR pUrlPrefix,
+ IN PHTTP_DATA_CHUNK pDataChunk,
+ IN PHTTP_CACHE_POLICY pCachePolicy,
+ IN LPOVERLAPPED pOverlapped OPTIONAL
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpReadFragmentFromCache(
+ IN HANDLE ReqQueueHandle,
+ IN PCWSTR pUrlPrefix,
+ IN PHTTP_BYTE_RANGE pByteRange OPTIONAL,
+ __out_bcount_part(BufferLength, *pBytesRead) OUT PVOID pBuffer,
+ IN ULONG BufferLength,
+ OUT PULONG pBytesRead OPTIONAL,
+ IN LPOVERLAPPED pOverlapped OPTIONAL
+ );
+
+//
+// Server configuration APIs
+//
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpSetServiceConfiguration(
+ __reserved IN HANDLE ServiceHandle,
+ IN HTTP_SERVICE_CONFIG_ID ConfigId,
+ __in_bcount(ConfigInformationLength) IN PVOID pConfigInformation,
+ IN ULONG ConfigInformationLength,
+ __reserved IN LPOVERLAPPED pOverlapped
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpDeleteServiceConfiguration(
+ __reserved IN HANDLE ServiceHandle,
+ IN HTTP_SERVICE_CONFIG_ID ConfigId,
+ __in_bcount(ConfigInformationLength) IN PVOID pConfigInformation,
+ IN ULONG ConfigInformationLength,
+ __reserved IN LPOVERLAPPED pOverlapped
+ );
+
+HTTPAPI_LINKAGE
+ULONG
+WINAPI
+HttpQueryServiceConfiguration(
+ __reserved IN HANDLE ServiceHandle,
+ IN HTTP_SERVICE_CONFIG_ID ConfigId,
+ __in_bcount_opt(InputConfigInformationLength)
+ IN PVOID pInputConfigInformation OPTIONAL,
+ IN ULONG InputConfigInformationLength OPTIONAL,
+ __out_bcount_part_opt(OutputConfigInformationLength, *pReturnLength)
+ OUT PVOID pOutputConfigInformation OPTIONAL,
+ IN ULONG OutputConfigInformationLength OPTIONAL,
+ __out_opt OUT PULONG pReturnLength OPTIONAL,
+ __reserved IN LPOVERLAPPED pOverlapped
+ );
+
+
+#if BUILD_IIS_FOR_XP
+
+// part of the httpp.h necessary to build for XP
+
+//
+// Counter Group.
+//
+
+//
+// Counter property description.
+//
+
+typedef struct _HTTP_PROP_DESC
+{
+ ULONG Size;
+ ULONG Offset;
+ BOOLEAN WPZeros;
+
+} HTTP_PROP_DESC, *PHTTP_PROP_DESC;
+
+
+//
+// This enum defines the available counter groups.
+//
+
+typedef enum _HTTP_COUNTER_GROUP
+{
+ HttpCounterGroupSite,
+ HttpCounterGroupGlobal,
+
+ HttpCounterGroupMaximum
+
+} HTTP_COUNTER_GROUP, *PHTTP_COUNTER_GROUP;
+
+//
+// Structures for IOCTL_HTTP_GET_COUNTERS.
+//
+
+typedef struct _HTTP_COUNTER_INFO
+{
+ HTTP_SERVER_SESSION_ID ServerSessionId;
+ HTTP_COUNTER_GROUP CounterGroup;
+
+} HTTP_COUNTER_INFO, *PHTTP_COUNTER_INFO;
+
+//
+// This enum defines the type of global couters.
+//
+
+typedef enum _HTTP_GLOBAL_COUNTER_ID
+{
+ HttpGlobalCounterCurrentUrisCached,
+ HttpGlobalCounterTotalUrisCached,
+ HttpGlobalCounterUriCacheHits,
+ HttpGlobalCounterUriCacheMisses,
+ HttpGlobalCounterUriCacheFlushes,
+ HttpGlobalCounterTotalFlushedUris,
+
+ HttpGlobalCounterMaximum
+
+} HTTP_GLOBAL_COUNTER_ID, *PHTTP_GLOBAL_COUNTER_ID;
+
+
+//
+// Global couters.
+//
+
+typedef struct _HTTP_GLOBAL_COUNTERS
+{
+ ULONG CurrentUrisCached;
+ ULONG TotalUrisCached;
+ ULONG UriCacheHits;
+ ULONG UriCacheMisses;
+ ULONG UriCacheFlushes;
+ ULONG TotalFlushedUris;
+
+} HTTP_GLOBAL_COUNTERS, *PHTTP_GLOBAL_COUNTERS;
+
+
+//
+// This enum defines the type of site counters.
+// NB: HTTP_SITE_COUNTER_ID and HTTP_SITE_COUNTERS
+// must be in the same order
+//
+
+typedef enum _HTTP_SITE_COUNTER_ID
+{
+ HttpSiteCounterBytesSent,
+ HttpSiteCounterBytesReceived,
+ HttpSiteCounterBytesTransfered,
+ HttpSiteCounterCurrentConns,
+ HttpSiteCounterMaxConnections,
+ HttpSiteCounterConnAttempts,
+ HttpSiteCounterGetReqs,
+ HttpSiteCounterHeadReqs,
+ HttpSiteCounterAllReqs,
+ HttpSiteCounterMeasuredIoBandwidthUsage,
+ HttpSiteCounterCurrentBlockedBandwidthBytes,
+ HttpSiteCounterTotalBlockedBandwidthBytes,
+
+ HttpSiteCounterMaximum
+
+} HTTP_SITE_COUNTER_ID, *PHTTP_SITE_COUNTER_ID;
+
+
+//
+// Site counters.
+//
+
+typedef struct _HTTP_SITE_COUNTERS
+{
+ ULONG SiteId;
+ ULONGLONG BytesSent;
+ ULONGLONG BytesReceived;
+ ULONGLONG BytesTransfered;
+ ULONG CurrentConns;
+ ULONG MaxConnections;
+ ULONG ConnAttempts;
+ ULONG GetReqs;
+ ULONG HeadReqs;
+ ULONG AllReqs;
+ ULONG MeasuredIoBandwidthUsage;
+ ULONG CurrentBlockedBandwidthBytes;
+ ULONG TotalBlockedBandwidthBytes;
+
+} HTTP_SITE_COUNTERS, *PHTTP_SITE_COUNTERS;
+
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+#endif // _WIN32_WINNT >= 0x0501
+
+#endif // __HTTP_H__
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/httpserv_xp.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/httpserv_xp.h
new file mode 100644
index 0000000000..6e9437d7ed
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/httpserv_xp.h
@@ -0,0 +1,3404 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef _HTTPSERV_H_
+#define _HTTPSERV_H_
+
+#if (!defined(_WIN64) && !defined(WIN32))
+#error httpserv.h is only supported on WIN32 or WIN64 platforms
+#endif
+
+#include
+
+#if _WIN32_WINNT >= 0x0600
+#include "http.h"
+#else
+#include "http_xp.h"
+#endif
+
+//
+// Request deterministic notifications
+//
+
+// request is beginning
+#define RQ_BEGIN_REQUEST 0x00000001
+// request is being authenticated
+#define RQ_AUTHENTICATE_REQUEST 0x00000002
+// request is being authorized
+#define RQ_AUTHORIZE_REQUEST 0x00000004
+// satisfy request from cache
+#define RQ_RESOLVE_REQUEST_CACHE 0x00000008
+// map handler for request
+#define RQ_MAP_REQUEST_HANDLER 0x00000010
+// acquire request state
+#define RQ_ACQUIRE_REQUEST_STATE 0x00000020
+// pre-execute handler
+#define RQ_PRE_EXECUTE_REQUEST_HANDLER 0x00000040
+// execute handler
+#define RQ_EXECUTE_REQUEST_HANDLER 0x00000080
+// release request state
+#define RQ_RELEASE_REQUEST_STATE 0x00000100
+// update cache
+#define RQ_UPDATE_REQUEST_CACHE 0x00000200
+// log request
+#define RQ_LOG_REQUEST 0x00000400
+// end request
+#define RQ_END_REQUEST 0x00000800
+
+//
+// Request non-deterministic notifications
+//
+
+// custom notification
+#define RQ_CUSTOM_NOTIFICATION 0x10000000
+// send response
+#define RQ_SEND_RESPONSE 0x20000000
+// read entity
+#define RQ_READ_ENTITY 0x40000000
+// map a url to a physical path
+#define RQ_MAP_PATH 0x80000000
+
+//
+// Global notifications
+//
+
+// stop accepting new requests
+#define GL_STOP_LISTENING 0x00000002
+// cache cleanup before termination
+#define GL_CACHE_CLEANUP 0x00000004
+// cache operation
+#define GL_CACHE_OPERATION 0x00000010
+// health check
+#define GL_HEALTH_CHECK 0x00000020
+// configuration changed
+#define GL_CONFIGURATION_CHANGE 0x00000040
+// file changed
+#define GL_FILE_CHANGE 0x00000080
+// before request pipeline has started
+#define GL_PRE_BEGIN_REQUEST 0x00000100
+// application start
+#define GL_APPLICATION_START 0x00000200
+// resolve modules for an application
+#define GL_APPLICATION_RESOLVE_MODULES 0x00000400
+// application end
+#define GL_APPLICATION_STOP 0x00000800
+// RSCA query
+#define GL_RSCA_QUERY 0x00001000
+// trace event was raised
+#define GL_TRACE_EVENT 0x00002000
+// custom notification
+#define GL_CUSTOM_NOTIFICATION 0x00004000
+// thread cleanup notification
+#define GL_THREAD_CLEANUP 0x00008000
+// application preload notification
+#define GL_APPLICATION_PRELOAD 0x00010000
+
+//
+// Request notification return status
+//
+
+typedef enum REQUEST_NOTIFICATION_STATUS
+{
+ RQ_NOTIFICATION_CONTINUE, // continue processing
+ // for notification
+ RQ_NOTIFICATION_PENDING, // suspend processing
+ // for notification
+ RQ_NOTIFICATION_FINISH_REQUEST // finish request
+ // processing
+};
+
+//
+// Out of band return codes
+//
+
+typedef enum GLOBAL_NOTIFICATION_STATUS
+{
+ GL_NOTIFICATION_CONTINUE, // continue processing
+ // for notification
+ GL_NOTIFICATION_HANDLED // finish processing for
+ // notification
+};
+
+//
+// Priority class aliases
+//
+
+#define PRIORITY_ALIAS_FIRST L"FIRST"
+#define PRIORITY_ALIAS_HIGH L"HIGH"
+#define PRIORITY_ALIAS_MEDIUM L"MEDIUM"
+#define PRIORITY_ALIAS_LOW L"LOW"
+#define PRIORITY_ALIAS_LAST L"LAST"
+
+//
+// Cache operations
+//
+
+typedef enum CACHE_OPERATION
+{
+ CACHE_OPERATION_RETRIEVE,
+ CACHE_OPERATION_ADD,
+ CACHE_OPERATION_DELETE,
+ CACHE_OPERATION_FLUSH_PREFIX,
+ CACHE_OPERATION_ENUM
+};
+
+//
+// Module identifier
+//
+
+typedef VOID* HTTP_MODULE_ID;
+
+//
+// Flags for IHttpContext->CloneContext()
+//
+
+#define CLONE_FLAG_BASICS 0x01
+#define CLONE_FLAG_HEADERS 0x02
+#define CLONE_FLAG_ENTITY 0x04
+#define CLONE_FLAG_NO_PRECONDITION 0x08
+#define CLONE_FLAG_NO_DAV 0x10
+
+//
+// Flags for IHttpContext->ExecuteRequest()
+//
+
+#define EXECUTE_FLAG_NO_HEADERS 0x01
+#define EXECUTE_FLAG_IGNORE_CURRENT_INTERCEPTOR 0x02
+#define EXECUTE_FLAG_IGNORE_APPPOOL 0x04
+#define EXECUTE_FLAG_DISABLE_CUSTOM_ERROR 0x08
+#define EXECUTE_FLAG_SAME_URL 0x10
+// do not flush the child response but copy it back to the parent
+#define EXECUTE_FLAG_BUFFER_RESPONSE 0x20
+// child response is still eligible for http.sys caching
+#define EXECUTE_FLAG_HTTP_CACHE_ELIGIBLE 0x40
+
+
+//
+// forward declarations
+//
+struct HTTP_TRACE_CONFIGURATION;
+struct HTTP_TRACE_EVENT;
+
+class IWpfSettings;
+class IHttpTraceContext;
+
+//
+// Module-specific context descriptor
+//
+class __declspec(uuid("f1927f76-790e-4ccb-a72e-396bdfdae05d"))
+IHttpStoredContext
+{
+ public:
+ virtual
+ VOID
+ CleanupStoredContext(
+ VOID
+ ) = 0;
+};
+
+//
+// Context container
+//
+class __declspec(uuid("d7fad7c9-aa27-4ab9-bd60-e55ccba3f5dc"))
+IHttpModuleContextContainer
+{
+ public:
+ virtual
+ IHttpStoredContext *
+ GetModuleContext(
+ IN HTTP_MODULE_ID moduleId
+ ) = 0;
+
+ virtual
+ HRESULT
+ SetModuleContext(
+ IN IHttpStoredContext * ppStoredContext,
+ IN HTTP_MODULE_ID moduleId
+ ) = 0;
+};
+
+//
+// Dispensed context container
+//
+class __declspec(uuid("2ae49359-95dd-4e48-ae20-c0cb9d0bc03a"))
+IDispensedHttpModuleContextContainer : public IHttpModuleContextContainer
+{
+public:
+ virtual
+ VOID
+ ReleaseContainer(
+ VOID
+ ) = 0;
+};
+
+//
+// Performance counter descriptor
+//
+class __declspec(uuid("bdfc4c4a-12a4-4744-87d8-765eb320c59f"))
+IHttpPerfCounterInfo
+{
+ public:
+ virtual
+ VOID
+ IncrementCounter(
+ DWORD dwCounterIndex,
+ DWORD dwValue = 1
+ ) = 0;
+
+ virtual
+ VOID
+ DecrementCounter(
+ DWORD dwCounterIndex,
+ DWORD dwValue = 1
+ ) = 0;
+};
+
+//
+// Application descriptor
+//
+class __declspec(uuid("3f75d9e6-1075-422c-ad89-93a85f2d7bdc"))
+IHttpApplication
+{
+ public:
+ virtual
+ PCWSTR
+ GetApplicationPhysicalPath(
+ VOID
+ ) const = 0;
+
+ virtual
+ PCWSTR
+ GetApplicationId(
+ VOID
+ ) const = 0;
+
+ virtual
+ PCWSTR
+ GetAppConfigPath(
+ VOID
+ ) const = 0;
+
+ virtual
+ IHttpModuleContextContainer *
+ GetModuleContextContainer(
+ VOID
+ ) = 0;
+};
+
+//
+// URI cache entry descriptor
+//
+class __declspec(uuid("7e0e6167-0094-49a1-8287-ecf6dc6e73a6"))
+IHttpUrlInfo
+{
+ public:
+ virtual
+ IHttpModuleContextContainer *
+ GetModuleContextContainer(
+ VOID
+ ) = 0;
+
+ virtual
+ BOOL
+ IsFrequentlyHit(
+ VOID
+ ) const = 0;
+};
+
+//
+// Script map descriptor
+//
+class __declspec(uuid("d7fe3d77-68bc-4d4a-851f-eec9fb68017c"))
+IScriptMapInfo
+{
+ public:
+ virtual
+ PCWSTR
+ GetPath(
+ VOID
+ ) const = 0;
+
+ virtual
+ PCSTR
+ GetAllowedVerbs(
+ VOID
+ ) const = 0;
+
+ virtual
+ PCWSTR
+ GetModules(
+ OUT DWORD * pcchModules = NULL
+ ) const = 0;
+
+ virtual
+ PCWSTR
+ GetScriptProcessor(
+ OUT DWORD * pcchScriptProcessor = NULL
+ ) const = 0;
+
+ virtual
+ PCWSTR
+ GetManagedType(
+ OUT DWORD * pcchManagedType = NULL
+ ) const = 0;
+
+ virtual
+ BOOL
+ GetAllowPathInfoForScriptMappings(
+ VOID
+ ) const = 0;
+
+ virtual
+ DWORD
+ GetRequiredAccess(
+ VOID
+ ) const = 0;
+
+ virtual
+ DWORD
+ GetResourceType(
+ VOID
+ ) const = 0;
+
+ virtual
+ BOOL
+ GetIsStarScriptMap(
+ VOID
+ ) const = 0;
+
+ virtual
+ DWORD
+ GetResponseBufferLimit(
+ VOID
+ ) const = 0;
+
+ virtual
+ PCWSTR
+ GetName(
+ VOID
+ ) const = 0;
+};
+
+class __declspec(uuid("fd86e6de-fb0e-47dd-820a-e0da12be46e9"))
+IHttpTokenEntry;
+
+//
+// Metadata descriptor
+//
+class __declspec(uuid("48b10633-825d-495e-93b0-225380053e8e"))
+IMetadataInfo
+{
+ public:
+ virtual
+ PCWSTR
+ GetMetaPath(
+ VOID
+ ) const = 0;
+
+ virtual
+ PCWSTR
+ GetVrPath(
+ VOID
+ ) const = 0;
+
+ virtual
+ IHttpTokenEntry *
+ GetVrToken(
+ VOID
+ ) = 0;
+
+ virtual
+ IHttpModuleContextContainer *
+ GetModuleContextContainer(
+ VOID
+ ) = 0;
+};
+
+//
+// Provides an interface to an HTTP request object. The methods on this
+// class can be used to inspect and modify request data.
+//
+class __declspec(uuid("e8698f7e-576e-4cac-a309-67435355faef"))
+IHttpRequest
+{
+ public:
+ virtual
+ HTTP_REQUEST *
+ GetRawHttpRequest(
+ VOID
+ ) = 0;
+
+ virtual
+ const HTTP_REQUEST *
+ GetRawHttpRequest(
+ VOID
+ ) const = 0;
+
+ virtual
+ PCSTR
+ GetHeader(
+ IN PCSTR pszHeaderName,
+ OUT USHORT * pcchHeaderValue = NULL
+ ) const = 0;
+
+ virtual
+ PCSTR
+ GetHeader(
+ IN HTTP_HEADER_ID ulHeaderIndex,
+ OUT USHORT * pcchHeaderValue = NULL
+ ) const = 0;
+
+ virtual
+ HRESULT
+ SetHeader(
+ IN PCSTR pszHeaderName,
+ IN PCSTR pszHeaderValue,
+ IN USHORT cchHeaderValue,
+ IN BOOL fReplace
+ ) = 0;
+
+ virtual
+ HRESULT
+ SetHeader(
+ IN HTTP_HEADER_ID ulHeaderIndex,
+ IN PCSTR pszHeaderValue,
+ IN USHORT cchHeaderValue,
+ IN BOOL fReplace
+ ) = 0;
+
+ virtual
+ HRESULT
+ DeleteHeader(
+ IN PCSTR pszHeaderName
+ ) = 0;
+
+ virtual
+ HRESULT
+ DeleteHeader(
+ IN HTTP_HEADER_ID ulHeaderIndex
+ ) = 0;
+
+ virtual
+ PCSTR
+ GetHttpMethod(
+ VOID
+ ) const = 0;
+
+ virtual
+ HRESULT
+ SetHttpMethod(
+ IN PCSTR pszHttpMethod
+ ) = 0;
+
+ virtual
+ HRESULT
+ SetUrl(
+ IN PCWSTR pszUrl,
+ IN DWORD cchUrl,
+ IN BOOL fResetQueryString
+ ) = 0;
+
+ virtual
+ HRESULT
+ SetUrl(
+ IN PCSTR pszUrl,
+ IN DWORD cchUrl,
+ IN BOOL fResetQueryString
+ ) = 0;
+
+ virtual
+ BOOL
+ GetUrlChanged(
+ VOID
+ ) const = 0;
+
+ virtual
+ PCWSTR
+ GetForwardedUrl(
+ VOID
+ ) const = 0;
+
+ virtual
+ PSOCKADDR
+ GetLocalAddress(
+ VOID
+ ) const = 0;
+
+ virtual
+ PSOCKADDR
+ GetRemoteAddress(
+ VOID
+ ) const = 0;
+
+ virtual
+ HRESULT
+ ReadEntityBody(
+ OUT VOID * pvBuffer,
+ IN DWORD cbBuffer,
+ IN BOOL fAsync,
+ OUT DWORD * pcbBytesReceived,
+ OUT BOOL * pfCompletionPending = NULL
+ ) = 0;
+
+ virtual
+ HRESULT
+ InsertEntityBody(
+ IN VOID * pvBuffer,
+ IN DWORD cbBuffer
+ ) = 0;
+
+ virtual
+ DWORD
+ GetRemainingEntityBytes(
+ VOID
+ ) = 0;
+
+ virtual
+ VOID
+ GetHttpVersion(
+ OUT USHORT * pMajorVersion,
+ OUT USHORT * pMinorVersion
+ ) const = 0;
+
+ virtual
+ HRESULT
+ GetClientCertificate(
+ OUT HTTP_SSL_CLIENT_CERT_INFO ** ppClientCertInfo,
+ OUT BOOL * pfClientCertNegotiated
+ ) = 0;
+
+ virtual
+ HRESULT
+ NegotiateClientCertificate(
+ IN BOOL fAsync,
+ OUT BOOL * pfCompletionPending = NULL
+ ) = 0;
+
+ virtual
+ DWORD
+ GetSiteId(
+ VOID
+ ) const = 0;
+
+ virtual
+ HRESULT
+ GetHeaderChanges(
+ IN DWORD dwOldChangeNumber,
+ OUT DWORD * pdwNewChangeNumber,
+ IN OUT PCSTR knownHeaderSnapshot[HttpHeaderRequestMaximum],
+ IN OUT DWORD * pdwUnknownHeaderSnapshot,
+ IN OUT PCSTR **ppUnknownHeaderNameSnapshot,
+ IN OUT PCSTR **ppUnknownHeaderValueSnapshot,
+ __out_ecount(HttpHeaderRequestMaximum+1)
+ DWORD diffedKnownHeaderIndices[HttpHeaderRequestMaximum+1],
+ OUT DWORD * pdwDiffedUnknownHeaders,
+ OUT DWORD **ppDiffedUnknownHeaderIndices
+ ) = 0;
+};
+
+class __declspec(uuid("d9244ae1-51f8-4aa1-a66d-19277c33e610"))
+IHttpRequest2 : public IHttpRequest
+{
+ public:
+ virtual
+ HRESULT
+ GetChannelBindingToken(
+ __deref_out_bcount_part(*pTokenSize, *pTokenSize)
+ PBYTE * ppToken,
+ DWORD * pTokenSize
+ ) = 0;
+};
+
+class __declspec(uuid("cb1c40ca-70f2-41a0-add2-881f5ef57388"))
+IHttpCachePolicy
+{
+ public:
+ virtual
+ HTTP_CACHE_POLICY *
+ GetKernelCachePolicy(
+ VOID
+ ) = 0;
+
+ virtual
+ VOID
+ SetKernelCacheInvalidatorSet(
+ VOID
+ ) = 0;
+
+ virtual
+ HTTP_CACHE_POLICY *
+ GetUserCachePolicy(
+ VOID
+ ) = 0;
+
+ virtual
+ HRESULT
+ AppendVaryByHeader(
+ PCSTR pszHeader
+ ) = 0;
+
+ virtual
+ PCSTR
+ GetVaryByHeaders(
+ VOID
+ ) const = 0;
+
+ virtual
+ HRESULT
+ AppendVaryByQueryString(
+ PCSTR pszParam
+ ) = 0;
+
+ virtual
+ PCSTR
+ GetVaryByQueryStrings(
+ VOID
+ ) const = 0;
+
+ virtual
+ HRESULT
+ SetVaryByValue(
+ PCSTR pszValue
+ ) = 0;
+
+ virtual
+ PCSTR
+ GetVaryByValue(
+ VOID
+ ) const = 0;
+
+ virtual
+ BOOL
+ IsUserCacheEnabled(
+ VOID
+ ) const = 0;
+
+ virtual
+ VOID
+ DisableUserCache(
+ VOID
+ ) = 0;
+
+ virtual
+ BOOL
+ IsCached(
+ VOID
+ ) const = 0;
+
+ virtual
+ VOID
+ SetIsCached(
+ VOID
+ ) = 0;
+
+ virtual
+ BOOL
+ GetKernelCacheInvalidatorSet(
+ VOID
+ ) const = 0;
+};
+
+class __declspec(uuid("9f4ba807-050e-4495-ae55-8870f7e9194a"))
+IHttpCachePolicy2 : public IHttpCachePolicy
+{
+ public:
+ virtual
+ BOOL
+ IsForceUpdateSet(
+ VOID
+ ) const = 0;
+
+ virtual
+ VOID
+ SetForceUpdate(
+ VOID
+ ) = 0;
+};
+
+//
+// Response descriptor
+//
+class __declspec(uuid("7e1c6b38-628f-4e6c-95dc-41237eb7f95e"))
+IHttpResponse
+{
+ public:
+ virtual
+ HTTP_RESPONSE *
+ GetRawHttpResponse(
+ VOID
+ ) = 0;
+
+ virtual
+ const HTTP_RESPONSE *
+ GetRawHttpResponse(
+ VOID
+ ) const = 0;
+
+ virtual
+ IHttpCachePolicy *
+ GetCachePolicy(
+ VOID
+ ) = 0;
+
+ virtual
+ HRESULT
+ SetStatus(
+ IN USHORT statusCode,
+ IN PCSTR pszReason,
+ IN USHORT uSubStatus = 0,
+ IN HRESULT hrErrorToReport = S_OK,
+ IN IAppHostConfigException *pException = NULL,
+ IN BOOL fTrySkipCustomErrors = FALSE
+ ) = 0;
+
+ virtual
+ HRESULT
+ SetHeader(
+ IN PCSTR pszHeaderName,
+ IN PCSTR pszHeaderValue,
+ IN USHORT cchHeaderValue,
+ IN BOOL fReplace
+ ) = 0;
+
+ virtual
+ HRESULT
+ SetHeader(
+ IN HTTP_HEADER_ID ulHeaderIndex,
+ IN PCSTR pszHeaderValue,
+ IN USHORT cchHeaderValue,
+ IN BOOL fReplace
+ ) = 0;
+
+ virtual
+ HRESULT
+ DeleteHeader(
+ IN PCSTR pszHeaderName
+ ) = 0;
+
+ virtual
+ HRESULT
+ DeleteHeader(
+ IN HTTP_HEADER_ID ulHeaderIndex
+ ) = 0;
+
+ virtual
+ PCSTR
+ GetHeader(
+ IN PCSTR pszHeaderName,
+ OUT USHORT * pcchHeaderValue = NULL
+ ) const = 0;
+
+ virtual
+ PCSTR
+ GetHeader(
+ IN HTTP_HEADER_ID ulHeaderIndex,
+ OUT USHORT * pcchHeaderValue = NULL
+ ) const = 0;
+
+ virtual
+ VOID
+ Clear(
+ VOID
+ ) = 0;
+
+ virtual
+ VOID
+ ClearHeaders(
+ VOID
+ ) = 0;
+
+ virtual
+ VOID
+ SetNeedDisconnect(
+ VOID
+ ) = 0;
+
+ virtual
+ VOID
+ ResetConnection(
+ VOID
+ ) = 0;
+
+ virtual
+ VOID
+ DisableKernelCache(
+ ULONG reason = 9
+ ) = 0;
+
+ virtual
+ BOOL
+ GetKernelCacheEnabled(
+ VOID
+ ) const = 0;
+
+ virtual
+ VOID
+ SuppressHeaders(
+ VOID
+ ) = 0;
+
+ virtual
+ BOOL
+ GetHeadersSuppressed(
+ VOID
+ ) const = 0;
+
+ virtual
+ HRESULT
+ Flush(
+ IN BOOL fAsync,
+ IN BOOL fMoreData,
+ OUT DWORD * pcbSent,
+ OUT BOOL * pfCompletionExpected = NULL
+ ) = 0;
+
+ virtual
+ HRESULT
+ Redirect(
+ IN PCSTR pszUrl,
+ IN BOOL fResetStatusCode = TRUE,
+ IN BOOL fIncludeParameters = FALSE
+ ) = 0;
+
+ virtual
+ HRESULT
+ WriteEntityChunkByReference(
+ IN HTTP_DATA_CHUNK * pDataChunk,
+ IN LONG lInsertPosition = -1
+ ) = 0;
+
+ virtual
+ HRESULT
+ WriteEntityChunks(
+ IN HTTP_DATA_CHUNK * pDataChunks,
+ IN DWORD nChunks,
+ IN BOOL fAsync,
+ IN BOOL fMoreData,
+ OUT DWORD * pcbSent,
+ OUT BOOL * pfCompletionExpected = NULL
+ ) = 0;
+
+ virtual
+ VOID
+ DisableBuffering(
+ VOID
+ ) = 0;
+
+ virtual
+ VOID
+ GetStatus(
+ OUT USHORT * pStatusCode,
+ OUT USHORT * pSubStatus = NULL,
+ OUT PCSTR * ppszReason = NULL,
+ OUT USHORT * pcchReason = NULL,
+ OUT HRESULT * phrErrorToReport = NULL,
+ OUT PCWSTR * ppszModule = NULL,
+ OUT DWORD * pdwNotification = NULL,
+ OUT IAppHostConfigException ** ppException = NULL,
+ OUT BOOL * pfTrySkipCustomErrors = NULL
+ ) = 0;
+
+ virtual
+ HRESULT
+ SetErrorDescription(
+ IN PCWSTR pszDescription,
+ IN DWORD cchDescription,
+ IN BOOL fHtmlEncode = TRUE
+ ) = 0;
+
+ virtual
+ PCWSTR
+ GetErrorDescription(
+ OUT DWORD * pcchDescription = NULL
+ ) = 0;
+
+ virtual
+ HRESULT
+ GetHeaderChanges(
+ IN DWORD dwOldChangeNumber,
+ OUT DWORD * pdwNewChangeNumber,
+ IN OUT PCSTR knownHeaderSnapshot[HttpHeaderResponseMaximum],
+ IN OUT DWORD * pdwUnknownHeaderSnapshot,
+ IN OUT PCSTR **ppUnknownHeaderNameSnapshot,
+ IN OUT PCSTR **ppUnknownHeaderValueSnapshot,
+ __out_ecount(HttpHeaderResponseMaximum+1)
+ DWORD diffedKnownHeaderIndices[HttpHeaderResponseMaximum+1],
+ OUT DWORD * pdwDiffedUnknownHeaders,
+ OUT DWORD **ppDiffedUnknownHeaderIndices
+ ) = 0;
+
+ virtual
+ VOID
+ CloseConnection(
+ VOID
+ ) = 0;
+};
+
+//
+// User descriptor
+//
+class __declspec(uuid("8059e6f8-10ce-4d61-b47e-5a1d8d9a8b67"))
+IHttpUser
+{
+ public:
+ virtual
+ PCWSTR
+ GetRemoteUserName(
+ VOID
+ ) = 0;
+
+ virtual
+ PCWSTR
+ GetUserName(
+ VOID
+ ) = 0;
+
+ virtual
+ PCWSTR
+ GetAuthenticationType(
+ VOID
+ ) = 0;
+
+ virtual
+ PCWSTR
+ GetPassword(
+ VOID
+ ) = 0;
+
+ virtual
+ HANDLE
+ GetImpersonationToken(
+ VOID
+ ) = 0;
+
+ virtual
+ HANDLE
+ GetPrimaryToken(
+ VOID
+ ) = 0;
+
+ virtual
+ VOID
+ ReferenceUser(
+ VOID
+ ) = 0;
+
+ virtual
+ VOID
+ DereferenceUser(
+ VOID
+ ) = 0;
+
+ virtual
+ BOOL
+ SupportsIsInRole(
+ VOID
+ ) = 0;
+
+ virtual
+ HRESULT
+ IsInRole(
+ IN PCWSTR pszRoleName,
+ OUT BOOL * pfInRole
+ ) = 0;
+
+ virtual
+ PVOID
+ GetUserVariable(
+ IN PCSTR pszVariableName
+ ) = 0;
+};
+
+#define HTTP_USER_VARIABLE_SID "SID"
+#define HTTP_USER_VARIABLE_CTXT_HANDLE "CtxtHandle"
+#define HTTP_USER_VARIABLE_CRED_HANDLE "CredHandle"
+
+class __declspec(uuid("841d9a71-75f4-4626-8b97-66046ca7e45b"))
+IHttpConnectionStoredContext : public IHttpStoredContext
+{
+ public:
+ virtual
+ VOID
+ NotifyDisconnect(
+ VOID
+ ) = 0;
+};
+
+class __declspec(uuid("f3dd2fb3-4d11-4295-b8ab-4cb667add1fe"))
+IHttpConnectionModuleContextContainer : public IHttpModuleContextContainer
+{
+ public:
+ virtual
+ IHttpConnectionStoredContext *
+ GetConnectionModuleContext(
+ IN HTTP_MODULE_ID moduleId
+ ) = 0;
+
+ virtual
+ HRESULT
+ SetConnectionModuleContext(
+ IN IHttpConnectionStoredContext * ppStoredContext,
+ IN HTTP_MODULE_ID moduleId
+ ) = 0;
+};
+
+//
+// Connection descriptor
+//
+class __declspec(uuid("d9a5de00-3346-4599-9826-fe88565e1226"))
+IHttpConnection
+{
+ public:
+ virtual
+ BOOL
+ IsConnected(
+ VOID
+ ) const = 0;
+
+ virtual
+ VOID *
+ AllocateMemory(
+ DWORD cbAllocation
+ ) = 0;
+
+ virtual
+ IHttpConnectionModuleContextContainer *
+ GetModuleContextContainer(
+ VOID
+ ) = 0;
+};
+
+//
+// Forward declarations
+//
+class __declspec(uuid("71e95595-8c74-44d9-88a9-f5112d5f5900"))
+IHttpFileInfo;
+
+class __declspec(uuid("eb16a6ec-ba5d-436f-bf24-3ede13906450"))
+IHttpSite;
+
+class __declspec(uuid("671e6d34-9380-4df4-b453-91129df02b24"))
+ICustomNotificationProvider;
+
+class __declspec(uuid("6f3f657d-2fb8-43c6-a096-5064b41f0580"))
+IHttpEventProvider;
+
+class CHttpModule;
+
+//
+// IHttpContext extended interface versions (deprecated)
+//
+enum HTTP_CONTEXT_INTERFACE_VERSION
+{
+};
+
+//
+// Context object representing the processing of an HTTP request
+//
+class __declspec(uuid("424c1b8c-a1ba-44d7-ac98-9f8f457701a5"))
+IHttpContext
+{
+ public:
+ virtual
+ IHttpSite *
+ GetSite(
+ VOID
+ ) = 0;
+
+ virtual
+ IHttpApplication *
+ GetApplication(
+ VOID
+ ) = 0;
+
+ virtual
+ IHttpConnection *
+ GetConnection(
+ VOID
+ ) = 0;
+
+ virtual
+ IHttpRequest *
+ GetRequest(
+ VOID
+ ) = 0;
+
+ virtual
+ IHttpResponse *
+ GetResponse(
+ VOID
+ ) = 0;
+
+ virtual
+ BOOL
+ GetResponseHeadersSent(
+ VOID
+ ) const = 0;
+
+ virtual
+ IHttpUser *
+ GetUser(
+ VOID
+ ) const = 0;
+
+ virtual
+ IHttpModuleContextContainer *
+ GetModuleContextContainer(
+ VOID
+ ) = 0;
+
+ virtual
+ VOID
+ IndicateCompletion(
+ IN REQUEST_NOTIFICATION_STATUS notificationStatus
+ ) = 0;
+
+ virtual
+ HRESULT
+ PostCompletion(
+ IN DWORD cbBytes
+ ) = 0;
+
+ virtual
+ VOID
+ DisableNotifications(
+ IN DWORD dwNotifications,
+ IN DWORD dwPostNotifications
+ ) = 0;
+
+ virtual
+ BOOL
+ GetNextNotification(
+ IN REQUEST_NOTIFICATION_STATUS status,
+ OUT DWORD * pdwNotification,
+ OUT BOOL * pfIsPostNotification,
+ OUT CHttpModule ** ppModuleInfo,
+ OUT IHttpEventProvider ** ppRequestOutput
+ ) = 0;
+
+ virtual
+ BOOL
+ GetIsLastNotification(
+ IN REQUEST_NOTIFICATION_STATUS status
+ ) = 0;
+
+ virtual
+ HRESULT
+ ExecuteRequest(
+ IN BOOL fAsync,
+ IN IHttpContext * pHttpContext,
+ IN DWORD dwExecuteFlags,
+ IN IHttpUser * pHttpUser,
+ OUT BOOL * pfCompletionExpected = NULL
+ ) = 0;
+
+ virtual
+ DWORD
+ GetExecuteFlags(
+ VOID
+ ) const = 0;
+
+ virtual
+ HRESULT
+ GetServerVariable(
+ PCSTR pszVariableName,
+ __deref_out_ecount(*pcchValueLength) PCWSTR * ppszValue,
+ __out DWORD * pcchValueLength
+ ) = 0;
+
+ virtual
+ HRESULT
+ GetServerVariable(
+ PCSTR pszVariableName,
+ __deref_out_ecount(*pcchValueLength) PCSTR * ppszValue,
+ __out DWORD * pcchValueLength
+ ) = 0;
+
+ virtual
+ HRESULT
+ SetServerVariable(
+ PCSTR pszVariableName,
+ PCWSTR pszVariableValue
+ ) = 0;
+
+ virtual
+ VOID *
+ AllocateRequestMemory(
+ IN DWORD cbAllocation
+ ) = 0;
+
+ virtual
+ IHttpUrlInfo *
+ GetUrlInfo(
+ VOID
+ ) = 0;
+
+ virtual
+ IMetadataInfo *
+ GetMetadata(
+ VOID
+ ) = 0;
+
+ virtual
+ PCWSTR
+ GetPhysicalPath(
+ OUT DWORD * pcchPhysicalPath = NULL
+ ) = 0;
+
+ virtual
+ PCWSTR
+ GetScriptName(
+ OUT DWORD * pcchScriptName = NULL
+ ) const = 0;
+
+ virtual
+ PCWSTR
+ GetScriptTranslated(
+ OUT DWORD * pcchScriptTranslated = NULL
+ ) = 0;
+
+ virtual
+ IScriptMapInfo *
+ GetScriptMap(
+ VOID
+ ) const = 0;
+
+ virtual
+ VOID
+ SetRequestHandled(
+ VOID
+ ) = 0;
+
+ virtual
+ IHttpFileInfo *
+ GetFileInfo(
+ VOID
+ ) const = 0;
+
+ virtual
+ HRESULT
+ MapPath(
+ PCWSTR pszUrl,
+ __out_bcount_opt(*pcbPhysicalPath) PWSTR pszPhysicalPath,
+ IN OUT DWORD * pcbPhysicalPath
+ ) = 0;
+
+ virtual
+ HRESULT
+ NotifyCustomNotification(
+ ICustomNotificationProvider * pCustomOutput,
+ OUT BOOL * pfCompletionExpected
+ ) = 0;
+
+ virtual
+ IHttpContext *
+ GetParentContext(
+ VOID
+ ) const = 0;
+
+ virtual
+ IHttpContext *
+ GetRootContext(
+ VOID
+ ) const = 0;
+
+ virtual
+ HRESULT
+ CloneContext(
+ IN DWORD dwCloneFlags,
+ OUT IHttpContext ** ppHttpContext
+ ) = 0;
+
+ virtual
+ HRESULT
+ ReleaseClonedContext(
+ VOID
+ ) = 0;
+
+ virtual
+ HRESULT
+ GetCurrentExecutionStats(
+ OUT DWORD * pdwNotification,
+ OUT DWORD * pdwNotificationStartTickCount = NULL,
+ OUT PCWSTR * ppszModule = NULL,
+ OUT DWORD * pdwModuleStartTickCount = NULL,
+ OUT DWORD * pdwAsyncNotification = NULL,
+ OUT DWORD * pdwAsyncNotificationStartTickCount = NULL
+ ) const = 0;
+
+ virtual
+ IHttpTraceContext *
+ GetTraceContext(
+ VOID
+ ) const = 0;
+
+ virtual
+ HRESULT
+ GetServerVarChanges(
+ IN DWORD dwOldChangeNumber,
+ OUT DWORD * pdwNewChangeNumber,
+ IN OUT DWORD * pdwVariableSnapshot,
+ IN OUT PCSTR ** ppVariableNameSnapshot,
+ IN OUT PCWSTR ** ppVariableValueSnapshot,
+ OUT DWORD * pdwDiffedVariables,
+ OUT DWORD ** ppDiffedVariableIndices
+ ) = 0;
+
+ virtual
+ HRESULT
+ CancelIo(
+ VOID
+ ) = 0;
+
+ virtual
+ HRESULT
+ MapHandler(
+ IN DWORD dwSiteId,
+ IN PCWSTR pszSiteName,
+ IN PCWSTR pszUrl,
+ IN PCSTR pszVerb,
+ OUT IScriptMapInfo ** ppScriptMap,
+ IN BOOL fIgnoreWildcardMappings = FALSE
+ ) = 0;
+
+ __declspec(deprecated("This method is deprecated. Use the HttpGetExtendedInterface helper function instead."))
+ virtual
+ HRESULT
+ GetExtendedInterface(
+ IN HTTP_CONTEXT_INTERFACE_VERSION version,
+ OUT PVOID * ppInterface
+ ) = 0;
+};
+
+class __declspec(uuid("9f9098d5-915c-4294-a52e-66532a232bc9"))
+IHttpTraceContext
+{
+public:
+ virtual
+ HRESULT
+ GetTraceConfiguration(
+ IN OUT HTTP_TRACE_CONFIGURATION * pHttpTraceConfiguration
+ ) = 0;
+
+ virtual
+ HRESULT
+ SetTraceConfiguration(
+ IN HTTP_MODULE_ID moduleId,
+ IN HTTP_TRACE_CONFIGURATION * pHttpTraceConfiguration,
+ IN DWORD cHttpTraceConfiguration = 1
+ ) = 0;
+
+ virtual
+ HRESULT
+ RaiseTraceEvent(
+ IN HTTP_TRACE_EVENT * pTraceEvent
+ ) = 0;
+
+ virtual
+ LPCGUID
+ GetTraceActivityId(
+ ) = 0;
+
+ virtual
+ HRESULT
+ QuickTrace(
+ IN PCWSTR pszData1,
+ IN PCWSTR pszData2 = NULL,
+ IN HRESULT hrLastError = S_OK,
+ //
+ // 4 == TRACE_LEVEL_INFORMATION
+ //
+ IN UCHAR Level = 4
+ ) = 0;
+};
+
+class __declspec(uuid("37776aff-852e-4eec-93a5-b85a285a95b8"))
+IHttpCacheSpecificData;
+
+//
+// Cache helpers
+//
+class __declspec(uuid("cdef2aad-20b3-4512-b1b1-094b3844aeb2"))
+IHttpCacheKey
+{
+ public:
+ virtual
+ DWORD
+ GetHash(
+ VOID
+ ) const = 0;
+
+ virtual
+ PCWSTR
+ GetCacheName(
+ VOID
+ ) const = 0;
+
+ virtual
+ bool
+ GetIsEqual(
+ IHttpCacheKey * pCacheCompareKey
+ ) const = 0;
+
+ virtual
+ bool
+ GetIsPrefix(
+ IHttpCacheKey * pCacheCompareKey
+ ) const = 0;
+
+ virtual
+ VOID
+ Enum(
+ IHttpCacheSpecificData *
+ ) = 0;
+};
+
+class __declspec(uuid("37776aff-852e-4eec-93a5-b85a285a95b8"))
+IHttpCacheSpecificData
+{
+ public:
+ virtual
+ IHttpCacheKey *
+ GetCacheKey(
+ VOID
+ ) const = 0;
+
+ virtual
+ VOID
+ ReferenceCacheData(
+ VOID
+ ) = 0;
+
+ virtual
+ VOID
+ DereferenceCacheData(
+ VOID
+ ) = 0;
+
+ virtual
+ VOID
+ ResetTTL(
+ VOID
+ ) = 0;
+
+ virtual
+ VOID
+ DecrementTTL(
+ OUT BOOL *pfTTLExpired
+ ) = 0;
+
+ virtual
+ VOID
+ SetFlushed(
+ VOID
+ ) = 0;
+
+ virtual
+ BOOL
+ GetFlushed(
+ VOID
+ ) const = 0;
+};
+
+//
+// Site descriptor
+//
+class __declspec(uuid("eb16a6ec-ba5d-436f-bf24-3ede13906450"))
+IHttpSite
+{
+ public:
+ virtual
+ DWORD
+ GetSiteId(
+ VOID
+ ) const = 0;
+
+ virtual
+ PCWSTR
+ GetSiteName(
+ VOID
+ ) const = 0;
+
+ virtual
+ IHttpModuleContextContainer *
+ GetModuleContextContainer(
+ VOID
+ ) = 0;
+
+ virtual
+ IHttpPerfCounterInfo *
+ GetPerfCounterInfo(
+ VOID
+ ) = 0;
+};
+
+//
+// File change monitor
+//
+//
+class __declspec(uuid("985422da-b0cf-473b-ba9e-8148ceb3e240"))
+IHttpFileMonitor
+{
+ public:
+ virtual
+ IHttpModuleContextContainer *
+ GetModuleContextContainer(
+ VOID
+ ) = 0;
+
+ virtual
+ VOID
+ DereferenceFileMonitor(
+ VOID
+ ) = 0;
+};
+
+//
+// File descriptor
+//
+//
+class __declspec(uuid("71e95595-8c74-44d9-88a9-f5112d5f5900"))
+IHttpFileInfo : public IHttpCacheSpecificData
+{
+ public:
+ virtual
+ DWORD
+ GetAttributes(
+ VOID
+ ) const = 0;
+
+ virtual
+ VOID
+ GetSize(
+ OUT ULARGE_INTEGER * pliSize
+ ) const = 0;
+
+ virtual
+ const BYTE *
+ GetFileBuffer(
+ VOID
+ ) const = 0;
+
+ virtual
+ HANDLE
+ GetFileHandle(
+ VOID
+ ) const = 0;
+
+ virtual
+ PCWSTR
+ GetFilePath(
+ VOID
+ ) const = 0;
+
+ virtual
+ PCSTR
+ GetETag(
+ OUT USHORT * pcchETag = NULL
+ ) const = 0;
+
+ virtual
+ VOID
+ GetLastModifiedTime(
+ OUT FILETIME * pFileTime
+ ) const = 0;
+
+ virtual
+ PCSTR
+ GetLastModifiedString(
+ VOID
+ ) const = 0;
+
+ virtual
+ BOOL
+ GetHttpCacheAllowed(
+ OUT DWORD * pSecondsToLive
+ ) const = 0;
+
+ virtual
+ HRESULT
+ AccessCheck(
+ IN HANDLE hUserToken,
+ IN PSID pUserSid
+ ) = 0;
+
+ virtual
+ HANDLE
+ GetVrToken(
+ VOID
+ ) const = 0;
+
+ virtual
+ PCWSTR
+ GetVrPath(
+ VOID
+ ) const = 0;
+
+ virtual
+ IHttpModuleContextContainer *
+ GetModuleContextContainer(
+ VOID
+ ) = 0;
+
+ virtual
+ BOOL
+ CheckIfFileHasChanged(
+ IN HANDLE hUserToken
+ ) = 0;
+};
+
+
+//
+// Token-cache entry
+//
+class __declspec(uuid("fd86e6de-fb0e-47dd-820a-e0da12be46e9"))
+IHttpTokenEntry : public IHttpCacheSpecificData
+{
+ public:
+ virtual
+ HANDLE
+ GetImpersonationToken(
+ VOID
+ ) = 0;
+
+ virtual
+ HANDLE
+ GetPrimaryToken(
+ VOID
+ ) = 0;
+
+ virtual
+ PSID
+ GetSid(
+ VOID
+ ) = 0;
+};
+
+
+//
+// IHttpServer extended interface versions
+//
+enum HTTP_SERVER_INTERFACE_VERSION
+{
+ HTTP_SERVER_INTERFACE_V2
+};
+
+
+//
+// Global utility descriptor
+//
+class __declspec(uuid("eda2a40f-fb92-4d6d-b52b-c8c207380b4e"))
+IHttpServer
+{
+ public:
+ virtual
+ BOOL
+ IsCommandLineLaunch(
+ VOID
+ ) const = 0;
+
+ virtual
+ PCWSTR
+ GetAppPoolName(
+ VOID
+ ) const = 0;
+
+ virtual
+ HRESULT
+ AssociateWithThreadPool(
+ IN HANDLE hHandle,
+ IN LPOVERLAPPED_COMPLETION_ROUTINE completionRoutine
+ ) = 0;
+
+ virtual
+ VOID
+ IncrementThreadCount(
+ VOID
+ ) = 0;
+
+ virtual
+ VOID
+ DecrementThreadCount(
+ VOID
+ ) = 0;
+
+ virtual
+ VOID
+ ReportUnhealthy(
+ IN PCWSTR pszReasonString,
+ IN HRESULT hrReason
+ ) = 0;
+
+ virtual
+ VOID
+ RecycleProcess(
+ PCWSTR pszReason
+ ) = 0;
+
+ virtual
+ IAppHostAdminManager *
+ GetAdminManager(
+ VOID
+ ) const = 0;
+
+ virtual
+ HRESULT
+ GetFileInfo(
+ IN PCWSTR pszPhysicalPath,
+ IN HANDLE hUserToken,
+ IN PSID pSid,
+ IN PCWSTR pszChangeNotificationPath,
+ IN HANDLE hChangeNotificationToken,
+ IN BOOL fCache,
+ OUT IHttpFileInfo ** ppFileInfo,
+ IN IHttpTraceContext * pHttpTraceContext = NULL
+ ) = 0;
+
+ virtual
+ HRESULT
+ FlushKernelCache(
+ IN PCWSTR pszUrl
+ ) = 0;
+
+ virtual
+ HRESULT
+ DoCacheOperation(
+ IN CACHE_OPERATION cacheOperation,
+ IN IHttpCacheKey * pCacheKey,
+ OUT IHttpCacheSpecificData ** ppCacheSpecificData,
+ IN IHttpTraceContext * pHttpTraceContext = NULL
+ ) = 0;
+
+ virtual
+ GLOBAL_NOTIFICATION_STATUS
+ NotifyCustomNotification(
+ ICustomNotificationProvider * pCustomOutput
+ ) = 0;
+
+ virtual
+ IHttpPerfCounterInfo *
+ GetPerfCounterInfo(
+ VOID
+ ) = 0;
+
+ virtual
+ VOID
+ RecycleApplication(
+ PCWSTR pszAppConfigPath
+ ) = 0;
+
+ virtual
+ VOID
+ NotifyConfigurationChange(
+ PCWSTR pszPath
+ ) = 0;
+
+ virtual
+ VOID
+ NotifyFileChange(
+ PCWSTR pszFileName
+ ) = 0;
+
+ virtual
+ IDispensedHttpModuleContextContainer *
+ DispenseContainer(
+ VOID
+ ) = 0;
+
+ virtual
+ HRESULT
+ AddFragmentToCache(
+ IN HTTP_DATA_CHUNK * pDataChunk,
+ PCWSTR pszFragmentName
+ ) = 0;
+
+ virtual
+ HRESULT
+ ReadFragmentFromCache(
+ PCWSTR pszFragmentName,
+ OUT BYTE * pvBuffer,
+ DWORD cbSize,
+ OUT DWORD * pcbCopied
+ ) = 0;
+
+ virtual
+ HRESULT
+ RemoveFragmentFromCache(
+ PCWSTR pszFragmentName
+ ) = 0;
+
+ virtual
+ HRESULT
+ GetWorkerProcessSettings(
+ OUT IWpfSettings ** ppWorkerProcessSettings
+ ) = 0;
+
+ virtual
+ HRESULT
+ GetProtocolManagerCustomInterface(
+ IN PCWSTR pProtocolManagerDll,
+ IN PCWSTR pProtocolManagerDllInitFunction,
+ IN DWORD dwCustomInterfaceId,
+ OUT PVOID* ppCustomInterface
+ ) = 0;
+
+ virtual
+ BOOL
+ SatisfiesPrecondition(
+ PCWSTR pszPrecondition,
+ BOOL * pfUnknownPrecondition = NULL
+ ) const = 0;
+
+ virtual
+ IHttpTraceContext *
+ GetTraceContext(
+ VOID
+ ) const = 0;
+
+ virtual
+ HRESULT
+ RegisterFileChangeMonitor(
+ PCWSTR pszPath,
+ HANDLE hToken,
+ IHttpFileMonitor ** ppFileMonitor
+ ) = 0;
+
+ virtual
+ HRESULT
+ GetExtendedInterface(
+ IN HTTP_SERVER_INTERFACE_VERSION version,
+ OUT PVOID * ppInterface
+ ) = 0;
+};
+
+class __declspec(uuid("34af637e-afe8-4556-bcc1-767f8e0b4a4e"))
+IHttpServer2 : public IHttpServer
+{
+ public:
+
+ virtual
+ HRESULT
+ GetToken(
+ PCWSTR pszUserName,
+ PCWSTR pszPassword,
+ DWORD dwLogonMethod,
+ IHttpTokenEntry ** ppTokenEntry,
+ PCWSTR pszDefaultDomain = NULL,
+ PSOCKADDR pSockAddr = NULL,
+ IHttpTraceContext * pHttpTraceContext = NULL
+ ) = 0;
+
+ virtual
+ PCWSTR
+ GetAppPoolConfigFile(
+ __out DWORD * pcchConfigFilePath = NULL
+ ) const = 0;
+
+ virtual
+ HRESULT
+ GetExtendedInterface(
+ __in const GUID & Version1,
+ __in PVOID pInput,
+ __in const GUID & Version2,
+ __deref_out PVOID * ppOutput
+ ) = 0;
+};
+
+//
+// Helper function to get extended HTTP interfaces.
+//
+// Template parameters (HttpType1 and HttpType2)
+// can be deduced from the arguments to the function.
+//
+// Example:
+//
+// IHttpRequest * pHttpRequest = pHttpContext->GetRequest();
+// IHttpRequest2 * pHttpRequest2;
+// HRESULT hr = HttpGetExtendedInterface(g_pHttpServer, pHttpRequest, &pHttpRequest2);
+// if( SUCCEEDED(hr) )
+// {
+// // Use pHttpRequest2.
+// }
+//
+// Where pHttpContext is an IHttpContext pointer and
+// g_pHttpServer is an IHttpServer pointer.
+//
+
+template
+HRESULT
+HttpGetExtendedInterface(
+ __in IHttpServer * pHttpServer,
+ __in HttpType1 * pInput,
+ __deref_out HttpType2 ** ppOutput
+)
+{
+ HRESULT hr;
+ IHttpServer2 * pHttpServer2;
+ hr = pHttpServer->GetExtendedInterface(HTTP_SERVER_INTERFACE_V2,
+ reinterpret_cast(&pHttpServer2) );
+ if (SUCCEEDED(hr))
+ {
+ hr = pHttpServer2->GetExtendedInterface(__uuidof(HttpType1),
+ pInput,
+ __uuidof(HttpType2),
+ reinterpret_cast(ppOutput) );
+ }
+ return hr;
+}
+
+//
+// Notification specific output for notifications
+//
+class __declspec(uuid("6f3f657d-2fb8-43c6-a096-5064b41f0580"))
+IHttpEventProvider
+{
+ public:
+ virtual
+ VOID
+ SetErrorStatus(
+ HRESULT hrError
+ ) = 0;
+};
+
+//
+// Completion information for notifications
+//
+class __declspec(uuid("49dd20e3-d9c0-463c-8821-f3413b55cc00"))
+IHttpCompletionInfo
+{
+ public:
+ virtual
+ DWORD
+ GetCompletionBytes(
+ VOID
+ ) const = 0;
+
+ virtual
+ HRESULT
+ GetCompletionStatus(
+ VOID
+ ) const = 0;
+};
+
+//
+// RQ_ and GL_ CUSTOM_NOTIFICATION outputs
+//
+class __declspec(uuid("671e6d34-9380-4df4-b453-91129df02b24"))
+ICustomNotificationProvider : public IHttpEventProvider
+{
+ public:
+ virtual
+ PCWSTR
+ QueryNotificationType(
+ VOID
+ ) = 0;
+};
+
+//
+// RQ_REQUEST_AUTHENTICATE descriptor
+//
+class __declspec(uuid("304d51d0-0307-45ed-83fd-dd3fc032fdfc"))
+IAuthenticationProvider : public IHttpEventProvider
+{
+ public:
+ virtual
+ VOID
+ SetUser(
+ IN IHttpUser * pUser
+ ) = 0;
+};
+
+//
+// RQ_MAP_REQUEST_HANDLER
+//
+class __declspec(uuid("fea3ce6b-e346-47e7-b2a6-ad265baeff2c"))
+IMapHandlerProvider : public IHttpEventProvider
+{
+ public:
+ virtual
+ HRESULT
+ SetScriptName(
+ PCWSTR pszScriptName,
+ DWORD cchScriptName
+ ) = 0;
+
+ virtual
+ VOID
+ SetScriptMap(
+ IN IScriptMapInfo * pScriptMap
+ ) = 0;
+
+ virtual
+ VOID
+ SetFileInfo(
+ IN IHttpFileInfo * pFileInfo
+ ) = 0;
+};
+
+//
+// RQ_MAP_PATH
+//
+class __declspec(uuid("8efdf557-a8f1-4bc9-b462-6df3b038a59a"))
+IMapPathProvider : public IHttpEventProvider
+{
+ public:
+ virtual
+ PCWSTR
+ GetUrl(
+ ) const = 0;
+
+ virtual
+ PCWSTR
+ GetPhysicalPath(
+ ) const = 0;
+
+ virtual
+ HRESULT
+ SetPhysicalPath(
+ PCWSTR pszPhysicalPath,
+ DWORD cchPhysicalPath
+ ) = 0;
+};
+
+//
+// RQ_SEND_RESPONSE
+//
+class __declspec(uuid("57f2e7bc-0bcf-4a9f-94a4-10e55c6e5b51"))
+ISendResponseProvider : public IHttpEventProvider
+{
+ public:
+ virtual
+ BOOL
+ GetHeadersBeingSent(
+ VOID
+ ) const = 0;
+
+ virtual
+ DWORD
+ GetFlags(
+ VOID
+ ) const = 0;
+
+ virtual
+ VOID
+ SetFlags(
+ DWORD dwFlags
+ ) = 0;
+
+ virtual
+ HTTP_LOG_DATA *
+ GetLogData(
+ VOID
+ ) const = 0;
+
+ virtual
+ HRESULT
+ SetLogData(
+ IN HTTP_LOG_DATA *pLogData
+ ) = 0;
+
+ virtual
+ BOOL
+ GetReadyToLogData(
+ VOID
+ ) const = 0;
+};
+
+//
+// RQ_READ_ENTITY
+//
+class __declspec(uuid("fe6d905a-99b8-49fd-b389-cfc809562b81"))
+IReadEntityProvider : public IHttpEventProvider
+{
+ public:
+ virtual
+ VOID
+ GetEntity(
+ OUT PVOID * ppBuffer,
+ OUT DWORD * pcbData,
+ OUT DWORD * pcbBuffer
+ ) = 0;
+
+ virtual
+ VOID
+ SetEntity(
+ IN PVOID pBuffer,
+ DWORD cbData,
+ DWORD cbBuffer
+ ) = 0;
+};
+
+//
+// GL_PRE_BEGIN_REQUEST provider
+//
+class __declspec(uuid("fb715d26-aff9-476a-8fc0-6b1acb3d1098"))
+IPreBeginRequestProvider : public IHttpEventProvider
+{
+ public:
+ virtual
+ IHttpContext *
+ GetHttpContext(
+ VOID
+ ) = 0;
+};
+
+//
+// GL_APPLICATION_START provider
+//
+class __declspec(uuid("1de2c71c-c126-4512-aed3-f4f885e14997"))
+IHttpApplicationProvider : public IHttpEventProvider
+{
+ public:
+ virtual
+ IHttpApplication *
+ GetApplication(
+ VOID
+ ) = 0;
+};
+
+typedef IHttpApplicationProvider IHttpApplicationStartProvider;
+
+class __declspec(uuid("ba32d330-9ea8-4b9e-89f1-8c76a323277f"))
+IHttpModuleFactory;
+
+//
+// GL_APPLICATION_RESOLVE_MODULES provider
+//
+class __declspec(uuid("0617d9b9-e20f-4a9f-94f9-35403b3be01e"))
+IHttpApplicationResolveModulesProvider : public IHttpApplicationProvider
+{
+ public:
+ virtual
+ HRESULT
+ RegisterModule(
+ IN HTTP_MODULE_ID parentModuleId,
+ IN IHttpModuleFactory * pModuleFactory,
+ IN PCWSTR pszModuleName,
+ IN PCWSTR pszModuleType,
+ IN PCWSTR pszModulePreCondition,
+ IN DWORD dwRequestNotifications,
+ IN DWORD dwPostRequestNotifications
+ ) = 0;
+
+ virtual
+ HRESULT
+ SetPriorityForRequestNotification(
+ IN PCWSTR pszModuleName,
+ IN DWORD dwRequestNotification,
+ IN PCWSTR pszPriorityAlias
+ ) = 0;
+};
+
+//
+// GL_APPLICATION_STOP provider
+//
+typedef IHttpApplicationProvider IHttpApplicationStopProvider;
+
+//
+// GL_RSCA_QUERY provider
+//
+class __declspec(uuid("63fdc43f-934a-4ee5-bcd8-7e7b50b75605"))
+IGlobalRSCAQueryProvider : public IHttpEventProvider
+{
+ public:
+ virtual
+ PCWSTR
+ GetFunctionName(
+ VOID
+ ) const = 0;
+
+ virtual
+ PCWSTR
+ GetFunctionParameters(
+ VOID
+ ) const = 0;
+
+ virtual
+ HRESULT
+ GetOutputBuffer(
+ DWORD cbBuffer,
+ OUT BYTE ** ppbBuffer
+ ) = 0;
+
+ virtual
+ HRESULT
+ ResizeOutputBuffer(
+ DWORD cbNewBuffer,
+ DWORD cbBytesToCopy,
+ IN OUT BYTE ** ppbBuffer
+ ) = 0;
+
+ virtual
+ VOID
+ SetResult(
+ DWORD cbData,
+ HRESULT hr
+ ) = 0;
+};
+
+//
+// GL_STOP_LISTENING
+//
+class __declspec(uuid("41f9a601-e25d-4ac8-8a1f-635698a30ab9"))
+IGlobalStopListeningProvider : public IHttpEventProvider
+{
+ public:
+ virtual
+ BOOL
+ DrainRequestsGracefully(
+ VOID
+ ) const = 0;
+};
+
+//
+// GL_CACHE_OPERATION
+//
+class __declspec(uuid("58925fb9-7c5e-4684-833b-4a04e1286690"))
+ICacheProvider : public IHttpEventProvider
+{
+ public:
+ virtual
+ CACHE_OPERATION
+ GetCacheOperation(
+ VOID
+ ) const = 0;
+
+ virtual
+ IHttpCacheKey *
+ GetCacheKey(
+ VOID
+ ) const = 0;
+
+ virtual
+ IHttpCacheSpecificData *
+ GetCacheRecord(
+ VOID
+ ) const = 0;
+
+ virtual
+ VOID
+ SetCacheRecord(
+ IHttpCacheSpecificData * pCacheRecord
+ ) = 0;
+
+ virtual
+ IHttpTraceContext *
+ GetTraceContext(
+ VOID
+ ) const = 0;
+};
+
+//
+// GL_CONFIGURATION_CHANGE
+//
+class __declspec(uuid("3405f3b4-b3d6-4b73-b5f5-4d8a3cc642ce"))
+IGlobalConfigurationChangeProvider : public IHttpEventProvider
+{
+ public:
+ virtual
+ PCWSTR
+ GetChangePath(
+ VOID
+ ) const = 0;
+};
+
+//
+// GL_FILE_CHANGE
+//
+class __declspec(uuid("ece31ee5-0486-4fb0-a875-6739a2d7daf5"))
+IGlobalFileChangeProvider : public IHttpEventProvider
+{
+public:
+ virtual
+ PCWSTR
+ GetFileName(
+ VOID
+ ) const = 0;
+
+ virtual
+ IHttpFileMonitor *
+ GetFileMonitor(
+ VOID
+ ) = 0;
+};
+
+//
+// GL_TRACE_EVENT
+//
+class __declspec(uuid("7c6bb150-0310-4718-a01f-6faceb62dc1d"))
+IGlobalTraceEventProvider : public IHttpEventProvider
+{
+ public:
+ virtual
+ HRESULT
+ GetTraceEvent(
+ OUT HTTP_TRACE_EVENT ** ppTraceEvent
+ ) = 0;
+
+ virtual
+ BOOL
+ CheckSubscription(
+ IN HTTP_MODULE_ID ModuleId
+ ) = 0;
+
+ virtual
+ HRESULT
+ GetCurrentHttpRequestContext(
+ OUT IHttpContext ** ppHttpContext
+ ) = 0;
+};
+
+//
+// GL_THREAD_CLEANUP
+//
+class __declspec(uuid("6b36a149-8620-45a0-8197-00814a706e2e"))
+IGlobalThreadCleanupProvider : public IHttpEventProvider
+{
+public:
+ virtual
+ IHttpApplication *
+ GetApplication(
+ VOID
+ ) = 0;
+};
+
+//
+// GL_APPLICATION_PRELOAD
+//
+class __declspec(uuid("2111f8d6-0c41-4ff7-bd45-5c04c7e91a73"))
+IGlobalApplicationPreloadProvider : public IHttpEventProvider
+{
+public:
+ virtual
+ HRESULT
+ CreateContext(
+ OUT IHttpContext ** ppHttpContext
+ ) = 0;
+
+ virtual
+ HRESULT
+ ExecuteRequest(
+ IN IHttpContext * pHttpContext,
+ IN IHttpUser * pHttpUser
+ ) = 0;
+};
+
+class CHttpModule
+{
+public:
+ // RQ_BEGIN_REQUEST
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnBeginRequest(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnPostBeginRequest(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+
+ // RQ_AUTHENTICATE_REQUEST
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnAuthenticateRequest(
+ IN IHttpContext * pHttpContext,
+ IN IAuthenticationProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnPostAuthenticateRequest(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+
+ // RQ_AUTHORIZE_REQUEST
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnAuthorizeRequest(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnPostAuthorizeRequest(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+
+ // RQ_RESOLVE_REQUEST_CACHE
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnResolveRequestCache(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnPostResolveRequestCache(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+
+ // RQ_MAP_REQUEST_HANDLER
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnMapRequestHandler(
+ IN IHttpContext * pHttpContext,
+ IN IMapHandlerProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnPostMapRequestHandler(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+
+ // RQ_ACQUIRE_REQUEST_STATE
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnAcquireRequestState(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnPostAcquireRequestState(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+
+ // RQ_PRE_EXECUTE_REQUEST_HANDLER
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnPreExecuteRequestHandler(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnPostPreExecuteRequestHandler(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+
+ // RQ_EXECUTE_REQUEST_HANDLER
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnExecuteRequestHandler(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnPostExecuteRequestHandler(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+ // RQ_RELEASE_REQUEST_STATE
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnReleaseRequestState(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnPostReleaseRequestState(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+
+ // RQ_UPDATE_REQUEST_CACHE
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnUpdateRequestCache(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnPostUpdateRequestCache(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+ // RQ_LOG_REQUEST
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnLogRequest(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnPostLogRequest(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+ // RQ_END_REQUEST
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnEndRequest(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnPostEndRequest(
+ IN IHttpContext * pHttpContext,
+ IN IHttpEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+ // RQ_SEND_RESPONSE
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnSendResponse(
+ IN IHttpContext * pHttpContext,
+ IN ISendResponseProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+ // RQ_MAP_PATH
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnMapPath(
+ IN IHttpContext * pHttpContext,
+ IN IMapPathProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+ // RQ_READ_ENTITY
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnReadEntity(
+ IN IHttpContext * pHttpContext,
+ IN IReadEntityProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+ // RQ_CUSTOM_NOTIFICATION
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnCustomRequestNotification(
+ IN IHttpContext * pHttpContext,
+ IN ICustomNotificationProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+ // Completion
+
+ virtual
+ REQUEST_NOTIFICATION_STATUS
+ OnAsyncCompletion(
+ IN IHttpContext * pHttpContext,
+ IN DWORD dwNotification,
+ IN BOOL fPostNotification,
+ IN IHttpEventProvider * pProvider,
+ IN IHttpCompletionInfo * pCompletionInfo
+ )
+ {
+ UNREFERENCED_PARAMETER( pHttpContext );
+ UNREFERENCED_PARAMETER( dwNotification );
+ UNREFERENCED_PARAMETER( fPostNotification );
+ UNREFERENCED_PARAMETER( pProvider );
+ UNREFERENCED_PARAMETER( pCompletionInfo );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CHttpModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return RQ_NOTIFICATION_CONTINUE;
+ }
+
+ virtual
+ VOID
+ Dispose(
+ VOID
+ )
+ {
+ delete this;
+ }
+
+ protected:
+
+ CHttpModule()
+ {}
+
+ virtual
+ ~CHttpModule()
+ {}
+};
+
+class CGlobalModule
+{
+ public:
+
+ // GL_STOP_LISTENING
+
+ virtual
+ GLOBAL_NOTIFICATION_STATUS
+ OnGlobalStopListening(
+ IN IGlobalStopListeningProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CGlobalModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return GL_NOTIFICATION_CONTINUE;
+ }
+
+ // GL_CACHE_CLEANUP
+
+ virtual
+ GLOBAL_NOTIFICATION_STATUS
+ OnGlobalCacheCleanup(
+ VOID
+ )
+ {
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CGlobalModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return GL_NOTIFICATION_CONTINUE;
+ }
+
+ // GL_CACHE_OPERATION
+
+ virtual
+ GLOBAL_NOTIFICATION_STATUS
+ OnGlobalCacheOperation(
+ IN ICacheProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CGlobalModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return GL_NOTIFICATION_CONTINUE;
+ }
+
+ // GL_HEALTH_CHECK
+
+ virtual
+ GLOBAL_NOTIFICATION_STATUS
+ OnGlobalHealthCheck(
+ VOID
+ )
+ {
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CGlobalModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return GL_NOTIFICATION_CONTINUE;
+ }
+
+ // GL_CONFIGURATION_CHANGE
+
+ virtual
+ GLOBAL_NOTIFICATION_STATUS
+ OnGlobalConfigurationChange(
+ IN IGlobalConfigurationChangeProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CGlobalModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return GL_NOTIFICATION_CONTINUE;
+ }
+
+ // GL_FILE_CHANGE
+
+ virtual
+ GLOBAL_NOTIFICATION_STATUS
+ OnGlobalFileChange(
+ IN IGlobalFileChangeProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CGlobalModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return GL_NOTIFICATION_CONTINUE;
+ }
+
+ // GL_PRE_BEGIN_REQUEST
+
+ virtual
+ GLOBAL_NOTIFICATION_STATUS
+ OnGlobalPreBeginRequest(
+ IN IPreBeginRequestProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CGlobalModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return GL_NOTIFICATION_CONTINUE;
+ }
+
+ // GL_APPLICATION_START
+
+ virtual
+ GLOBAL_NOTIFICATION_STATUS
+ OnGlobalApplicationStart(
+ IN IHttpApplicationStartProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CGlobalModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return GL_NOTIFICATION_CONTINUE;
+ }
+
+ // GL_APPLICATION_RESOLVE_MODULES
+
+ virtual
+ GLOBAL_NOTIFICATION_STATUS
+ OnGlobalApplicationResolveModules(
+ IN IHttpApplicationResolveModulesProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CGlobalModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return GL_NOTIFICATION_CONTINUE;
+ }
+
+ // GL_APPLICATION_STOP
+
+ virtual
+ GLOBAL_NOTIFICATION_STATUS
+ OnGlobalApplicationStop(
+ IN IHttpApplicationStopProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CGlobalModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return GL_NOTIFICATION_CONTINUE;
+ }
+
+ // GL_RSCA_QUERY
+
+ virtual
+ GLOBAL_NOTIFICATION_STATUS
+ OnGlobalRSCAQuery(
+ IN IGlobalRSCAQueryProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CGlobalModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return GL_NOTIFICATION_CONTINUE;
+ }
+
+ // GL_TRACE_EVENT
+
+ virtual
+ GLOBAL_NOTIFICATION_STATUS
+ OnGlobalTraceEvent(
+ IN IGlobalTraceEventProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CGlobalModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return GL_NOTIFICATION_CONTINUE;
+ }
+
+ // GL_CUSTOM_NOTIFICATION
+
+ virtual
+ GLOBAL_NOTIFICATION_STATUS
+ OnGlobalCustomNotification(
+ IN ICustomNotificationProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CGlobalModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return GL_NOTIFICATION_CONTINUE;
+ }
+
+ virtual
+ VOID
+ Terminate(
+ VOID
+ ) = 0;
+
+ // GL_THREAD_CLEANUP
+
+ virtual
+ GLOBAL_NOTIFICATION_STATUS
+ OnGlobalThreadCleanup(
+ IN IGlobalThreadCleanupProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CGlobalModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return GL_NOTIFICATION_CONTINUE;
+ }
+
+ // GL_APPLICATION_PRELOAD
+
+ virtual
+ GLOBAL_NOTIFICATION_STATUS
+ OnGlobalApplicationPreload(
+ IN IGlobalApplicationPreloadProvider * pProvider
+ )
+ {
+ UNREFERENCED_PARAMETER( pProvider );
+ OutputDebugStringA(
+ "This module subscribed to event "
+ __FUNCTION__
+ " but did not override the method in its CGlobalModule implementation."
+ " Please check the method signature to make sure it matches the corresponding method.\n");
+ DebugBreak();
+
+ return GL_NOTIFICATION_CONTINUE;
+ }
+
+};
+
+class __declspec(uuid("85c1679c-0b21-491c-afb5-c7b5c86464c4"))
+IModuleAllocator
+{
+ public:
+ virtual
+ VOID *
+ AllocateMemory(
+ IN DWORD cbAllocation
+ ) = 0;
+};
+
+class __declspec(uuid("ba32d330-9ea8-4b9e-89f1-8c76a323277f"))
+IHttpModuleFactory
+{
+ public:
+ virtual
+ HRESULT
+ GetHttpModule(
+ OUT CHttpModule ** ppModule,
+ IN IModuleAllocator * pAllocator
+ ) = 0;
+
+ virtual
+ VOID
+ Terminate(
+ VOID
+ ) = 0;
+};
+
+//
+// Register-module descriptor
+//
+class __declspec(uuid("07e5beb3-b798-459d-a98a-e6c485b2b3bc"))
+IHttpModuleRegistrationInfo
+{
+ public:
+ virtual
+ PCWSTR
+ GetName(
+ VOID
+ ) const = 0;
+
+ virtual
+ HTTP_MODULE_ID
+ GetId(
+ VOID
+ ) const = 0;
+
+ virtual
+ HRESULT
+ SetRequestNotifications(
+ IN IHttpModuleFactory * pModuleFactory,
+ IN DWORD dwRequestNotifications,
+ IN DWORD dwPostRequestNotifications
+ ) = 0;
+
+ virtual
+ HRESULT
+ SetGlobalNotifications(
+ IN CGlobalModule * pGlobalModule,
+ IN DWORD dwGlobalNotifications
+ ) = 0;
+
+ virtual
+ HRESULT
+ SetPriorityForRequestNotification(
+ IN DWORD dwRequestNotification,
+ IN PCWSTR pszPriority
+ ) = 0;
+
+ virtual
+ HRESULT
+ SetPriorityForGlobalNotification(
+ IN DWORD dwGlobalNotification,
+ IN PCWSTR pszPriority
+ ) = 0;
+};
+
+
+//
+// Register Module entry point
+//
+
+typedef
+HRESULT
+(WINAPI * PFN_REGISTERMODULE)(
+ DWORD dwServerVersion,
+ IHttpModuleRegistrationInfo * pModuleInfo,
+ IHttpServer * pGlobalInfo
+);
+
+#define MODULE_REGISTERMODULE "RegisterModule"
+
+#endif
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hybrid_array.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hybrid_array.h
new file mode 100644
index 0000000000..4d0d5735bc
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hybrid_array.h
@@ -0,0 +1,243 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+template
+class HYBRID_ARRAY
+{
+public:
+
+ HYBRID_ARRAY(
+ VOID
+ ) : m_pArray(m_InlineArray),
+ m_Capacity(ARRAYSIZE(m_InlineArray))
+ {
+ }
+
+ ~HYBRID_ARRAY()
+ {
+ if ( !QueryUsesInlineArray() )
+ {
+ delete [] m_pArray;
+ m_pArray = NULL;
+ }
+ }
+
+ SIZE_T
+ QueryCapacity(
+ VOID
+ ) const
+ {
+ //
+ // Number of elements available in the array.
+ //
+ return m_Capacity;
+ }
+
+ TYPE *
+ QueryArray(
+ VOID
+ ) const
+ {
+ //
+ // Raw pointer to the current array.
+ //
+ return m_pArray;
+ }
+
+ TYPE &
+ QueryItem(
+ __in const SIZE_T Index
+ )
+ {
+ //
+ // Gets the array item giving the index.
+ //
+ return m_pArray[Index];
+ }
+
+ TYPE &
+ operator [] (const SIZE_T Index)
+ {
+ //
+ // Operator override for convenience.
+ // Please don't add other overloads like '++' '--'
+ // in order to keep it simple.
+ //
+ return m_pArray[Index];
+ }
+
+ const TYPE &
+ operator [] (const SIZE_T Index) const
+ {
+ return m_pArray[Index];
+ }
+
+ template
+ HRESULT
+ Copy(
+ __in TYPE const (&SourceArray)[SourceSize],
+ __in bool fHasTrivialAssign = false
+ )
+ /*++
+
+ Routine Description:
+
+ Copies a source array like:
+
+ int source[] = { 1, 2, 3 };
+ hr = hybridArray.Copy( source );
+
+ It will statically determinate the length of the source array.
+
+ Arguments:
+
+ SourceArray - The array to copy.
+ SourceSize - The number of array elements.
+ fHasTrivialAssign - True if safe to perform buffer copy.
+
+ Return Value:
+
+ HRESULT
+
+ --*/
+ {
+ return Copy( SourceArray, SourceSize, fHasTrivialAssign );
+ }
+
+ HRESULT
+ Copy(
+ __in_ecount(SourceSize)
+ const TYPE * pSourceArray,
+ __in const SIZE_T SourceSize,
+ __in bool fHasTrivialAssign = false
+ )
+ /*++
+
+ Routine Description:
+
+ Copies a source array.
+
+ Arguments:
+
+ pSourceArray - The array to copy.
+ SourceSize - The number of array elements.
+ fHasTrivialAssign - True if safe to perform buffer copy.
+
+ Return Value:
+
+ HRESULT
+
+ --*/
+ {
+ HRESULT hr;
+
+ hr = EnsureCapacity( SourceSize,
+ FALSE, // fCopyPrevious
+ FALSE ); // fHasTrivialAssign
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+
+ if ( fHasTrivialAssign ) // Future Work: use std::tr1::has_trivial_assign
+ {
+ CopyMemory(m_pArray, pSourceArray, m_Capacity * sizeof(TYPE));
+ }
+ else
+ {
+ for ( SIZE_T Index = 0; Index < SourceSize; ++Index )
+ {
+ m_pArray[Index] = pSourceArray[Index];
+ }
+ }
+
+ return S_OK;
+ }
+
+ HRESULT
+ EnsureCapacity(
+ __in const SIZE_T MinimumCapacity,
+ __in bool fCopyPrevious,
+ __in bool fHasTrivialAssign = false
+ )
+ /*++
+
+ Routine Description:
+
+ Copies a source array.
+
+ Arguments:
+
+ MinimumCapacity - The expected length of the array.
+ fCopyPrevious - Must be always explicit parameter.
+ True if copy previous array data.
+ fHasTrivialAssign - True if safe to perform buffer copy.
+
+ Return Value:
+
+ HRESULT
+
+ --*/
+ {
+ //
+ // Caller is responsible for calculating a length that won't cause
+ // too many reallocations in the future.
+ //
+
+ if ( MinimumCapacity <= ARRAYSIZE(m_InlineArray) )
+ {
+ return S_OK;
+ }
+
+ TYPE * pNewArray;
+
+ pNewArray = new TYPE[ MinimumCapacity ];
+ if ( pNewArray == NULL )
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ if ( fCopyPrevious )
+ {
+ if ( fHasTrivialAssign )
+ {
+ CopyMemory(pNewArray, m_pArray, m_Capacity * sizeof(TYPE));
+ }
+ else
+ {
+ for ( SIZE_T Index = 0; Index < m_Capacity; ++Index )
+ {
+ pNewArray[Index] = m_pArray[Index];
+ }
+ }
+ }
+
+ if ( QueryUsesInlineArray() )
+ {
+ m_pArray = pNewArray;
+ }
+ else
+ {
+ delete [] m_pArray;
+ m_pArray = pNewArray;
+ }
+
+ m_Capacity = MinimumCapacity;
+
+ return S_OK;
+ }
+
+private:
+
+ bool
+ QueryUsesInlineArray(
+ VOID
+ ) const
+ {
+ return m_pArray == m_InlineArray;
+ }
+
+ TYPE m_InlineArray[SIZE];
+ TYPE * m_pArray;
+ SIZE_T m_Capacity;
+};
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/listentry.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/listentry.h
new file mode 100644
index 0000000000..04c1d1ab46
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/listentry.h
@@ -0,0 +1,163 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#pragma once
+
+#ifndef _LIST_ENTRY_H
+#define _LIST_ENTRY_H
+
+//
+// Doubly-linked list manipulation routines.
+//
+
+
+#define InitializeListHead32(ListHead) (\
+ (ListHead)->Flink = (ListHead)->Blink = PtrToUlong((ListHead)))
+
+
+FORCEINLINE
+VOID
+InitializeListHead(
+ IN PLIST_ENTRY ListHead
+ )
+{
+ ListHead->Flink = ListHead->Blink = ListHead;
+}
+
+FORCEINLINE
+BOOLEAN
+IsListEmpty(
+ IN const LIST_ENTRY * ListHead
+ )
+{
+ return (BOOLEAN)(ListHead->Flink == ListHead);
+}
+
+FORCEINLINE
+BOOLEAN
+RemoveEntryList(
+ IN PLIST_ENTRY Entry
+ )
+{
+ PLIST_ENTRY Blink;
+ PLIST_ENTRY Flink;
+
+ Flink = Entry->Flink;
+ Blink = Entry->Blink;
+ Blink->Flink = Flink;
+ Flink->Blink = Blink;
+ return (BOOLEAN)(Flink == Blink);
+}
+
+FORCEINLINE
+PLIST_ENTRY
+RemoveHeadList(
+ IN PLIST_ENTRY ListHead
+ )
+{
+ PLIST_ENTRY Flink;
+ PLIST_ENTRY Entry;
+
+ Entry = ListHead->Flink;
+ Flink = Entry->Flink;
+ ListHead->Flink = Flink;
+ Flink->Blink = ListHead;
+ return Entry;
+}
+
+
+
+FORCEINLINE
+PLIST_ENTRY
+RemoveTailList(
+ IN PLIST_ENTRY ListHead
+ )
+{
+ PLIST_ENTRY Blink;
+ PLIST_ENTRY Entry;
+
+ Entry = ListHead->Blink;
+ Blink = Entry->Blink;
+ ListHead->Blink = Blink;
+ Blink->Flink = ListHead;
+ return Entry;
+}
+
+
+FORCEINLINE
+VOID
+InsertTailList(
+ IN PLIST_ENTRY ListHead,
+ IN PLIST_ENTRY Entry
+ )
+{
+ PLIST_ENTRY Blink;
+
+ Blink = ListHead->Blink;
+ Entry->Flink = ListHead;
+ Entry->Blink = Blink;
+ Blink->Flink = Entry;
+ ListHead->Blink = Entry;
+}
+
+
+FORCEINLINE
+VOID
+InsertHeadList(
+ IN PLIST_ENTRY ListHead,
+ IN PLIST_ENTRY Entry
+ )
+{
+ PLIST_ENTRY Flink;
+
+ Flink = ListHead->Flink;
+ Entry->Flink = Flink;
+ Entry->Blink = ListHead;
+ Flink->Blink = Entry;
+ ListHead->Flink = Entry;
+}
+
+FORCEINLINE
+VOID
+AppendTailList(
+ IN PLIST_ENTRY ListHead,
+ IN PLIST_ENTRY ListToAppend
+ )
+{
+ PLIST_ENTRY ListEnd = ListHead->Blink;
+
+ ListHead->Blink->Flink = ListToAppend;
+ ListHead->Blink = ListToAppend->Blink;
+ ListToAppend->Blink->Flink = ListHead;
+ ListToAppend->Blink = ListEnd;
+}
+
+FORCEINLINE
+PSINGLE_LIST_ENTRY
+PopEntryList(
+ PSINGLE_LIST_ENTRY ListHead
+ )
+{
+ PSINGLE_LIST_ENTRY FirstEntry;
+ FirstEntry = ListHead->Next;
+ if (FirstEntry != NULL) {
+ ListHead->Next = FirstEntry->Next;
+ }
+
+ return FirstEntry;
+}
+
+
+FORCEINLINE
+VOID
+PushEntryList(
+ PSINGLE_LIST_ENTRY ListHead,
+ PSINGLE_LIST_ENTRY Entry
+ )
+{
+ Entry->Next = ListHead->Next;
+ ListHead->Next = Entry;
+}
+
+
+#endif
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/macros.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/macros.h
new file mode 100644
index 0000000000..56a67eb1c4
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/macros.h
@@ -0,0 +1,63 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef _MACROS_H
+#define _MACROS_H
+
+//
+// The DIFF macro should be used around an expression involving pointer
+// subtraction. The expression passed to DIFF is cast to a size_t type,
+// allowing the result to be easily assigned to any 32-bit variable or
+// passed to a function expecting a 32-bit argument.
+//
+
+#define DIFF(x) ((size_t)(x))
+
+// Change a hexadecimal digit to its numerical equivalent
+#define TOHEX( ch ) \
+ ((ch) > L'9' ? \
+ (ch) >= L'a' ? \
+ (ch) - L'a' + 10 : \
+ (ch) - L'A' + 10 \
+ : (ch) - L'0')
+
+
+// Change a number to its Hexadecimal equivalent
+
+#define TODIGIT( nDigit ) \
+ (CHAR)((nDigit) > 9 ? \
+ (nDigit) - 10 + 'A' \
+ : (nDigit) + '0')
+
+
+inline int
+SAFEIsSpace(UCHAR c)
+{
+ return isspace( c );
+}
+
+inline int
+SAFEIsAlNum(UCHAR c)
+{
+ return isalnum( c );
+}
+
+inline int
+SAFEIsAlpha(UCHAR c)
+{
+ return isalpha( c );
+}
+
+inline int
+SAFEIsXDigit(UCHAR c)
+{
+ return isxdigit( c );
+}
+
+inline int
+SAFEIsDigit(UCHAR c)
+{
+ return isdigit( c );
+}
+
+#endif // _MACROS_H
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisz.hxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisz.hxx
new file mode 100644
index 0000000000..dd891b3252
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisz.hxx
@@ -0,0 +1,225 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef _MULTISZ_HXX_
+#define _MULTISZ_HXX_
+
+# include
+
+
+/*++
+ class MULTISZ:
+
+ Intention:
+ A light-weight multi-string class supporting encapsulated string class.
+
+ This object is derived from BUFFER class.
+ It maintains following state:
+
+ m_fValid - whether this object is valid -
+ used only by MULTISZ() init functions
+ * NYI: I need to kill this someday *
+ m_cchLen - string length cached when we update the string.
+ m_cStrings - number of strings.
+
+ Member Functions:
+ There are two categories of functions:
+ 1) Safe Functions - which do integrity checking of state
+ 2) UnSafe Functions - which do not do integrity checking, but
+ enable writing to the data stream freely.
+ (someday this will be enabled as Safe versions without
+ problem for users)
+
+--*/
+class MULTISZ : public BUFFER
+{
+public:
+
+ MULTISZ()
+ : BUFFER (),
+ m_cchLen ( 0),
+ m_cStrings(0)
+ { Reset(); }
+
+ // creates a stack version of the MULTISZ object - uses passed in stack buffer
+ // MULTISZ does not free this pbInit on its own.
+ MULTISZ( __in_bcount(cbInit) WCHAR * pbInit, DWORD cbInit)
+ : BUFFER( (BYTE *) pbInit, cbInit),
+ m_cchLen (0),
+ m_cStrings(0)
+ {}
+
+ MULTISZ( const WCHAR * pchInit )
+ : BUFFER (),
+ m_cchLen ( 0),
+ m_cStrings(0)
+ { AuxInit(pchInit); }
+
+ MULTISZ( const MULTISZ & str )
+ : BUFFER (),
+ m_cchLen ( 0),
+ m_cStrings(0)
+ { AuxInit( str.QueryStr()); }
+
+// BOOL IsValid(VOID) const { return ( BUFFER::IsValid()) ; }
+ //
+ // Checks and returns TRUE if this string has no valid data else FALSE
+ //
+ BOOL IsEmpty( VOID) const { return ( *QueryStr() == L'\0'); }
+
+ BOOL Append( const WCHAR * pchInit ) {
+ return ((pchInit != NULL) ? (AuxAppend( pchInit,
+ (DWORD) (::wcslen(pchInit)) * sizeof(WCHAR)
+ )) :
+ TRUE);
+ }
+
+
+ BOOL Append( const WCHAR * pchInit, DWORD cchLen ) {
+ return ((pchInit != NULL) ? (AuxAppend( pchInit,
+ cchLen * sizeof(WCHAR))) :
+ TRUE);
+ }
+
+ BOOL Append( STRU & str )
+ { return AuxAppend( str.QueryStr(),
+ (str.QueryCCH()) * sizeof(WCHAR)); }
+
+ // Resets the internal string to be NULL string. Buffer remains cached.
+ VOID Reset( VOID)
+ { DBG_ASSERT( QueryPtr() != NULL);
+ QueryStr()[0] = L'\0';
+ QueryStr()[1] = L'\0';
+ m_cchLen = 2;
+ m_cStrings = 0;
+ }
+
+ BOOL Copy( const WCHAR * pchInit, IN DWORD cbLen ) {
+ if ( QueryPtr() ) { Reset(); }
+ return ( (pchInit != NULL) ?
+ AuxAppend( pchInit, cbLen, FALSE ):
+ TRUE);
+ }
+
+ BOOL Copy( const MULTISZ & str )
+ { return ( Copy(str.QueryStr(), str.QueryCB())); }
+
+ //
+ // Returns the number of bytes in the string including the terminating
+ // NULLs
+ //
+ UINT QueryCB( VOID ) const
+ { return ( m_cchLen * sizeof(WCHAR)); }
+
+ //
+ // Returns # of characters in the string including the terminating NULLs
+ //
+ UINT QueryCCH( VOID ) const { return (m_cchLen); }
+
+ //
+ // Returns # of strings in the multisz.
+ //
+
+ DWORD QueryStringCount( VOID ) const { return m_cStrings; }
+
+ //
+ // Makes a copy of the stored string in given buffer
+ //
+ BOOL CopyToBuffer( __out_ecount_opt(*lpcch) WCHAR * lpszBuffer, LPDWORD lpcch) const;
+
+ //
+ // Return the string buffer
+ //
+ WCHAR * QueryStrA( VOID ) const { return ( QueryStr()); }
+ WCHAR * QueryStr( VOID ) const { return ((WCHAR *) QueryPtr()); }
+
+ //
+ // Makes a clone of the current string in the string pointer passed in.
+ //
+ BOOL
+ Clone( OUT MULTISZ * pstrClone) const
+ {
+ return ((pstrClone == NULL) ?
+ (SetLastError(ERROR_INVALID_PARAMETER), FALSE) :
+ (pstrClone->Copy( *this))
+ );
+ } // MULTISZ::Clone()
+
+ //
+ // Recalculates the length of *this because we've modified the buffers
+ // directly
+ //
+
+ VOID RecalcLen( VOID )
+ { m_cchLen = MULTISZ::CalcLength( QueryStr(), &m_cStrings ); }
+
+ //
+ // Calculate total character length of a MULTI_SZ, including the
+ // terminating NULLs.
+ //
+
+ static DWORD CalcLength( const WCHAR * str,
+ LPDWORD pcStrings = NULL );
+
+ //
+ // Determine if the MULTISZ contains a specific string.
+ //
+
+ BOOL FindString( const WCHAR * str );
+
+ BOOL FindString( STRU & str )
+ { return FindString( str.QueryStr() ); }
+
+ //
+ // Determine if the MULTISZ contains a specific string - case-insensitive
+ //
+
+ BOOL FindStringNoCase( const WCHAR * str );
+
+ BOOL FindStringNoCase( STRU & str )
+ { return FindStringNoCase( str.QueryStr() ); }
+
+ //
+ // Used for scanning a multisz.
+ //
+
+ const WCHAR * First( VOID ) const
+ { return *QueryStr() == L'\0' ? NULL : QueryStr(); }
+
+ const WCHAR * Next( const WCHAR * Current ) const
+ { Current += ::wcslen( Current ) + 1;
+ return *Current == L'\0' ? NULL : Current; }
+
+ BOOL
+ Equals(
+ MULTISZ* pmszRhs
+ );
+
+private:
+
+ DWORD m_cchLen;
+ DWORD m_cStrings;
+ VOID AuxInit( const WCHAR * pInit );
+ BOOL AuxAppend( const WCHAR * pInit,
+ UINT cbStr, BOOL fAddSlop = TRUE );
+
+};
+
+//
+// Quick macro for declaring a MULTISZ that will use stack memory of
+// bytes. If the buffer overflows then a heap buffer will be allocated
+//
+
+#define STACK_MULTISZ( name, size ) WCHAR __ach##name[size]; \
+ MULTISZ name( __ach##name, sizeof( __ach##name ))
+
+HRESULT
+SplitCommaDelimitedString(
+ PCWSTR pszList,
+ BOOL fTrimEntries,
+ BOOL fRemoveEmptyEntries,
+ MULTISZ * pmszList
+);
+
+#endif // !_MULTISZ_HXX_
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisza.hxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisza.hxx
new file mode 100644
index 0000000000..44aa802563
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisza.hxx
@@ -0,0 +1,225 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef _MULTISZA_HXX_
+#define _MULTISZA_HXX_
+
+# include
+
+
+/*++
+ class MULTISZ:
+
+ Intention:
+ A light-weight multi-string class supporting encapsulated string class.
+
+ This object is derived from BUFFER class.
+ It maintains following state:
+
+ m_fValid - whether this object is valid -
+ used only by MULTISZ() init functions
+ * NYI: I need to kill this someday *
+ m_cchLen - string length cached when we update the string.
+ m_cStrings - number of strings.
+
+ Member Functions:
+ There are two categories of functions:
+ 1) Safe Functions - which do integrity checking of state
+ 2) UnSafe Functions - which do not do integrity checking, but
+ enable writing to the data stream freely.
+ (someday this will be enabled as Safe versions without
+ problem for users)
+
+--*/
+class MULTISZA : public BUFFER
+{
+public:
+
+ MULTISZA()
+ : BUFFER (),
+ m_cchLen ( 0),
+ m_cStrings(0)
+ { Reset(); }
+
+ // creates a stack version of the MULTISZA object - uses passed in stack buffer
+ // MULTISZA does not free this pbInit on its own.
+ MULTISZA( __in_bcount(cbInit) CHAR * pbInit, DWORD cbInit)
+ : BUFFER( (BYTE *) pbInit, cbInit),
+ m_cchLen (0),
+ m_cStrings(0)
+ {}
+
+ MULTISZA( const CHAR * pchInit )
+ : BUFFER (),
+ m_cchLen ( 0),
+ m_cStrings(0)
+ { AuxInit(pchInit); }
+
+ MULTISZA( const MULTISZA & str )
+ : BUFFER (),
+ m_cchLen ( 0),
+ m_cStrings(0)
+ { AuxInit( str.QueryStr()); }
+
+// BOOL IsValid(VOID) const { return ( BUFFER::IsValid()) ; }
+ //
+ // Checks and returns TRUE if this string has no valid data else FALSE
+ //
+ BOOL IsEmpty( VOID) const { return ( *QueryStr() == L'\0'); }
+
+ BOOL Append( const CHAR * pchInit ) {
+ return ((pchInit != NULL) ? (AuxAppend( pchInit,
+ (DWORD) (::strlen(pchInit)) * sizeof(CHAR)
+ )) :
+ TRUE);
+ }
+
+
+ BOOL Append( const CHAR * pchInit, DWORD cchLen ) {
+ return ((pchInit != NULL) ? (AuxAppend( pchInit,
+ cchLen * sizeof(CHAR))) :
+ TRUE);
+ }
+
+ BOOL Append( STRA & str )
+ { return AuxAppend( str.QueryStr(),
+ (str.QueryCCH()) * sizeof(CHAR)); }
+
+ // Resets the internal string to be NULL string. Buffer remains cached.
+ VOID Reset( VOID)
+ { DBG_ASSERT( QueryPtr() != NULL);
+ QueryStr()[0] = L'\0';
+ QueryStr()[1] = L'\0';
+ m_cchLen = 2;
+ m_cStrings = 0;
+ }
+
+ BOOL Copy( const CHAR * pchInit, IN DWORD cbLen ) {
+ if ( QueryPtr() ) { Reset(); }
+ return ( (pchInit != NULL) ?
+ AuxAppend( pchInit, cbLen, FALSE ):
+ TRUE);
+ }
+
+ BOOL Copy( const MULTISZA & str )
+ { return ( Copy(str.QueryStr(), str.QueryCB())); }
+
+ //
+ // Returns the number of bytes in the string including the terminating
+ // NULLs
+ //
+ UINT QueryCB( VOID ) const
+ { return ( m_cchLen * sizeof(CHAR)); }
+
+ //
+ // Returns # of characters in the string including the terminating NULLs
+ //
+ UINT QueryCCH( VOID ) const { return (m_cchLen); }
+
+ //
+ // Returns # of strings in the MULTISZA.
+ //
+
+ DWORD QueryStringCount( VOID ) const { return m_cStrings; }
+
+ //
+ // Makes a copy of the stored string in given buffer
+ //
+ BOOL CopyToBuffer( __out_ecount_opt(*lpcch) CHAR * lpszBuffer, LPDWORD lpcch) const;
+
+ //
+ // Return the string buffer
+ //
+ CHAR * QueryStrA( VOID ) const { return ( QueryStr()); }
+ CHAR * QueryStr( VOID ) const { return ((CHAR *) QueryPtr()); }
+
+ //
+ // Makes a clone of the current string in the string pointer passed in.
+ //
+ BOOL
+ Clone( OUT MULTISZA * pstrClone) const
+ {
+ return ((pstrClone == NULL) ?
+ (SetLastError(ERROR_INVALID_PARAMETER), FALSE) :
+ (pstrClone->Copy( *this))
+ );
+ } // MULTISZA::Clone()
+
+ //
+ // Recalculates the length of *this because we've modified the buffers
+ // directly
+ //
+
+ VOID RecalcLen( VOID )
+ { m_cchLen = MULTISZA::CalcLength( QueryStr(), &m_cStrings ); }
+
+ //
+ // Calculate total character length of a MULTI_SZ, including the
+ // terminating NULLs.
+ //
+
+ static DWORD CalcLength( const CHAR * str,
+ LPDWORD pcStrings = NULL );
+
+ //
+ // Determine if the MULTISZA contains a specific string.
+ //
+
+ BOOL FindString( const CHAR * str );
+
+ BOOL FindString( STRA & str )
+ { return FindString( str.QueryStr() ); }
+
+ //
+ // Determine if the MULTISZA contains a specific string - case-insensitive
+ //
+
+ BOOL FindStringNoCase( const CHAR * str );
+
+ BOOL FindStringNoCase( STRA & str )
+ { return FindStringNoCase( str.QueryStr() ); }
+
+ //
+ // Used for scanning a MULTISZA.
+ //
+
+ const CHAR * First( VOID ) const
+ { return *QueryStr() == L'\0' ? NULL : QueryStr(); }
+
+ const CHAR * Next( const CHAR * Current ) const
+ { Current += ::strlen( Current ) + 1;
+ return *Current == L'\0' ? NULL : Current; }
+
+ BOOL
+ Equals(
+ MULTISZA* pmszRhs
+ );
+
+private:
+
+ DWORD m_cchLen;
+ DWORD m_cStrings;
+ VOID AuxInit( const CHAR * pInit );
+ BOOL AuxAppend( const CHAR * pInit,
+ UINT cbStr, BOOL fAddSlop = TRUE );
+
+};
+
+//
+// Quick macro for declaring a MULTISZA that will use stack memory of
+// bytes. If the buffer overflows then a heap buffer will be allocated
+//
+
+#define STACK_MULTISZA( name, size ) CHAR __ach##name[size]; \
+ MULTISZA name( __ach##name, sizeof( __ach##name ))
+
+HRESULT
+SplitCommaDelimitedString(
+ PCSTR pszList,
+ BOOL fTrimEntries,
+ BOOL fRemoveEmptyEntries,
+ MULTISZA * pmszList
+);
+
+#endif // !_MULTISZA_HXX_
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/normalize.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/normalize.h
new file mode 100644
index 0000000000..411c3660a4
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/normalize.h
@@ -0,0 +1,40 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef __NORMALIZE_URL__H__
+#define __NORMALIZE_URL__H__
+
+HRESULT
+NormalizeUrl(
+ __inout LPSTR pszUrl
+);
+
+
+HRESULT
+NormalizeUrlW(
+ __inout LPWSTR pszUrl
+);
+
+
+
+HRESULT
+UlCleanAndCopyUrl(
+ __in LPSTR pSource,
+ IN ULONG SourceLength,
+ OUT PULONG pBytesCopied,
+ __inout PWSTR pDestination,
+ __deref_opt_out_opt PWSTR * ppQueryString OPTIONAL
+);
+
+HRESULT
+UlInitializeParsing(
+ VOID
+);
+
+HRESULT
+InitializeNormalizeUrl(
+ VOID
+);
+
+
+#endif
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ntassert.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ntassert.h
new file mode 100644
index 0000000000..8a8d656f21
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ntassert.h
@@ -0,0 +1,32 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#pragma once
+
+#ifdef _ASSERTE
+ #undef _ASSERTE
+#endif
+
+#ifdef ASSERT
+ #undef ASSERT
+#endif
+
+#if defined( DBG ) && DBG
+ #define SX_ASSERT( _x ) ( (VOID)( ( ( _x ) ) ? TRUE : ( __annotation( L"Debug", L"AssertFail", L#_x ), DbgRaiseAssertionFailure(), FALSE ) ) )
+ #define SX_ASSERTMSG( _m, _x ) ( (VOID)( ( ( _x ) ) ? TRUE : ( __annotation( L"Debug", L"AssertFail", L##_m ), DbgRaiseAssertionFailure(), FALSE ) ) )
+ #define SX_VERIFY( _x ) SX_ASSERT( _x )
+ #define _ASSERTE( _x ) SX_ASSERT( _x )
+ #define ASSERT( _x ) SX_ASSERT( _x )
+ #define assert( _x ) SX_ASSERT( _x )
+ #define DBG_ASSERT( _x ) SX_ASSERT( _x )
+ #define DBG_REQUIRE( _x ) SX_ASSERT( _x )
+#else
+ #define SX_ASSERT( _x ) ( (VOID)0 )
+ #define SX_ASSERTMSG( _m, _x ) ( (VOID)0 )
+ #define SX_VERIFY( _x ) ( (VOID)( ( _x ) ? TRUE : FALSE ) )
+ #define _ASSERTE( _x ) ( (VOID)0 )
+ #define assert( _x ) ( (VOID)0 )
+ #define DBG_ASSERT( _x ) ( (VOID)0 )
+ #define DBG_REQUIRE( _x ) ((VOID)(_x))
+#endif
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/percpu.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/percpu.h
new file mode 100644
index 0000000000..ae59b1c805
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/percpu.h
@@ -0,0 +1,305 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#pragma once
+
+template
+class PER_CPU
+{
+public:
+
+ template
+ inline
+ static
+ HRESULT
+ Create(
+ FunctionInitializer Initializer,
+ __deref_out PER_CPU ** ppInstance
+ );
+
+ inline
+ T *
+ GetLocal(
+ VOID
+ );
+
+ template
+ inline
+ VOID
+ ForEach(
+ FunctionForEach Function
+ );
+
+ inline
+ VOID
+ Dispose(
+ VOID
+ );
+
+private:
+
+ PER_CPU(
+ VOID
+ )
+ {
+ //
+ // Don't perform any operation during constructor.
+ // Constructor will never be called.
+ //
+ }
+
+ ~PER_CPU(
+ VOID
+ )
+ {
+ //
+ // Don't perform any operation during destructor.
+ // Constructor will never be called.
+ //
+ }
+
+ template
+ HRESULT
+ Initialize(
+ FunctionInitializer Initializer,
+ DWORD NumberOfVariables,
+ DWORD Alignment
+ );
+
+ T *
+ GetObject(
+ DWORD Index
+ );
+
+ static
+ HRESULT
+ GetProcessorInformation(
+ __out DWORD * pCacheLineSize,
+ __out DWORD * pNumberOfProcessors
+ );
+
+ //
+ // Pointer to the begining of the inlined array.
+ //
+ PVOID m_pVariables;
+ SIZE_T m_Alignment;
+ SIZE_T m_VariablesCount;
+};
+
+template
+template
+inline
+// static
+HRESULT
+PER_CPU::Create(
+ FunctionInitializer Initializer,
+ __deref_out PER_CPU ** ppInstance
+)
+{
+ HRESULT hr = S_OK;
+ DWORD CacheLineSize = 0;
+ DWORD ObjectCacheLineSize = 0;
+ DWORD NumberOfProcessors = 0;
+ PER_CPU * pInstance = NULL;
+
+ hr = GetProcessorInformation(&CacheLineSize,
+ &NumberOfProcessors);
+ if (FAILED(hr))
+ {
+ goto Finished;
+ }
+
+ if (sizeof(T) > CacheLineSize)
+ {
+ //
+ // Round to the next multiple of the cache line size.
+ //
+ ObjectCacheLineSize = (sizeof(T) + CacheLineSize-1) & (CacheLineSize-1);
+ }
+ else
+ {
+ ObjectCacheLineSize = CacheLineSize;
+ }
+
+ //
+ // Calculate the size of the PER_CPU object, including the array.
+ // The first cache line is for the member variables and the array
+ // starts in the next cache line.
+ //
+ SIZE_T Size = CacheLineSize + NumberOfProcessors * ObjectCacheLineSize;
+
+ pInstance = (PER_CPU*) _aligned_malloc(Size, CacheLineSize);
+ if (pInstance == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Finished;
+ }
+ ZeroMemory(pInstance, Size);
+
+ //
+ // The array start in the 2nd cache line.
+ //
+ pInstance->m_pVariables = reinterpret_cast(pInstance) + CacheLineSize;
+
+ //
+ // Pass a disposer for disposing initialized items in case of failure.
+ //
+ hr = pInstance->Initialize(Initializer,
+ NumberOfProcessors,
+ ObjectCacheLineSize);
+ if (FAILED(hr))
+ {
+ goto Finished;
+ }
+
+ *ppInstance = pInstance;
+ pInstance = NULL;
+
+Finished:
+
+ if (pInstance != NULL)
+ {
+ //
+ // Free the instance without disposing it.
+ //
+ pInstance->Dispose();
+ pInstance = NULL;
+ }
+
+ return hr;
+}
+
+template
+inline
+T *
+PER_CPU::GetLocal(
+ VOID
+)
+{
+ // Use GetCurrentProcessorNumber (up to 64 logical processors) instead of
+ // GetCurrentProcessorNumberEx (more than 64 logical processors) because
+ // the number of processors are not densely packed per group.
+ // The idea of distributing variables per CPU is to have
+ // a scalability multiplier (could be NUMA node instead).
+ //
+ // Make sure the index don't go beyond the array size, if that happens,
+ // there won't be even distribution, but still better
+ // than one single variable.
+ //
+ return GetObject(GetCurrentProcessorNumber());
+}
+
+template
+inline
+T *
+PER_CPU::GetObject(
+ DWORD Index
+)
+{
+ return reinterpret_cast(static_cast(m_pVariables) + Index * m_Alignment);
+}
+
+template
+template
+inline
+VOID
+PER_CPU::ForEach(
+ FunctionForEach Function
+)
+{
+ for(DWORD Index = 0; Index < m_VariablesCount; ++Index)
+ {
+ T * pObject = GetObject(Index);
+ Function(pObject);
+ }
+}
+
+template
+VOID
+PER_CPU::Dispose(
+ VOID
+)
+{
+ _aligned_free(this);
+}
+
+template
+template
+inline
+HRESULT
+PER_CPU::Initialize(
+ FunctionInitializer Initializer,
+ DWORD NumberOfVariables,
+ DWORD Alignment
+)
+/*++
+
+Routine Description:
+
+ Initialize each object using the initializer function.
+ If initialization for any object fails, it dispose the
+ objects that were successfully initialized.
+
+Arguments:
+
+ Initializer - Function for initialize one object.
+ Signature: HRESULT Func(T*)
+ Dispose - Function for disposing initialized objects in case of failure.
+ Signature: void Func(T*)
+ NumberOfVariables - The length of the array of variables.
+ Alignment - Alignment to use for avoiding false sharing.
+
+Return:
+
+ HRESULT - E_OUTOFMEMORY
+
+--*/
+{
+ HRESULT hr = S_OK;
+ DWORD Index = 0;
+
+ m_VariablesCount = NumberOfVariables;
+ m_Alignment = Alignment;
+
+ for (; Index < m_VariablesCount; ++Index)
+ {
+ T * pObject = GetObject(Index);
+ Initializer(pObject);
+ }
+
+ return hr;
+}
+
+template
+// static
+HRESULT
+PER_CPU::GetProcessorInformation(
+ __out DWORD * pCacheLineSize,
+ __out DWORD * pNumberOfProcessors
+)
+/*++
+
+Routine Description:
+
+ Gets the CPU cache-line size for the current system.
+ This information is used for avoiding CPU false sharing.
+
+Arguments:
+
+ pCacheLineSize - The processor cache-line size.
+ pNumberOfProcessors - Maximum number of processors per group.
+
+Return:
+
+ HRESULT - E_OUTOFMEMORY
+
+--*/
+{
+ SYSTEM_INFO SystemInfo = { };
+
+ GetSystemInfo(&SystemInfo);
+ *pNumberOfProcessors = SystemInfo.dwNumberOfProcessors;
+ *pCacheLineSize = SYSTEM_CACHE_ALIGNMENT_SIZE;
+
+ return S_OK;
+}
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/prime.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/prime.h
new file mode 100644
index 0000000000..77fcb75b8a
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/prime.h
@@ -0,0 +1,85 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#pragma once
+
+#include
+#include
+
+//
+// Pre-calculated prime numbers (up to 10,049,369).
+//
+extern __declspec(selectany) const DWORD g_Primes [] = {
+ 3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631,
+ 761, 919, 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103,
+ 12143, 14591, 17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631,
+ 130363, 156437, 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403,
+ 968897, 1162687, 1395263, 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559,
+ 5999471, 7199369, 7849369, 8649369, 9249369, 10049369
+};
+
+class PRIME
+{
+public:
+
+ static
+ DWORD
+ GetPrime(
+ DWORD dwMinimum
+ )
+ {
+ //
+ // Try to use the precalculated numbers.
+ //
+ for ( DWORD Index = 0; Index < _countof( g_Primes ); Index++ )
+ {
+ DWORD dwCandidate = g_Primes[Index];
+ if ( dwCandidate >= dwMinimum )
+ {
+ return dwCandidate;
+ }
+ }
+
+ //
+ // Do calculation.
+ //
+ for ( DWORD dwCandidate = dwMinimum | 1;
+ dwCandidate < MAXDWORD;
+ dwCandidate += 2 )
+ {
+ if ( IsPrime( dwCandidate ) )
+ {
+ return dwCandidate;
+ }
+ }
+ return dwMinimum;
+ }
+
+private:
+
+ static
+ BOOL
+ IsPrime(
+ DWORD dwCandidate
+ )
+ {
+ if ((dwCandidate & 1) == 0)
+ {
+ return ( dwCandidate == 2 );
+ }
+
+ DWORD dwMax = static_cast(sqrt(static_cast(dwCandidate)));
+
+ for ( DWORD Index = 3; Index <= dwMax; Index += 2 )
+ {
+ if ( (dwCandidate % Index) == 0 )
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+ }
+
+ PRIME() {}
+ ~PRIME() {}
+};
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/reftrace.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/reftrace.h
new file mode 100644
index 0000000000..ace85dcde2
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/reftrace.h
@@ -0,0 +1,88 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef _REFTRACE_H_
+#define _REFTRACE_H_
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif // __cplusplus
+
+
+#include
+
+
+//
+// This is the number of stack backtrace values captured in each
+// trace log entry. This value is chosen to make the log entry
+// exactly twelve dwords long, making it a bit easier to interpret
+// from within the debugger without the debugger extension.
+//
+
+#define REF_TRACE_LOG_STACK_DEPTH 9
+
+// No-op value for the Context1,2,3 parameters of WriteRefTraceLogEx
+//#define REF_TRACE_EMPTY_CONTEXT ((PVOID) -1)
+#define REF_TRACE_EMPTY_CONTEXT NULL
+
+
+//
+// This defines the entry written to the trace log.
+//
+
+typedef struct _REF_TRACE_LOG_ENTRY {
+
+ LONG NewRefCount;
+ CONST VOID * Context;
+ CONST VOID * Context1;
+ CONST VOID * Context2;
+ CONST VOID * Context3;
+ DWORD Thread;
+ PVOID Stack[REF_TRACE_LOG_STACK_DEPTH];
+
+} REF_TRACE_LOG_ENTRY, *PREF_TRACE_LOG_ENTRY;
+
+
+//
+// Manipulators.
+//
+
+PTRACE_LOG
+CreateRefTraceLog(
+ IN LONG LogSize,
+ IN LONG ExtraBytesInHeader
+ );
+
+VOID
+DestroyRefTraceLog(
+ IN PTRACE_LOG Log
+ );
+
+LONG
+__cdecl
+WriteRefTraceLog(
+ IN PTRACE_LOG Log,
+ IN LONG NewRefCount,
+ IN CONST VOID * Context
+ );
+
+LONG
+__cdecl
+WriteRefTraceLogEx(
+ IN PTRACE_LOG Log,
+ IN LONG NewRefCount,
+ IN CONST VOID * Context,
+ IN CONST VOID * Context1,
+ IN CONST VOID * Context2,
+ IN CONST VOID * Context3
+ );
+
+
+#if defined(__cplusplus)
+} // extern "C"
+#endif // __cplusplus
+
+
+#endif // _REFTRACE_H_
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/rwlock.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/rwlock.h
new file mode 100644
index 0000000000..50b9b1ca11
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/rwlock.h
@@ -0,0 +1,193 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#pragma once
+
+#if (_WIN32_WINNT < 0x600)
+
+//
+// XP implementation.
+//
+class CWSDRWLock
+{
+public:
+
+ CWSDRWLock()
+ : m_bInited(FALSE)
+ {
+ }
+
+ ~CWSDRWLock()
+ {
+ if (m_bInited)
+ {
+ DeleteCriticalSection(&m_rwLock.critsec);
+ CloseHandle(m_rwLock.ReadersDoneEvent);
+ }
+ }
+
+ BOOL QueryInited() const
+ {
+ return m_bInited;
+ }
+
+ HRESULT Init()
+ {
+ HRESULT hr = S_OK;
+
+ if (FALSE == m_bInited)
+ {
+ m_rwLock.fWriterWaiting = FALSE;
+ m_rwLock.LockCount = 0;
+ if ( !InitializeCriticalSectionAndSpinCount( &m_rwLock.critsec, 0 ))
+ {
+ DWORD dwError = GetLastError();
+ hr = HRESULT_FROM_WIN32(dwError);
+ return hr;
+ }
+
+ m_rwLock.ReadersDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if( NULL == m_rwLock.ReadersDoneEvent )
+ {
+ DWORD dwError = GetLastError();
+ hr = HRESULT_FROM_WIN32(dwError);
+ DeleteCriticalSection(&m_rwLock.critsec);
+ return hr;
+ }
+ m_bInited = TRUE;
+ }
+
+ return hr;
+ }
+
+ void SharedAcquire()
+ {
+ EnterCriticalSection(&m_rwLock.critsec);
+ InterlockedIncrement(&m_rwLock.LockCount);
+ LeaveCriticalSection(&m_rwLock.critsec);
+ }
+
+ void SharedRelease()
+ {
+ ReleaseRWLock();
+ }
+
+ void ExclusiveAcquire()
+ {
+ EnterCriticalSection( &m_rwLock.critsec );
+
+ m_rwLock.fWriterWaiting = TRUE;
+
+ // check if there are any readers active
+ if ( InterlockedExchangeAdd( &m_rwLock.LockCount, 0 ) > 0 )
+ {
+ //
+ // Wait for all the readers to get done..
+ //
+ WaitForSingleObject( m_rwLock.ReadersDoneEvent, INFINITE );
+ }
+ m_rwLock.LockCount = -1;
+ }
+
+ void ExclusiveRelease()
+ {
+ ReleaseRWLock();
+ }
+
+private:
+
+ BOOL m_bInited;
+
+ typedef struct _RW_LOCK
+ {
+ BOOL fWriterWaiting; // Is a writer waiting on the lock?
+ LONG LockCount;
+ CRITICAL_SECTION critsec;
+ HANDLE ReadersDoneEvent;
+ } RW_LOCK, *PRW_LOCK;
+
+ RW_LOCK m_rwLock;
+
+private:
+
+ void ReleaseRWLock()
+ {
+ LONG Count = InterlockedDecrement( &m_rwLock.LockCount );
+
+ if ( 0 <= Count )
+ {
+ // releasing a read lock
+ if (( m_rwLock.fWriterWaiting ) && ( 0 == Count ))
+ {
+ SetEvent( m_rwLock.ReadersDoneEvent );
+ }
+ }
+ else
+ {
+ // Releasing a write lock
+ m_rwLock.LockCount = 0;
+ m_rwLock.fWriterWaiting = FALSE;
+ LeaveCriticalSection(&m_rwLock.critsec);
+ }
+ }
+};
+
+#else
+
+//
+// Implementation for Windows Vista or greater.
+//
+class CWSDRWLock
+{
+public:
+
+ CWSDRWLock()
+ {
+ InitializeSRWLock(&m_rwLock);
+ }
+
+ BOOL QueryInited()
+ {
+ return TRUE;
+ }
+
+
+ HRESULT Init()
+ {
+ //
+ // Method defined to keep compatibility with CWSDRWLock class for XP.
+ //
+ return S_OK;
+ }
+
+ void SharedAcquire()
+ {
+ AcquireSRWLockShared(&m_rwLock);
+ }
+
+ void SharedRelease()
+ {
+ ReleaseSRWLockShared(&m_rwLock);
+ }
+
+ void ExclusiveAcquire()
+ {
+ AcquireSRWLockExclusive(&m_rwLock);
+ }
+
+ void ExclusiveRelease()
+ {
+ ReleaseSRWLockExclusive(&m_rwLock);
+ }
+
+private:
+
+ SRWLOCK m_rwLock;
+};
+
+#endif
+
+//
+// Rename the lock class to a more clear name.
+//
+typedef CWSDRWLock READ_WRITE_LOCK;
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/statichash.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/statichash.h
new file mode 100644
index 0000000000..f2c7980405
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/statichash.h
@@ -0,0 +1,730 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef __STATIC_HASH__H_
+#define __STATIC_HASH__H_
+
+#define STATIC_STRING_HASH_BUCKETS 131
+
+//
+// SERVER_VARIABLE_HASH maps server variable string to routines to eval them
+//
+
+struct STATIC_STRING_HASH_RECORD
+{
+ CHAR * _pszName;
+ STATIC_STRING_HASH_RECORD * _pNext;
+ USHORT _cchName;
+};
+
+struct STATIC_STRING_HASH_ITER
+{
+ STATIC_STRING_HASH_RECORD *_pCursor;
+ DWORD _dwBucket;
+ BOOL _fRemove;
+};
+
+class STATIC_STRING_HASH
+{
+ public:
+
+ STATIC_STRING_HASH(
+ BOOL fCaseSensitive = FALSE
+ ) : _fCaseSensitive( fCaseSensitive )
+ {
+ Reset();
+ }
+
+ VOID
+ Reset()
+ {
+ ZeroMemory( &_rgBuckets, sizeof( _rgBuckets ) );
+ }
+
+ static
+ PCSTR
+ ExtractKey(
+ __in const STATIC_STRING_HASH_RECORD * pRecord
+ )
+ /*++
+
+ Routine Description:
+
+ Get the key out of the record
+
+ Arguments:
+
+ record to fetch the key from
+
+ Return Value:
+
+ key
+
+ --*/
+ {
+ DBG_ASSERT( pRecord != NULL );
+ return pRecord->_pszName;
+ }
+
+ VOID
+ InsertRecord(
+ __in STATIC_STRING_HASH_RECORD * pRecord
+ )
+ /*++
+
+ Routine Description:
+
+ Insert record to hash table
+
+ Note: remember this is static hash table
+ There is no synchronization on the table
+ Exclusive acess must be assured by caller
+
+ Arguments:
+
+ record to fetch the key from
+
+ Return Value:
+
+ VOID
+
+ --*/
+ {
+ DWORD dwIndex;
+ STATIC_STRING_HASH_RECORD* pCursor;
+
+ DBG_ASSERT( pRecord != NULL );
+ DBG_ASSERT( pRecord->_pszName != NULL );
+
+ if(NULL == pRecord->_pszName)
+ {
+ return;
+ }
+
+ if (_fCaseSensitive)
+ {
+ dwIndex = HashString( pRecord->_pszName ) % STATIC_STRING_HASH_BUCKETS;
+ }
+ else
+ {
+ dwIndex = HashStringNoCase( pRecord->_pszName ) % STATIC_STRING_HASH_BUCKETS;
+ }
+
+ pCursor = _rgBuckets[ dwIndex ];
+
+ pRecord->_pNext = pCursor;
+ _rgBuckets[ dwIndex ] = pRecord;
+ }
+
+ STATIC_STRING_HASH_RECORD *
+ FindKey(
+ __in PCSTR pszName,
+ BOOL fRemove = FALSE
+ )
+ /*++
+
+ Routine Description:
+
+ Find key in the table (and remove it optionally)
+
+ Arguments:
+
+ key
+
+ Return Value:
+
+ record containing the key
+
+ --*/
+ {
+ DWORD dwIndex;
+ STATIC_STRING_HASH_RECORD* pRecord;
+ STATIC_STRING_HASH_RECORD* pLastRecord = NULL;
+
+ DBG_ASSERT( pszName != NULL );
+
+ if (_fCaseSensitive)
+ {
+ dwIndex = HashString( pszName ) % STATIC_STRING_HASH_BUCKETS;
+ }
+ else
+ {
+ dwIndex = HashStringNoCase( pszName ) % STATIC_STRING_HASH_BUCKETS;
+ }
+
+ pRecord = _rgBuckets[ dwIndex ];
+ while ( pRecord != NULL )
+ {
+ if (_fCaseSensitive)
+ {
+ if ( strcmp( pszName, pRecord->_pszName ) == 0 )
+ {
+ break;
+ }
+ }
+ else if ( _stricmp( pszName, pRecord->_pszName ) == 0 )
+ {
+ break;
+ }
+
+ pLastRecord = pRecord;
+ pRecord = pRecord->_pNext;
+ }
+
+ if (fRemove &&
+ pRecord != NULL)
+ {
+ if (pLastRecord != NULL)
+ {
+ pLastRecord->_pNext = pRecord->_pNext;
+ }
+ else
+ {
+ _rgBuckets[dwIndex] = pRecord->_pNext;
+ }
+ }
+
+ return pRecord;
+ }
+
+ BOOL
+ CheckDistribution(
+ IN DWORD dwConflictThreshold,
+ IN BOOL fToDebugger
+ )
+ /*++
+
+ Routine Description:
+
+ Simple verification on conflicts within the table
+
+ Arguments:
+
+ dwConflictThreshold - max number of entries tolerated per bucket
+ fToDebbuger - spew the entries exceeding threshold into debugger
+
+ Return Value:
+
+ FALSE it threshold was reached (means hash funcion may not be optimal)
+
+ --*/
+ {
+ BOOL fThresholdReached = FALSE;
+ STATIC_STRING_HASH_RECORD* pRecord;
+ for ( DWORD dwIndex = 0; dwIndex < STATIC_STRING_HASH_BUCKETS; dwIndex++)
+ {
+ pRecord = _rgBuckets[ dwIndex ];
+ DWORD countInBucket = 0;
+ while ( pRecord != NULL )
+ {
+ countInBucket++;
+ pRecord = pRecord->_pNext;
+ }
+ //
+ // print out the list of multiple entries in bucket
+ //
+ if ( countInBucket > dwConflictThreshold && fToDebugger )
+ {
+ fThresholdReached = TRUE;
+
+ pRecord = _rgBuckets[ dwIndex ];
+ while ( pRecord != NULL )
+ {
+ pRecord = pRecord->_pNext;
+ }
+ }
+ }
+ return fThresholdReached;
+ }
+
+ STATIC_STRING_HASH_RECORD *
+ FindFirst(
+ STATIC_STRING_HASH_ITER *pIterator,
+ BOOL fRemove = FALSE
+ )
+ /*++
+
+ Routine Description:
+
+ Begins a new hash item enumeration.
+
+ Arguments:
+
+ pIterator - Supplies the context for the enumeration.
+
+ fRemove - Supplies TRUE if the items should be removed
+ from the hash as they are enumerated.
+
+ Return Value:
+
+ The first entry in the hash if successful, NULL otherwise.
+
+ --*/
+ {
+ pIterator->_dwBucket = 0;
+ pIterator->_fRemove = fRemove;
+ pIterator->_pCursor = FindNextBucket(&pIterator->_dwBucket);
+
+ if (pIterator->_fRemove && pIterator->_pCursor != NULL)
+ {
+ _rgBuckets[pIterator->_dwBucket] = pIterator->_pCursor->_pNext;
+ }
+
+ return pIterator->_pCursor;
+ }
+
+ STATIC_STRING_HASH_RECORD *
+ FindNext(
+ STATIC_STRING_HASH_ITER *pIterator
+ )
+ /*++
+
+ Routine Description:
+
+ Continues a hash item enumeration.
+
+ Arguments:
+
+ pIterator - Supplies the context for the enumeration.
+
+ Return Value:
+
+ The next entry in the hash if successful, NULL otherwise.
+
+ --*/
+ {
+ if (pIterator->_pCursor != NULL)
+ {
+ if (pIterator->_fRemove)
+ {
+ pIterator->_pCursor = _rgBuckets[pIterator->_dwBucket];
+ }
+ else
+ {
+ pIterator->_pCursor = pIterator->_pCursor->_pNext;
+ }
+
+ if (pIterator->_pCursor == NULL)
+ {
+ pIterator->_dwBucket++;
+ pIterator->_pCursor = FindNextBucket(&pIterator->_dwBucket);
+ }
+ }
+
+ if (pIterator->_fRemove && pIterator->_pCursor != NULL)
+ {
+ _rgBuckets[pIterator->_dwBucket] = pIterator->_pCursor->_pNext;
+ }
+
+ return pIterator->_pCursor;
+ }
+
+ protected:
+
+ STATIC_STRING_HASH_RECORD * _rgBuckets[ STATIC_STRING_HASH_BUCKETS ];
+
+ private:
+
+ BOOL _fCaseSensitive;
+
+ STATIC_STRING_HASH_RECORD *
+ FindNextBucket(
+ DWORD *pdwStartingBucket
+ )
+ /*++
+
+ Routine Description:
+
+ Scan for the next non-empty bucket.
+
+ Arguments:
+
+ pdwStartingBucket - Supplies a pointer to the starting
+ bucket index. This value is updated with the index
+ of the next non-empty bucket if successful.
+
+ Return Value:
+
+ The first entry in the next non-empty bucket if successful,
+ NULL otherwise.
+
+ --*/
+ {
+ DWORD i;
+ STATIC_STRING_HASH_RECORD *pScan = NULL;
+
+ for (i = *pdwStartingBucket ; i < STATIC_STRING_HASH_BUCKETS ; i++)
+ {
+ pScan = _rgBuckets[i];
+
+ if (pScan != NULL)
+ {
+ break;
+ }
+ }
+
+ *pdwStartingBucket = i;
+ return pScan;
+ }
+};
+
+
+
+
+struct STATIC_WSTRING_HASH_RECORD
+{
+ WCHAR * _pszName;
+ STATIC_WSTRING_HASH_RECORD * _pNext;
+ USHORT _cchName;
+};
+
+
+struct STATIC_WSTRING_HASH_ITER
+{
+ STATIC_WSTRING_HASH_RECORD *_pCursor;
+ DWORD _dwBucket;
+ BOOL _fRemove;
+};
+
+
+class STATIC_WSTRING_HASH
+{
+ public:
+ STATIC_WSTRING_HASH(
+ BOOL fCaseSensitive = FALSE
+ ) : _fCaseSensitive( fCaseSensitive )
+ {
+ Reset();
+ }
+
+ VOID
+ Reset()
+ {
+ ZeroMemory( &_rgBuckets, sizeof( _rgBuckets ) );
+ }
+
+ static
+ PCWSTR
+ ExtractKey(
+ __in const STATIC_WSTRING_HASH_RECORD * pRecord
+ )
+ /*++
+
+ Routine Description:
+
+ Get the key out of the record
+
+ Arguments:
+
+ record to fetch the key from
+
+ Return Value:
+
+ key
+
+ --*/
+ {
+ DBG_ASSERT( pRecord != NULL );
+ return pRecord->_pszName;
+ }
+
+ VOID
+ InsertRecord(
+ __in STATIC_WSTRING_HASH_RECORD * pRecord
+ )
+ /*++
+
+ Routine Description:
+
+ Insert record to hash table
+
+ Note: remember this is static hash table
+ There is no synchronization on the table
+ Exclusive acess must be assured by caller
+
+ Arguments:
+
+ record to fetch the key from
+
+ Return Value:
+
+ VOID
+
+ --*/
+ {
+ DWORD dwIndex;
+ STATIC_WSTRING_HASH_RECORD* pCursor;
+
+ DBG_ASSERT( pRecord != NULL );
+ DBG_ASSERT( pRecord->_pszName != NULL );
+
+ if (_fCaseSensitive)
+ {
+ dwIndex = HashString( pRecord->_pszName ) % STATIC_STRING_HASH_BUCKETS;
+ }
+ else
+ {
+ dwIndex = HashStringNoCase( pRecord->_pszName ) % STATIC_STRING_HASH_BUCKETS;
+ }
+
+ pCursor = _rgBuckets[ dwIndex ];
+
+ pRecord->_pNext = pCursor;
+ _rgBuckets[ dwIndex ] = pRecord;
+ }
+
+ STATIC_WSTRING_HASH_RECORD *
+ FindKey(
+ __in PCWSTR pszName,
+ BOOL fRemove = FALSE
+ )
+ /*++
+
+ Routine Description:
+
+ Find key in the table (and remove it optionally)
+
+ Arguments:
+
+ key
+
+ Return Value:
+
+ record containing the key
+
+ --*/
+ {
+ DWORD dwIndex;
+ STATIC_WSTRING_HASH_RECORD* pRecord;
+ STATIC_WSTRING_HASH_RECORD* pLastRecord = NULL;
+
+ DBG_ASSERT( pszName != NULL );
+
+ if (_fCaseSensitive)
+ {
+ dwIndex = HashString( pszName ) % STATIC_STRING_HASH_BUCKETS;
+ }
+ else
+ {
+ dwIndex = HashStringNoCase( pszName ) % STATIC_STRING_HASH_BUCKETS;
+ }
+
+ pRecord = _rgBuckets[ dwIndex ];
+ while ( pRecord != NULL )
+ {
+ if ( _fCaseSensitive )
+ {
+ if ( wcscmp( pszName, pRecord->_pszName ) == 0 )
+ {
+ break;
+ }
+ }
+ else if ( _wcsicmp( pszName, pRecord->_pszName ) == 0 )
+ {
+ break;
+ }
+
+ pLastRecord = pRecord;
+ pRecord = pRecord->_pNext;
+ }
+
+ if (fRemove &&
+ pRecord != NULL)
+ {
+ if (pLastRecord != NULL)
+ {
+ pLastRecord->_pNext = pRecord->_pNext;
+ }
+ else
+ {
+ _rgBuckets[dwIndex] = pRecord->_pNext;
+ }
+ }
+
+ return pRecord;
+ }
+
+ BOOL
+ CheckDistribution(
+ IN DWORD dwConflictThreshold,
+ IN BOOL fToDebugger
+ )
+ /*++
+
+ Routine Description:
+
+ Simple verification on conflicts within the table
+
+ Arguments:
+
+ dwConflictThreshold - max number of entries tolerated per bucket
+ fToDebbuger - spew the entries exceeding threshold into debugger
+
+ Return Value:
+
+ FALSE it threshold was reached (means hash funcion may not be optimal)
+
+ --*/
+ {
+ BOOL fThresholdReached = FALSE;
+ STATIC_WSTRING_HASH_RECORD* pRecord;
+ for ( DWORD dwIndex = 0; dwIndex < STATIC_STRING_HASH_BUCKETS; dwIndex++)
+ {
+ pRecord = _rgBuckets[ dwIndex ];
+ DWORD countInBucket = 0;
+ while ( pRecord != NULL )
+ {
+ countInBucket++;
+ pRecord = pRecord->_pNext;
+ }
+ //
+ // print out the list of multiple entries in bucket
+ //
+ if ( countInBucket > dwConflictThreshold && fToDebugger )
+ {
+ fThresholdReached = TRUE;
+
+ pRecord = _rgBuckets[ dwIndex ];
+ while ( pRecord != NULL )
+ {
+ pRecord = pRecord->_pNext;
+ }
+ }
+ }
+ return fThresholdReached;
+ }
+
+ STATIC_WSTRING_HASH_RECORD *
+ FindFirst(
+ STATIC_WSTRING_HASH_ITER *pIterator,
+ BOOL fRemove = FALSE
+ )
+ /*++
+
+ Routine Description:
+
+ Begins a new hash item enumeration.
+
+ Arguments:
+
+ pIterator - Supplies the context for the enumeration.
+
+ fRemove - Supplies TRUE if the items should be removed
+ from the hash as they are enumerated.
+
+ Return Value:
+
+ The first entry in the hash if successful, NULL otherwise.
+
+ --*/
+ {
+ pIterator->_dwBucket = 0;
+ pIterator->_fRemove = fRemove;
+ pIterator->_pCursor = FindNextBucket(&pIterator->_dwBucket);
+
+ if (pIterator->_fRemove && pIterator->_pCursor != NULL)
+ {
+ _rgBuckets[pIterator->_dwBucket] = pIterator->_pCursor->_pNext;
+ }
+
+ return pIterator->_pCursor;
+ }
+
+ STATIC_WSTRING_HASH_RECORD *
+ FindNext(
+ STATIC_WSTRING_HASH_ITER *pIterator
+ )
+ /*++
+
+ Routine Description:
+
+ Continues a hash item enumeration.
+
+ Arguments:
+
+ pIterator - Supplies the context for the enumeration.
+
+ Return Value:
+
+ The next entry in the hash if successful, NULL otherwise.
+
+ --*/
+ {
+ if (pIterator->_pCursor != NULL)
+ {
+ if (pIterator->_fRemove)
+ {
+ pIterator->_pCursor = _rgBuckets[pIterator->_dwBucket];
+ }
+ else
+ {
+ pIterator->_pCursor = pIterator->_pCursor->_pNext;
+ }
+
+ if (pIterator->_pCursor == NULL)
+ {
+ pIterator->_dwBucket++;
+ pIterator->_pCursor = FindNextBucket(&pIterator->_dwBucket);
+ }
+ }
+
+ if (pIterator->_fRemove && pIterator->_pCursor != NULL)
+ {
+ _rgBuckets[pIterator->_dwBucket] = pIterator->_pCursor->_pNext;
+ }
+
+ return pIterator->_pCursor;
+ }
+
+ protected:
+
+ STATIC_WSTRING_HASH_RECORD * _rgBuckets[ STATIC_STRING_HASH_BUCKETS ];
+
+ private:
+
+ BOOL _fCaseSensitive;
+
+ STATIC_WSTRING_HASH_RECORD *
+ FindNextBucket(
+ DWORD *pdwStartingBucket
+ )
+ /*++
+
+ Routine Description:
+
+ Scan for the next non-empty bucket.
+
+ Arguments:
+
+ pdwStartingBucket - Supplies a pointer to the starting
+ bucket index. This value is updated with the index
+ of the next non-empty bucket if successful.
+
+ Return Value:
+
+ The first entry in the next non-empty bucket if successful,
+ NULL otherwise.
+
+ --*/
+ {
+ DWORD i;
+ STATIC_WSTRING_HASH_RECORD *pScan = NULL;
+
+ for (i = *pdwStartingBucket ; i < STATIC_STRING_HASH_BUCKETS ; i++)
+ {
+ pScan = _rgBuckets[i];
+
+ if (pScan != NULL)
+ {
+ break;
+ }
+ }
+
+ *pdwStartingBucket = i;
+ return pScan;
+ }
+};
+
+
+#endif //__STATIC_HASH__H_
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stdtypes.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stdtypes.h
new file mode 100644
index 0000000000..53a631b036
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stdtypes.h
@@ -0,0 +1,24 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#pragma once
+
+//
+// Use C++ standard 'nullptr'
+//
+
+#ifdef NULL
+#undef NULL
+#endif
+
+#ifdef __cplusplus
+#ifdef _NATIVE_NULLPTR_SUPPORTED
+#define NULL nullptr
+#else
+#define NULL 0
+#define nullptr 0
+#endif
+#else
+#define NULL ((void *)0)
+//#define nullptr ((void *)0)
+#endif
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringa.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringa.h
new file mode 100644
index 0000000000..d38604014e
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringa.h
@@ -0,0 +1,515 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#pragma once
+
+#include "buffer.h"
+#include "macros.h"
+#include
+
+class STRA
+{
+
+public:
+
+ STRA(
+ VOID
+ );
+
+ STRA(
+ __inout_ecount(cchInit) CHAR* pbInit,
+ __in DWORD cchInit
+ );
+
+ BOOL
+ IsEmpty(
+ VOID
+ ) const;
+
+ BOOL
+ Equals(
+ __in PCSTR pszRhs,
+ __in BOOL fIgnoreCase = FALSE
+ ) const;
+
+ BOOL
+ Equals(
+ __in const STRA * pstrRhs,
+ __in BOOL fIgnoreCase = FALSE
+ ) const;
+
+ BOOL
+ Equals(
+ __in const STRA & strRhs,
+ __in BOOL fIgnoreCase = FALSE
+ ) const;
+
+ static
+ BOOL
+ Equals(
+ __in PCSTR pszLhs,
+ __in PCSTR pszRhs,
+ __in bool fIgnoreCase = false
+ )
+ {
+ // Return FALSE if either or both strings are NULL.
+ if (!pszLhs || !pszRhs) return FALSE;
+
+ if( fIgnoreCase )
+ {
+ return ( 0 == _stricmp( pszLhs, pszRhs ) );
+ }
+
+ return ( 0 == strcmp( pszLhs, pszRhs ) );
+ }
+
+ VOID
+ Trim();
+
+ BOOL
+ StartsWith(
+ __in const STRA * pStraPrefix,
+ __in bool fIgnoreCase = FALSE
+ ) const;
+
+ BOOL
+ StartsWith(
+ __in const STRA & straPrefix,
+ __in bool fIgnoreCase = FALSE
+ ) const;
+
+ BOOL
+ StartsWith(
+ __in PCSTR pszPrefix,
+ __in bool fIgnoreCase = FALSE
+ ) const;
+
+ BOOL
+ EndsWith(
+ __in const STRA * pStraSuffix,
+ __in bool fIgnoreCase = FALSE
+ ) const;
+
+ BOOL
+ EndsWith(
+ __in const STRA & straSuffix,
+ __in bool fIgnoreCase = FALSE
+ ) const;
+
+ BOOL
+ EndsWith(
+ __in PCSTR pszSuffix,
+ __in bool fIgnoreCase = FALSE
+ ) const;
+
+ INT
+ IndexOf(
+ __in CHAR charValue,
+ __in DWORD dwStartIndex = 0
+ ) const;
+
+ INT
+ IndexOf(
+ __in PCSTR pszValue,
+ __in DWORD dwStartIndex = 0
+ ) const;
+
+ INT
+ LastIndexOf(
+ __in CHAR charValue,
+ __in DWORD dwStartIndex = 0
+ ) const;
+
+ DWORD
+ QueryCB(
+ VOID
+ ) const;
+
+ DWORD
+ QueryCCH(
+ VOID
+ ) const;
+
+ DWORD
+ QuerySizeCCH(
+ VOID
+ ) const;
+
+ DWORD
+ QuerySize(
+ VOID
+ ) const;
+
+ __nullterminated
+ __bcount(this->m_cchLen)
+ CHAR *
+ QueryStr(
+ VOID
+ ) const;
+
+ VOID
+ Reset(
+ VOID
+ );
+
+ HRESULT
+ Resize(
+ __in DWORD cchSize
+ );
+
+ HRESULT
+ SyncWithBuffer(
+ VOID
+ );
+
+ HRESULT
+ Copy(
+ __in PCSTR pszCopy
+ );
+
+ HRESULT
+ Copy(
+ __in_ecount(cbLen)
+ PCSTR pszCopy,
+ __in SIZE_T cbLen
+ );
+
+ HRESULT
+ Copy(
+ __in const STRA * pstrRhs
+ );
+
+ HRESULT
+ Copy(
+ __in const STRA & strRhs
+ );
+
+ HRESULT
+ CopyW(
+ __in PCWSTR pszCopyW
+ );
+
+ HRESULT
+ CopyW(
+ __in_ecount(cchLen)
+ PCWSTR pszCopyW,
+ __in SIZE_T cchLen,
+ __in UINT CodePage = CP_UTF8,
+ __in BOOL fFailIfNoTranslation = FALSE
+ )
+ {
+ _ASSERTE( cchLen <= MAXDWORD );
+
+ return AuxAppendW(
+ pszCopyW,
+ static_cast(cchLen),
+ 0,
+ CodePage,
+ fFailIfNoTranslation
+ );
+ }
+
+ HRESULT
+ CopyWTruncate(
+ __in PCWSTR pszCopyWTruncate
+ );
+
+ HRESULT
+ CopyWTruncate(
+ __in_ecount(cchLen)
+ PCWSTR pszCopyWTruncate,
+ __in SIZE_T cchLen
+ );
+
+ HRESULT
+ Append(
+ __in PCSTR pszAppend
+ );
+
+ HRESULT
+ Append(
+ __in_ecount(cbLen)
+ PCSTR pszAppend,
+ __in SIZE_T cbLen
+ );
+
+ HRESULT
+ Append(
+ __in const STRA * pstrRhs
+ );
+
+ HRESULT
+ Append(
+ __in const STRA & strRhs
+ );
+
+ HRESULT
+ AppendW(
+ __in PCWSTR pszAppendW
+ )
+ {
+ HRESULT hr;
+ size_t cchLen;
+ hr = StringCchLengthW( pszAppendW,
+ STRSAFE_MAX_CCH,
+ &cchLen );
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+ return AppendW( pszAppendW, cchLen );
+ }
+
+ HRESULT
+ AppendW(
+ __in_ecount(cchLen)
+ PCWSTR pszAppendW,
+ __in SIZE_T cchLen,
+ __in UINT CodePage = CP_UTF8,
+ __in BOOL fFailIfNoTranslation = FALSE
+ )
+ {
+ _ASSERTE( cchLen <= MAXDWORD );
+ if ( cchLen == 0 )
+ {
+ return S_OK;
+ }
+ return AuxAppendW(
+ pszAppendW,
+ static_cast(cchLen),
+ QueryCB(),
+ CodePage,
+ fFailIfNoTranslation
+ );
+ }
+
+ HRESULT
+ AppendWTruncate(
+ __in PCWSTR pszAppendWTruncate
+ );
+
+ HRESULT
+ AppendWTruncate(
+ __in_ecount(cchLen)
+ PCWSTR pszAppendWTruncate,
+ __in SIZE_T cchLen
+ );
+
+ HRESULT
+ CopyToBuffer(
+ __out_bcount(*pcb) CHAR* pszBuffer,
+ __inout DWORD * pcb
+ ) const;
+
+ HRESULT
+ SetLen(
+ __in DWORD cchLen
+ );
+
+ HRESULT
+ SafeSnprintf(
+ __in __format_string
+ PCSTR pszFormatString,
+ ...
+ );
+
+ HRESULT
+ SafeVsnprintf(
+ __in __format_string
+ PCSTR pszFormatString,
+ va_list argsList
+ );
+
+ HRESULT
+ Escape(
+ VOID
+ );
+
+ HRESULT
+ EscapeUtf8(
+ VOID
+ );
+
+ VOID
+ Unescape(
+ VOID
+ );
+
+ HRESULT
+ CopyWToUTF8Unescaped(
+ __in LPCWSTR cpchStr
+ );
+
+ HRESULT
+ CopyWToUTF8Unescaped(
+ __in_ecount(cch)
+ LPCWSTR cpchStr,
+ __in DWORD cch
+ );
+
+ HRESULT
+ CopyWToUTF8Escaped(
+ __in LPCWSTR cpchStr
+ );
+
+ HRESULT
+ CopyWToUTF8Escaped(
+ __in_ecount(cch)
+ LPCWSTR cpchStr,
+ __in DWORD cch
+ );
+
+private:
+
+ //
+ // Avoid C++ errors. This object should never go through a copy
+ // constructor, unintended cast or assignment.
+ //
+ STRA( const STRA &);
+ STRA & operator = (const STRA &);
+
+ HRESULT
+ AuxAppend(
+ __in_ecount(cbLen)
+ LPCSTR pStr,
+ __in DWORD cbLen,
+ __in DWORD cbOffset
+ );
+
+ HRESULT
+ AuxAppendW(
+ __in_ecount(cchAppendW)
+ PCWSTR pszAppendW,
+ __in DWORD cchAppendW,
+ __in DWORD cbOffset,
+ __in UINT CodePage,
+ __in BOOL fFailIfNoTranslation
+ )
+ {
+ DWORD dwFlags = 0;
+
+ if( CP_ACP == CodePage )
+ {
+ dwFlags = WC_NO_BEST_FIT_CHARS;
+ }
+ else if( fFailIfNoTranslation && CodePage == CP_UTF8 )
+ {
+ //
+ // WC_ERR_INVALID_CHARS is only supported in Longhorn or greater.
+ //
+#if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN
+ dwFlags |= WC_ERR_INVALID_CHARS;
+#else
+ UNREFERENCED_PARAMETER(fFailIfNoTranslation);
+#endif
+ }
+
+ return AuxAppendW( pszAppendW,
+ cchAppendW,
+ cbOffset,
+ CodePage,
+ fFailIfNoTranslation,
+ dwFlags );
+ }
+
+ HRESULT
+ AuxAppendW(
+ __in_ecount(cchAppendW)
+ PCWSTR pszAppendW,
+ __in DWORD cchAppendW,
+ __in DWORD cbOffset,
+ __in UINT CodePage,
+ __in BOOL fFailIfNoTranslation,
+ __in DWORD dwFlags
+ );
+
+ HRESULT
+ AuxAppendWTruncate(
+ __in_ecount(cchAppendW)
+ __in PCWSTR pszAppendW,
+ __in DWORD cchAppendW,
+ __in DWORD cbOffset
+ );
+
+ static
+ int
+ ConvertUnicodeToCodePage(
+ __in_ecount(dwStringLen)
+ LPCWSTR pszSrcUnicodeString,
+ __inout BUFFER_T * pbufDstAnsiString,
+ __in DWORD dwStringLen,
+ __in UINT uCodePage
+ );
+
+ static
+ HRESULT
+ ConvertUnicodeToMultiByte(
+ __in_ecount(dwStringLen)
+ LPCWSTR pszSrcUnicodeString,
+ __in BUFFER_T * pbufDstAnsiString,
+ __in DWORD dwStringLen
+ );
+
+ static
+ HRESULT
+ ConvertUnicodeToUTF8(
+ __in_ecount(dwStringLen)
+ LPCWSTR pszSrcUnicodeString,
+ __in BUFFER_T * pbufDstAnsiString,
+ __in DWORD dwStringLen
+ );
+
+ typedef bool (* PFN_F_SHOULD_ESCAPE)(BYTE ch);
+
+ HRESULT
+ EscapeInternal(
+ PFN_F_SHOULD_ESCAPE pfnFShouldEscape
+ );
+
+ //
+ // Buffer with an inline buffer of 1,
+ // enough to hold null-terminating character.
+ //
+ BUFFER_T m_Buff;
+ DWORD m_cchLen;
+};
+
+inline
+HRESULT
+AppendToString(
+ ULONGLONG Number,
+ STRA & String
+)
+{
+ // prefast complains Append requires input
+ // to be null terminated, so zero initialize
+ // and pass the size of the buffer minus one
+ // to _ui64toa_s
+ CHAR chNumber[32] = {0};
+ if (_ui64toa_s(Number,
+ chNumber,
+ sizeof(chNumber) - sizeof(CHAR),
+ 10) != 0)
+ {
+ return E_INVALIDARG;
+ }
+ return String.Append(chNumber);
+}
+
+template
+CHAR* InitHelper(__out CHAR (&psz)[size])
+{
+ psz[0] = '\0';
+ return psz;
+}
+
+//
+// Heap operation reduction macros
+//
+#define STACK_STRA(name, size) CHAR __ach##name[size];\
+ STRA name(InitHelper(__ach##name), sizeof(__ach##name))
+
+#define INLINE_STRA(name, size) CHAR __ach##name[size];\
+ STRA name;
+
+#define INLINE_STRA_INIT(name) name(InitHelper(__ach##name), sizeof(__ach##name))
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringu.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringu.h
new file mode 100644
index 0000000000..6c8f8f755b
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringu.h
@@ -0,0 +1,433 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#pragma once
+
+#include "buffer.h"
+#include
+
+class STRU
+{
+
+public:
+
+ STRU(
+ VOID
+ );
+
+ STRU(
+ __inout_ecount(cchInit) WCHAR* pbInit,
+ __in DWORD cchInit
+ );
+
+ BOOL
+ IsEmpty(
+ VOID
+ ) const;
+
+ BOOL
+ Equals(
+ __in const STRU * pstrRhs,
+ __in BOOL fIgnoreCase = FALSE
+ ) const
+ {
+ _ASSERTE( pstrRhs != NULL );
+ return Equals( pstrRhs->QueryStr(), fIgnoreCase );
+ }
+
+ BOOL
+ Equals(
+ __in const STRU & strRhs,
+ __in BOOL fIgnoreCase = FALSE
+ ) const
+ {
+ return Equals( strRhs.QueryStr(), fIgnoreCase );
+ }
+
+ BOOL
+ Equals(
+ __in PCWSTR pszRhs,
+ __in BOOL fIgnoreCase = FALSE
+ ) const
+ {
+ _ASSERTE( NULL != pszRhs );
+ if ( NULL == pszRhs )
+ {
+ return FALSE;
+ }
+
+ #if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN
+
+ return ( CSTR_EQUAL == CompareStringOrdinal( QueryStr(),
+ QueryCCH(),
+ pszRhs,
+ -1,
+ fIgnoreCase ) );
+ #else
+
+ if( fIgnoreCase )
+ {
+ return ( 0 == _wcsicmp( QueryStr(), pszRhs ) );
+ }
+ return ( 0 == wcscmp( QueryStr(), pszRhs ) );
+
+ #endif
+ }
+
+
+ static
+ BOOL
+ Equals(
+ __in PCWSTR pwszLhs,
+ __in PCWSTR pwszRhs,
+ __in bool fIgnoreCase = false
+ )
+ {
+ // Return FALSE if either or both strings are NULL.
+ if (!pwszLhs || !pwszRhs) return FALSE;
+
+ //
+ // This method performs a ordinal string comparison when OS is Vista or
+ // greater and a culture sensitive comparison if not (XP). This is
+ // consistent with the existing Equals implementation (see above).
+ //
+#if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN
+
+ return ( CSTR_EQUAL == CompareStringOrdinal( pwszLhs,
+ -1,
+ pwszRhs,
+ -1,
+ fIgnoreCase ) );
+#else
+
+ if( fIgnoreCase )
+ {
+ return ( 0 == _wcsicmp( pwszLhs, pwszRhs ) );
+ }
+ else
+ {
+ return ( 0 == wcscmp( pwszLhs, pwszRhs ) );
+ }
+
+#endif
+ }
+
+ VOID
+ Trim();
+
+ BOOL
+ StartsWith(
+ __in const STRU * pStruPrefix,
+ __in bool fIgnoreCase = FALSE
+ ) const
+ {
+ _ASSERTE( pStruPrefix != NULL );
+ return StartsWith( pStruPrefix->QueryStr(), fIgnoreCase );
+ }
+
+ BOOL
+ StartsWith(
+ __in const STRU & struPrefix,
+ __in bool fIgnoreCase = FALSE
+ ) const
+ {
+ return StartsWith( struPrefix.QueryStr(), fIgnoreCase );
+ }
+
+ BOOL
+ StartsWith(
+ __in PCWSTR pwszPrefix,
+ __in bool fIgnoreCase = FALSE
+ ) const;
+
+ BOOL
+ EndsWith(
+ __in const STRU * pStruSuffix,
+ __in bool fIgnoreCase = FALSE
+ ) const
+ {
+ _ASSERTE( pStruSuffix != NULL );
+ return EndsWith( pStruSuffix->QueryStr(), fIgnoreCase );
+ }
+
+ BOOL
+ EndsWith(
+ __in const STRU & struSuffix,
+ __in bool fIgnoreCase = FALSE
+ ) const
+ {
+ return EndsWith( struSuffix.QueryStr(), fIgnoreCase );
+ }
+
+ BOOL
+ EndsWith(
+ __in PCWSTR pwszSuffix,
+ __in bool fIgnoreCase = FALSE
+ ) const;
+
+ INT
+ IndexOf(
+ __in WCHAR charValue,
+ __in DWORD dwStartIndex = 0
+ ) const;
+
+ INT
+ IndexOf(
+ __in PCWSTR pwszValue,
+ __in DWORD dwStartIndex = 0
+ ) const;
+
+ INT
+ LastIndexOf(
+ __in WCHAR charValue,
+ __in DWORD dwStartIndex = 0
+ ) const;
+
+ DWORD
+ QueryCB(
+ VOID
+ ) const;
+
+ DWORD
+ QueryCCH(
+ VOID
+ ) const;
+
+ DWORD
+ QuerySizeCCH(
+ VOID
+ ) const;
+
+ __nullterminated
+ __ecount(this->m_cchLen)
+ WCHAR*
+ QueryStr(
+ VOID
+ ) const;
+
+ VOID
+ Reset(
+ VOID
+ );
+
+ HRESULT
+ Resize(
+ DWORD cchSize
+ );
+
+ HRESULT
+ SyncWithBuffer(
+ VOID
+ );
+
+ template
+ HRESULT
+ Copy(
+ __in PCWSTR const (&rgpszStrings)[size]
+ )
+ //
+ // Copies an array of strings declared as stack array. For example:
+ //
+ // LPCWSTR rgExample[] { L"one", L"two" };
+ // hr = str.Copy( rgExample );
+ //
+ {
+ Reset();
+
+ return AuxAppend( rgpszStrings, _countof( rgpszStrings ) );
+ }
+
+ HRESULT
+ Copy(
+ __in PCWSTR pszCopy
+ );
+
+ HRESULT
+ Copy(
+ __in_ecount(cchLen)
+ PCWSTR pszCopy,
+ SIZE_T cchLen
+ );
+
+ HRESULT
+ Copy(
+ __in const STRU * pstrRhs
+ );
+
+ HRESULT
+ Copy(
+ __in const STRU & str
+ );
+
+ HRESULT
+ CopyAndExpandEnvironmentStrings(
+ __in PCWSTR pszSource
+ );
+
+ HRESULT
+ CopyA(
+ __in PCSTR pszCopyA
+ );
+
+ HRESULT
+ CopyA(
+ __in_bcount(cchLen)
+ PCSTR pszCopyA,
+ SIZE_T cchLen,
+ UINT CodePage = CP_UTF8
+ );
+
+ template
+ HRESULT
+ Append(
+ __in PCWSTR const (&rgpszStrings)[size]
+ )
+ //
+ // Appends an array of strings declared as stack array. For example:
+ //
+ // LPCWSTR rgExample[] { L"one", L"two" };
+ // hr = str.Append( rgExample );
+ //
+ {
+ return AuxAppend( rgpszStrings, _countof( rgpszStrings ) );
+ }
+
+ HRESULT
+ Append(
+ __in PCWSTR pszAppend
+ );
+
+ HRESULT
+ Append(
+ __in_ecount(cchLen)
+ PCWSTR pszAppend,
+ SIZE_T cchLen
+ );
+
+ HRESULT
+ Append(
+ __in const STRU * pstrRhs
+ );
+
+ HRESULT
+ Append(
+ __in const STRU & strRhs
+ );
+
+ HRESULT
+ AppendA(
+ __in PCSTR pszAppendA
+ );
+
+ HRESULT
+ AppendA(
+ __in_bcount(cchLen)
+ PCSTR pszAppendA,
+ SIZE_T cchLen,
+ UINT CodePage = CP_UTF8
+ );
+
+ HRESULT
+ CopyToBuffer(
+ __out_bcount(*pcb) WCHAR* pszBuffer,
+ PDWORD pcb
+ ) const;
+
+ HRESULT
+ CopyToBufferA(
+ __out_bcount(*pcb) CHAR* pszBuffer,
+ __inout PDWORD pcb
+ ) const;
+
+ HRESULT
+ SetLen(
+ __in DWORD cchLen
+ );
+
+ HRESULT
+ SafeSnwprintf(
+ __in PCWSTR pwszFormatString,
+ ...
+ );
+
+ HRESULT
+ SafeVsnwprintf(
+ __in PCWSTR pwszFormatString,
+ va_list argsList
+ );
+
+ static
+ HRESULT ExpandEnvironmentVariables(
+ __in PCWSTR pszString,
+ __out STRU * pstrExpandedString
+ );
+
+private:
+
+ //
+ // Avoid C++ errors. This object should never go through a copy
+ // constructor, unintended cast or assignment.
+ //
+ STRU( const STRU & );
+ STRU & operator = ( const STRU & );
+
+ HRESULT
+ AuxAppend(
+ __in_ecount(cNumStrings)
+ PCWSTR const rgpszStrings[],
+ SIZE_T cNumStrings
+ );
+
+ HRESULT
+ AuxAppend(
+ __in_bcount(cbStr)
+ const WCHAR* pStr,
+ SIZE_T cbStr,
+ DWORD cbOffset
+ );
+
+ HRESULT
+ AuxAppendA(
+ __in_bcount(cbStr)
+ const CHAR* pStr,
+ SIZE_T cbStr,
+ DWORD cbOffset,
+ UINT CodePage
+ );
+
+ //
+ // Buffer with an inline buffer of 1,
+ // enough to hold null-terminating character.
+ //
+ BUFFER_T m_Buff;
+ DWORD m_cchLen;
+};
+
+//
+// Helps to initialize an external buffer before
+// constructing the STRU object.
+//
+template
+WCHAR* InitHelper(__out WCHAR (&psz)[size])
+{
+ psz[0] = L'\0';
+ return psz;
+}
+
+//
+// Heap operation reduction macros
+//
+#define STACK_STRU(name, size) WCHAR __ach##name[size];\
+ STRU name(InitHelper(__ach##name), sizeof(__ach##name)/sizeof(*__ach##name))
+
+#define INLINE_STRU(name, size) WCHAR __ach##name[size];\
+ STRU name;
+
+#define INLINE_STRU_INIT(name) name(InitHelper(__ach##name), sizeof(__ach##name)/sizeof(*__ach##name))
+
+
+HRESULT
+MakePathCanonicalizationProof(
+ IN PCWSTR pszName,
+ OUT STRU * pstrPath
+);
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/sttimer.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/sttimer.h
new file mode 100644
index 0000000000..b0fba23559
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/sttimer.h
@@ -0,0 +1,243 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef _STTIMER_H
+#define _STTIMER_H
+
+class STTIMER
+{
+public:
+
+ STTIMER()
+ : _pTimer( NULL )
+ {
+ fInCanel = FALSE;
+ }
+
+ virtual
+ ~STTIMER()
+ {
+ if ( _pTimer )
+ {
+ CancelTimer();
+
+ CloseThreadpoolTimer( _pTimer );
+
+ _pTimer = NULL;
+ }
+ }
+
+ HRESULT
+ InitializeTimer(
+ PTP_TIMER_CALLBACK pfnCallback,
+ VOID * pContext,
+ DWORD dwInitialWait = 0,
+ DWORD dwPeriod = 0
+ )
+ {
+ _pTimer = CreateThreadpoolTimer( pfnCallback,
+ pContext,
+ NULL );
+
+ if ( !_pTimer )
+ {
+ return HRESULT_FROM_WIN32( GetLastError() );
+ }
+
+ if ( dwInitialWait )
+ {
+ SetTimer( dwInitialWait,
+ dwPeriod );
+ }
+
+ return S_OK;
+ }
+
+ VOID
+ SetTimer(
+ DWORD dwInitialWait,
+ DWORD dwPeriod = 0
+ )
+ {
+ FILETIME ftInitialWait;
+
+ if ( dwInitialWait == 0 && dwPeriod == 0 )
+ {
+ //
+ // Special case. We are preventing new callbacks
+ // from being queued. Any existing callbacks in the
+ // queue will still run.
+ //
+ // This effectively disables the timer. It can be
+ // re-enabled by setting non-zero initial wait or
+ // period values.
+ //
+ if (_pTimer != NULL)
+ {
+ SetThreadpoolTimer(_pTimer, NULL, 0, 0);
+ }
+
+ return;
+ }
+
+ InitializeRelativeFileTime( &ftInitialWait, dwInitialWait );
+
+ SetThreadpoolTimer( _pTimer,
+ &ftInitialWait,
+ dwPeriod,
+ 0 );
+ }
+
+ VOID
+ CancelTimer()
+ {
+ //
+ // Disable the timer
+ //
+ if (fInCanel)
+ return;
+
+ fInCanel = TRUE;
+ SetTimer( 0 );
+
+ //
+ // Wait until any callbacks queued prior to disabling
+ // have completed.
+ //
+ if (_pTimer != NULL)
+ WaitForThreadpoolTimerCallbacks( _pTimer, TRUE );
+
+ _pTimer = NULL;
+ fInCanel = FALSE;
+ }
+
+private:
+
+ VOID
+ InitializeRelativeFileTime(
+ FILETIME * pft,
+ DWORD dwMilliseconds
+ )
+ {
+ LARGE_INTEGER li;
+
+ //
+ // The pftDueTime parameter expects the time to be
+ // expressed as the number of 100 nanosecond intervals
+ // times -1.
+ //
+ // To convert from milliseconds, we'll multiply by
+ // -10000
+ //
+
+ li.QuadPart = (LONGLONG)dwMilliseconds * -10000;
+
+ pft->dwHighDateTime = li.HighPart;
+ pft->dwLowDateTime = li.LowPart;
+ };
+
+ TP_TIMER * _pTimer;
+ BOOL fInCanel;
+};
+
+class STELAPSED
+{
+public:
+
+ STELAPSED()
+ : _dwInitTime( 0 ),
+ _dwInitTickCount( 0 ),
+ _dwPerfCountsPerMillisecond( 0 ),
+ _fUsingHighResolution( FALSE )
+ {
+ LARGE_INTEGER li;
+ BOOL fResult;
+
+ _dwInitTickCount = GetTickCount64();
+
+ fResult = QueryPerformanceFrequency( &li );
+
+ if ( !fResult )
+ {
+ goto Finished;
+ }
+
+ _dwPerfCountsPerMillisecond = li.QuadPart / 1000;
+
+ fResult = QueryPerformanceCounter( &li );
+
+ if ( !fResult )
+ {
+ goto Finished;
+ }
+
+ _dwInitTime = li.QuadPart / _dwPerfCountsPerMillisecond;
+
+ _fUsingHighResolution = TRUE;
+
+Finished:
+
+ return;
+ }
+
+ virtual
+ ~STELAPSED()
+ {
+ }
+
+ LONGLONG
+ QueryElapsedTime()
+ {
+ LARGE_INTEGER li;
+
+ if ( _fUsingHighResolution && QueryPerformanceCounter( &li ) )
+ {
+ DWORD64 dwCurrentTime = li.QuadPart / _dwPerfCountsPerMillisecond;
+
+ if ( dwCurrentTime < _dwInitTime )
+ {
+ //
+ // It's theoretically possible that QueryPerformanceCounter
+ // may return slightly different values on different CPUs.
+ // In this case, we don't want to return an unexpected value
+ // so we'll return zero. This is acceptable because
+ // presumably such a case would only happen for a very short
+ // time window.
+ //
+ // It would be possible to prevent this by ensuring processor
+ // affinity for all calls to QueryPerformanceCounter, but that
+ // would be undesirable in the general case because it could
+ // introduce unnecessary context switches and potentially a
+ // CPU bottleneck.
+ //
+ // Note that this issue also applies to callers doing rapid
+ // calls to this function. If a caller wants to mitigate
+ // that, they could enforce the affinitization, or they
+ // could implement a similar sanity check when comparing
+ // returned values from this function.
+ //
+
+ return 0;
+ }
+
+ return dwCurrentTime - _dwInitTime;
+ }
+
+ return GetTickCount64() - _dwInitTickCount;
+ }
+
+ BOOL
+ QueryUsingHighResolution()
+ {
+ return _fUsingHighResolution;
+ }
+
+private:
+
+ DWORD64 _dwInitTime;
+ DWORD64 _dwInitTickCount;
+ DWORD64 _dwPerfCountsPerMillisecond;
+ BOOL _fUsingHighResolution;
+};
+
+#endif // _STTIMER_H
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/tracelog.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/tracelog.h
new file mode 100644
index 0000000000..1caff82ce3
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/tracelog.h
@@ -0,0 +1,105 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef _TRACELOG_H_
+#define _TRACELOG_H_
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif // __cplusplus
+
+
+typedef struct _TRACE_LOG {
+
+ //
+ // Signature.
+ //
+
+ LONG Signature;
+
+ //
+ // The total number of entries available in the log.
+ //
+
+ LONG LogSize;
+
+ //
+ // The index of the next entry to use.
+ //
+
+ LONG NextEntry;
+
+ //
+ // The byte size of each entry.
+ //
+
+ LONG EntrySize;
+
+ //
+ // Pointer to the start of the circular buffer.
+ //
+
+ PUCHAR LogBuffer;
+
+ //
+ // The extra header bytes and actual log entries go here.
+ //
+ // BYTE ExtraHeaderBytes[ExtraBytesInHeader];
+ // BYTE Entries[LogSize][EntrySize];
+ //
+
+} TRACE_LOG, *PTRACE_LOG;
+
+
+//
+// Log header signature.
+//
+
+#define TRACE_LOG_SIGNATURE ((DWORD)'gOlT')
+#define TRACE_LOG_SIGNATURE_X ((DWORD)'golX')
+
+
+//
+// This macro maps a TRACE_LOG pointer to a pointer to the 'extra'
+// data associated with the log.
+//
+
+#define TRACE_LOG_TO_EXTRA_DATA(log) (PVOID)( (log) + 1 )
+
+
+//
+// Manipulators.
+//
+
+PTRACE_LOG
+CreateTraceLog(
+ IN LONG LogSize,
+ IN LONG ExtraBytesInHeader,
+ IN LONG EntrySize
+ );
+
+VOID
+DestroyTraceLog(
+ IN PTRACE_LOG Log
+ );
+
+LONG
+WriteTraceLog(
+ IN PTRACE_LOG Log,
+ IN PVOID Entry
+ );
+
+VOID
+ResetTraceLog(
+ IN PTRACE_LOG Log
+ );
+
+
+#if defined(__cplusplus)
+} // extern "C"
+#endif // __cplusplus
+
+
+#endif // _TRACELOG_H_
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/treehash.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/treehash.h
new file mode 100644
index 0000000000..79f5a83ead
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/treehash.h
@@ -0,0 +1,850 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#pragma once
+
+#include
+#include "rwlock.h"
+#include "prime.h"
+
+template
+class TREE_HASH_NODE
+{
+ template
+ friend class TREE_HASH_TABLE;
+
+ private:
+ // Next node in the hash table look-aside
+ TREE_HASH_NODE<_Record> *_pNext;
+
+ // links in the tree structure
+ TREE_HASH_NODE * _pParentNode;
+ TREE_HASH_NODE * _pFirstChild;
+ TREE_HASH_NODE * _pNextSibling;
+
+ // actual record
+ _Record * _pRecord;
+
+ // hash value
+ PCWSTR _pszPath;
+ DWORD _dwHash;
+};
+
+template
+class TREE_HASH_TABLE
+{
+protected:
+ typedef BOOL
+ (PFN_DELETE_IF)(
+ _Record * pRecord,
+ PVOID pvContext
+ );
+
+ typedef VOID
+ (PFN_APPLY)(
+ _Record * pRecord,
+ PVOID pvContext
+ );
+
+public:
+ TREE_HASH_TABLE(
+ BOOL fCaseSensitive
+ ) : _ppBuckets( NULL ),
+ _nBuckets( 0 ),
+ _nItems( 0 ),
+ _fCaseSensitive( fCaseSensitive )
+ {
+ }
+
+ virtual
+ ~TREE_HASH_TABLE();
+
+ virtual
+ VOID
+ ReferenceRecord(
+ _Record * pRecord
+ ) = 0;
+
+ virtual
+ VOID
+ DereferenceRecord(
+ _Record * pRecord
+ ) = 0;
+
+ virtual
+ PCWSTR
+ GetKey(
+ _Record * pRecord
+ ) = 0;
+
+ DWORD
+ Count()
+ {
+ return _nItems;
+ }
+
+ virtual
+ VOID
+ Clear();
+
+ HRESULT
+ Initialize(
+ DWORD nBucketSize
+ );
+
+ DWORD
+ CalcHash(
+ PCWSTR pszKey
+ )
+ {
+ return _fCaseSensitive ? HashString(pszKey) : HashStringNoCase(pszKey);
+ }
+
+ virtual
+ VOID
+ FindKey(
+ PCWSTR pszKey,
+ _Record ** ppRecord
+ );
+
+ virtual
+ HRESULT
+ InsertRecord(
+ _Record * pRecord
+ );
+
+ virtual
+ VOID
+ DeleteKey(
+ PCWSTR pszKey
+ );
+
+ virtual
+ VOID
+ DeleteIf(
+ PFN_DELETE_IF pfnDeleteIf,
+ PVOID pvContext
+ );
+
+ VOID
+ Apply(
+ PFN_APPLY pfnApply,
+ PVOID pvContext
+ );
+
+private:
+
+ BOOL
+ FindNodeInternal(
+ PCWSTR pszKey,
+ DWORD dwHash,
+ TREE_HASH_NODE<_Record> ** ppNode,
+ TREE_HASH_NODE<_Record> *** pppPreviousNodeNextPointer = NULL
+ );
+
+ HRESULT
+ AddNodeInternal(
+ PCWSTR pszPath,
+ DWORD dwHash,
+ _Record * pRecord,
+ TREE_HASH_NODE<_Record> * pParentNode,
+ TREE_HASH_NODE<_Record> ** ppNewNode
+ );
+
+ HRESULT
+ AllocateNode(
+ PCWSTR pszPath,
+ DWORD dwHash,
+ _Record * pRecord,
+ TREE_HASH_NODE<_Record> * pParentNode,
+ TREE_HASH_NODE<_Record> ** ppNewNode
+ );
+
+ VOID
+ DeleteNode(
+ TREE_HASH_NODE<_Record> * pNode
+ )
+ {
+ if (pNode->_pRecord != NULL)
+ {
+ DereferenceRecord(pNode->_pRecord);
+ pNode->_pRecord = NULL;
+ }
+
+ HeapFree(GetProcessHeap(),
+ 0,
+ pNode);
+ }
+
+ VOID
+ DeleteNodeInternal(
+ TREE_HASH_NODE<_Record> ** ppPreviousNodeNextPointer,
+ TREE_HASH_NODE<_Record> * pNode
+ );
+
+ VOID
+ RehashTableIfNeeded(
+ VOID
+ );
+
+ TREE_HASH_NODE<_Record> ** _ppBuckets;
+ DWORD _nBuckets;
+ DWORD _nItems;
+ BOOL _fCaseSensitive;
+ CWSDRWLock _tableLock;
+};
+
+template
+HRESULT
+TREE_HASH_TABLE<_Record>::AllocateNode(
+ PCWSTR pszPath,
+ DWORD dwHash,
+ _Record * pRecord,
+ TREE_HASH_NODE<_Record> * pParentNode,
+ TREE_HASH_NODE<_Record> ** ppNewNode
+)
+{
+ //
+ // Allocate enough extra space for pszPath
+ //
+ DWORD cchPath = (DWORD) wcslen(pszPath);
+ if (cchPath >= ((0xffffffff - sizeof(TREE_HASH_NODE<_Record>))/sizeof(WCHAR) - 1))
+ {
+ return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
+ }
+ TREE_HASH_NODE<_Record> *pNode = (TREE_HASH_NODE<_Record> *)HeapAlloc(
+ GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof(TREE_HASH_NODE<_Record>) + (cchPath+1)*sizeof(WCHAR));
+ if (pNode == NULL)
+ {
+ return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
+ }
+
+ memcpy(pNode+1, pszPath, (cchPath+1)*sizeof(WCHAR));
+ pNode->_pszPath = (PCWSTR)(pNode+1);
+ pNode->_dwHash = dwHash;
+ pNode->_pNext = pNode->_pNextSibling = pNode->_pFirstChild = NULL;
+ pNode->_pParentNode = pParentNode;
+ pNode->_pRecord = pRecord;
+
+ *ppNewNode = pNode;
+ return S_OK;
+}
+
+template
+HRESULT
+TREE_HASH_TABLE<_Record>::Initialize(
+ DWORD nBuckets
+)
+{
+ HRESULT hr = S_OK;
+
+ if ( nBuckets == 0 )
+ {
+ hr = E_INVALIDARG;
+ goto Failed;
+ }
+
+ hr = _tableLock.Init();
+ if ( FAILED( hr ) )
+ {
+ goto Failed;
+ }
+
+ if (nBuckets >= 0xffffffff/sizeof(TREE_HASH_NODE<_Record> *))
+ {
+ hr = E_INVALIDARG;
+ goto Failed;
+ }
+
+ _ppBuckets = (TREE_HASH_NODE<_Record> **)HeapAlloc(
+ GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ nBuckets*sizeof(TREE_HASH_NODE<_Record> *));
+ if (_ppBuckets == NULL)
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
+ goto Failed;
+ }
+ _nBuckets = nBuckets;
+
+ return S_OK;
+
+Failed:
+
+ if (_ppBuckets)
+ {
+ HeapFree(GetProcessHeap(),
+ 0,
+ _ppBuckets);
+ _ppBuckets = NULL;
+ }
+
+ return hr;
+}
+
+
+template
+TREE_HASH_TABLE<_Record>::~TREE_HASH_TABLE()
+{
+ if (_ppBuckets == NULL)
+ {
+ return;
+ }
+
+ _ASSERTE(_nItems == 0);
+
+ HeapFree(GetProcessHeap(),
+ 0,
+ _ppBuckets);
+ _ppBuckets = NULL;
+ _nBuckets = 0;
+}
+
+template
+VOID
+TREE_HASH_TABLE<_Record>::Clear()
+{
+ TREE_HASH_NODE<_Record> *pCurrent;
+ TREE_HASH_NODE<_Record> *pNext;
+
+ _tableLock.ExclusiveAcquire();
+
+ for (DWORD i=0; i<_nBuckets; i++)
+ {
+ pCurrent = _ppBuckets[i];
+ _ppBuckets[i] = NULL;
+ while (pCurrent != NULL)
+ {
+ pNext = pCurrent->_pNext;
+ DeleteNode(pCurrent);
+ pCurrent = pNext;
+ }
+ }
+
+ _nItems = 0;
+ _tableLock.ExclusiveRelease();
+}
+
+template
+BOOL
+TREE_HASH_TABLE<_Record>::FindNodeInternal(
+ PCWSTR pszKey,
+ DWORD dwHash,
+ TREE_HASH_NODE<_Record> ** ppNode,
+ TREE_HASH_NODE<_Record> *** pppPreviousNodeNextPointer
+)
+/*++
+ Return value indicates whether the item is found
+ key, dwHash - key and hash for the node to find
+ ppNode - on successful return, the node found, on failed return, the first
+ node with hash value greater than the node to be found
+ pppPreviousNodeNextPointer - the pointer to previous node's _pNext
+
+ This routine may be called under either read or write lock
+--*/
+{
+ TREE_HASH_NODE<_Record> **ppPreviousNodeNextPointer;
+ TREE_HASH_NODE<_Record> *pNode;
+ BOOL fFound = FALSE;
+
+ ppPreviousNodeNextPointer = _ppBuckets + (dwHash % _nBuckets);
+ pNode = *ppPreviousNodeNextPointer;
+ while (pNode != NULL)
+ {
+ if (pNode->_dwHash == dwHash)
+ {
+ if (CompareStringOrdinal(pszKey,
+ -1,
+ pNode->_pszPath,
+ -1,
+ !_fCaseSensitive) == CSTR_EQUAL)
+ {
+ fFound = TRUE;
+ break;
+ }
+ }
+ else if (pNode->_dwHash > dwHash)
+ {
+ break;
+ }
+
+ ppPreviousNodeNextPointer = &(pNode->_pNext);
+ pNode = *ppPreviousNodeNextPointer;
+ }
+
+ *ppNode = pNode;
+ if (pppPreviousNodeNextPointer != NULL)
+ {
+ *pppPreviousNodeNextPointer = ppPreviousNodeNextPointer;
+ }
+ return fFound;
+}
+
+template
+VOID
+TREE_HASH_TABLE<_Record>::FindKey(
+ PCWSTR pszKey,
+ _Record ** ppRecord
+)
+{
+ TREE_HASH_NODE<_Record> *pNode;
+
+ *ppRecord = NULL;
+
+ DWORD dwHash = CalcHash(pszKey);
+
+ _tableLock.SharedAcquire();
+
+ if (FindNodeInternal(pszKey, dwHash, &pNode) &&
+ pNode->_pRecord != NULL)
+ {
+ ReferenceRecord(pNode->_pRecord);
+ *ppRecord = pNode->_pRecord;
+ }
+
+ _tableLock.SharedRelease();
+}
+
+template
+HRESULT
+TREE_HASH_TABLE<_Record>::AddNodeInternal(
+ PCWSTR pszPath,
+ DWORD dwHash,
+ _Record * pRecord,
+ TREE_HASH_NODE<_Record> * pParentNode,
+ TREE_HASH_NODE<_Record> ** ppNewNode
+)
+/*++
+ Return value is HRESULT indicating sucess or failure
+ pszPath, dwHash, pRecord - path, hash value and record to be inserted
+ pParentNode - this will be the parent of the node being inserted
+ ppNewNode - on successful return, the new node created and inserted
+
+ This function may be called under a read or write lock
+--*/
+{
+ TREE_HASH_NODE<_Record> *pNewNode;
+ TREE_HASH_NODE<_Record> *pNextNode;
+ TREE_HASH_NODE<_Record> **ppNextPointer;
+ HRESULT hr;
+
+ //
+ // Ownership of pRecord is not transferred to pNewNode yet, so remember
+ // to either set it to null before deleting pNewNode or add an extra
+ // reference later - this is to make sure we do not do an extra ref/deref
+ // which users may view as getting flushed out of the hash-table
+ //
+ hr = AllocateNode(pszPath,
+ dwHash,
+ pRecord,
+ pParentNode,
+ &pNewNode);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ do
+ {
+ //
+ // Find the right place to add this node
+ //
+
+ if (FindNodeInternal(pszPath, dwHash, &pNextNode, &ppNextPointer))
+ {
+ //
+ // If node already there, record may still need updating
+ //
+ if (pRecord != NULL &&
+ InterlockedCompareExchangePointer((PVOID *)&pNextNode->_pRecord,
+ pRecord,
+ NULL) == NULL)
+ {
+ ReferenceRecord(pRecord);
+ hr = S_OK;
+ }
+ else
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
+ }
+
+ // ownership of pRecord has either passed to existing record or
+ // not to anyone at all
+ pNewNode->_pRecord = NULL;
+ DeleteNode(pNewNode);
+ *ppNewNode = pNextNode;
+ return hr;
+ }
+
+ //
+ // If another node got inserted in betwen, we will have to retry
+ //
+ pNewNode->_pNext = pNextNode;
+ } while (InterlockedCompareExchangePointer((PVOID *)ppNextPointer,
+ pNewNode,
+ pNextNode) != pNextNode);
+ // pass ownership of pRecord now
+ if (pRecord != NULL)
+ {
+ ReferenceRecord(pRecord);
+ pRecord = NULL;
+ }
+ InterlockedIncrement((LONG *)&_nItems);
+
+ //
+ // update the parent
+ //
+ if (pParentNode != NULL)
+ {
+ ppNextPointer = &pParentNode->_pFirstChild;
+ do
+ {
+ pNextNode = *ppNextPointer;
+ pNewNode->_pNextSibling = pNextNode;
+ } while (InterlockedCompareExchangePointer((PVOID *)ppNextPointer,
+ pNewNode,
+ pNextNode) != pNextNode);
+ }
+
+ *ppNewNode = pNewNode;
+ return S_OK;
+}
+
+template
+HRESULT
+TREE_HASH_TABLE<_Record>::InsertRecord(
+ _Record * pRecord
+)
+/*++
+ This method inserts a node for this record and also empty nodes for paths
+ in the heirarchy leading upto this path
+
+ The insert is done under only a read-lock - this is possible by keeping
+ the hashes in a bucket in increasing order and using interlocked operations
+ to actually insert the item in the hash-bucket lookaside list and the parent
+ children list
+
+ Returns HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) if the record already exists.
+ Never leak this error to the end user because "*file* already exists" may be confusing.
+--*/
+{
+ PCWSTR pszKey = GetKey(pRecord);
+ STACK_STRU( strPartialPath, 256);
+ PWSTR pszPartialPath;
+ DWORD dwHash;
+ DWORD cchEnd;
+ HRESULT hr;
+ TREE_HASH_NODE<_Record> *pParentNode = NULL;
+
+ hr = strPartialPath.Copy(pszKey);
+ if (FAILED(hr))
+ {
+ goto Finished;
+ }
+ pszPartialPath = strPartialPath.QueryStr();
+
+ _tableLock.SharedAcquire();
+
+ //
+ // First find the lowest parent node present
+ //
+ for (cchEnd = strPartialPath.QueryCCH() - 1; cchEnd > 0; cchEnd--)
+ {
+ if (pszPartialPath[cchEnd] == L'/' || pszPartialPath[cchEnd] == L'\\')
+ {
+ pszPartialPath[cchEnd] = L'\0';
+
+ dwHash = CalcHash(pszPartialPath);
+ if (FindNodeInternal(pszPartialPath, dwHash, &pParentNode))
+ {
+ pszPartialPath[cchEnd] = pszKey[cchEnd];
+ break;
+ }
+ pParentNode = NULL;
+ }
+ }
+
+ //
+ // Now go ahead and add the rest of the tree (including our record)
+ //
+ for (; cchEnd <= strPartialPath.QueryCCH(); cchEnd++)
+ {
+ if (pszPartialPath[cchEnd] == L'\0')
+ {
+ dwHash = CalcHash(pszPartialPath);
+ hr = AddNodeInternal(
+ pszPartialPath,
+ dwHash,
+ (cchEnd == strPartialPath.QueryCCH()) ? pRecord : NULL,
+ pParentNode,
+ &pParentNode);
+ if (FAILED(hr) &&
+ hr != HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS))
+ {
+ goto Finished;
+ }
+
+ pszPartialPath[cchEnd] = pszKey[cchEnd];
+ }
+ }
+
+Finished:
+ _tableLock.SharedRelease();
+
+ if (SUCCEEDED(hr))
+ {
+ RehashTableIfNeeded();
+ }
+
+ return hr;
+}
+
+template
+VOID
+TREE_HASH_TABLE<_Record>::DeleteNodeInternal(
+ TREE_HASH_NODE<_Record> ** ppNextPointer,
+ TREE_HASH_NODE<_Record> * pNode
+)
+/*++
+ pNode is the node to be deleted
+ ppNextPointer is the pointer to the previous node's next pointer pointing
+ to this node
+
+ This function should be called under write-lock
+--*/
+{
+ //
+ // First remove this node from hash table
+ //
+ *ppNextPointer = pNode->_pNext;
+
+ //
+ // Now fixup parent
+ //
+ if (pNode->_pParentNode != NULL)
+ {
+ ppNextPointer = &pNode->_pParentNode->_pFirstChild;
+ while (*ppNextPointer != pNode)
+ {
+ ppNextPointer = &(*ppNextPointer)->_pNextSibling;
+ }
+ *ppNextPointer = pNode->_pNextSibling;
+ }
+
+ //
+ // Now remove all children recursively
+ //
+ TREE_HASH_NODE<_Record> *pChild = pNode->_pFirstChild;
+ TREE_HASH_NODE<_Record> *pNextChild;
+ while (pChild != NULL)
+ {
+ pNextChild = pChild->_pNextSibling;
+
+ ppNextPointer = _ppBuckets + (pChild->_dwHash % _nBuckets);
+ while (*ppNextPointer != pChild)
+ {
+ ppNextPointer = &(*ppNextPointer)->_pNext;
+ }
+ pChild->_pParentNode = NULL;
+ DeleteNodeInternal(ppNextPointer, pChild);
+
+ pChild = pNextChild;
+ }
+
+ DeleteNode(pNode);
+ _nItems--;
+}
+
+template
+VOID
+TREE_HASH_TABLE<_Record>::DeleteKey(
+ PCWSTR pszKey
+)
+{
+ TREE_HASH_NODE<_Record> *pNode;
+ TREE_HASH_NODE<_Record> **ppPreviousNodeNextPointer;
+
+ DWORD dwHash = CalcHash(pszKey);
+
+ _tableLock.ExclusiveAcquire();
+
+ if (FindNodeInternal(pszKey, dwHash, &pNode, &ppPreviousNodeNextPointer))
+ {
+ DeleteNodeInternal(ppPreviousNodeNextPointer, pNode);
+ }
+
+ _tableLock.ExclusiveRelease();
+}
+
+template
+VOID
+TREE_HASH_TABLE<_Record>::DeleteIf(
+ PFN_DELETE_IF pfnDeleteIf,
+ PVOID pvContext
+)
+{
+ TREE_HASH_NODE<_Record> *pNode;
+ TREE_HASH_NODE<_Record> **ppPreviousNodeNextPointer;
+ BOOL fDelete;
+
+ _tableLock.ExclusiveAcquire();
+
+ for (DWORD i=0; i<_nBuckets; i++)
+ {
+ ppPreviousNodeNextPointer = _ppBuckets + i;
+ pNode = *ppPreviousNodeNextPointer;
+ while (pNode != NULL)
+ {
+ //
+ // Non empty nodes deleted based on DeleteIf, empty nodes deleted
+ // if they have no children
+ //
+ fDelete = FALSE;
+ if (pNode->_pRecord != NULL)
+ {
+ if (pfnDeleteIf(pNode->_pRecord, pvContext))
+ {
+ fDelete = TRUE;
+ }
+ }
+ else if (pNode->_pFirstChild == NULL)
+ {
+ fDelete = TRUE;
+ }
+
+ if (fDelete)
+ {
+ if (pNode->_pFirstChild == NULL)
+ {
+ DeleteNodeInternal(ppPreviousNodeNextPointer, pNode);
+ }
+ else
+ {
+ DereferenceRecord(pNode->_pRecord);
+ pNode->_pRecord = NULL;
+ }
+ }
+ else
+ {
+ ppPreviousNodeNextPointer = &pNode->_pNext;
+ }
+
+ pNode = *ppPreviousNodeNextPointer;
+ }
+ }
+
+ _tableLock.ExclusiveRelease();
+}
+
+template
+VOID
+TREE_HASH_TABLE<_Record>::Apply(
+ PFN_APPLY pfnApply,
+ PVOID pvContext
+)
+{
+ TREE_HASH_NODE<_Record> *pNode;
+
+ _tableLock.SharedAcquire();
+
+ for (DWORD i=0; i<_nBuckets; i++)
+ {
+ pNode = _ppBuckets[i];
+ while (pNode != NULL)
+ {
+ if (pNode->_pRecord != NULL)
+ {
+ pfnApply(pNode->_pRecord, pvContext);
+ }
+
+ pNode = pNode->_pNext;
+ }
+ }
+
+ _tableLock.SharedRelease();
+}
+
+template
+VOID
+TREE_HASH_TABLE<_Record>::RehashTableIfNeeded(
+ VOID
+)
+{
+ TREE_HASH_NODE<_Record> **ppBuckets;
+ DWORD nBuckets;
+ TREE_HASH_NODE<_Record> *pNode;
+ TREE_HASH_NODE<_Record> *pNextNode;
+ TREE_HASH_NODE<_Record> **ppNextPointer;
+ TREE_HASH_NODE<_Record> *pNewNextNode;
+ DWORD nNewBuckets;
+
+ //
+ // If number of items has become too many, we will double the hash table
+ // size (we never reduce it however)
+ //
+ if (_nItems <= PRIME::GetPrime(2*_nBuckets))
+ {
+ return;
+ }
+
+ _tableLock.ExclusiveAcquire();
+
+ nNewBuckets = PRIME::GetPrime(2*_nBuckets);
+
+ if (_nItems <= nNewBuckets)
+ {
+ goto Finished;
+ }
+
+ nBuckets = nNewBuckets;
+ if (nBuckets >= 0xffffffff/sizeof(TREE_HASH_NODE<_Record> *))
+ {
+ goto Finished;
+ }
+ ppBuckets = (TREE_HASH_NODE<_Record> **)HeapAlloc(
+ GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ nBuckets*sizeof(TREE_HASH_NODE<_Record> *));
+ if (ppBuckets == NULL)
+ {
+ goto Finished;
+ }
+
+ //
+ // Take out nodes from the old hash table and insert in the new one, make
+ // sure to keep the hashes in increasing order
+ //
+ for (DWORD i=0; i<_nBuckets; i++)
+ {
+ pNode = _ppBuckets[i];
+ while (pNode != NULL)
+ {
+ pNextNode = pNode->_pNext;
+
+ ppNextPointer = ppBuckets + (pNode->_dwHash % nBuckets);
+ pNewNextNode = *ppNextPointer;
+ while (pNewNextNode != NULL &&
+ pNewNextNode->_dwHash <= pNode->_dwHash)
+ {
+ ppNextPointer = &pNewNextNode->_pNext;
+ pNewNextNode = pNewNextNode->_pNext;
+ }
+ pNode->_pNext = pNewNextNode;
+ *ppNextPointer = pNode;
+
+ pNode = pNextNode;
+ }
+ }
+
+ HeapFree(GetProcessHeap(), 0, _ppBuckets);
+ _ppBuckets = ppBuckets;
+ _nBuckets = nBuckets;
+ ppBuckets = NULL;
+
+Finished:
+
+ _tableLock.ExclusiveRelease();
+}
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/LICENSE b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/LICENSE
new file mode 100644
index 0000000000..21071075c2
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/LICENSE
@@ -0,0 +1,21 @@
+ MIT License
+
+ Copyright (c) Microsoft Corporation. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/MySQL/MySqlConnector.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/MySQL/MySqlConnector.cs
new file mode 100644
index 0000000000..ee607e28c7
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/MySQL/MySqlConnector.cs
@@ -0,0 +1,28 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+
+namespace Microsoft.Web.Utility
+{
+ internal static class MySqlConnector
+ {
+ public static string[] HardCodedAssemblyVersions
+ {
+ get
+ {
+ return new string[]
+ {
+ "MySql.Data, Version=6.5.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d",
+ "MySql.Data, Version=6.4.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d",
+ "MySql.Data, Version=6.3.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d",
+ "MySql.Data, Version=6.2.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d",
+ "MySql.Data, Version=6.0.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d",
+ "MySql.Data, Version=6.0.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d",
+ "MySql.Data, Version=5.2.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d",
+ "MySql.Data, Version=5.2.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d",
+ };
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/AdvApi32.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/AdvApi32.cs
new file mode 100644
index 0000000000..9dc6dbfc23
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/AdvApi32.cs
@@ -0,0 +1,386 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Security;
+using System.Runtime.Versioning;
+using System.Runtime.ConstrainedExecution;
+using Microsoft.Win32.SafeHandles;
+
+namespace Microsoft.Web.Management.PInvoke.AdvApi32
+{
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct TOKEN_PRIVILEGES
+ {
+ public UInt32 PrivilegeCount;
+ public long Luid;
+ public UInt32 Attributes;
+ }
+
+ internal enum TOKEN_INFORMATION_CLASS
+ {
+ ///
+ /// The buffer receives a TOKEN_USER structure that contains the user account of the token.
+ ///
+ TokenUser = 1,
+
+ ///
+ /// The buffer receives a TOKEN_GROUPS structure that contains the group accounts associated with the token.
+ ///
+ TokenGroups,
+
+ ///
+ /// The buffer receives a TOKEN_PRIVILEGES structure that contains the privileges of the token.
+ ///
+ TokenPrivileges,
+
+ ///
+ /// The buffer receives a TOKEN_OWNER structure that contains the default owner security identifier (SID) for newly created objects.
+ ///
+ TokenOwner,
+
+ ///
+ /// The buffer receives a TOKEN_PRIMARY_GROUP structure that contains the default primary group SID for newly created objects.
+ ///
+ TokenPrimaryGroup,
+
+ ///
+ /// The buffer receives a TOKEN_DEFAULT_DACL structure that contains the default DACL for newly created objects.
+ ///
+ TokenDefaultDacl,
+
+ ///
+ /// The buffer receives a TOKEN_SOURCE structure that contains the source of the token. TOKEN_QUERY_SOURCE access is needed to retrieve this information.
+ ///
+ TokenSource,
+
+ ///
+ /// The buffer receives a TOKEN_TYPE value that indicates whether the token is a primary or impersonation token.
+ ///
+ TokenType,
+
+ ///
+ /// The buffer receives a SECURITY_IMPERSONATION_LEVEL value that indicates the impersonation level of the token. If the access token is not an impersonation token, the function fails.
+ ///
+ TokenImpersonationLevel,
+
+ ///
+ /// The buffer receives a TOKEN_STATISTICS structure that contains various token statistics.
+ ///
+ TokenStatistics,
+
+ ///
+ /// The buffer receives a TOKEN_GROUPS structure that contains the list of restricting SIDs in a restricted token.
+ ///
+ TokenRestrictedSids,
+
+ ///
+ /// The buffer receives a DWORD value that indicates the Terminal Services session identifier that is associated with the token.
+ ///
+ TokenSessionId,
+
+ ///
+ /// The buffer receives a TOKEN_GROUPS_AND_PRIVILEGES structure that contains the user SID, the group accounts, the restricted SIDs, and the authentication ID associated with the token.
+ ///
+ TokenGroupsAndPrivileges,
+
+ ///
+ /// Reserved.
+ ///
+ TokenSessionReference,
+
+ ///
+ /// The buffer receives a DWORD value that is nonzero if the token includes the SANDBOX_INERT flag.
+ ///
+ TokenSandBoxInert,
+
+ ///
+ /// Reserved.
+ ///
+ TokenAuditPolicy,
+
+ ///
+ /// The buffer receives a TOKEN_ORIGIN value.
+ ///
+ TokenOrigin,
+
+ ///
+ /// The buffer receives a TOKEN_ELEVATION_TYPE value that specifies the elevation level of the token.
+ ///
+ TokenElevationType,
+
+ ///
+ /// The buffer receives a TOKEN_LINKED_TOKEN structure that contains a handle to another token that is linked to this token.
+ ///
+ TokenLinkedToken,
+
+ ///
+ /// The buffer receives a TOKEN_ELEVATION structure that specifies whether the token is elevated.
+ ///
+ TokenElevation,
+
+ ///
+ /// The buffer receives a DWORD value that is nonzero if the token has ever been filtered.
+ ///
+ TokenHasRestrictions,
+
+ ///
+ /// The buffer receives a TOKEN_ACCESS_INFORMATION structure that specifies security information contained in the token.
+ ///
+ TokenAccessInformation,
+
+ ///
+ /// The buffer receives a DWORD value that is nonzero if virtualization is allowed for the token.
+ ///
+ TokenVirtualizationAllowed,
+
+ ///
+ /// The buffer receives a DWORD value that is nonzero if virtualization is enabled for the token.
+ ///
+ TokenVirtualizationEnabled,
+
+ ///
+ /// The buffer receives a TOKEN_MANDATORY_LABEL structure that specifies the token's integrity level.
+ ///
+ TokenIntegrityLevel,
+
+ ///
+ /// The buffer receives a DWORD value that is nonzero if the token has the UIAccess flag set.
+ ///
+ TokenUIAccess,
+
+ ///
+ /// The buffer receives a TOKEN_MANDATORY_POLICY structure that specifies the token's mandatory integrity policy.
+ ///
+ TokenMandatoryPolicy,
+
+ ///
+ /// The buffer receives the token's logon security identifier (SID).
+ ///
+ TokenLogonSid,
+
+ ///
+ /// The maximum value for this enumeration
+ ///
+ MaxTokenInfoClass
+ }
+
+ internal enum TOKEN_ELEVATION_TYPE
+ {
+ TokenElevationTypeDefault = 1,
+ TokenElevationTypeFull,
+ TokenElevationTypeLimited
+ }
+
+ [Flags]
+ internal enum AccessTokenRights : uint
+ {
+ STANDARD_RIGHTS_REQUIRED = 0x000F0000,
+ STANDARD_RIGHTS_READ = 0x00020000,
+ TOKEN_ASSIGN_PRIMARY = 0x0001,
+ TOKEN_DUPLICATE = 0x0002,
+ TOKEN_IMPERSONATE = 0x0004,
+ TOKEN_QUERY = 0x0008,
+ TOKEN_QUERY_SOURCE = 0x0010,
+ TOKEN_ADJUST_PRIVILEGES = 0x0020,
+ TOKEN_ADJUST_GROUPS = 0x0040,
+ TOKEN_ADJUST_DEFAULT = 0x0080,
+ TOKEN_ADJUST_SESSIONID = 0x0100,
+ TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY,
+ TOKEN_ALL_ACCESS =
+ STANDARD_RIGHTS_REQUIRED |
+ TOKEN_ASSIGN_PRIMARY |
+ TOKEN_DUPLICATE |
+ TOKEN_IMPERSONATE |
+ TOKEN_QUERY |
+ TOKEN_QUERY_SOURCE |
+ TOKEN_ADJUST_PRIVILEGES |
+ TOKEN_ADJUST_GROUPS |
+ TOKEN_ADJUST_DEFAULT |
+ TOKEN_ADJUST_SESSIONID
+ }
+
+ internal static class NativeMethods
+ {
+ private const String ADVAPI32 = "advapi32.dll";
+
+ // TODO: Should be moved into enums?
+ internal const int READ_CONTROL = 0x00020000;
+ internal const int SYNCHRONIZE = 0x00100000;
+ internal const int STANDARD_RIGHTS_READ = READ_CONTROL;
+ internal const int STANDARD_RIGHTS_WRITE = READ_CONTROL;
+
+ internal const int KEY_QUERY_VALUE = 0x0001;
+ internal const int KEY_SET_VALUE = 0x0002;
+ internal const int KEY_CREATE_SUB_KEY = 0x0004;
+ internal const int KEY_ENUMERATE_SUB_KEYS = 0x0008;
+ internal const int KEY_NOTIFY = 0x0010;
+
+ internal const int KEY_READ = ((STANDARD_RIGHTS_READ |
+ KEY_QUERY_VALUE |
+ KEY_ENUMERATE_SUB_KEYS |
+ KEY_NOTIFY)
+ &
+ (~SYNCHRONIZE));
+
+ internal const int KEY_WRITE = ((STANDARD_RIGHTS_WRITE |
+ KEY_SET_VALUE |
+ KEY_CREATE_SUB_KEY)
+ &
+ (~SYNCHRONIZE));
+
+ internal const int KEY_WOW64_64KEY = 0x0100;
+ internal const int KEY_WOW64_32KEY = 0x0200;
+
+ internal const int ERROR_MORE_DATA = 0xEA;
+ internal const int ERROR_ACCESS_DENIED = 0x5;
+
+ internal const int REG_OPTION_NON_VOLATILE = 0x0000; // (default) keys are persisted beyond reboot/unload
+ internal const int REG_OPTION_VOLATILE = 0x0001; // All keys created by the function are volatile
+ internal const int REG_OPTION_CREATE_LINK = 0x0002; // They key is a symbolic link
+ internal const int REG_OPTION_BACKUP_RESTORE = 0x0004; // Use SE_BACKUP_NAME process special privileges
+ internal const int REG_NONE = 0; // No value type
+ internal const int REG_SZ = 1; // Unicode nul terminated string
+ internal const int REG_EXPAND_SZ = 2; // Unicode nul terminated string
+ internal const int REG_BINARY = 3; // Free form binary
+ internal const int REG_DWORD = 4; // 32-bit number
+ internal const int REG_DWORD_LITTLE_ENDIAN = 4; // 32-bit number (same as REG_DWORD)
+ internal const int REG_DWORD_BIG_ENDIAN = 5; // 32-bit number
+ internal const int REG_LINK = 6; // Symbolic Link (unicode)
+ internal const int REG_MULTI_SZ = 7; // Multiple Unicode strings
+ internal const int REG_RESOURCE_LIST = 8; // Resource list in the resource map
+ internal const int REG_FULL_RESOURCE_DESCRIPTOR = 9; // Resource list in the hardware description
+ internal const int REG_RESOURCE_REQUIREMENTS_LIST = 10;
+ internal const int REG_QWORD = 11; // 64-bit number
+
+ [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool AdjustTokenPrivileges(
+ SafeHandleZeroIsInvalid TokenHandle,
+ [MarshalAs(UnmanagedType.Bool)]
+ bool DisableAllPrivileges,
+ ref TOKEN_PRIVILEGES NewState,
+ int len,
+ IntPtr prev,
+ IntPtr relen);
+
+ [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
+
+ [DllImport("advapi32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool GetTokenInformation(
+ SafeHandleZeroIsInvalid TokenHandle,
+ TOKEN_INFORMATION_CLASS TokenInformationClass,
+ HGlobalBuffer TokenInformation,
+ int TokenInformationLength,
+ out int ReturnLength);
+
+ [DllImport("advapi32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool OpenProcessToken(
+ SafeHandleZeroIsInvalid ProcessHandle,
+ AccessTokenRights DesiredAccess,
+ out SafeHandleZeroIsInvalid TokenHandle);
+
+ [DllImport("ADVAPI32.DLL"),
+ SuppressUnmanagedCodeSecurity,
+ ResourceExposure(ResourceScope.None),
+ ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern int RegCloseKey(IntPtr hKey);
+
+ [DllImport(ADVAPI32, CharSet = CharSet.Auto, BestFitMapping = false)]
+ internal static extern int RegOpenKeyEx(SafeRegistryHandle hKey, String lpSubKey,
+ int ulOptions, int samDesired, out SafeRegistryHandle hkResult);
+
+ [DllImport(ADVAPI32, CharSet = CharSet.Auto, BestFitMapping = false)]
+ internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int[] lpReserved, ref int lpType, [Out] byte[] lpData,
+ ref int lpcbData);
+
+ [DllImport(ADVAPI32, CharSet = CharSet.Auto, BestFitMapping = false)]
+ internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int[] lpReserved, ref int lpType, ref int lpData,
+ ref int lpcbData);
+
+ [DllImport(ADVAPI32, CharSet = CharSet.Auto, BestFitMapping = false)]
+ internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int[] lpReserved, ref int lpType, ref long lpData,
+ ref int lpcbData);
+
+ [DllImport(ADVAPI32, CharSet = CharSet.Auto, BestFitMapping = false)]
+ internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int[] lpReserved, ref int lpType, [Out] char[] lpData,
+ ref int lpcbData);
+
+ [DllImport(ADVAPI32, CharSet = CharSet.Auto, BestFitMapping = false)]
+ internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int[] lpReserved, ref int lpType, StringBuilder lpData,
+ ref int lpcbData);
+
+ public static void EnableShutdownPrivilege()
+ {
+ const int SE_PRIVILEGE_ENABLED = 0x00000002;
+ const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
+
+ bool retVal;
+
+ using (SafeHandleZeroIsInvalid hproc = Kernel32.NativeMethods.GetCurrentProcess())
+ {
+ TOKEN_PRIVILEGES tp;
+ SafeHandleZeroIsInvalid htok;
+ retVal = OpenProcessToken(hproc, AccessTokenRights.TOKEN_ADJUST_PRIVILEGES | AccessTokenRights.TOKEN_QUERY, out htok);
+ if (!retVal)
+ {
+ throw new Win32Exception(Marshal.GetLastWin32Error());
+ }
+
+ using (htok)
+ {
+ tp.PrivilegeCount = 1;
+ tp.Luid = 0;
+ tp.Attributes = SE_PRIVILEGE_ENABLED;
+ retVal = LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);
+ if (!retVal)
+ {
+ throw new Win32Exception(Marshal.GetLastWin32Error());
+ }
+
+ retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
+ if (!retVal)
+ {
+ throw new Win32Exception(Marshal.GetLastWin32Error());
+ }
+ }
+ }
+ }
+ }
+
+ [SecurityCritical]
+ internal sealed class SafeRegistryHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ [SecurityCritical]
+ internal SafeRegistryHandle()
+ : base(true)
+ {
+ }
+
+ [SecurityCritical]
+ public SafeRegistryHandle(IntPtr preexistingHandle, bool ownsHandle)
+ : base(ownsHandle)
+ {
+ SetHandle(preexistingHandle);
+ }
+
+ [SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ return (Microsoft.Web.Management.PInvoke.AdvApi32.NativeMethods.RegCloseKey(handle) == 0);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Common.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Common.cs
new file mode 100644
index 0000000000..6d6a3209a7
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Common.cs
@@ -0,0 +1,111 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+
+// Any reference to Common.cs should also include Kernel32.cs because
+// SafeHandleZeroIsInvalid (from Common.cs) uses CloseHandle (from Kernel32.cs)
+namespace Microsoft.Web.Management.PInvoke
+{
+ internal enum Win32ErrorCode
+ {
+ ERROR_FILE_NOT_FOUND = 2,
+ ERROR_PATH_NOT_FOUND = 3,
+ ERROR_ACCESS_DENIED = 5,
+ ERROR_INVALID_HANDLE = 6,
+ ERROR_INVALID_DRIVE = 15,
+ ERROR_NO_MORE_FILES = 18,
+ ERROR_NOT_READY = 21,
+ ERROR_SHARING_VIOLATION = 32,
+ ERROR_FILE_EXISTS = 80,
+ ERROR_INVALID_PARAMETER = 87, // 0x57
+ ERROR_INVALID_NAME = 123, // 0x7b
+ ERROR_BAD_PATHNAME = 161,
+ ERROR_ALREADY_EXISTS = 183,
+ ERROR_FILENAME_EXCED_RANGE = 206,
+ ERROR_OPERATION_ABORTED = 995,
+ ELEMENT_NOT_FOUND = 0x490
+ }
+
+ internal static class Extension
+ {
+ public static int AsHRESULT(Win32ErrorCode errorCode)
+ {
+ return (int)((uint)errorCode | 0x80070000);
+ }
+ }
+
+ internal class SafeHandleZeroIsInvalid : SafeHandle
+ {
+ public SafeHandleZeroIsInvalid()
+ : base(IntPtr.Zero, true)
+ {
+ }
+
+ public SafeHandleZeroIsInvalid(IntPtr newHandle)
+ : base(IntPtr.Zero, true)
+ {
+ this.SetHandle(newHandle);
+ }
+
+ public override bool IsInvalid
+ {
+ get
+ {
+ return this.handle == IntPtr.Zero;
+ }
+ }
+
+ protected override bool ReleaseHandle()
+ {
+ return Kernel32.NativeMethods.CloseHandle(this.handle);
+ }
+ }
+
+ internal class HGlobalBuffer : SafeHandle
+ {
+ private int _size;
+
+ public HGlobalBuffer(int size)
+ : base(IntPtr.Zero, true)
+ {
+ _size = size;
+ this.handle = Marshal.AllocHGlobal(size);
+ }
+
+ protected override bool ReleaseHandle()
+ {
+ if (!this.IsInvalid)
+ {
+ Marshal.FreeHGlobal(this.handle);
+ this.handle = IntPtr.Zero;
+ }
+
+ return true;
+ }
+
+ public override bool IsInvalid
+ {
+ get
+ {
+ return this.handle == IntPtr.Zero;
+ }
+ }
+
+ public T GetCopyAs()
+ {
+ return (T)Marshal.PtrToStructure(this.handle, typeof(T));
+ }
+
+ public int Size
+ {
+ get
+ {
+ return _size;
+ }
+ }
+
+ public static readonly HGlobalBuffer NULL = new HGlobalBuffer(0);
+ }
+}
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Fusion.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Fusion.cs
new file mode 100644
index 0000000000..dd3391ff94
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Fusion.cs
@@ -0,0 +1,179 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Microsoft.Web.Utility.PInvoke.Fusion
+{
+ [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("CD193BC0-B4BC-11d2-9833-00C04FC31D2E")]
+ internal interface IAssemblyName
+ {
+ [PreserveSig()]
+ int SetProperty(
+ int PropertyId,
+ IntPtr pvProperty,
+ int cbProperty);
+
+ [PreserveSig()]
+ int GetProperty(
+ int PropertyId,
+ IntPtr pvProperty,
+ ref int pcbProperty);
+
+ [PreserveSig()]
+ int Finalize();
+
+ [PreserveSig()]
+ int GetDisplayName(
+ StringBuilder pDisplayName,
+ ref int pccDisplayName,
+ int displayFlags);
+
+ [PreserveSig()]
+ int Reserved(ref Guid guid,
+ Object obj1,
+ Object obj2,
+ String string1,
+ Int64 llFlags,
+ IntPtr pvReserved,
+ int cbReserved,
+ out IntPtr ppv);
+
+ [PreserveSig()]
+ int GetName(
+ ref int pccBuffer,
+ StringBuilder pwzName);
+
+ [PreserveSig()]
+ int GetVersion(
+ out int versionHi,
+ out int versionLow);
+ [PreserveSig()]
+ int IsEqual(
+ IAssemblyName pAsmName,
+ int cmpFlags);
+
+ [PreserveSig()]
+ int Clone(out IAssemblyName pAsmName);
+ }// IAssemblyName
+
+ [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("e707dcde-d1cd-11d2-bab9-00c04f8eceae")]
+ internal interface IAssemblyCache
+ {
+ [PreserveSig()]
+ int UninstallAssembly(
+ int flags,
+ [MarshalAs(UnmanagedType.LPWStr)]
+ string assemblyName,
+ IntPtr refData,
+ out int disposition);
+
+ [PreserveSig()]
+ int QueryAssemblyInfo(
+ int flags,
+ [MarshalAs(UnmanagedType.LPWStr)]
+ string assemblyName,
+ ref AssemblyInfo assemblyInfo);
+ [PreserveSig()]
+ int Reserved(
+ int flags,
+ IntPtr pvReserved,
+ out object ppAsmItem,
+ [MarshalAs(UnmanagedType.LPWStr)]
+ string assemblyName);
+ [PreserveSig()]
+ int Reserved(out object ppAsmScavenger);
+
+ [PreserveSig()]
+ int InstallAssembly(
+ int flags,
+ [MarshalAs(UnmanagedType.LPWStr)]
+ string assemblyFilePath,
+ IntPtr refData);
+ }// IAssemblyCache
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct AssemblyInfo
+ {
+ public int cbAssemblyInfo; // size of this structure for future expansion
+ public int assemblyFlags;
+ public long assemblySizeInKB;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string currentAssemblyPath;
+ public int cchBuf; // size of path buf.
+ }
+
+ [Flags]
+ internal enum AssemblyCacheFlags
+ {
+ GAC = 2,
+ }
+
+ [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("21b8916c-f28e-11d2-a473-00c04f8ef448")]
+ internal interface IAssemblyEnum
+ {
+ [PreserveSig()]
+ int GetNextAssembly(
+ IntPtr pvReserved,
+ out IAssemblyName ppName,
+ int flags);
+
+ [PreserveSig()]
+ int Reset();
+ [PreserveSig()]
+ int Clone(out IAssemblyEnum ppEnum);
+ }
+
+ [Flags]
+ internal enum AssemblyNameDisplayFlags
+ {
+ VERSION = 0x01,
+ CULTURE = 0x02,
+ PUBLIC_KEY_TOKEN = 0x04,
+ PROCESSORARCHITECTURE = 0x20,
+ RETARGETABLE = 0x80,
+
+ // This enum might change in the future to include
+ // more attributes.
+ ALL =
+ VERSION
+ | CULTURE
+ | PUBLIC_KEY_TOKEN
+ | PROCESSORARCHITECTURE
+ | RETARGETABLE
+ }
+
+ internal enum CreateAssemblyNameObjectFlags
+ {
+ CANOF_DEFAULT = 0,
+ CANOF_PARSE_DISPLAY_NAME = 1,
+ }
+
+ internal static class NativeMethods
+ {
+ [DllImport("fusion.dll")]
+ public static extern int CreateAssemblyCache(
+ out IAssemblyCache ppAsmCache,
+ int reserved);
+
+ [DllImport("fusion.dll")]
+ public static extern int CreateAssemblyEnum(
+ out IAssemblyEnum ppEnum,
+ IntPtr pUnkReserved,
+ IAssemblyName pName,
+ AssemblyCacheFlags flags,
+ IntPtr pvReserved);
+
+ [DllImport("fusion.dll")]
+ public static extern int CreateAssemblyNameObject(
+ out IAssemblyName ppAssemblyNameObj,
+ [MarshalAs(UnmanagedType.LPWStr)]
+ String szAssemblyName,
+ CreateAssemblyNameObjectFlags flags,
+ IntPtr pvReserved);
+ }
+}
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Kernel32.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Kernel32.cs
new file mode 100644
index 0000000000..91265956b5
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Kernel32.cs
@@ -0,0 +1,99 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.InteropServices;
+
+// Any reference to Common.cs should also include Kernel32.cs because
+// SafeHandleZeroIsInvalid (from Common.cs) uses CloseHandle (from Kernel32.cs)
+namespace Microsoft.Web.Management.PInvoke.Kernel32
+{
+ internal enum OSProductType : byte
+ {
+ VER_NT_WORKSTATION = 0x0000001,
+ VER_NT_SERVER = 0x0000003,
+ VER_NT_DOMAIN_CONTROLLER = 0x0000002,
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct OSVERSIONINFOEX
+ {
+ public int dwOSVersionInfoSize;
+ public int dwMajorVersion;
+ public int dwMinorVersion;
+ public int dwBuildNumber;
+ public int dwPlatformId;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
+ public string szCSDVersion;
+ public short wServicePackMajor;
+ public short wServicePackMinor;
+ public short wSuiteMask;
+ public OSProductType wProductType;
+ public byte wReserved;
+
+ public bool IsServer
+ {
+ get
+ {
+ return
+ wProductType == OSProductType.VER_NT_SERVER ||
+ wProductType == OSProductType.VER_NT_DOMAIN_CONTROLLER;
+ }
+ }
+
+ public bool IsClient
+ {
+ get
+ {
+ return
+ wProductType == OSProductType.VER_NT_WORKSTATION;
+ }
+ }
+ }
+
+ internal static class NativeMethods
+ {
+ public static OSVERSIONINFOEX GetVersionEx()
+ {
+ OSVERSIONINFOEX osVersionInfo = new OSVERSIONINFOEX();
+ osVersionInfo.dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX));
+ if (!GetVersionEx(ref osVersionInfo))
+ {
+ throw new Win32Exception();
+ }
+
+ return osVersionInfo;
+ }
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool CloseHandle(IntPtr hHandle);
+
+ [DllImport("kernel32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ [SuppressMessage("Microsoft.Usage", "CA2205:UseManagedEquivalentsOfWin32Api", Justification = "GetVersionEx returns more information")]
+ private static extern bool GetVersionEx(ref OSVERSIONINFOEX osVersionInfo);
+
+ [DllImport("kernel32.dll", ExactSpelling = true)]
+ internal static extern SafeHandleZeroIsInvalid GetCurrentProcess();
+
+ // WARNING: Vista+ ONLY
+ [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool GetProductInfo(uint dwOSMajorVersion, uint dwOSMinorVersion, uint dwSpMajorVersion, uint spMinorVersion, out uint pdwReturnedProductType);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WritePrivateProfileString(string applicationName, string keyName, string stringValue, string fileName);
+ }
+}
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Mlang.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Mlang.cs
new file mode 100644
index 0000000000..e6e1ff51bd
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Mlang.cs
@@ -0,0 +1,768 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+
+namespace Microsoft.Web.Management.PInvoke.MLang
+{
+ internal enum HRESULT : uint
+ {
+ S_OK = 0x0,
+ S_FALSE = 0x1,
+ E_FAIL = 0x80004005,
+ }
+
+ internal static class NativeMethods
+ {
+ [StructLayout(LayoutKind.Explicit, Pack = 4)]
+ public struct __MIDL_IWinTypes_0009
+ {
+ // Fields
+ [FieldOffset(0)]
+ public int hInproc;
+ [FieldOffset(0)]
+ public int hRemote;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ public struct _RemotableHandle
+ {
+ public int fContext;
+ public __MIDL_IWinTypes_0009 u;
+ }
+
+ [ComImport, CoClass(typeof(CMLangConvertCharsetClass)), Guid("D66D6F98-CDAA-11D0-B822-00C04FC9B31F")]
+ public interface CMLangConvertCharset : IMLangConvertCharset
+ {
+ }
+
+ [ComImport, TypeLibType((short)2), Guid("D66D6F99-CDAA-11D0-B822-00C04FC9B31F"), ClassInterface((short)0)]
+ public class CMLangConvertCharsetClass : IMLangConvertCharset, CMLangConvertCharset
+ {
+ // Methods
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void DoConversion([In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void DoConversionFromUnicode([In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void DoConversionToUnicode([In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetDestinationCodePage(out uint puiDstCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetProperty(out uint pdwProperty);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetSourceCodePage(out uint puiSrcCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void Initialize([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty);
+ }
+
+ [ComImport, Guid("C04D65CE-B70D-11D0-B188-00AA0038C969"), CoClass(typeof(CMLangStringClass))]
+ public interface CMLangString : IMLangString
+ {
+ }
+
+ [ComImport, TypeLibType((short)2), Guid("C04D65CF-B70D-11D0-B188-00AA0038C969"), ClassInterface((short)0)]
+ public class CMLangStringClass : IMLangString, CMLangString, IMLangStringWStr, IMLangStringAStr
+ {
+ // Methods
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetAStr([In] int lSrcPos, [In] int lSrcLen, [In] uint uCodePageIn, out uint puCodePageOut, [Out, MarshalAs(UnmanagedType.LPStr)] string pszDest, [In] int cchDest, out int pcchActual, out int plActualLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern int GetLength();
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetLocale([In] int lSrcPos, [In] int lSrcMaxLen, out uint plocale, out int plLocalePos, out int plLocaleLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetMLStr([In] int lSrcPos, [In] int lSrcLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, [In] uint dwClsContext, [In] ref Guid piid, [MarshalAs(UnmanagedType.IUnknown)] out object ppDestMLStr, out int plDestPos, out int plDestLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetStrBufA([In] int lSrcPos, [In] int lSrcMaxLen, out uint puDestCodePage, [MarshalAs(UnmanagedType.Interface)] out IMLangStringBufA ppDestBuf, out int plDestLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetStrBufW([In] int lSrcPos, [In] int lSrcMaxLen, [MarshalAs(UnmanagedType.Interface)] out IMLangStringBufW ppDestBuf, out int plDestLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetWStr([In] int lSrcPos, [In] int lSrcLen, [Out, MarshalAs(UnmanagedType.LPWStr)] string pszDest, [In] int cchDest, out int pcchActual, out int plActualLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern int IMLangStringAStr_GetLength();
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMLangStringAStr_GetLocale([In] int lSrcPos, [In] int lSrcMaxLen, out uint plocale, out int plLocalePos, out int plLocaleLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMLangStringAStr_GetMLStr([In] int lSrcPos, [In] int lSrcLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, [In] uint dwClsContext, [In] ref Guid piid, [MarshalAs(UnmanagedType.IUnknown)] out object ppDestMLStr, out int plDestPos, out int plDestLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMLangStringAStr_SetLocale([In] int lDestPos, [In] int lDestLen, [In] uint locale);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMLangStringAStr_SetMLStr([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pSrcMLStr, [In] int lSrcPos, [In] int lSrcLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMLangStringAStr_Sync([In] int fNoAccess);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern int IMLangStringWStr_GetLength();
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMLangStringWStr_GetMLStr([In] int lSrcPos, [In] int lSrcLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, [In] uint dwClsContext, [In] ref Guid piid, [MarshalAs(UnmanagedType.IUnknown)] out object ppDestMLStr, out int plDestPos, out int plDestLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMLangStringWStr_SetMLStr([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pSrcMLStr, [In] int lSrcPos, [In] int lSrcLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMLangStringWStr_Sync([In] int fNoAccess);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void LockAStr([In] int lSrcPos, [In] int lSrcLen, [In] int lFlags, [In] uint uCodePageIn, [In] int cchRequest, out uint puCodePageOut, [MarshalAs(UnmanagedType.LPStr)] out string ppszDest, out int pcchDest, out int plDestLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void LockWStr([In] int lSrcPos, [In] int lSrcLen, [In] int lFlags, [In] int cchRequest, [MarshalAs(UnmanagedType.LPWStr)] out string ppszDest, out int pcchDest, out int plDestLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void SetAStr([In] int lDestPos, [In] int lDestLen, [In] uint uCodePage, [In, MarshalAs(UnmanagedType.LPStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void SetLocale([In] int lDestPos, [In] int lDestLen, [In] uint locale);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void SetMLStr([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pSrcMLStr, [In] int lSrcPos, [In] int lSrcLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void SetStrBufA([In] int lDestPos, [In] int lDestLen, [In] uint uCodePage, [In, MarshalAs(UnmanagedType.Interface)] IMLangStringBufA pSrcBuf, out int pcchActual, out int plActualLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void SetStrBufW([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.Interface)] IMLangStringBufW pSrcBuf, out int pcchActual, out int plActualLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void SetWStr([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.LPWStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void Sync([In] int fNoAccess);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void UnlockAStr([In, MarshalAs(UnmanagedType.LPStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void UnlockWStr([In, MarshalAs(UnmanagedType.LPWStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen);
+ }
+
+ [ComImport, Guid("275C23E1-3747-11D0-9FEA-00AA003F8646"), CoClass(typeof(CMultiLanguageClass))]
+ public interface CMultiLanguage : IMultiLanguage
+ {
+ }
+
+ [ComImport, TypeLibType(TypeLibTypeFlags.FCanCreate), ClassInterface(ClassInterfaceType.None), Guid("275C23E2-3747-11D0-9FEA-00AA003F8646")]
+ public class CMultiLanguageClass : IMultiLanguage, CMultiLanguage, IMLangCodePages, IMLangFontLink, IMLangLineBreakConsole, IMultiLanguage2, IMLangFontLink2, IMultiLanguage3
+ {
+ // Methods
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void BreakLineA([In] uint locale, [In] uint uCodePage, [In] ref sbyte pszSrc, [In] int cchSrc, [In] int cMaxColumns, out int pcchLine, out int pcchSkip);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void BreakLineML([In, MarshalAs(UnmanagedType.Interface)] CMLangString pSrcMLStr, [In] int lSrcPos, [In] int lSrcLen, [In] int cMinColumns, [In] int cMaxColumns, out int plLineLen, out int plSkipLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void BreakLineW([In] uint locale, [In] ref ushort pszSrc, [In] int cchSrc, [In] int cMaxColumns, out int pcchLine, out int pcchSkip);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void CodePagesToCodePage([In] uint dwCodePages, [In] uint uDefaultCodePage, out uint puCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void CodePageToCodePages([In] uint uCodePage, out uint pdwCodePages);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void CodePageToScriptID([In] uint uiCodePage, out byte pSid);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void ConvertString([In, Out] ref uint pdwMode, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void ConvertStringFromUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void ConvertStringFromUnicodeEx([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize, [In] uint dwFlag, [In] ref ushort lpFallBack);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void ConvertStringInIStream([In, Out] ref uint pdwMode, [In] uint dwFlag, [In] ref ushort lpFallBack, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmIn, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmOut);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void ConvertStringReset();
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void ConvertStringToUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void ConvertStringToUnicodeEx([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize, [In] uint dwFlag, [In] ref ushort lpFallBack);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void CreateConvertCharset([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty, [MarshalAs(UnmanagedType.Interface)] out CMLangConvertCharset ppMLangConvertCharset);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void DetectCodepageInIStream([In] uint dwFlag, [In] uint dwPrefWinCodePage, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmIn, out DetectEncodingInfo lpEncoding, [In, Out] ref int pnScores);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ [PreserveSig]
+ public virtual extern HRESULT DetectInputCodepage([In] MLDETECTCP dwFlag, [In] uint dwPrefWinCodePage, [In] ref byte pSrcStr, [In, Out] ref int pcSrcSize, ref DetectEncodingInfo lpEncoding, [In, Out] ref int pnScores);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void DetectOutboundCodePage([In] uint dwFlags, [In, MarshalAs(UnmanagedType.LPWStr)] string lpWideCharStr, [In] uint cchWideChar, [In] ref uint puiPreferredCodePages, [In] uint nPreferredCodePages, out uint puiDetectedCodePages, [In, Out] ref uint pnDetectedCodePages, [In, MarshalAs(UnmanagedType.LPWStr)] string lpSpecialChar);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void DetectOutboundCodePageInIStream([In] uint dwFlags, [In, MarshalAs(UnmanagedType.Interface)] IStream pStrIn, [In] ref uint puiPreferredCodePages, [In] uint nPreferredCodePages, out uint puiDetectedCodePages, [In, Out] ref uint pnDetectedCodePages, [In, MarshalAs(UnmanagedType.LPWStr)] string lpSpecialChar);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ [return: MarshalAs(UnmanagedType.Interface)]
+ public virtual extern IEnumCodePage EnumCodePages([In] NativeMethods.MIMECONTF grfFlags);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void EnumCodePages([In] uint grfFlags, [In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumCodePage ppEnumCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void EnumRfc1766([MarshalAs(UnmanagedType.Interface)] out IEnumRfc1766 ppEnumRfc1766);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void EnumRfc1766([In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumRfc1766 ppEnumRfc1766);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void EnumScripts([In] uint dwFlags, [In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumScript ppEnumScript);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetCharCodePages([In] ushort chSrc, out uint pdwCodePages);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetCharsetInfo([In, MarshalAs(UnmanagedType.BStr)] string Charset, out MIMECSETINFO pCharsetInfo);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetCodePageDescription([In] uint uiCodePage, [In] uint lcid, [Out, MarshalAs(UnmanagedType.LPWStr)] string lpWideCharStr, [In] int cchWideChar);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetCodePageInfo([In] uint uiCodePage, out MIMECPINFO pCodePageInfo);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetCodePageInfo([In] uint uiCodePage, [In] ushort LangId, out MIMECPINFO pCodePageInfo);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetFamilyCodePage([In] uint uiCodePage, out uint puiFamilyCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetFontCodePages([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont, out uint pdwCodePages);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetFontUnicodeRanges([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In, Out] ref uint puiRanges, out UNICODERANGE pUranges);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetLcidFromRfc1766(out uint plocale, [In, MarshalAs(UnmanagedType.BStr)] string bstrRfc1766);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetNumberOfCodePageInfo(out uint pcCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetNumberOfScripts(out uint pnScripts);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetRfc1766FromLcid([In] uint locale, [MarshalAs(UnmanagedType.BStr)] out string pbstrRfc1766);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetRfc1766Info([In] uint locale, out RFC1766INFO pRfc1766Info);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetRfc1766Info([In] uint locale, [In] ushort LangId, out RFC1766INFO pRfc1766Info);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetScriptFontInfo([In] byte sid, [In] uint dwFlags, [In, Out] ref uint puiFonts, out SCRIPFONTINFO pScriptFont);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void GetStrCodePages([In] ref ushort pszSrc, [In] int cchSrc, [In] uint dwPriorityCodePages, out uint pdwCodePages, out int pcchCodePages);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMLangFontLink_CodePagesToCodePage([In] uint dwCodePages, [In] uint uDefaultCodePage, out uint puCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMLangFontLink_CodePageToCodePages([In] uint uCodePage, out uint pdwCodePages);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMLangFontLink_GetCharCodePages([In] ushort chSrc, out uint pdwCodePages);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMLangFontLink_GetStrCodePages([In] ref ushort pszSrc, [In] int cchSrc, [In] uint dwPriorityCodePages, out uint pdwCodePages, out int pcchCodePages);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMLangFontLink2_CodePagesToCodePage([In] uint dwCodePages, [In] uint uDefaultCodePage, out uint puCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMLangFontLink2_CodePageToCodePages([In] uint uCodePage, out uint pdwCodePages);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMLangFontLink2_GetCharCodePages([In] ushort chSrc, out uint pdwCodePages);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMLangFontLink2_GetFontCodePages([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont, out uint pdwCodePages);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMLangFontLink2_GetStrCodePages([In] ref ushort pszSrc, [In] int cchSrc, [In] uint dwPriorityCodePages, out uint pdwCodePages, out int pcchCodePages);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMLangFontLink2_ReleaseFont([In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMLangFontLink2_ResetFontMapping();
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage2_ConvertString([In, Out] ref uint pdwMode, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage2_ConvertStringFromUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage2_ConvertStringReset();
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage2_ConvertStringToUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage2_CreateConvertCharset([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty, [MarshalAs(UnmanagedType.Interface)] out CMLangConvertCharset ppMLangConvertCharset);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage2_GetCharsetInfo([In, MarshalAs(UnmanagedType.BStr)] string Charset, out MIMECSETINFO pCharsetInfo);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage2_GetFamilyCodePage([In] uint uiCodePage, out uint puiFamilyCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage2_GetLcidFromRfc1766(out uint plocale, [In, MarshalAs(UnmanagedType.BStr)] string bstrRfc1766);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage2_GetNumberOfCodePageInfo(out uint pcCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage2_GetRfc1766FromLcid([In] uint locale, [MarshalAs(UnmanagedType.BStr)] out string pbstrRfc1766);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage2_IsConvertible([In] uint dwSrcEncoding, [In] uint dwDstEncoding);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_ConvertString([In, Out] ref uint pdwMode, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_ConvertStringFromUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_ConvertStringFromUnicodeEx([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize, [In] uint dwFlag, [In] ref ushort lpFallBack);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_ConvertStringInIStream([In, Out] ref uint pdwMode, [In] uint dwFlag, [In] ref ushort lpFallBack, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmIn, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmOut);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_ConvertStringReset();
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_ConvertStringToUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_ConvertStringToUnicodeEx([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize, [In] uint dwFlag, [In] ref ushort lpFallBack);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_CreateConvertCharset([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty, [MarshalAs(UnmanagedType.Interface)] out CMLangConvertCharset ppMLangConvertCharset);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_DetectCodepageInIStream([In] uint dwFlag, [In] uint dwPrefWinCodePage, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmIn, out DetectEncodingInfo lpEncoding, [In, Out] ref int pnScores);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_DetectInputCodepage([In] uint dwFlag, [In] uint dwPrefWinCodePage, [In] ref sbyte pSrcStr, [In, Out] ref int pcSrcSize, out DetectEncodingInfo lpEncoding, [In, Out] ref int pnScores);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_EnumCodePages([In] NativeMethods.MIMECONTF grfFlags, [In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumCodePage ppEnumCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_EnumRfc1766([In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumRfc1766 ppEnumRfc1766);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_EnumScripts([In] uint dwFlags, [In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumScript ppEnumScript);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_GetCharsetInfo([In, MarshalAs(UnmanagedType.BStr)] string Charset, out MIMECSETINFO pCharsetInfo);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_GetCodePageDescription([In] uint uiCodePage, [In] uint lcid, [Out, MarshalAs(UnmanagedType.LPWStr)] string lpWideCharStr, [In] int cchWideChar);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_GetCodePageInfo([In] uint uiCodePage, [In] ushort LangId, out MIMECPINFO pCodePageInfo);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_GetFamilyCodePage([In] uint uiCodePage, out uint puiFamilyCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_GetLcidFromRfc1766(out uint plocale, [In, MarshalAs(UnmanagedType.BStr)] string bstrRfc1766);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_GetNumberOfCodePageInfo(out uint pcCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_GetNumberOfScripts(out uint pnScripts);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_GetRfc1766FromLcid([In] uint locale, [MarshalAs(UnmanagedType.BStr)] out string pbstrRfc1766);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_GetRfc1766Info([In] uint locale, [In] ushort LangId, out RFC1766INFO pRfc1766Info);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_IsCodePageInstallable([In] uint uiCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_IsConvertible([In] uint dwSrcEncoding, [In] uint dwDstEncoding);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_SetMimeDBSource([In] MIMECONTF dwSource);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_ValidateCodePage([In] uint uiCodePage, [In, ComAliasName("MultiLanguage.wireHWND")] ref _RemotableHandle hwnd);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IMultiLanguage3_ValidateCodePageEx([In] uint uiCodePage, [In, ComAliasName("MultiLanguage.wireHWND")] ref _RemotableHandle hwnd, [In] uint dwfIODControl);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IsCodePageInstallable([In] uint uiCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void IsConvertible([In] uint dwSrcEncoding, [In] uint dwDstEncoding);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void MapFont([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In] uint dwCodePages, [In] ushort chSrc, [Out, ComAliasName("MultiLanguage.wireHFONT")] IntPtr pFont);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void MapFont([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In] uint dwCodePages, [In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hSrcFont, [Out, ComAliasName("MultiLanguage.wireHFONT")] IntPtr phDestFont);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void ReleaseFont([In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void ResetFontMapping();
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void SetMimeDBSource([In] MIMECONTF dwSource);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void ValidateCodePage([In] uint uiCodePage, [In, ComAliasName("MultiLanguage.wireHWND")] ref _RemotableHandle hwnd);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void ValidateCodePageEx([In] uint uiCodePage, [In, ComAliasName("MultiLanguage.wireHWND")] ref _RemotableHandle hwnd, [In] uint dwfIODControl);
+ }
+
+ [ComImport, Guid("275C23E3-3747-11D0-9FEA-00AA003F8646"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IEnumCodePage
+ {
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void Clone([MarshalAs(UnmanagedType.Interface)] out IEnumCodePage ppEnum);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ [PreserveSig]
+ HRESULT Next([In] uint celt, out MIMECPINFO rgelt, out uint pceltFetched);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void Reset();
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void Skip([In] uint celt);
+ }
+
+ [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("3DC39D1D-C030-11D0-B81B-00C04FC9B31F")]
+ public interface IEnumRfc1766
+ {
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void Clone([MarshalAs(UnmanagedType.Interface)] out IEnumRfc1766 ppEnum);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void Next([In] uint celt, out RFC1766INFO rgelt, out uint pceltFetched);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void Reset();
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void Skip([In] uint celt);
+ }
+
+ [ComImport, Guid("AE5F1430-388B-11D2-8380-00C04F8F5DA1"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IEnumScript
+ {
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void Clone([MarshalAs(UnmanagedType.Interface)] out IEnumScript ppEnum);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void Next([In] uint celt, out SCRIPTINFO rgelt, out uint pceltFetched);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void Reset();
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void Skip([In] uint celt);
+ }
+
+ [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("359F3443-BD4A-11D0-B188-00AA0038C969")]
+ public interface IMLangCodePages
+ {
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetCharCodePages([In] ushort chSrc, out uint pdwCodePages);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetStrCodePages([In] ref ushort pszSrc, [In] int cchSrc, [In] uint dwPriorityCodePages, out uint pdwCodePages, out int pcchCodePages);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void CodePageToCodePages([In] uint uCodePage, out uint pdwCodePages);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void CodePagesToCodePage([In] uint dwCodePages, [In] uint uDefaultCodePage, out uint puCodePage);
+ }
+
+ [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("D66D6F98-CDAA-11D0-B822-00C04FC9B31F")]
+ public interface IMLangConvertCharset
+ {
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void Initialize([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetSourceCodePage(out uint puiSrcCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetDestinationCodePage(out uint puiDstCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetProperty(out uint pdwProperty);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void DoConversion([In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void DoConversionToUnicode([In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void DoConversionFromUnicode([In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize);
+ }
+
+ [ComImport, Guid("359F3441-BD4A-11D0-B188-00AA0038C969"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComConversionLoss]
+ public interface IMLangFontLink : IMLangCodePages
+ {
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetFontCodePages([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont, out uint pdwCodePages);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void MapFont([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In] uint dwCodePages, [In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hSrcFont, [Out, ComAliasName("MultiLanguage.wireHFONT")] IntPtr phDestFont);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void ReleaseFont([In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void ResetFontMapping();
+ }
+
+ [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("DCCFC162-2B38-11D2-B7EC-00C04F8F5D9A"), ComConversionLoss]
+ public interface IMLangFontLink2 : IMLangCodePages
+ {
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetFontCodePages([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont, out uint pdwCodePages);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void ReleaseFont([In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void ResetFontMapping();
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void MapFont([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In] uint dwCodePages, [In] ushort chSrc, [Out, ComAliasName("MultiLanguage.wireHFONT")] IntPtr pFont);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetFontUnicodeRanges([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In, Out] ref uint puiRanges, out UNICODERANGE pUranges);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetScriptFontInfo([In] byte sid, [In] uint dwFlags, [In, Out] ref uint puiFonts, out SCRIPFONTINFO pScriptFont);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void CodePageToScriptID([In] uint uiCodePage, out byte pSid);
+ }
+
+ [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("F5BE2EE1-BFD7-11D0-B188-00AA0038C969")]
+ public interface IMLangLineBreakConsole
+ {
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void BreakLineML([In, MarshalAs(UnmanagedType.Interface)] CMLangString pSrcMLStr, [In] int lSrcPos, [In] int lSrcLen, [In] int cMinColumns, [In] int cMaxColumns, out int plLineLen, out int plSkipLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void BreakLineW([In] uint locale, [In] ref ushort pszSrc, [In] int cchSrc, [In] int cMaxColumns, out int pcchLine, out int pcchSkip);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void BreakLineA([In] uint locale, [In] uint uCodePage, [In] ref sbyte pszSrc, [In] int cchSrc, [In] int cMaxColumns, out int pcchLine, out int pcchSkip);
+ }
+
+ [ComImport, Guid("C04D65CE-B70D-11D0-B188-00AA0038C969"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IMLangString
+ {
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void Sync([In] int fNoAccess);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ int GetLength();
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void SetMLStr([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pSrcMLStr, [In] int lSrcPos, [In] int lSrcLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetMLStr([In] int lSrcPos, [In] int lSrcLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, [In] uint dwClsContext, [In] ref Guid piid, [MarshalAs(UnmanagedType.IUnknown)] out object ppDestMLStr, out int plDestPos, out int plDestLen);
+ }
+
+ [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("C04D65D2-B70D-11D0-B188-00AA0038C969")]
+ public interface IMLangStringAStr : IMLangString
+ {
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void SetAStr([In] int lDestPos, [In] int lDestLen, [In] uint uCodePage, [In, MarshalAs(UnmanagedType.LPStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void SetStrBufA([In] int lDestPos, [In] int lDestLen, [In] uint uCodePage, [In, MarshalAs(UnmanagedType.Interface)] IMLangStringBufA pSrcBuf, out int pcchActual, out int plActualLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetAStr([In] int lSrcPos, [In] int lSrcLen, [In] uint uCodePageIn, out uint puCodePageOut, [Out, MarshalAs(UnmanagedType.LPStr)] string pszDest, [In] int cchDest, out int pcchActual, out int plActualLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetStrBufA([In] int lSrcPos, [In] int lSrcMaxLen, out uint puDestCodePage, [MarshalAs(UnmanagedType.Interface)] out IMLangStringBufA ppDestBuf, out int plDestLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void LockAStr([In] int lSrcPos, [In] int lSrcLen, [In] int lFlags, [In] uint uCodePageIn, [In] int cchRequest, out uint puCodePageOut, [MarshalAs(UnmanagedType.LPStr)] out string ppszDest, out int pcchDest, out int plDestLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void UnlockAStr([In, MarshalAs(UnmanagedType.LPStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void SetLocale([In] int lDestPos, [In] int lDestLen, [In] uint locale);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetLocale([In] int lSrcPos, [In] int lSrcMaxLen, out uint plocale, out int plLocalePos, out int plLocaleLen);
+ }
+
+ [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComConversionLoss, Guid("D24ACD23-BA72-11D0-B188-00AA0038C969")]
+ public interface IMLangStringBufA
+ {
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetStatus(out int plFlags, out int pcchBuf);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void LockBuf([In] int cchOffset, [In] int cchMaxLock, [Out] IntPtr ppszBuf, out int pcchBuf);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void UnlockBuf([In] ref sbyte pszBuf, [In] int cchOffset, [In] int cchWrite);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void Insert([In] int cchOffset, [In] int cchMaxInsert, out int pcchActual);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void Delete([In] int cchOffset, [In] int cchDelete);
+ }
+
+ [ComImport, ComConversionLoss, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("D24ACD21-BA72-11D0-B188-00AA0038C969")]
+ public interface IMLangStringBufW
+ {
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetStatus(out int plFlags, out int pcchBuf);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void LockBuf([In] int cchOffset, [In] int cchMaxLock, [Out] IntPtr ppszBuf, out int pcchBuf);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void UnlockBuf([In] ref ushort pszBuf, [In] int cchOffset, [In] int cchWrite);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void Insert([In] int cchOffset, [In] int cchMaxInsert, out int pcchActual);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void Delete([In] int cchOffset, [In] int cchDelete);
+ }
+
+ [ComImport, Guid("C04D65D0-B70D-11D0-B188-00AA0038C969"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IMLangStringWStr : IMLangString
+ {
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void SetWStr([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.LPWStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void SetStrBufW([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.Interface)] IMLangStringBufW pSrcBuf, out int pcchActual, out int plActualLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetWStr([In] int lSrcPos, [In] int lSrcLen, [Out, MarshalAs(UnmanagedType.LPWStr)] string pszDest, [In] int cchDest, out int pcchActual, out int plActualLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetStrBufW([In] int lSrcPos, [In] int lSrcMaxLen, [MarshalAs(UnmanagedType.Interface)] out IMLangStringBufW ppDestBuf, out int plDestLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void LockWStr([In] int lSrcPos, [In] int lSrcLen, [In] int lFlags, [In] int cchRequest, [MarshalAs(UnmanagedType.LPWStr)] out string ppszDest, out int pcchDest, out int plDestLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void UnlockWStr([In, MarshalAs(UnmanagedType.LPWStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void SetLocale([In] int lDestPos, [In] int lDestLen, [In] uint locale);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetLocale([In] int lSrcPos, [In] int lSrcMaxLen, out uint plocale, out int plLocalePos, out int plLocaleLen);
+ }
+
+ [ComImport, Guid("275C23E1-3747-11D0-9FEA-00AA003F8646"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IMultiLanguage
+ {
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetNumberOfCodePageInfo(out uint pcCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetCodePageInfo([In] uint uiCodePage, out MIMECPINFO pCodePageInfo);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetFamilyCodePage([In] uint uiCodePage, out uint puiFamilyCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ [return: MarshalAs(UnmanagedType.Interface)]
+ IEnumCodePage EnumCodePages([In] NativeMethods.MIMECONTF grfFlags);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetCharsetInfo([In, MarshalAs(UnmanagedType.BStr)] string Charset, out MIMECSETINFO pCharsetInfo);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void IsConvertible([In] uint dwSrcEncoding, [In] uint dwDstEncoding);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void ConvertString([In, Out] ref uint pdwMode, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void ConvertStringToUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void ConvertStringFromUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void ConvertStringReset();
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetRfc1766FromLcid([In] uint locale, [MarshalAs(UnmanagedType.BStr)] out string pbstrRfc1766);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetLcidFromRfc1766(out uint plocale, [In, MarshalAs(UnmanagedType.BStr)] string bstrRfc1766);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void EnumRfc1766([MarshalAs(UnmanagedType.Interface)] out IEnumRfc1766 ppEnumRfc1766);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetRfc1766Info([In] uint locale, out RFC1766INFO pRfc1766Info);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void CreateConvertCharset([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty, [MarshalAs(UnmanagedType.Interface)] out CMLangConvertCharset ppMLangConvertCharset);
+ }
+
+ [ComImport, Guid("DCCFC164-2B38-11D2-B7EC-00C04F8F5D9A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IMultiLanguage2
+ {
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetNumberOfCodePageInfo(out uint pcCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetCodePageInfo([In] uint uiCodePage, [In] ushort LangId, out MIMECPINFO pCodePageInfo);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetFamilyCodePage([In] uint uiCodePage, out uint puiFamilyCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void EnumCodePages([In] uint grfFlags, [In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumCodePage ppEnumCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetCharsetInfo([In, MarshalAs(UnmanagedType.BStr)] string Charset, out MIMECSETINFO pCharsetInfo);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void IsConvertible([In] uint dwSrcEncoding, [In] uint dwDstEncoding);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void ConvertString([In, Out] ref uint pdwMode, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void ConvertStringToUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void ConvertStringFromUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void ConvertStringReset();
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetRfc1766FromLcid([In] uint locale, [MarshalAs(UnmanagedType.BStr)] out string pbstrRfc1766);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetLcidFromRfc1766(out uint plocale, [In, MarshalAs(UnmanagedType.BStr)] string bstrRfc1766);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void EnumRfc1766([In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumRfc1766 ppEnumRfc1766);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetRfc1766Info([In] uint locale, [In] ushort LangId, out RFC1766INFO pRfc1766Info);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void CreateConvertCharset([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty, [MarshalAs(UnmanagedType.Interface)] out CMLangConvertCharset ppMLangConvertCharset);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void ConvertStringInIStream([In, Out] ref uint pdwMode, [In] uint dwFlag, [In] ref ushort lpFallBack, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmIn, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmOut);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void ConvertStringToUnicodeEx([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize, [In] uint dwFlag, [In] ref ushort lpFallBack);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void ConvertStringFromUnicodeEx([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize, [In] uint dwFlag, [In] ref ushort lpFallBack);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void DetectCodepageInIStream([In] uint dwFlag, [In] uint dwPrefWinCodePage, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmIn, out DetectEncodingInfo lpEncoding, [In, Out] ref int pnScores);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ [PreserveSig]
+ HRESULT DetectInputCodepage([In] MLDETECTCP dwFlag, [In] uint dwPrefWinCodePage, [In] ref byte pSrcStr, [In, Out] ref int pcSrcSize, [In, Out] ref DetectEncodingInfo lpEncoding, [In, Out] ref int pnScores);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void ValidateCodePage([In] uint uiCodePage, [In, ComAliasName("MultiLanguage.wireHWND")] ref _RemotableHandle hwnd);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetCodePageDescription([In] uint uiCodePage, [In] uint lcid, [Out, MarshalAs(UnmanagedType.LPWStr)] string lpWideCharStr, [In] int cchWideChar);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void IsCodePageInstallable([In] uint uiCodePage);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void SetMimeDBSource([In] MIMECONTF dwSource);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetNumberOfScripts(out uint pnScripts);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void EnumScripts([In] uint dwFlags, [In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumScript ppEnumScript);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void ValidateCodePageEx([In] uint uiCodePage, [In, ComAliasName("MultiLanguage.wireHWND")] ref _RemotableHandle hwnd, [In] uint dwfIODControl);
+ }
+
+ [ComImport, Guid("4E5868AB-B157-4623-9ACC-6A1D9CAEBE04"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IMultiLanguage3 : IMultiLanguage2
+ {
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void DetectOutboundCodePage([In] uint dwFlags, [In, MarshalAs(UnmanagedType.LPWStr)] string lpWideCharStr, [In] uint cchWideChar, [In] ref uint puiPreferredCodePages, [In] uint nPreferredCodePages, out uint puiDetectedCodePages, [In, Out] ref uint pnDetectedCodePages, [In, MarshalAs(UnmanagedType.LPWStr)] string lpSpecialChar);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void DetectOutboundCodePageInIStream([In] uint dwFlags, [In, MarshalAs(UnmanagedType.Interface)] IStream pStrIn, [In] ref uint puiPreferredCodePages, [In] uint nPreferredCodePages, out uint puiDetectedCodePages, [In, Out] ref uint pnDetectedCodePages, [In, MarshalAs(UnmanagedType.LPWStr)] string lpSpecialChar);
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ public struct DetectEncodingInfo
+ {
+ public uint nLangID;
+ public uint nCodePage;
+ public int nDocPercent;
+ public int nConfidence;
+ }
+
+ public enum MIMECONTF
+ {
+ MIMECONTF_BROWSER = 2,
+ MIMECONTF_EXPORT = 0x400,
+ MIMECONTF_IMPORT = 8,
+ MIMECONTF_MAILNEWS = 1,
+ MIMECONTF_MIME_IE4 = 0x10000000,
+ MIMECONTF_MIME_LATEST = 0x20000000,
+ MIMECONTF_MIME_REGISTRY = 0x40000000,
+ MIMECONTF_MINIMAL = 4,
+ MIMECONTF_PRIVCONVERTER = 0x10000,
+ MIMECONTF_SAVABLE_BROWSER = 0x200,
+ MIMECONTF_SAVABLE_MAILNEWS = 0x100,
+ MIMECONTF_VALID = 0x20000,
+ MIMECONTF_VALID_NLS = 0x40000
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
+ public struct MIMECPINFO
+ {
+ public uint dwFlags;
+ public uint uiCodePage;
+ public uint uiFamilyCodePage;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x40)]
+ public string wszDescription;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
+ public string wszWebCharset;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
+ public string wszHeaderCharset;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
+ public string wszBodyCharset;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
+ public string wszFixedWidthFont;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
+ public string wszProportionalFont;
+ public byte bGDICharset;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ public struct MIMECSETINFO
+ {
+ public uint uiCodePage;
+ public uint uiInternetEncoding;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)]
+ public ushort[] wszCharset;
+ }
+
+ public enum MLSTR_FLAGS
+ {
+ MLSTR_READ = 1,
+ MLSTR_WRITE = 2
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ public struct RFC1766INFO
+ {
+ public uint lcid;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
+ public ushort[] wszRfc1766;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
+ public ushort[] wszLocaleName;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ public struct SCRIPFONTINFO
+ {
+ public long scripts;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
+ public ushort[] wszFont;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ public struct SCRIPTINFO
+ {
+ public byte ScriptId;
+ public uint uiCodePage;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x30)]
+ public ushort[] wszDescription;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
+ public ushort[] wszFixedWidthFont;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
+ public ushort[] wszProportionalFont;
+ }
+
+ public enum MLDETECTCP
+ {
+ MLDETECTCP_NONE = 0,
+ MLDETECTCP_7BIT = 1,
+ MLDETECTCP_8BIT = 2,
+ MLDETECTCP_DBCS = 4,
+ MLDETECTCP_HTML = 8,
+ MLDETECTCP_NUMBER = 16
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ public struct STATSTG
+ {
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string pwcsName;
+ public uint type;
+ public ulong cbSize;
+ public System.Runtime.InteropServices.ComTypes.FILETIME mtime;
+ public System.Runtime.InteropServices.ComTypes.FILETIME ctime;
+ public System.Runtime.InteropServices.ComTypes.FILETIME atime;
+ public uint grfMode;
+ public uint grfLocksSupported;
+ public Guid clsid;
+ public uint grfStateBits;
+ public uint reserved;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 2)]
+ public struct UNICODERANGE
+ {
+ public ushort wcFrom;
+ public ushort wcTo;
+ }
+ }
+}
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/User32.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/User32.cs
new file mode 100644
index 0000000000..b158632572
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/User32.cs
@@ -0,0 +1,88 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Microsoft.Web.Management.PInvoke.User32
+{
+ internal enum WindowMessage
+ {
+ PBS_SMOOTH = 0x1,
+ PBS_MARQUEE = 0x8,
+ WM_SETREDRAW = 0xB,
+ PBM_SETMARQUEE = 0x400 + 10,
+ }
+
+ [Flags]
+ internal enum ExitWindows : uint
+ {
+ //
+ // ONE of the following five:
+ //
+ LogOff = 0x00,
+ ShutDown = 0x01,
+ Reboot = 0x02,
+ PowerOff = 0x08,
+ RestartApps = 0x40,
+
+ //
+ // plus AT MOST ONE of the following two:
+ //
+ Force = 0x04,
+ ForceIfHung = 0x10,
+ }
+
+ [Flags]
+ internal enum ShutdownReason : uint
+ {
+ MajorApplication = 0x00040000,
+ MajorHardware = 0x00010000,
+ MajorLegacyApi = 0x00070000,
+ MajorOperatingSystem = 0x00020000,
+ MajorOther = 0x00000000,
+ MajorPower = 0x00060000,
+ MajorSoftware = 0x00030000,
+ MajorSystem = 0x00050000,
+
+ MinorBlueScreen = 0x0000000F,
+ MinorCordUnplugged = 0x0000000b,
+ MinorDisk = 0x00000007,
+ MinorEnvironment = 0x0000000c,
+ MinorHardwareDriver = 0x0000000d,
+ MinorHotfix = 0x00000011,
+ MinorHung = 0x00000005,
+ MinorInstallation = 0x00000002,
+ MinorMaintenance = 0x00000001,
+ MinorMMC = 0x00000019,
+ MinorNetworkConnectivity = 0x00000014,
+ MinorNetworkCard = 0x00000009,
+ MinorOther = 0x00000000,
+ MinorOtherDriver = 0x0000000e,
+ MinorPowerSupply = 0x0000000a,
+ MinorProcessor = 0x00000008,
+ MinorReconfig = 0x00000004,
+ MinorSecurity = 0x00000013,
+ MinorSecurityFix = 0x00000012,
+ MinorSecurityFixUninstall = 0x00000018,
+ MinorServicePack = 0x00000010,
+ MinorServicePackUninstall = 0x00000016,
+ MinorTermSrv = 0x00000020,
+ MinorUnstable = 0x00000006,
+ MinorUpgrade = 0x00000003,
+ MinorWMI = 0x00000015,
+
+ FlagUserDefined = 0x40000000,
+ FlagPlanned = 0x80000000
+ }
+
+ internal static class NativeMethods
+ {
+ [DllImport("User32.dll", CharSet = CharSet.Auto)]
+ public static extern IntPtr SendMessage(IntPtr hWnd, WindowMessage msg, int wParam, int lParam);
+
+ [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool ExitWindowsEx(ExitWindows uFlags, ShutdownReason dwReason);
+ }
+}
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/UxTheme.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/UxTheme.cs
new file mode 100644
index 0000000000..520c923505
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/UxTheme.cs
@@ -0,0 +1,46 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Diagnostics;
+
+namespace Microsoft.Web.Management.PInvoke.UxTheme
+{
+ internal static class NativeMethods
+ {
+ [DllImport("UxTheme.dll", ExactSpelling = true, CharSet = CharSet.Unicode)]
+ public extern static void SetWindowTheme(IntPtr hWnd, string textSubAppName, string textSubIdList);
+
+ [DllImport("uxtheme.dll", CharSet = CharSet.Unicode, PreserveSig = true)]
+ private static extern int GetCurrentThemeName(StringBuilder pszThemeFileName, int dwMaxNameChars, StringBuilder pszColorBuff, int dwMaxColorChars, StringBuilder pszSizeBuff, int cchMaxSizeChars);
+
+ public static bool TryGetCurrentThemeName(out string themeName, out string color, out string size)
+ {
+ StringBuilder nameBuilder = new StringBuilder(512);
+ StringBuilder colorBuilder = new StringBuilder(512);
+ StringBuilder sizeBuilder = new StringBuilder(512);
+ int hr = GetCurrentThemeName(nameBuilder, nameBuilder.Capacity, colorBuilder, colorBuilder.Capacity, sizeBuilder, sizeBuilder.Capacity);
+ if (hr == 0)
+ {
+ themeName = nameBuilder.ToString();
+ color = colorBuilder.ToString();
+ size = sizeBuilder.ToString();
+ return true;
+ }
+ else
+ {
+ themeName = null;
+ color = null;
+ size = null;
+ if (hr != Extension.AsHRESULT(Win32ErrorCode.ELEMENT_NOT_FOUND))
+ {
+ Debug.Fail("GetCurrentThemeName returned: " + hr.ToString());
+ }
+
+ return false;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLoc.targets b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLoc.targets
new file mode 100644
index 0000000000..0222289f2c
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLoc.targets
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLocalizer.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLocalizer.cs
new file mode 100644
index 0000000000..fccf038061
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLocalizer.cs
@@ -0,0 +1,456 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Reflection;
+using System.Resources;
+
+namespace Microsoft.Web.Utility
+{
+#if PSEUDOLOCALIZER_ENABLED || DEBUG
+
+ ///
+ /// Class that pseudo-localizes resources from a RESX file by intercepting calls to the managed wrapper class.
+ ///
+ internal static class PseudoLocalizer
+ {
+ private static bool _shouldPseudoLocalize;
+ private static double _plocPaddingLengthRatio;
+
+ static PseudoLocalizer()
+ {
+ _shouldPseudoLocalize = false;
+ int plocLengthPaddingPercentage = 50;
+#if DEBUG
+ string plocValue = Environment.GetEnvironmentVariable("PSEUDOLOCALIZE");
+ if (!string.IsNullOrEmpty(plocValue))
+ {
+ _shouldPseudoLocalize = true;
+ int.TryParse(plocValue, out plocLengthPaddingPercentage);
+ if (plocLengthPaddingPercentage < 10)
+ {
+ plocLengthPaddingPercentage = 50;
+ }
+ }
+#endif // DEBUG
+
+ _plocPaddingLengthRatio = plocLengthPaddingPercentage * 0.01;
+ if (_plocPaddingLengthRatio < 0.1)
+ {
+ DebugTrace("ploc should be at least 10% padded");
+ }
+
+#if PSEUDOLOCALIZER_ENABLED
+ _shouldPseudoLocalize = true;
+#endif // PSEUDOLOCALIZER_ENABLED
+ }
+
+ public static bool ShouldPseudoLocalize
+ {
+ get
+ {
+ return _shouldPseudoLocalize;
+ }
+ }
+
+ // Need to use this method instead of tracing/debugging directly otherwise
+ // the application will not be able to disable asserts from the exe.config file.
+ // this is because this code is run very early on in the app before the
+ // default trace listener has had a chance to initialize its settings
+ // correctly
+ private static void DebugTrace(string format, params object[] args)
+ {
+ ////only uncomment these lines when actually debugging something
+ ////otherwise the application wont be able to toggle the assert ui
+ ////if (args == null || args.Length == 0)
+ ////{
+ //// Debug.WriteLine(format);
+ ////}
+ ////else
+ ////{
+ //// Debug.WriteLine(format, args);
+ ////}
+ }
+
+ ///
+ /// Enables pseudo-localization on any type that is of the form {AssemblyName}.Resources
+ ///
+ ///
+ /// true if succeeded, false if failed.
+ public static bool TryEnableAssembly(Assembly assembly)
+ {
+ bool retVal = false;
+ if (assembly != null)
+ {
+ AssemblyName assemblyName = assembly.GetName();
+ string resourceTypeName = assemblyName.Name + ".Resources";
+ try
+ {
+ Type resourceType = assembly.GetType(resourceTypeName, false);
+ if (resourceType != null)
+ {
+ Enable(resourceType);
+ retVal = true;
+ }
+ else
+ {
+ DebugTrace("PLOC: no type {0} found in the assembly {1}",
+ resourceTypeName,
+ assembly.FullName);
+ }
+ }
+ catch (Exception ex)
+ {
+ DebugTrace(ex.ToString());
+ }
+ }
+ else
+ {
+ DebugTrace("assembly should not be null");
+ }
+
+ return retVal;
+ }
+
+ ///
+ /// Enables pseudo-localization for the specified RESX managed wrapper class.
+ ///
+ /// Type of the RESX managed wrapper class.
+ [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "ResourceManager", Justification = "Name of property.")]
+ [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "resourceMan", Justification = "Name of field.")]
+ public static void Enable(Type resourcesType)
+ {
+ if (null == resourcesType)
+ {
+ throw new ArgumentNullException("resourcesType");
+ }
+
+ // Get the ResourceManager property
+ var resourceManagerProperty = resourcesType.GetProperty("ResourceManager", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
+ if (null == resourceManagerProperty)
+ {
+ throw new NotSupportedException("RESX managed wrapper class does not contain the expected internal/public static ResourceManager property.");
+ }
+
+ // Get the ResourceManager value (ensures the resourceMan field gets initialized)
+ var resourceManagerValue = resourceManagerProperty.GetValue(null, null) as ResourceManager;
+ if (null == resourceManagerValue)
+ {
+ throw new NotSupportedException("RESX managed wrapper class returned null for the ResourceManager property getter.");
+ }
+
+ // Get the resourceMan field
+ var resourceManField = resourcesType.GetField("resourceMan", BindingFlags.Static | BindingFlags.NonPublic);
+ if (null == resourceManField)
+ {
+ throw new NotSupportedException("RESX managed wrapper class does not contain the expected private static resourceMan field.");
+ }
+
+ // Create a substitute ResourceManager to do the pseudo-localization
+ var resourceManSubstitute = new PseudoLocalizerResourceManager(
+ _plocPaddingLengthRatio,
+ resourceManagerValue.BaseName,
+ resourcesType.Assembly);
+
+ // Replace the resourceMan field value
+ resourceManField.SetValue(null, resourceManSubstitute);
+ }
+
+ ///
+ /// Enables Pseudo-localization for all assemblies that get loaded from the current
+ /// host. Within the assemblie, only types that are of the form {AssemblyName}.Resources
+ /// will get pseudo-localization enabled.
+ ///
+ public static void EnableAutoPseudoLocalizationFromHostExecutable()
+ {
+ if (ShouldPseudoLocalize)
+ {
+ //set up pseudo-localization for ourselves
+ TryEnableAssembly(Assembly.GetExecutingAssembly());
+
+ //set up pseudo-localization for anything that gets loaded later
+ AppDomain.CurrentDomain.AssemblyLoad +=
+ new AssemblyLoadEventHandler(OnCurrentDomainAssemblyLoad);
+ }
+ }
+
+ public static string PseudoLocalizeString(string str)
+ {
+ return PseudoLocalizerResourceManager.PseudoLocalizeString(
+ _plocPaddingLengthRatio,
+ str);
+ }
+
+ private static void OnCurrentDomainAssemblyLoad(object sender,
+ AssemblyLoadEventArgs args)
+ {
+ Assembly assembly = args.LoadedAssembly;
+ bool isThisMyAssembly;
+ if (!assembly.GlobalAssemblyCache)
+ {
+ isThisMyAssembly = true;
+ }
+ else if (assembly.FullName.StartsWith("Microsoft.Web",
+ StringComparison.OrdinalIgnoreCase))
+ {
+ isThisMyAssembly = true;
+ }
+ else
+ {
+ isThisMyAssembly = false;
+ }
+
+ if (isThisMyAssembly)
+ {
+ TryEnableAssembly(assembly);
+ }
+ }
+
+ ///
+ /// Class that overrides default ResourceManager behavior by pseudo-localizing its content.
+ ///
+ private class PseudoLocalizerResourceManager : ResourceManager
+ {
+ ///
+ /// Stores a Dictionary for character translations.
+ ///
+ private static Dictionary _translations = CreateTranslationsMap();
+
+ private static Dictionary CreateTranslationsMap()
+ {
+ // Map standard "English" characters to similar-looking counterparts from other languages
+ Dictionary translations = new Dictionary
+ {
+ { 'a', 'ä' },
+ { 'b', 'ƃ' },
+ { 'c', 'č' },
+ { 'd', 'ƌ' },
+ { 'e', 'ë' },
+ { 'f', 'ƒ' },
+ { 'g', 'ğ' },
+ { 'h', 'ħ' },
+ { 'i', 'ï' },
+ { 'j', 'ĵ' },
+ { 'k', 'ƙ' },
+ { 'l', 'ł' },
+ { 'm', 'ɱ' },
+ { 'n', 'ň' },
+ { 'o', 'ö' },
+ { 'p', 'þ' },
+ { 'q', 'ɋ' },
+ { 'r', 'ř' },
+ { 's', 'š' },
+ { 't', 'ŧ' },
+ { 'u', 'ü' },
+ { 'v', 'ṽ' },
+ { 'w', 'ŵ' },
+ { 'x', 'ӿ' },
+ { 'y', 'ŷ' },
+ { 'z', 'ž' },
+ { 'A', 'Ä' },
+ { 'B', 'Ɓ' },
+ { 'C', 'Č' },
+ { 'D', 'Đ' },
+ { 'E', 'Ë' },
+ { 'F', 'Ƒ' },
+ { 'G', 'Ğ' },
+ { 'H', 'Ħ' },
+ { 'I', 'Ï' },
+ { 'J', 'Ĵ' },
+ { 'K', 'Ҟ' },
+ { 'L', 'Ł' },
+ { 'M', 'Ӎ' },
+ { 'N', 'Ň' },
+ { 'O', 'Ö' },
+ { 'P', 'Ҏ' },
+ { 'Q', 'Ǫ' },
+ { 'R', 'Ř' },
+ { 'S', 'Š' },
+ { 'T', 'Ŧ' },
+ { 'U', 'Ü' },
+ { 'V', 'Ṽ' },
+ { 'W', 'Ŵ' },
+ { 'X', 'Ӿ' },
+ { 'Y', 'Ŷ' },
+ { 'Z', 'Ž' },
+ };
+
+ return translations;
+ }
+
+ private double _paddingLengthRatio;
+
+ ///
+ /// Initializes a new instance of the PseudoLocalizerResourceManager class.
+ ///
+ /// The root name of the resource file without its extension but including any fully qualified namespace name.
+ /// The main assembly for the resources.
+ public PseudoLocalizerResourceManager(double paddingLengthRatio,
+ string baseName,
+ Assembly assembly)
+ : base(baseName, assembly)
+ {
+ _paddingLengthRatio = paddingLengthRatio;
+ }
+
+ ///
+ /// Returns the value of the specified String resource.
+ ///
+ /// The name of the resource to get.
+ /// The value of the resource localized for the caller's current culture settings.
+ public override string GetString(string name)
+ {
+ return PseudoLocalizeString(base.GetString(name));
+ }
+
+ ///
+ /// Gets the value of the String resource localized for the specified culture.
+ ///
+ /// The name of the resource to get.
+ /// The CultureInfo object that represents the culture for which the resource is localized.
+ /// The value of the resource localized for the specified culture.
+ public override string GetString(string name, CultureInfo culture)
+ {
+ return PseudoLocalizeString(base.GetString(name, culture));
+ }
+
+ private string PseudoLocalizeString(string str)
+ {
+ return PseudoLocalizeString(_paddingLengthRatio, str);
+ }
+
+ ///
+ /// Pseudo-localizes a string.
+ ///
+ /// Input string.
+ /// Pseudo-localized string.
+ internal static string PseudoLocalizeString(double paddingLengthRatio, string str)
+ {
+ const string minprefix = "[";
+ const string minsuffix = "]";
+
+ // Create a new string with the "translated" values of each character
+ var translatedChars = new char[str.Length];
+ if (IsXamlString(str))
+ {
+ DoCaseTranslation(str, translatedChars);
+ }
+ else
+ {
+ DoFunkyCharacterTranslation(str, translatedChars);
+ }
+
+ string mungedString = new string(translatedChars);
+
+ int padLengthPerSide = GetPaddingLengthPerSide(
+ str.Length,
+ paddingLengthRatio,
+ minprefix.Length + minsuffix.Length);
+
+ string extraPadding = new string('=', padLengthPerSide);
+ string finalString = string.Concat(minprefix, extraPadding, mungedString, extraPadding, minsuffix);
+
+ return finalString;
+ }
+
+ private static int GetPaddingLengthPerSide(int originalStringLength, double paddingRatio, int minPadLength)
+ {
+ int padLengthPerSide;
+ double exactTotalPadding = (originalStringLength * paddingRatio);
+ padLengthPerSide = (int)(exactTotalPadding + 1) / 2;
+ if (padLengthPerSide < 1)
+ {
+ padLengthPerSide = 1;
+ }
+
+ return padLengthPerSide;
+ }
+
+ private static void DoCaseTranslation(string str, char[] translatedChars)
+ {
+ bool inXamlTag = false;
+ for (var i = 0; i < str.Length; i++)
+ {
+ var c = str[i];
+
+ if (inXamlTag)
+ {
+ translatedChars[i] = c;
+ if (c == '>')
+ {
+ inXamlTag = false;
+ }
+ }
+ else
+ {
+ translatedChars[i] = (i % 2) == 0 ? char.ToUpper(c) : char.ToLower(c);
+ if (c == '<' && str.IndexOf('>', i) > -1)
+ {
+ inXamlTag = true;
+ }
+ }
+ }
+ }
+
+ private static void DoFunkyCharacterTranslation(string str, char[] translatedChars)
+ {
+ for (var i = 0; i < str.Length; i++)
+ {
+ var c = str[i];
+ translatedChars[i] = _translations.ContainsKey(c) ? _translations[c] : c;
+ }
+ }
+
+ private static bool IsXamlString(string str)
+ {
+ // check if this string has a '<' followed by a '>' and assume it's a xaml string if so
+ int lessThanIndex = str.IndexOf('<');
+ if (lessThanIndex > -1)
+ {
+ if (str.IndexOf('>', lessThanIndex) > -1)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+ }
+#else
+ ///
+ /// Dummy class needed to keep the public interface be identical in debug and retail builds
+ ///
+ internal static class PseudoLocalizer
+ {
+ public static bool ShouldPseudoLocalize
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public static bool TryEnableAssembly(Assembly assembly)
+ {
+ return true;
+ }
+
+ public static void Enable(Type resourcesType)
+ {
+ }
+
+ public static void EnableAutoPseudoLocalizationFromHostExecutable()
+ {
+ }
+
+ public static string PseudoLocalizeString(string str)
+ {
+ return str;
+ }
+ }
+#endif
+}
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/References/v7Sp1/Microsoft.Web.administration.dll b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/References/v7Sp1/Microsoft.Web.administration.dll
new file mode 100644
index 0000000000..5c786c3d92
Binary files /dev/null and b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/References/v7Sp1/Microsoft.Web.administration.dll differ
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/References/v7Sp1/Microsoft.Web.management.dll b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/References/v7Sp1/Microsoft.Web.management.dll
new file mode 100644
index 0000000000..cbae9ccf92
Binary files /dev/null and b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/References/v7Sp1/Microsoft.Web.management.dll differ
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/AuthenticationModule.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/AuthenticationModule.cs
new file mode 100644
index 0000000000..f284d02d0e
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/AuthenticationModule.cs
@@ -0,0 +1,111 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.Net;
+using System.Text;
+
+namespace Microsoft.WebMatrix.Utility
+{
+ ///
+ /// This AuthenticationModule implements basic authentication but uses UTF8 Encoding to support international characters.
+ /// Unfortunately the System.Net implementation uses the Default encoding which breaks with them.
+ ///
+ internal class AuthenticationModule : IAuthenticationModule
+ {
+ private const string AuthenticationTypeName = "Basic";
+ private static AuthenticationModule _module = null;
+ private static object _lock = new object();
+
+ public static void InstantiateIfNeeded()
+ {
+ lock (_lock)
+ {
+ if (_module == null)
+ {
+ _module = new AuthenticationModule();
+ }
+ }
+ }
+
+ private AuthenticationModule()
+ {
+ AuthenticationManager.Unregister(AuthenticationTypeName);
+ AuthenticationManager.Register(this);
+ }
+
+ string IAuthenticationModule.AuthenticationType
+ {
+ get
+ {
+ return AuthenticationTypeName;
+ }
+ }
+
+ bool IAuthenticationModule.CanPreAuthenticate
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ Authorization IAuthenticationModule.Authenticate(string challenge, WebRequest request, ICredentials credentials)
+ {
+ HttpWebRequest httpWebRequest = request as HttpWebRequest;
+ if (httpWebRequest == null)
+ {
+ return null;
+ }
+
+ // Verify that the challenge is a Basic Challenge
+ if (challenge == null || !challenge.StartsWith(AuthenticationTypeName, StringComparison.OrdinalIgnoreCase))
+ {
+ return null;
+ }
+
+ return Authenticate(httpWebRequest, credentials);
+ }
+
+ Authorization IAuthenticationModule.PreAuthenticate(WebRequest request, ICredentials credentials)
+ {
+ HttpWebRequest httpWebRequest = request as HttpWebRequest;
+
+ if (httpWebRequest == null)
+ {
+ return null;
+ }
+
+ return Authenticate(httpWebRequest, credentials);
+ }
+
+ private Authorization Authenticate(HttpWebRequest httpWebRequest, ICredentials credentials)
+ {
+ if (credentials == null)
+ {
+ return null;
+ }
+
+ // Get the username and password from the credentials
+ NetworkCredential nc = credentials.GetCredential(httpWebRequest.RequestUri, AuthenticationTypeName);
+ if (nc == null)
+ {
+ return null;
+ }
+
+ ICredentialPolicy policy = AuthenticationManager.CredentialPolicy;
+ if (policy != null && !policy.ShouldSendCredential(httpWebRequest.RequestUri, httpWebRequest, nc, this))
+ {
+ return null;
+ }
+
+ string domain = nc.Domain;
+
+ string basicTicket = (!String.IsNullOrEmpty(domain) ? (domain + "\\") : "") + nc.UserName + ":" + nc.Password;
+ byte[] bytes = Encoding.UTF8.GetBytes(basicTicket);
+
+ string header = AuthenticationTypeName + " " + Convert.ToBase64String(bytes);
+ return new Authorization(header, true);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/ExceptionHelper.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/ExceptionHelper.cs
new file mode 100644
index 0000000000..b3a6c24c2e
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/ExceptionHelper.cs
@@ -0,0 +1,122 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+
+namespace Microsoft.WebMatrix.Utility
+{
+ internal class ExceptionHelper
+ {
+ private const int PublicKeyTokenLength = 8;
+
+ ///
+ /// This will return a list of assemblies that are present in the call stack for
+ /// the input exception. The list CAN have duplicates.
+ ///
+ ///
+ ///
+ public static IEnumerable GetAssembliesInCallStack(Exception exception)
+ {
+ // an AggregateException might have multiple inner exceptions, so we handle it specially
+ AggregateException aggregateException = exception as AggregateException;
+ if (exception == null)
+ {
+ return Enumerable.Empty();
+ }
+ else if (aggregateException == null)
+ {
+ return GetAssembliesInSingleException(exception).Concat(GetAssembliesInCallStack(exception.InnerException));
+ }
+ else
+ {
+ return aggregateException.Flatten().InnerExceptions.SelectMany(ex => GetAssembliesInCallStack(ex));
+ }
+ }
+
+ private static IEnumerable GetAssembliesInSingleException(Exception exception)
+ {
+ // some exceptions (like AggregateException) don't have an associated stacktrace
+ if (exception != null && exception.StackTrace != null)
+ {
+ StackTrace stackTrace = new StackTrace(exception, false);
+ foreach (StackFrame frame in stackTrace.GetFrames())
+ {
+ // DeclaringType can be null for lambdas created by Reflection.Emit
+ Type declaringType = frame.GetMethod().DeclaringType;
+ if (declaringType != null)
+ {
+ Assembly currentAssembly = declaringType.Assembly;
+ Debug.Assert(currentAssembly != null, "currentAssembly must not be null");
+ if (currentAssembly != null)
+ {
+ yield return currentAssembly;
+ }
+ }
+ }
+ }
+ }
+
+ public static IEnumerable RemoveAssembliesThatAreIntheGAC(IEnumerable input)
+ {
+ foreach (Assembly assembly in input)
+ {
+ if (!assembly.GlobalAssemblyCache)
+ {
+ yield return assembly;
+ }
+ }
+ }
+
+ public static IEnumerable RemoveAssembliesThatAreSignedWithToken(IEnumerable input, byte[] publicKeyToken)
+ {
+ Debug.Assert(publicKeyToken.Length == PublicKeyTokenLength, "public key tokens should be 8 bytes");
+ foreach (Assembly assembly in input)
+ {
+ byte[] currentToken = assembly.GetName().GetPublicKeyToken();
+ bool shouldReturn;
+ if (currentToken.Length == 0)
+ {
+ // unsigned assembly
+ shouldReturn = true;
+ }
+ else if (AreTokensTheSame(currentToken, publicKeyToken))
+ {
+ // tokens are the same skip the assembly
+ shouldReturn = false;
+ }
+ else
+ {
+ // didnt match anything, return it
+ shouldReturn = true;
+ }
+
+ if (shouldReturn)
+ {
+ yield return assembly;
+ }
+ }
+ }
+
+ private static bool AreTokensTheSame(byte[] token1, byte[] token2)
+ {
+ Debug.Assert(
+ token1.Length == PublicKeyTokenLength &&
+ token2.Length == PublicKeyTokenLength,
+ "public key tokens should be 8 bytes");
+
+ for (int i = 0; i < PublicKeyTokenLength; i++)
+ {
+ if (token1[i] != token2[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/GACManagedAccess.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/GACManagedAccess.cs
new file mode 100644
index 0000000000..2dbd5c8ff1
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/GACManagedAccess.cs
@@ -0,0 +1,192 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Diagnostics;
+
+namespace Microsoft.Web.Utility
+{
+ // need to include \common\Managed\NativeMethods\Fusion.cs in your project to use this class
+ internal static class GACManagedAccess
+ {
+ public static List GetAssemblyList(string assemblyName)
+ {
+ return GetAssemblyList(assemblyName, true);
+ }
+
+ public static List GetAssemblyList(string assemblyName, bool getPhysicalPath)
+ {
+ if (string.IsNullOrEmpty(assemblyName))
+ {
+ throw new ArgumentNullException("assemblyName");
+ }
+
+ List assemblyList = new List();
+ using (GacAssembly gacAssembly = new GacAssembly(assemblyName))
+ {
+ while (true)
+ {
+ if (gacAssembly.GetNextAssembly())
+ {
+ if (getPhysicalPath)
+ {
+ using (GACAssemblyCache gacAssemblyCache = new GACAssemblyCache(assemblyName, gacAssembly.FullAssemblyName))
+ {
+ assemblyList.Add(gacAssemblyCache.AssemblyPath);
+ }
+ }
+ else
+ {
+ assemblyList.Add(gacAssembly.FullAssemblyName);
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ return assemblyList;
+ }
+ }
+
+ internal class GacAssembly : IDisposable
+ {
+ internal GacAssembly(string assemblyName)
+ {
+ _assemblyName = assemblyName;
+ int hResult = PInvoke.Fusion.NativeMethods.CreateAssemblyNameObject(
+ out _fusionName,
+ _assemblyName,
+ PInvoke.Fusion.CreateAssemblyNameObjectFlags.CANOF_PARSE_DISPLAY_NAME,
+ IntPtr.Zero);
+
+ if (hResult >= 0)
+ {
+ hResult = PInvoke.Fusion.NativeMethods.CreateAssemblyEnum(
+ out _assemblyEnum,
+ IntPtr.Zero,
+ _fusionName,
+ PInvoke.Fusion.AssemblyCacheFlags.GAC,
+ IntPtr.Zero);
+ }
+
+ if (hResult < 0 || _assemblyEnum == null)
+ {
+ throw Marshal.GetExceptionForHR(hResult);
+ }
+ }
+
+ internal bool GetNextAssembly()
+ {
+ int hResult = _assemblyEnum.GetNextAssembly((IntPtr)0, out _fusionName, 0);
+
+ if (hResult < 0 || _fusionName == null)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ internal string FullAssemblyName
+ {
+ get
+ {
+ StringBuilder sDisplayName = new StringBuilder(1024);
+ int iLen = 1024;
+
+ int hrLocal = _fusionName.GetDisplayName(
+ sDisplayName,
+ ref iLen,
+ (int)PInvoke.Fusion.AssemblyNameDisplayFlags.ALL);
+
+ if (hrLocal < 0)
+ {
+ throw Marshal.GetExceptionForHR(hrLocal);
+ }
+
+ return sDisplayName.ToString();
+ }
+ }
+
+ internal PInvoke.Fusion.IAssemblyName FusionName
+ {
+ get
+ {
+ return _fusionName;
+ }
+ }
+
+ public void Dispose()
+ {
+ PInvoke.Fusion.IAssemblyName tempName = _fusionName;
+ if (tempName != null)
+ {
+ _fusionName = null;
+ Marshal.ReleaseComObject(tempName);
+ }
+
+ PInvoke.Fusion.IAssemblyEnum tempEnum = _assemblyEnum;
+ if (tempEnum != null)
+ {
+ _assemblyEnum = null;
+ Marshal.ReleaseComObject(tempEnum);
+ }
+ }
+
+ private string _assemblyName;
+ private PInvoke.Fusion.IAssemblyEnum _assemblyEnum;
+ private PInvoke.Fusion.IAssemblyName _fusionName;
+ }
+
+ internal class GACAssemblyCache : IDisposable
+ {
+ internal GACAssemblyCache(string assemblyName, string fullAssemblyName)
+ {
+ PInvoke.Fusion.AssemblyInfo aInfo = new PInvoke.Fusion.AssemblyInfo();
+ aInfo.cchBuf = 1024;
+ aInfo.currentAssemblyPath = new string('\0', aInfo.cchBuf);
+
+ int hResult = PInvoke.Fusion.NativeMethods.CreateAssemblyCache(out _assemblyCache, 0);
+
+ if (hResult == 0)
+ {
+ hResult = _assemblyCache.QueryAssemblyInfo(0, fullAssemblyName, ref aInfo);
+ }
+
+ if (hResult != 0)
+ {
+ Marshal.GetExceptionForHR(hResult);
+ }
+
+ _assemblyPath = aInfo.currentAssemblyPath;
+ }
+
+ internal string AssemblyPath
+ {
+ get
+ {
+ return _assemblyPath;
+ }
+ }
+
+ public void Dispose()
+ {
+ PInvoke.Fusion.IAssemblyCache temp = _assemblyCache;
+ if (temp != null)
+ {
+ _assemblyCache = null;
+ Marshal.ReleaseComObject(temp);
+ }
+ }
+
+ private string _assemblyPath;
+ private PInvoke.Fusion.IAssemblyCache _assemblyCache;
+ }
+}
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/WebUtility.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/WebUtility.cs
new file mode 100644
index 0000000000..2f5a9c93c4
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/WebUtility.cs
@@ -0,0 +1,65 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Collections;
+using System.Net;
+
+namespace Microsoft.Web.Utility
+{
+ internal static class WebUtility
+ {
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification="We want to count any error as host doesn't exist")]
+ public static bool IsLocalMachine(string serverName, bool useDns)
+ {
+ if (String.Equals(serverName, Environment.MachineName, StringComparison.CurrentCultureIgnoreCase) ||
+ String.Equals(serverName, "localhost", StringComparison.OrdinalIgnoreCase) ||
+ String.Equals(serverName, "127.0.0.1") ||
+ String.Equals(serverName, "::1"))
+ {
+ return true;
+ }
+
+ if (useDns)
+ {
+ try
+ {
+ ArrayList serverAddressesList = new ArrayList();
+ ArrayList currentMachineAddressesList = new ArrayList();
+
+ IPAddress ownAddress = IPAddress.Parse("127.0.0.1");
+
+ // All the IP addresses of the hostname specified by the user
+ IPAddress[] serverAddress = Dns.GetHostAddresses(serverName);
+ serverAddressesList.AddRange(serverAddress);
+
+ /// All the IP addresses of the current machine
+ IPAddress[] currentMachineAddress = Dns.GetHostAddresses(Environment.MachineName);
+ currentMachineAddressesList.AddRange(currentMachineAddress);
+
+ // The address 127.0.0.1 also refers to the current machine
+ currentMachineAddressesList.Add(ownAddress);
+
+ // If any of the addresses for the current machine is the same
+ // as the address for the hostname specified by the user
+ // then use a local connection
+ foreach (IPAddress address in currentMachineAddressesList)
+ {
+ if (serverAddressesList.Contains(address))
+ {
+ return true;
+ }
+ }
+ }
+ catch
+ {
+ // If the Dns class throws an exception the host propbably does not
+ // exist so we return false
+ }
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/README.md b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/README.md
new file mode 100644
index 0000000000..77fc8404c4
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/README.md
@@ -0,0 +1,18 @@
+Microsoft IIS Common
+--------------------------------
+
+The repository contains common resources shared by IIS Out-Of-Band (OOB) products.
+
+### Contributing
+
+This project welcomes contributions and suggestions. Most contributions require you to agree to a
+Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
+the rights to use your contribution. For details, visit https://cla.microsoft.com.
+
+When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
+a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
+provided by the bot. You will only need to do this once across all repos using our CLA.
+
+This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
+For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
+contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/common_tests.rc b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/common_tests.rc
new file mode 100644
index 0000000000..98b1593b3b
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/common_tests.rc
@@ -0,0 +1,7 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#define RC_VERSION_INTERNAL_NAME "Common.UnitTests\0"
+#define RC_VERSION_ORIGINAL_FILE_NAME "Common.UnitTests.dll\0"
+#define RC_VERSION_FILE_DESCRIPTION "Common.UnitTests0"
+#include
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/dbgutil_tests.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/dbgutil_tests.cpp
new file mode 100644
index 0000000000..2fc97d6f95
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/dbgutil_tests.cpp
@@ -0,0 +1,72 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.hxx"
+#include "dbgutil.h"
+#include
+
+DECLARE_DEBUG_PRINT_OBJECT( "test" );
+
+VOID PrintLevel( DWORD level )
+{
+ DWORD old = DEBUG_FLAGS_VAR;
+ DEBUG_FLAGS_VAR = level;
+
+ DBGPRINTF(( DBG_CONTEXT, "Some Data %d\n", 47 ));
+ DBGINFO(( DBG_CONTEXT, "Some Info %s\n", "info" ));
+ DBGWARN(( DBG_CONTEXT, "Some Info %s\n", "warning" ));
+ DBGERROR(( DBG_CONTEXT, "Some Info %s\n", "error" ));
+
+ DEBUG_FLAGS_VAR = old;
+}
+
+
+#pragma managed
+
+using namespace Microsoft::VisualStudio::TestTools::UnitTesting;
+
+[TestClass]
+public ref class DebugUtilitiesTests
+{
+public:
+
+ [ClassInitialize]
+ static void InitializeDebugObjects(TestContext)
+ {
+ CREATE_DEBUG_PRINT_OBJECT;
+
+ _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
+ _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR );
+ }
+
+ [TestMethod]
+ void TestDbgError()
+ {
+ PrintLevel( DEBUG_FLAGS_ERROR );
+ }
+
+ [TestMethod]
+ void TestPrintAny()
+ {
+ PrintLevel( DEBUG_FLAGS_ANY );
+ }
+
+ [TestMethod]
+ void TestPrintError()
+ {
+ DBGERROR_HR( E_FAIL );
+ DBGERROR_STATUS( 47 );
+ }
+
+ [TestMethod]
+ void TestPrintWarn()
+ {
+ PrintLevel( DEBUG_FLAGS_WARN );
+ }
+
+ [TestMethod]
+ void TestPrintInfo()
+ {
+ PrintLevel( DEBUG_FLAGS_INFO );
+ }
+};
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hash_tests.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hash_tests.cpp
new file mode 100644
index 0000000000..c0fb29f5a2
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hash_tests.cpp
@@ -0,0 +1,52 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.hxx"
+#include "hashtable.h"
+#include "hashfn.h"
+#include "my_hash.h"
+
+VOID
+CountHash(
+ MY_OBJ * , //pRecord,
+ PVOID pVoid
+)
+{
+ DWORD * pActualCount = (DWORD*) pVoid;
+ ++(*pActualCount);
+}
+
+
+#pragma managed
+
+using namespace Microsoft::VisualStudio::TestTools::UnitTesting;
+
+[TestClass]
+public ref class HashTableTests
+{
+public:
+
+ [TestMethod]
+ void AddTwoRecordsTest()
+ {
+ MY_HASH hash;
+ HRESULT hr;
+ hr = hash.Initialize(32);
+
+ Assert::AreEqual(S_OK, hr, L"Invalid hash table initialization");
+
+ MY_OBJ one(L"one");
+ hr = hash.InsertRecord(&one);
+ Assert::AreEqual(S_OK, hr, L"Cannot add element 'one'");
+
+ MY_OBJ two(L"two");
+ hr = hash.InsertRecord(&two);
+ Assert::AreEqual(S_OK, hr, L"Cannot add element 'two'");
+
+ DWORD ActualCount = 0;
+ hash.Apply(CountHash, &ActualCount);
+ Assert::AreEqual((DWORD)2, ActualCount, L"ActualCount != 2");
+
+ hash.Clear();
+ }
+};
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hybrid_array_tests.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hybrid_array_tests.cpp
new file mode 100644
index 0000000000..9f54467e77
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hybrid_array_tests.cpp
@@ -0,0 +1,95 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.hxx"
+#include "hybrid_array.h"
+
+//
+// Cannot support mixed native/managed code for BUFFER class
+// because of alignment. We need to run the test as native.
+//
+#include
+
+
+void HybridArrayTest()
+{
+ HRESULT hr;
+
+ {
+ HYBRID_ARRAY arrPointers;
+ Assert::AreEqual(32, arrPointers.QueryCapacity(), L"Invalid initial length");
+ }
+
+ {
+ HYBRID_ARRAY arrIntegers;
+ int SourceArray[] = {1, 2, 3, 4};
+ hr = arrIntegers.Copy( SourceArray );
+ Assert::AreEqual(S_OK, hr, L"Copy failed.");
+ Assert::AreEqual(_countof(SourceArray), arrIntegers.QueryCapacity());
+ }
+
+ {
+ HYBRID_ARRAY arrIntegers;
+ int* pOriginal = arrIntegers.QueryArray();
+ int SourceArray[] = {1, 2, 3, 4};
+ hr = arrIntegers.Copy( SourceArray );
+ int* pNew = arrIntegers.QueryArray();
+ Assert::AreEqual(S_OK, hr, L"Copy failed.");
+ Assert::AreEqual(_countof(SourceArray), arrIntegers.QueryCapacity(), L"Size should be like source");
+ Assert::AreNotEqual((__int64)pNew, (__int64)pOriginal, L"Pointer should be different");
+
+ Assert::AreEqual(1, arrIntegers[0], L"Index 0 failed.");
+ Assert::AreEqual(2, arrIntegers.QueryItem(1), L"Index 1 failed.");
+ Assert::AreEqual(3, arrIntegers.QueryItem(2), L"Index 2 failed.");
+ Assert::AreEqual(4, arrIntegers[3], L"Index 3 failed.");
+ }
+
+ {
+ HYBRID_ARRAY arrIntegers;
+ hr = arrIntegers.EnsureCapacity(100, false);
+ Assert::AreEqual(S_OK, hr, L"Copy failed.");
+ Assert::AreEqual(100, arrIntegers.QueryCapacity());
+ }
+
+ {
+ HYBRID_ARRAY arrIntegers;
+ arrIntegers[0] = 123;
+ arrIntegers[1] = 999;
+ hr = arrIntegers.EnsureCapacity(100, true /*copy previous*/);
+ Assert::AreEqual(S_OK, hr, L"Copy failed.");
+ Assert::AreEqual(100, arrIntegers.QueryCapacity());
+ Assert::AreEqual(123, arrIntegers[0], L"Index resize 0 failed.");
+ Assert::AreEqual(999, arrIntegers[1], L"Index resize 1 failed.");
+
+ }
+
+ {
+ HYBRID_ARRAY arrIntegers;
+ arrIntegers[0] = 123;
+ arrIntegers[1] = 999;
+ hr = arrIntegers.EnsureCapacity(100, true /*copy previous*/, true /*trivial assign*/);
+ Assert::AreEqual(S_OK, hr, L"Copy failed.");
+ Assert::AreEqual(100, arrIntegers.QueryCapacity());
+ Assert::AreEqual(123, arrIntegers[0], L"Index resize trivial 0 failed.");
+ Assert::AreEqual(999, arrIntegers[1], L"Index resize trivial 1 failed.");
+
+ }
+}
+
+
+#pragma managed
+
+using namespace Microsoft::VisualStudio::TestTools::UnitTesting;
+
+[TestClass]
+public ref class ArrayTests
+{
+public:
+
+ [TestMethod]
+ void HybridArrayTest()
+ {
+ ::HybridArrayTest();
+ }
+
+};
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/my_hash.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/my_hash.h
new file mode 100644
index 0000000000..71417dc77b
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/my_hash.h
@@ -0,0 +1,63 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#pragma once
+
+class MY_OBJ
+{
+ public:
+ MY_OBJ(PCWSTR pstr)
+ : _pstr(pstr)
+ {}
+
+ PCWSTR GetString()
+ {
+ return _pstr;
+ }
+
+ private:
+ PCWSTR _pstr;
+};
+
+class MY_HASH : public HASH_TABLE
+{
+ public:
+ VOID
+ ReferenceRecord(
+ MY_OBJ * //pRecord
+ )
+ {}
+
+ VOID
+ DereferenceRecord(
+ MY_OBJ * //pRecord
+ )
+ {}
+
+ PCWSTR
+ ExtractKey(
+ MY_OBJ * pRecord
+ )
+ {
+ return pRecord->GetString();
+ }
+
+ DWORD
+ CalcKeyHash(
+ PCWSTR key
+ )
+ {
+ return HashString(key);
+ }
+
+ BOOL
+ EqualKeys(
+ PCWSTR key1,
+ PCWSTR key2
+ )
+ {
+ return (wcscmp(key1, key2) == 0);
+ }
+};
+
+void TestHash();
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/precomp.hxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/precomp.hxx
new file mode 100644
index 0000000000..16c76d9540
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/precomp.hxx
@@ -0,0 +1,7 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#pragma once
+// Native-only by default
+#pragma unmanaged
+#include
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/string_tests.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/string_tests.cpp
new file mode 100644
index 0000000000..0b987e9b58
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/string_tests.cpp
@@ -0,0 +1,680 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.hxx"
+#include "buffer.h"
+#include "stringu.h"
+#include "stringa.h"
+
+//
+// Cannot support mixed native/managed code for BUFFER class
+// because of alignment. We need to run the test as native.
+//
+#include
+
+void TestBuffer()
+{
+ //
+ // 104 == 8 byte size rounded, why is this needed?
+ //
+ STACK_BUFFER( bufStack, 104 );
+ BUFFER bufReg;
+ BUFFER* pBuf = new BUFFER;
+
+ //
+ // QueryPtr
+ //
+ Assert::IsNotNull( bufStack.QueryPtr( ) );
+ Assert::IsNotNull( bufReg.QueryPtr( ) );
+ Assert::IsNotNull( pBuf->QueryPtr( ) );
+
+ //
+ // QuerySize
+ //
+ Assert::IsTrue( 104 == bufStack.QuerySize( ) );
+ Assert::IsTrue( INLINED_BUFFER_LEN == bufReg.QuerySize( ) );
+ Assert::IsTrue( INLINED_BUFFER_LEN == pBuf->QuerySize( ) );
+
+ //
+ // Resize
+ //
+ Assert::IsTrue( bufStack.Resize( 64 ) );
+ Assert::IsTrue( bufReg.Resize( 128) );
+ Assert::IsTrue( pBuf->Resize( 256 ) );
+
+ //
+ // Resize again
+ //
+ Assert::IsTrue( bufStack.Resize( 512, true ) );
+ Assert::IsTrue( bufReg.Resize( 512, true ) );
+ Assert::IsTrue( pBuf->Resize( 512, true ) );
+
+ //
+ // Resize again
+ //
+ Assert::IsTrue( bufStack.Resize( 1024, false ) );
+ Assert::IsTrue( bufReg.Resize( 1024, false ) );
+ Assert::IsTrue( pBuf->Resize( 1024, false ) );
+
+ //
+ // write to mem
+ //
+ ZeroMemory( bufStack.QueryPtr( ), bufStack.QuerySize( ) );
+ ZeroMemory( bufReg.QueryPtr( ), bufReg.QuerySize( ) );
+ ZeroMemory( pBuf->QueryPtr( ), pBuf->QuerySize( ) );
+
+ delete pBuf;
+}
+
+void TestStraOverrun()
+{
+ STACK_STRA( straStack, 3 );
+ wchar_t Input[] = {0x65f6, 0x0};
+ HRESULT hr;
+
+ hr = straStack.CopyW(Input);
+ Assert::IsTrue( SUCCEEDED(hr) );
+ Assert::AreEqual( 3, straStack.QueryCCH(), L"Invalid string length." );
+ Assert::AreEqual( 4, straStack.QuerySizeCCH(), L"Invalid buffer length." );
+}
+
+#define LOWER_A_THING L"ä"
+#define UPPER_A_THING L"Ä"
+
+void TestStru()
+{
+ STACK_STRU( struStack, 104 );
+ STRU struReg;
+ wchar_t buf[100];
+ DWORD cbBuf = sizeof( buf );
+
+ //
+ // IsEmpty
+ //
+ Assert::IsTrue( struStack.IsEmpty( ) );
+ Assert::IsTrue( L'\0' == struStack.QueryStr()[0] );
+ Assert::IsTrue( struReg.IsEmpty( ) );
+
+ //
+ // Copy psz
+ // CopyA psz
+ //
+ Assert::IsTrue( SUCCEEDED( struStack.Copy( L"hello" ) ) );
+ Assert::IsTrue( SUCCEEDED( struReg.CopyA( "hello" ) ) );
+
+ //
+ // Equal
+ //
+ Assert::IsTrue( struStack.Equals( L"hello" ) );
+ Assert::IsTrue( !struStack.Equals( L"goodbye" ) );
+ Assert::IsTrue( !struStack.Equals( L"" ) );
+
+ STRU strHELLO;
+ Assert::IsTrue( SUCCEEDED( strHELLO.Copy( L"HELLO" ) ) );
+
+ Assert::IsTrue( struStack.Equals( &struReg ) );
+ Assert::IsTrue( struStack.Equals( struReg ) );
+
+ Assert::IsTrue( !struStack.Equals( &strHELLO ) );
+ Assert::IsTrue( !struStack.Equals( strHELLO ) );
+
+ Assert::IsTrue( struStack.Equals( &strHELLO, TRUE ) );
+ Assert::IsTrue( struStack.Equals( strHELLO, TRUE ) );
+
+ Assert::IsTrue( struStack.Equals( L"helLO", TRUE ) );
+
+
+ Assert::IsTrue( STRU::Equals( L"Hello", L"Hello" ) );
+ Assert::IsTrue( STRU::Equals( L"Hello", L"Hello", FALSE ) );
+ Assert::IsTrue( STRU::Equals( L"Hello", L"Hello", TRUE ) );
+
+ Assert::IsFalse( STRU::Equals( L"hello", L"Hello" ) );
+ Assert::IsFalse( STRU::Equals( L"hello", L"Hello", FALSE ) );
+ Assert::IsTrue( STRU::Equals( L"hello", L"Hello", TRUE ) );
+
+ Assert::IsFalse( STRU::Equals( L"hello", L"goodbye" ) );
+ Assert::IsFalse( STRU::Equals( L"hello", L"goodbye", FALSE ) );
+ Assert::IsFalse( STRU::Equals( L"hello", L"goodbye", TRUE ) );
+
+ Assert::IsFalse( STRU::Equals( (PCWSTR)NULL, (PCWSTR)NULL ) );
+ Assert::IsFalse( STRU::Equals( L"hello", (PCWSTR)NULL ) );
+ Assert::IsFalse( STRU::Equals( (PCWSTR)NULL, L"hello" ) );
+
+
+
+ //
+ // Query*
+ //
+ Assert::IsTrue( 5 * sizeof( wchar_t ) == struStack.QueryCB( ) );
+ Assert::IsTrue( 5 == struStack.QueryCCH( ) );
+ Assert::IsTrue( 6 <= struStack.QuerySizeCCH( ) );
+ Assert::IsTrue( L'h' == *( struStack.QueryStr( ) ) );
+
+ //
+ // Resize
+ //
+ Assert::IsTrue( SUCCEEDED( struReg.Resize( 7 ) ) );
+ Assert::IsTrue( 7 == struReg.QuerySizeCCH( ) );
+
+ //
+ // SyncWithBuffer
+ //
+ *(struStack.QueryStr() + 5) = L'\0';
+ Assert::AreEqual(S_OK, struStack.SyncWithBuffer( ));
+ Assert::IsTrue( 5 == struStack.QueryCCH( ) );
+
+ //
+ // Reset
+ //
+ struStack.Reset( );
+ Assert::IsTrue( 0 == wcslen( struStack.QueryStr( ) ) );
+
+ //
+ // Append*
+ //
+ Assert::IsTrue( SUCCEEDED( struStack.Append( L"hell" ) ) );
+ Assert::IsTrue( SUCCEEDED( struStack.Append( L"o", 1 ) ) );
+ Assert::IsTrue( SUCCEEDED( struStack.Append( &struReg ) ) );
+ Assert::IsTrue( SUCCEEDED( struStack.AppendA( "hell" ) ) );
+ Assert::IsTrue( SUCCEEDED( struStack.AppendA( "0", 1, CP_ACP ) ) );
+ Assert::IsTrue( 15 == wcslen( struStack.QueryStr( ) ) );
+
+ //
+ // CopyToBuffer
+ //
+ Assert::IsTrue( SUCCEEDED( struStack.CopyToBuffer( buf, &cbBuf ) ) );
+ Assert::IsTrue( 15 == wcslen( buf ) );
+ Assert::IsTrue( 16 * sizeof( wchar_t ) == cbBuf );
+
+ //
+ // Trim
+ //
+ Assert::IsTrue( SUCCEEDED( struStack.Copy(L" \n\tHello World! \n\t ") ) );
+ struStack.Trim();
+ Assert::IsTrue( struStack.Equals(L"Hello World!"));
+
+ Assert::IsTrue( SUCCEEDED( struStack.Copy(L" Test test") ) );
+ struStack.Trim();
+ Assert::IsTrue( struStack.Equals(L"Test test"));
+
+ Assert::IsTrue( SUCCEEDED( struStack.Copy(L"Test test ") ) );
+ struStack.Trim();
+ Assert::IsTrue( struStack.Equals(L"Test test"));
+
+ Assert::IsTrue( SUCCEEDED( struStack.Copy(L" Test test ") ) );
+ struStack.Trim();
+ Assert::IsTrue( struStack.Equals(L"Test test"));
+
+ Assert::IsTrue( SUCCEEDED( struStack.Copy(L" ") ) );
+ struStack.Trim();
+ Assert::IsTrue( struStack.Equals(L""));
+
+ Assert::IsTrue( SUCCEEDED( struStack.Copy(L" ") ) );
+ struStack.Trim();
+ Assert::IsTrue( struStack.Equals(L""));
+
+ Assert::IsTrue( SUCCEEDED( struStack.Copy(L"") ) );
+ struStack.Trim();
+ Assert::IsTrue( struStack.Equals(L""));
+
+ //
+ // StartsWith
+ //
+ Assert::IsTrue( SUCCEEDED( struStack.Copy(L"Just the facts, please.") ) );
+ Assert::IsTrue( struStack.StartsWith(L"Just the facts, please.") );
+ Assert::IsTrue( struStack.StartsWith(L"Just") );
+ Assert::IsTrue( struStack.StartsWith(L"Just the") );
+ Assert::IsTrue( !struStack.StartsWith(L"just the") );
+ Assert::IsTrue( struStack.StartsWith(L"just The", TRUE) );
+ Assert::IsTrue( !struStack.StartsWith((LPCWSTR) NULL, TRUE) );
+ Assert::IsTrue( !struStack.StartsWith(L"Just the facts, please...") );
+
+ //
+ // EndsWith
+ //
+ Assert::IsTrue( SUCCEEDED( struStack.Copy(L"The beginning of the end of the beginning.") ) );
+ Assert::IsTrue( struStack.EndsWith(L"The beginning of the end of the beginning.") );
+ Assert::IsTrue( struStack.EndsWith(L".") );
+ Assert::IsTrue( struStack.EndsWith(L"of the beginning.") );
+ Assert::IsTrue( !struStack.EndsWith(L"Beginning.") );
+ Assert::IsTrue( struStack.EndsWith(L"Beginning.", TRUE) );
+ Assert::IsTrue( struStack.EndsWith(L"tHe BeGiNnIng.", TRUE) );
+ Assert::IsTrue( !struStack.EndsWith((LPCWSTR) NULL, TRUE) );
+ Assert::IsTrue( !struStack.EndsWith(L" The beginning of the end of the beginning.") );
+
+ //
+ // IndexOf
+ //
+ Assert::IsTrue( SUCCEEDED( struStack.Copy(L"01234567890") ) );
+ Assert::IsTrue( 0 == struStack.IndexOf( L'0' ) );
+ Assert::IsTrue( 1 == struStack.IndexOf( L'1' ) );
+ Assert::IsTrue( 2 == struStack.IndexOf( L'2', 1 ) );
+ Assert::IsTrue( 10 == struStack.IndexOf( L'0', 1 ) );
+ Assert::IsTrue( -1 == struStack.IndexOf( L'A' ) );
+ Assert::IsTrue( -1 == struStack.IndexOf( L'0', 20 ) );
+
+ Assert::IsTrue( 0 == struStack.IndexOf( L"0123" ) );
+ Assert::IsTrue( -1 == struStack.IndexOf( L"0123", 1 ) );
+ Assert::IsTrue( 0 == struStack.IndexOf( L"01234567890" ) );
+ Assert::IsTrue( -1 == struStack.IndexOf( L"012345678901" ) );
+ Assert::IsTrue( 1 == struStack.IndexOf( L"1234" ) );
+ Assert::IsTrue( 1 == struStack.IndexOf( L"1234", 1 ) );
+ Assert::IsTrue( -1 == struStack.IndexOf( (PCWSTR)NULL ) );
+ Assert::IsTrue( 0 == struStack.IndexOf( L"" ) );
+ Assert::IsTrue( -1 == struStack.IndexOf( L"", 20 ) );
+
+ //
+ // LastIndexOf
+ //
+ Assert::IsTrue( 10 == struStack.LastIndexOf( L'0' ) );
+ Assert::IsTrue( 1 == struStack.LastIndexOf( L'1' ) );
+ Assert::IsTrue( 2 == struStack.LastIndexOf( L'2', 1 ) );
+ Assert::IsTrue( 10 == struStack.LastIndexOf( L'0', 1 ) );
+ Assert::IsTrue( -1 == struStack.LastIndexOf( L'A' ) );
+ Assert::IsTrue( -1 == struStack.LastIndexOf( L'0', 20 ) );
+
+ //
+ // SetLen
+ //
+ Assert::IsTrue( SUCCEEDED( struStack.SetLen( 2 ) ) );
+ Assert::IsTrue( 2 == struStack.QueryCCH( ) );
+
+#if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN
+
+ //
+ // OS-locale case-insensitive compare
+ // Note how the two case-insensitive comparisons have different expected results
+ //
+ Assert::IsTrue( SUCCEEDED( struStack.Copy( LOWER_A_THING ) ) );
+ Assert::IsTrue( SUCCEEDED( struReg.Copy( UPPER_A_THING ) ) );
+ Assert::IsTrue( !struStack.Equals( &struReg ) );
+ Assert::IsTrue( struStack.Equals( &struReg, TRUE ) );
+ Assert::IsTrue( 0 != _wcsicmp( LOWER_A_THING, UPPER_A_THING ) );
+
+#endif
+
+ Assert::IsTrue( SUCCEEDED( struReg.SafeSnwprintf( L"%s%d", L"Hello", 10 ) ) );
+
+ //
+ // Fail since there is no null-terminating char.
+ //
+ struStack.Reset();
+ struStack.Resize(200);
+ memset(struStack.QueryStr(), 'x', 200 * sizeof(WCHAR));
+ Assert::AreNotEqual(S_OK, struStack.SyncWithBuffer());
+}
+
+void TestStra()
+{
+ STACK_STRA( straStack, 104 );
+ STRA straReg;
+ char buf[100];
+ DWORD cbBuf = sizeof( buf );
+
+ //
+ // IsEmpty
+ //
+ Assert::IsTrue( straStack.IsEmpty( ) );
+ Assert::IsTrue( '\0' == straStack.QueryStr()[0] );
+ Assert::IsTrue( straReg.IsEmpty( ) );
+
+ //
+ // Copy psz
+ // CopyW psz
+ //
+ Assert::IsTrue( SUCCEEDED( straStack.Copy( "hello" ) ) );
+ Assert::IsTrue( SUCCEEDED( straReg.CopyW( L"hello" ) ) );
+
+ //
+ // Equal
+ //
+ Assert::IsTrue( straStack.Equals( "hello" ) );
+ Assert::IsTrue( straStack.Equals( &straReg ) );
+ Assert::IsTrue( straStack.Equals( "helLO", TRUE ) );
+
+
+ Assert::IsTrue( STRA::Equals( "Hello", "Hello" ) );
+ Assert::IsTrue( STRA::Equals( "Hello", "Hello", FALSE ) );
+ Assert::IsTrue( STRA::Equals( "Hello", "Hello", TRUE ) );
+
+ Assert::IsFalse( STRA::Equals( "hello", "Hello" ) );
+ Assert::IsFalse( STRA::Equals( "hello", "Hello", FALSE ) );
+ Assert::IsTrue( STRA::Equals( "hello", "Hello", TRUE ) );
+
+ Assert::IsFalse( STRA::Equals( "hello", "goodbye" ) );
+ Assert::IsFalse( STRA::Equals( "hello", "goodbye", FALSE ) );
+ Assert::IsFalse( STRA::Equals( "hello", "goodbye", TRUE ) );
+
+ Assert::IsFalse( STRA::Equals( (PCSTR)NULL, (PCSTR)NULL ) );
+ Assert::IsFalse( STRA::Equals( "hello", (PCSTR)NULL ) );
+ Assert::IsFalse( STRA::Equals( (PCSTR)NULL, "hello" ) );
+
+ //
+ // Query*
+ //
+ Assert::IsTrue( 5 * sizeof( char ) == straStack.QueryCB( ) );
+ Assert::IsTrue( 5 == straStack.QueryCCH( ) );
+ Assert::IsTrue( 6 <= straStack.QuerySizeCCH( ) );
+ Assert::IsTrue( 'h' == *( straStack.QueryStr( ) ) );
+
+ //
+ // Resize
+ //
+ Assert::IsTrue( SUCCEEDED( straReg.Resize( 7 ) ) );
+ Assert::IsTrue( 7 == straReg.QuerySizeCCH( ) );
+
+ //
+ // SyncWithBuffer
+ //
+ *(straStack.QueryStr() + 5) = L'\0';
+ Assert::AreEqual(S_OK, straStack.SyncWithBuffer( ));
+ Assert::IsTrue( 5 == straStack.QueryCCH( ) );
+
+ //
+ // Reset
+ //
+ straStack.Reset( );
+ Assert::IsTrue( 0 == strlen( straStack.QueryStr( ) ) );
+
+ //
+ // Append*
+ //
+ Assert::IsTrue( SUCCEEDED( straStack.Append( "hell" ) ) );
+ Assert::IsTrue( SUCCEEDED( straStack.Append( "o", 1 ) ) );
+ Assert::IsTrue( SUCCEEDED( straStack.Append( &straReg ) ) );
+ Assert::IsTrue( SUCCEEDED( straStack.AppendW( L"hell" ) ) );
+ Assert::IsTrue( SUCCEEDED( straStack.AppendW( L"0", 1, CP_ACP ) ) );
+ Assert::IsTrue( 15 == strlen( straStack.QueryStr( ) ) );
+
+ //
+ // CopyToBuffer
+ //
+ Assert::IsTrue( SUCCEEDED( straStack.CopyToBuffer( buf, &cbBuf ) ) );
+ Assert::IsTrue( 15 == strlen( buf ) );
+ Assert::IsTrue( 16 * sizeof( char ) == cbBuf );
+
+ //
+ // Trim
+ //
+ Assert::IsTrue( SUCCEEDED( straStack.Copy(" \n\tHello World! \n\t ") ) );
+ straStack.Trim();
+ Assert::IsTrue( straStack.Equals("Hello World!"));
+
+ Assert::IsTrue( SUCCEEDED( straStack.Copy(" Test test") ) );
+ straStack.Trim();
+ Assert::IsTrue( straStack.Equals("Test test"));
+
+ Assert::IsTrue( SUCCEEDED( straStack.Copy("Test test ") ) );
+ straStack.Trim();
+ Assert::IsTrue( straStack.Equals("Test test"));
+
+ Assert::IsTrue( SUCCEEDED( straStack.Copy(" Test test ") ) );
+ straStack.Trim();
+ Assert::IsTrue( straStack.Equals("Test test"));
+
+ Assert::IsTrue( SUCCEEDED( straStack.Copy(" ") ) );
+ straStack.Trim();
+ Assert::IsTrue( straStack.Equals(""));
+
+ Assert::IsTrue( SUCCEEDED( straStack.Copy(" ") ) );
+ straStack.Trim();
+ Assert::IsTrue( straStack.Equals(""));
+
+ Assert::IsTrue( SUCCEEDED( straStack.Copy("") ) );
+ straStack.Trim();
+ Assert::IsTrue( straStack.Equals(""));
+
+ //
+ // StartsWith
+ //
+ Assert::IsTrue( SUCCEEDED( straStack.Copy("Just the facts, please.") ) );
+ Assert::IsTrue( straStack.StartsWith("Just the facts, please.") );
+ Assert::IsTrue( straStack.StartsWith("Just") );
+ Assert::IsTrue( straStack.StartsWith("Just the") );
+ Assert::IsTrue( !straStack.StartsWith("just the") );
+ Assert::IsTrue( straStack.StartsWith("just The", TRUE) );
+ Assert::IsTrue( !straStack.StartsWith((LPCSTR) NULL, TRUE) );
+ Assert::IsTrue( !straStack.StartsWith("Just the facts, please...") );
+
+ //
+ // EndsWith
+ //
+ Assert::IsTrue( SUCCEEDED( straStack.Copy("The beginning of the end of the beginning.") ) );
+ Assert::IsTrue( straStack.EndsWith("The beginning of the end of the beginning.") );
+ Assert::IsTrue( straStack.EndsWith(".") );
+ Assert::IsTrue( straStack.EndsWith("of the beginning.") );
+ Assert::IsTrue( !straStack.EndsWith("Beginning.") );
+ Assert::IsTrue( straStack.EndsWith("Beginning.", TRUE) );
+ Assert::IsTrue( straStack.EndsWith("tHe BeGiNnIng.", TRUE) );
+ Assert::IsTrue( !straStack.EndsWith((LPCSTR) NULL, TRUE) );
+ Assert::IsTrue( !straStack.EndsWith(" The beginning of the end of the beginning.") );
+
+ //
+ // IndexOf
+ //
+ Assert::IsTrue( SUCCEEDED( straStack.Copy("01234567890") ) );
+ Assert::IsTrue( 0 == straStack.IndexOf( '0' ) );
+ Assert::IsTrue( 1 == straStack.IndexOf( '1' ) );
+ Assert::IsTrue( 2 == straStack.IndexOf( '2', 1 ) );
+ Assert::IsTrue( 10 == straStack.IndexOf( '0', 1 ) );
+ Assert::IsTrue( -1 == straStack.IndexOf( 'A' ) );
+ Assert::IsTrue( -1 == straStack.IndexOf( '0', 20 ) );
+
+ Assert::IsTrue( 0 == straStack.IndexOf( "0123" ) );
+ Assert::IsTrue( -1 == straStack.IndexOf( "0123", 1 ) );
+ Assert::IsTrue( 0 == straStack.IndexOf( "01234567890" ) );
+ Assert::IsTrue( -1 == straStack.IndexOf( "012345678901" ) );
+ Assert::IsTrue( 1 == straStack.IndexOf( "1234" ) );
+ Assert::IsTrue( 1 == straStack.IndexOf( "1234", 1 ) );
+ Assert::IsTrue( -1 == straStack.IndexOf( (PCSTR)NULL ) );
+ Assert::IsTrue( 0 == straStack.IndexOf( "" ) );
+ Assert::IsTrue( -1 == straStack.IndexOf( "", 20 ) );
+
+ //
+ // LastIndexOf
+ //
+ Assert::IsTrue( 10 == straStack.LastIndexOf( '0' ) );
+ Assert::IsTrue( 1 == straStack.LastIndexOf( '1' ) );
+ Assert::IsTrue( 2 == straStack.LastIndexOf( '2', 1 ) );
+ Assert::IsTrue( 10 == straStack.LastIndexOf( '0', 1 ) );
+ Assert::IsTrue( -1 == straStack.LastIndexOf( 'A' ) );
+ Assert::IsTrue( -1 == straStack.LastIndexOf( '0', 20 ) );
+
+ //
+ // SetLen
+ //
+ Assert::IsTrue( SUCCEEDED( straStack.SetLen( 2 ) ) );
+ Assert::IsTrue( 2 == straStack.QueryCCH( ) );
+
+
+ //
+ // Convert.
+ //
+ {
+ STRA str;
+ wchar_t psz[] = {0x41, L'Ã', 0x0};
+ char pszA[] = {0x41, 'Ã', 0x0};
+ Assert::IsTrue( SUCCEEDED(str.CopyW((LPCWSTR)psz, 2, CP_ACP )) );
+ Assert::IsTrue( 0 == strcmp( pszA, str.QueryStr() ) );
+ }
+ //
+ // Empty
+ //
+ {
+ STRA str;
+ wchar_t psz[] = {0x0};
+ char pszA[] = {0x0};
+ Assert::IsTrue( SUCCEEDED(str.CopyW((LPCWSTR)psz, 0, CP_ACP )) );
+ Assert::IsTrue( 0 == strcmp( pszA, str.QueryStr() ) );
+ }
+
+ //
+ // Fail since there is no null-terminating char.
+ //
+ straStack.Reset();
+ straStack.Resize(200);
+ memset(straStack.QueryStr(), 'x', 200);
+ Assert::AreNotEqual(S_OK, straStack.SyncWithBuffer());
+}
+
+VOID
+AsciiAssert(char * str1, char * str2, size_t length)
+{
+ for ( size_t index = 0; index < length; ++index )
+ {
+ Assert::AreEqual(str1[index], str2[index]);
+ }
+}
+
+void
+TestStraUnicode()
+{
+ STRA str;
+ HRESULT hr = S_OK;
+
+ //
+ // Tool used to convert unicode to UTF-8 code points and hexadecimal code points:
+ // http://rishida.net/scripts/uniview/conversion.php
+ //
+
+ //
+ // Input values to play with.
+ //
+
+ // Real unicode string.
+ LPCWSTR InputRealUnicode = L"?q=世加";
+
+ // This is the same value than InputRealUnicode, but represented as an array.
+ wchar_t InputRealUnicodeArray[] =
+ {
+ 0x3F, // ?
+ 0x71, // q
+ 0x3D, // =
+ 0x4E16, // 世
+ 0x52A0, // 加
+ 0x00 // L'\0'
+ };
+
+ wchar_t InputAscii[] =
+ {
+ 0x3F, // ?
+ 0x71, // q
+ 0x3D, // =
+ 0x7F, // 127
+ 0x00 // L'\0'
+ };
+
+ // Fake unicode
+ // UTF-8 code units in 'wchar_t' chars instead of 'char' chars.
+ // This is how WinHttp returns the query string.
+ wchar_t InputFakeUnicode[] =
+ {
+ 0x3F, // ?
+ 0x71, // q
+ 0x3D, // =
+ 0xE4, // 1st code unit for '世'
+ 0xB8, // 2nd code unit for '世'
+ 0x96, // 3rd code unit for '世'
+ 0xE5, // 1st code unit for '加'
+ 0x8A, // 2nd code unit for '加'
+ 0xA0, // 3rd code unit for '加'
+ 0x00 // L'\0'
+ };
+
+ //
+ // Expected values after translation.
+ //
+
+ unsigned char ExpectedAsciiCodeUnits[] =
+ {
+ 0x3F, // ?
+ 0x71, // q
+ 0x3D, // =
+ 0xE4, // 1st code unit for '世'
+ 0xB8, // 2nd code unit for '世'
+ 0x96, // 3rd code unit for '世'
+ 0xE5, // 1st code unit for '加'
+ 0x8A, // 2nd code unit for '加'
+ 0xA0, // 3rd code unit for '加'
+ 0x00 // L'\0'
+ };
+
+ char ExpectedAscii[] =
+ {
+ 0x3F, // ?
+ 0x71, // q
+ 0x3D, // =
+ 0x7F, // 127
+ 0x00 // L'\0'
+ };
+
+ //
+ // Act and Assert.
+ //
+
+ hr = str.CopyW(InputRealUnicode);
+ Assert::AreEqual(S_OK, hr);
+ Assert::AreEqual(9UL, str.QueryCCH(), L"Invalid real unicode query string length.");
+ AsciiAssert( (char*)ExpectedAsciiCodeUnits, str.QueryStr(), str.QueryCCH() );
+
+ hr = str.CopyW(InputRealUnicodeArray);
+ Assert::AreEqual(S_OK, hr);
+ Assert::AreEqual(9UL, str.QueryCCH(), L"Invalid real unicode query string length.");
+ AsciiAssert( (char*)ExpectedAsciiCodeUnits, str.QueryStr(), str.QueryCCH() );
+
+ hr = str.CopyWTruncate(InputFakeUnicode);
+ Assert::AreEqual(S_OK, hr);
+ Assert::AreEqual(9UL, str.QueryCCH(), L"Invalid truncated fake unicode query string length.");
+ AsciiAssert( (char*)ExpectedAsciiCodeUnits, str.QueryStr(), str.QueryCCH() );
+
+ hr = str.CopyWTruncate(InputAscii);
+ Assert::AreEqual(S_OK, hr);
+ Assert::AreEqual(4UL, str.QueryCCH(), L"Invalid truncated ASCII query string length.");
+ AsciiAssert( ExpectedAscii, str.QueryStr(), str.QueryCCH() );
+
+ hr = str.CopyW(InputAscii);
+ Assert::AreEqual(S_OK, hr);
+ Assert::AreEqual(4UL, str.QueryCCH(), L"Invalid CopyW ASCII query string length.");
+ AsciiAssert( ExpectedAscii, str.QueryStr(), str.QueryCCH() );
+
+}
+
+#pragma managed
+
+using namespace Microsoft::VisualStudio::TestTools::UnitTesting;
+
+[TestClass]
+public ref class StringTests
+{
+public:
+
+ [TestMethod]
+ void BufferTest()
+ {
+ ::TestBuffer();
+ }
+
+ [TestMethod]
+ void StruTest()
+ {
+ ::TestStru();
+ }
+
+ [TestMethod]
+ void StraTest()
+ {
+ ::TestStra();
+ }
+
+ [TestMethod]
+ void TestStraOverrun()
+ {
+ ::TestStraOverrun();
+ }
+
+ [TestMethod]
+ void StraUnicodeTest()
+ {
+ ::TestStraUnicode();
+ }
+};
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/compiler.props b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/compiler.props
new file mode 100644
index 0000000000..7394db4ad1
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/compiler.props
@@ -0,0 +1,17 @@
+
+
+
+ 14.11.25547
+ $(UserProfile)\.nuget\packages\visualcpptools.community.vs2017layout\$(CppNugetVersion)\build\native\VisualCppTools.Community.VS2017Layout.props
+ $(UserProfile)\.nuget\GlobalPackages\visualcpptools.community.vs2017layout.$(CppNugetVersion)\build\native\VisualCppTools.Community.VS2017Layout.props
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/copy-outputs.targets b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/copy-outputs.targets
new file mode 100644
index 0000000000..bdc59f4f6d
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/copy-outputs.targets
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+ $(Configuration)\$(PlatformShortname)\
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/exports.props b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/exports.props
new file mode 100644
index 0000000000..fb90d74264
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/exports.props
@@ -0,0 +1,9 @@
+
+
+
+
+
+ $(MSBuildThisFileDirectory)..\
+
+
+
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/settings.props b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/settings.props
new file mode 100644
index 0000000000..bd51e2d1af
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/settings.props
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/settings/common.props b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/settings/common.props
new file mode 100644
index 0000000000..0130b6e5ab
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/settings/common.props
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+ x64
+ x86
+
+
+
+
+
+ 10.0.15063.0
+ $(IisOobWinSdkVersion)
+ Unicode
+ bin\$(Configuration)\$(PlatformShortname)\
+ obj\$(Configuration)\$(PlatformShortname)\
+
+
+
+
+
+
+ Level3
+
+
+
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+
+
+ WIN32;%(PreprocessorDefinitions)
+
+
+
+
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/settings/debug.props b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/settings/debug.props
new file mode 100644
index 0000000000..710f5553d0
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/settings/debug.props
@@ -0,0 +1,29 @@
+
+
+
+
+
+ true
+ true
+ false
+
+
+
+
+
+
+ true
+ Disabled
+ true
+ EnableFastChecks
+ MultiThreadedDebug
+
+
+ false
+ false
+ true
+ /JMC-
+
+
+
+
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/settings/release.props b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/settings/release.props
new file mode 100644
index 0000000000..d7eb8ffa35
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/settings/release.props
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+
+
+ false
+ false
+ true
+
+
+
+
+
+
+ Full
+ Speed
+ false
+ MultiThreaded
+ true
+
+
+ true
+ true
+ UseLinkTimeCodeGeneration
+
+
+
+
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/submodule.props b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/submodule.props
new file mode 100644
index 0000000000..00046cf191
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/submodule.props
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/versions.props b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/versions.props
new file mode 100644
index 0000000000..3be2245e72
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/build/versions.props
@@ -0,0 +1,38 @@
+
+
+
+
+ 7
+ 1
+
+
+ $([MSBuild]::Multiply(12,$([MSBuild]::Subtract($([System.DateTime]::Now.Year), 2016))))
+ $([MSBuild]::Add( $([MSBuild]::Subtract($([System.DateTime]::Now.Month), 10)), $(VersionDateMonths)))
+ $([System.DateTime]::Now.ToString("dd"))
+ $([System.String]::Concat($([System.Int32]::Parse('$(VersionDateTotalMonths)').ToString("D3")), $(VersionDateDays)))
+ $(VersionBuildMajor)
+ $([System.DateTime]::Now.ToString("HHmm"))
+
+
+
+
+ /DPRODUCT_MAJOR=$(PRODUCT_MAJOR) %(AdditionalOptions)
+
+
+ /DPRODUCT_MINOR=$(PRODUCT_MINOR) %(AdditionalOptions)
+
+
+ /DBUILD_MAJOR=$(BUILD_MAJOR) %(AdditionalOptions)
+
+
+ /DBUILD_MINOR=$(BUILD_MINOR) %(AdditionalOptions)
+
+
+
+
+ PRODUCT_MAJOR=$(PRODUCT_MAJOR);$(ResourceCompilePreprocessorDefinitions)
+ PRODUCT_MINOR=$(PRODUCT_MINOR);$(ResourceCompilePreprocessorDefinitions)
+ BUILD_MAJOR=$(BUILD_MAJOR);$(ResourceCompilePreprocessorDefinitions)
+ BUILD_MINOR=$(BUILD_MINOR);$(ResourceCompilePreprocessorDefinitions)
+
+
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/CommonLib.vcxproj b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/CommonLib.vcxproj
new file mode 100644
index 0000000000..1e32646e9a
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/CommonLib.vcxproj
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ {B54A8F61-60DE-4AD9-87CA-D102F230678E}
+ Win32Proj
+ Lib
+ CommonLib
+
+
+
+ StaticLibrary
+ v141
+
+
+ false
+
+
+
+ $(ProjectDir)..\include;$(IncludePath)
+ iiscommon
+
+
+
+ true
+ precomp.h
+ _LIB;%(PreprocessorDefinitions)
+
+
+ Windows
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This project is trying to import a missing file: {0}.
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/acache.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/acache.cxx
new file mode 100644
index 0000000000..262c010a2a
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/acache.cxx
@@ -0,0 +1,443 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+LONG ALLOC_CACHE_HANDLER::sm_nFillPattern = 0xACA50000;
+HANDLE ALLOC_CACHE_HANDLER::sm_hHeap;
+
+//
+// This class is used to implement the free list. We cast the free'd
+// memory block to a FREE_LIST_HEADER*. The signature is used to guard against
+// double deletion. We also fill memory with a pattern.
+//
+class FREE_LIST_HEADER
+{
+public:
+ SLIST_ENTRY ListEntry;
+ DWORD dwSignature;
+
+ enum
+ {
+ FREE_SIGNATURE = (('A') | ('C' << 8) | ('a' << 16) | (('$' << 24) | 0x80)),
+ };
+};
+
+ALLOC_CACHE_HANDLER::ALLOC_CACHE_HANDLER(
+ VOID
+) : m_nThreshold(0),
+ m_cbSize(0),
+ m_pFreeLists(NULL),
+ m_nTotal(0)
+{
+}
+
+ALLOC_CACHE_HANDLER::~ALLOC_CACHE_HANDLER(
+ VOID
+)
+{
+ if (m_pFreeLists != NULL)
+ {
+ CleanupLookaside();
+ m_pFreeLists->Dispose();
+ m_pFreeLists = NULL;
+ }
+}
+
+HRESULT
+ALLOC_CACHE_HANDLER::Initialize(
+ DWORD cbSize,
+ LONG nThreshold
+)
+{
+ HRESULT hr = S_OK;
+
+ m_nThreshold = nThreshold;
+ if ( m_nThreshold > 0xffff)
+ {
+ //
+ // This will be compared against QueryDepthSList return value (USHORT).
+ //
+ m_nThreshold = 0xffff;
+ }
+
+ if ( IsPageheapEnabled() )
+ {
+ //
+ // Disable acache.
+ //
+ m_nThreshold = 0;
+ }
+
+ //
+ // Make sure the block is big enough to hold a FREE_LIST_HEADER.
+ //
+ m_cbSize = cbSize;
+ m_cbSize = max(m_cbSize, sizeof(FREE_LIST_HEADER));
+
+ //
+ // Round up the block size to a multiple of the size of a LONG (for
+ // the fill pattern in Free()).
+ //
+ m_cbSize = (m_cbSize + sizeof(LONG) - 1) & ~(sizeof(LONG) - 1);
+
+#if defined(_MSC_VER) && _MSC_VER >= 1600 // VC10
+ auto Init = [] (SLIST_HEADER* pHead)
+ {
+ InitializeSListHead(pHead);
+ };
+#else
+ class Functor
+ {
+ public:
+ void operator()(SLIST_HEADER* pHead)
+ {
+ InitializeSListHead(pHead);
+ }
+ } Init;
+#endif
+
+ hr = PER_CPU::Create(Init,
+ &m_pFreeLists );
+ if (FAILED(hr))
+ {
+ goto Finished;
+ }
+
+ m_nFillPattern = InterlockedIncrement(&sm_nFillPattern);
+
+Finished:
+
+ return hr;
+}
+
+// static
+HRESULT
+ALLOC_CACHE_HANDLER::StaticInitialize(
+ VOID
+)
+{
+ //
+ // Since the memory allocated is fixed size,
+ // a heap is not really needed, allocations can be done
+ // using VirtualAllocEx[Numa]. For now use Windows Heap.
+ //
+ // Be aware that creating one private heap consumes more
+ // virtual address space for the worker process.
+ //
+ sm_hHeap = GetProcessHeap();
+ return S_OK;
+}
+
+
+// static
+VOID
+ALLOC_CACHE_HANDLER::StaticTerminate(
+ VOID
+)
+{
+ sm_hHeap = NULL;
+}
+
+VOID
+ALLOC_CACHE_HANDLER::CleanupLookaside(
+ VOID
+)
+/*++
+ Description:
+ This function cleans up the lookaside list by removing storage space.
+
+ Arguments:
+ None.
+
+ Returns:
+ None
+--*/
+{
+ //
+ // Free up all the entries in the list.
+ // Don't use InterlockedFlushSList, in order to work
+ // memory must be 16 bytes aligned and currently it is 64.
+ //
+
+#if defined(_MSC_VER) && _MSC_VER >= 1600 // VC10
+ auto Predicate = [=] (SLIST_HEADER * pListHeader)
+ {
+ PSLIST_ENTRY pl;
+ LONG NodesToDelete = QueryDepthSList( pListHeader );
+
+ pl = InterlockedPopEntrySList( pListHeader );
+ while ( pl != NULL && --NodesToDelete >= 0 )
+ {
+ InterlockedDecrement( &m_nTotal);
+
+ ::HeapFree( sm_hHeap, 0, pl );
+
+ pl = InterlockedPopEntrySList(pListHeader);
+ }
+ };
+#else
+ class Functor
+ {
+ public:
+ explicit Functor(ALLOC_CACHE_HANDLER * pThis) : _pThis(pThis)
+ {
+ }
+ void operator()(SLIST_HEADER * pListHeader)
+ {
+ PSLIST_ENTRY pl;
+ LONG NodesToDelete = QueryDepthSList( pListHeader );
+
+ pl = InterlockedPopEntrySList( pListHeader );
+ while ( pl != NULL && --NodesToDelete >= 0 )
+ {
+ InterlockedDecrement( &_pThis->m_nTotal);
+
+ ::HeapFree( sm_hHeap, 0, pl );
+
+ pl = InterlockedPopEntrySList(pListHeader);
+ }
+ }
+ private:
+ ALLOC_CACHE_HANDLER * _pThis;
+ } Predicate(this);
+#endif
+
+ m_pFreeLists ->ForEach(Predicate);
+}
+
+LPVOID
+ALLOC_CACHE_HANDLER::Alloc(
+ VOID
+)
+{
+ LPVOID pMemory = NULL;
+
+ if ( m_nThreshold > 0 )
+ {
+ SLIST_HEADER * pListHeader = m_pFreeLists ->GetLocal();
+ pMemory = (LPVOID) InterlockedPopEntrySList(pListHeader); // get the real object
+
+ if (pMemory != NULL)
+ {
+ FREE_LIST_HEADER* pfl = (FREE_LIST_HEADER*) pMemory;
+ //
+ // If the signature is wrong then somebody's been scribbling
+ // on memory that they've freed.
+ //
+ DBG_ASSERT(pfl->dwSignature == FREE_LIST_HEADER::FREE_SIGNATURE);
+ }
+ }
+
+ if ( pMemory == NULL )
+ {
+ //
+ // No free entry. Need to alloc a new object.
+ //
+ pMemory = (LPVOID) ::HeapAlloc( sm_hHeap,
+ 0,
+ m_cbSize );
+
+ if ( pMemory != NULL )
+ {
+ //
+ // Update counters.
+ //
+ m_nTotal++;
+ }
+ }
+
+ if ( pMemory == NULL )
+ {
+ SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ }
+ else
+ {
+ FREE_LIST_HEADER* pfl = (FREE_LIST_HEADER*) pMemory;
+ pfl->dwSignature = 0; // clear; just in case caller never overwrites
+ }
+
+ return pMemory;
+}
+
+VOID
+ALLOC_CACHE_HANDLER::Free(
+ __in LPVOID pMemory
+)
+{
+ //
+ // Assume that this is allocated using the Alloc() function.
+ //
+ DBG_ASSERT(NULL != pMemory);
+
+ //
+ // Use a signature to check against double deletions.
+ //
+ FREE_LIST_HEADER* pfl = (FREE_LIST_HEADER*) pMemory;
+ DBG_ASSERT(pfl->dwSignature != FREE_LIST_HEADER::FREE_SIGNATURE);
+
+ //
+ // Start filling the space beyond the portion overlaid by the initial
+ // FREE_LIST_HEADER. Fill at most 6 DWORDS.
+ //
+ LONG* pl = (LONG*) (pfl+1);
+
+ for (LONG cb = (LONG)min(6 * sizeof(LONG),m_cbSize) - sizeof(FREE_LIST_HEADER);
+ cb > 0;
+ cb -= sizeof(LONG))
+ {
+ *pl++ = m_nFillPattern;
+ }
+
+ //
+ // Now, set the signature.
+ //
+ pfl->dwSignature = FREE_LIST_HEADER::FREE_SIGNATURE;
+
+ //
+ // Store the items in the alloc cache.
+ //
+ SLIST_HEADER * pListHeader = m_pFreeLists ->GetLocal();
+
+ if ( QueryDepthSList(pListHeader) >= m_nThreshold )
+ {
+ //
+ // Threshold for free entries is exceeded. Free the object to
+ // process pool.
+ //
+ ::HeapFree( sm_hHeap, 0, pMemory );
+ }
+ else
+ {
+ //
+ // Store the given pointer in the single linear list
+ //
+ InterlockedPushEntrySList(pListHeader, &pfl->ListEntry);
+ }
+}
+
+DWORD
+ALLOC_CACHE_HANDLER::QueryDepthForAllSLists(
+ VOID
+)
+/*++
+
+Description:
+
+ Aggregates the total count of elements in all lists.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Total count (snapshot).
+
+--*/
+{
+ DWORD Count = 0;
+
+ if (m_pFreeLists != NULL)
+ {
+#if defined(_MSC_VER) && _MSC_VER >= 1600 // VC10
+ auto Predicate = [&Count] (SLIST_HEADER * pListHeader)
+ {
+ Count += QueryDepthSList(pListHeader);
+ };
+#else
+ class Functor
+ {
+ public:
+ explicit Functor(DWORD& Count) : _Count(Count)
+ {
+ }
+ void operator()(SLIST_HEADER * pListHeader)
+ {
+ _Count += QueryDepthSList(pListHeader);
+ }
+ private:
+ DWORD& _Count;
+ } Predicate(Count);
+#endif
+ //
+ // [&Count] means that the method can modify local variable Count.
+ //
+ m_pFreeLists ->ForEach(Predicate);
+ }
+
+ return Count;
+}
+
+// static
+BOOL
+ALLOC_CACHE_HANDLER::IsPageheapEnabled(
+ VOID
+)
+{
+ BOOL fRet = FALSE;
+ BOOL fLockedHeap = FALSE;
+ HMODULE hModule = NULL;
+ HANDLE hHeap = NULL;
+ PROCESS_HEAP_ENTRY heapEntry = {0};
+
+ //
+ // If verifier.dll is loaded - we are running under app verifier == pageheap is enabled
+ //
+ hModule = GetModuleHandle( L"verifier.dll" );
+ if ( hModule != NULL )
+ {
+ hModule = NULL;
+ fRet = TRUE;
+ goto Finished;
+ }
+
+ //
+ // Create a heap for calling heapwalk
+ // otherwise HeapWalk turns off lookasides for a useful heap
+ //
+ hHeap = ::HeapCreate( 0, 0, 0 );
+ if ( hHeap == NULL )
+ {
+ fRet = FALSE;
+ goto Finished;
+ }
+
+ fRet = ::HeapLock( hHeap );
+ if ( !fRet )
+ {
+ goto Finished;
+ }
+ fLockedHeap = TRUE;
+
+ //
+ // If HeapWalk is unsupported -> then running page heap
+ //
+ fRet = ::HeapWalk( hHeap, &heapEntry );
+ if ( !fRet )
+ {
+ if ( GetLastError() == ERROR_INVALID_FUNCTION )
+ {
+ fRet = TRUE;
+ goto Finished;
+ }
+ }
+
+ fRet = FALSE;
+
+Finished:
+
+ if ( fLockedHeap )
+ {
+ fLockedHeap = FALSE;
+ DBG_REQUIRE( ::HeapUnlock( hHeap ) );
+ }
+
+ if ( hHeap )
+ {
+ DBG_REQUIRE( ::HeapDestroy( hHeap ) );
+ hHeap = NULL;
+ }
+
+ return fRet;
+}
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ahutil.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ahutil.cpp
new file mode 100644
index 0000000000..9685b233c8
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ahutil.cpp
@@ -0,0 +1,1734 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+HRESULT
+SetElementProperty(
+ IN IAppHostElement * pElement,
+ IN CONST WCHAR * szPropName,
+ IN CONST VARIANT * varPropValue
+ )
+{
+ HRESULT hr = NOERROR;
+
+ CComPtr pPropElement;
+
+ BSTR bstrPropName = SysAllocString( szPropName );
+
+ if( !bstrPropName )
+ {
+ hr = E_OUTOFMEMORY;
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+ hr = pElement->GetPropertyByName( bstrPropName,
+ &pPropElement );
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+ hr = pPropElement->put_Value( *varPropValue );
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+exit:
+
+ if( bstrPropName )
+ {
+ SysFreeString( bstrPropName );
+ bstrPropName = NULL;
+ }
+
+ return hr;
+}
+
+HRESULT
+SetElementStringProperty(
+ IN IAppHostElement * pElement,
+ IN CONST WCHAR * szPropName,
+ IN CONST WCHAR * szPropValue
+ )
+{
+ HRESULT hr;
+ VARIANT varPropValue;
+ VariantInit(&varPropValue);
+
+ hr = VariantAssign(&varPropValue, szPropValue);
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = SetElementProperty(pElement, szPropName, &varPropValue);
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+exit:
+
+ VariantClear(&varPropValue);
+ return hr;
+}
+
+HRESULT
+GetElementStringProperty(
+ IN IAppHostElement * pElement,
+ IN CONST WCHAR * szPropName,
+ OUT BSTR * pbstrPropValue
+ )
+{
+ HRESULT hr = S_OK;
+ BSTR bstrPropName = SysAllocString( szPropName );
+ IAppHostProperty* pProperty = NULL;
+
+ *pbstrPropValue = NULL;
+
+ if (!bstrPropName)
+ {
+ hr = E_OUTOFMEMORY;
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+ hr = pElement->GetPropertyByName( bstrPropName, &pProperty );
+ if (FAILED(hr))
+ {
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+ hr = pProperty->get_StringValue( pbstrPropValue );
+ if (FAILED(hr))
+ {
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+exit:
+
+ if (pProperty)
+ {
+ pProperty->Release();
+ }
+
+ if (bstrPropName)
+ {
+ SysFreeString( bstrPropName );
+ }
+
+ return hr;
+}
+
+
+HRESULT
+GetElementStringProperty(
+ IN IAppHostElement * pElement,
+ IN CONST WCHAR * szPropName,
+ OUT STRU * pstrPropValue
+ )
+{
+ HRESULT hr = S_OK;
+ BSTR bstrPropName = SysAllocString( szPropName );
+ IAppHostProperty* pProperty = NULL;
+ BSTR bstrPropValue = NULL;
+
+ if (!bstrPropName)
+ {
+ hr = E_OUTOFMEMORY;
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+ hr = pElement->GetPropertyByName( bstrPropName, &pProperty );
+ if (FAILED(hr))
+ {
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+ hr = pProperty->get_StringValue( &bstrPropValue );
+ if (FAILED(hr))
+ {
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+ hr = pstrPropValue->Copy(bstrPropValue);
+ if (FAILED(hr))
+ {
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+exit:
+
+ if (pProperty)
+ {
+ pProperty->Release();
+ }
+
+ if (bstrPropValue)
+ {
+ SysFreeString( bstrPropValue );
+ }
+
+ if (bstrPropName)
+ {
+ SysFreeString( bstrPropName );
+ }
+
+ return hr;
+}
+
+HRESULT
+GetElementChildByName(
+ IN IAppHostElement * pElement,
+ IN LPCWSTR pszElementName,
+ OUT IAppHostElement ** ppChildElement
+)
+{
+ BSTR bstrElementName = SysAllocString(pszElementName);
+ if (bstrElementName == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+ HRESULT hr = pElement->GetElementByName(bstrElementName,
+ ppChildElement);
+ SysFreeString(bstrElementName);
+ return hr;
+}
+
+HRESULT
+GetElementBoolProperty(
+ IN IAppHostElement * pElement,
+ IN LPCWSTR pszPropertyName,
+ OUT bool * pBool
+)
+{
+ BOOL fValue;
+ HRESULT hr = GetElementBoolProperty(pElement,
+ pszPropertyName,
+ &fValue);
+ if (SUCCEEDED(hr))
+ {
+ *pBool = !!fValue;
+ }
+ return hr;
+}
+
+HRESULT
+GetElementBoolProperty(
+ IN IAppHostElement * pElement,
+ IN LPCWSTR pszPropertyName,
+ OUT BOOL * pBool
+)
+{
+ HRESULT hr = S_OK;
+ BSTR bstrPropertyName = NULL;
+ IAppHostProperty * pProperty = NULL;
+ VARIANT varValue;
+
+ VariantInit( &varValue );
+
+ bstrPropertyName = SysAllocString( pszPropertyName );
+ if ( bstrPropertyName == NULL )
+ {
+ hr = E_OUTOFMEMORY;
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ // Now ask for the property and if it succeeds it is returned directly back.
+ hr = pElement->GetPropertyByName( bstrPropertyName, &pProperty );
+ if ( FAILED ( hr ) )
+ {
+ goto exit;
+ }
+
+ // Now let's get the property and then extract it from the Variant.
+ hr = pProperty->get_Value( &varValue );
+ if ( FAILED ( hr ) )
+ {
+ goto exit;
+ }
+
+ hr = VariantChangeType( &varValue, &varValue, 0, VT_BOOL );
+ if ( FAILED ( hr ) )
+ {
+ goto exit;
+ }
+
+ // extract the value
+ *pBool = ( V_BOOL( &varValue ) == VARIANT_TRUE );
+
+exit:
+
+ VariantClear( &varValue );
+
+ if ( bstrPropertyName != NULL )
+ {
+ SysFreeString( bstrPropertyName );
+ bstrPropertyName = NULL;
+ }
+
+ if ( pProperty != NULL )
+ {
+ pProperty->Release();
+ pProperty = NULL;
+ }
+
+ return hr;
+
+}
+
+HRESULT
+GetElementDWORDProperty(
+ IN IAppHostElement * pSitesCollectionEntry,
+ IN LPCWSTR pwszName,
+ OUT DWORD * pdwValue
+)
+{
+ HRESULT hr = S_OK;
+ IAppHostProperty * pProperty = NULL;
+ BSTR bstrName = NULL;
+ VARIANT varValue;
+
+ VariantInit( &varValue );
+
+ bstrName = SysAllocString( pwszName );
+ if ( bstrName == NULL )
+ {
+ hr = E_OUTOFMEMORY;
+ DBGERROR_HR(hr);
+ goto error;
+ }
+
+ hr = pSitesCollectionEntry->GetPropertyByName( bstrName,
+ &pProperty );
+ if ( FAILED ( hr ) )
+ {
+ goto error;
+ }
+
+ hr = pProperty->get_Value( &varValue );
+ if ( FAILED ( hr ) )
+ {
+ goto error;
+ }
+
+ hr = VariantChangeType( &varValue, &varValue, 0, VT_UI4 );
+ if ( FAILED ( hr ) )
+ {
+ goto error;
+ }
+
+ // extract the value
+ *pdwValue = varValue.ulVal;
+
+error:
+
+ VariantClear( &varValue );
+
+ if ( pProperty != NULL )
+ {
+ pProperty->Release();
+ pProperty = NULL;
+ }
+
+ if ( bstrName != NULL )
+ {
+ SysFreeString( bstrName );
+ bstrName = NULL;
+ }
+
+ return hr;
+}
+
+HRESULT
+GetElementINTProperty(
+ IN IAppHostElement * pElement,
+ IN LPCWSTR pszPropertyName,
+ OUT INT * pintValue
+)
+{
+ HRESULT hr = S_OK;
+ IAppHostProperty * pProperty = NULL;
+ BSTR bstrName = NULL;
+ VARIANT varValue;
+
+ VariantInit( &varValue );
+
+ bstrName = SysAllocString( pszPropertyName );
+ if ( bstrName == NULL )
+ {
+ hr = E_OUTOFMEMORY;
+ DBGERROR_HR( hr );
+ goto error;
+ }
+
+ hr = pElement->GetPropertyByName( bstrName,
+ &pProperty );
+ if ( FAILED( hr ) )
+ {
+ goto error;
+ }
+
+ hr = pProperty->get_Value( &varValue );
+ if ( FAILED( hr ) )
+ {
+ goto error;
+ }
+
+ hr = VariantChangeType( &varValue, &varValue, 0, VT_I4 );
+ if ( FAILED( hr ) )
+ {
+ goto error;
+ }
+
+ // extract the value
+ *pintValue = varValue.intVal;
+
+error:
+
+ VariantClear( &varValue );
+
+ if ( pProperty != NULL )
+ {
+ pProperty->Release();
+ pProperty = NULL;
+ }
+
+ if ( bstrName != NULL )
+ {
+ SysFreeString( bstrName );
+ bstrName = NULL;
+ }
+
+ return hr;
+}
+
+HRESULT
+GetElementLONGLONGProperty(
+ IN IAppHostElement * pSitesCollectionEntry,
+ IN LPCWSTR pwszName,
+ OUT LONGLONG * pllValue
+)
+{
+ HRESULT hr = S_OK;
+ IAppHostProperty * pProperty = NULL;
+ BSTR bstrName = NULL;
+ VARIANT varValue;
+
+ VariantInit( &varValue );
+
+ bstrName = SysAllocString( pwszName );
+ if ( bstrName == NULL )
+ {
+ hr = E_OUTOFMEMORY;
+ DBGERROR_HR(hr);
+ goto error;
+ }
+
+ hr = pSitesCollectionEntry->GetPropertyByName( bstrName,
+ &pProperty );
+ if ( FAILED ( hr ) )
+ {
+ goto error;
+ }
+
+ hr = pProperty->get_Value( &varValue );
+ if ( FAILED ( hr ) )
+ {
+ goto error;
+ }
+
+ hr = VariantChangeType( &varValue, &varValue, 0, VT_I8 );
+ if ( FAILED ( hr ) )
+ {
+ goto error;
+ }
+
+ // extract the value
+ *pllValue = varValue.ulVal;
+
+error:
+
+ VariantClear( &varValue );
+
+ if ( pProperty != NULL )
+ {
+ pProperty->Release();
+ pProperty = NULL;
+ }
+
+ if ( bstrName != NULL )
+ {
+ SysFreeString( bstrName );
+ bstrName = NULL;
+ }
+
+ return hr;
+}
+
+HRESULT
+GetElementRawTimeSpanProperty(
+ IN IAppHostElement * pElement,
+ IN LPCWSTR pszPropertyName,
+ OUT ULONGLONG * pulonglong
+)
+{
+ HRESULT hr = S_OK;
+ BSTR bstrPropertyName = NULL;
+ IAppHostProperty * pProperty = NULL;
+ VARIANT varValue;
+
+ VariantInit( &varValue );
+
+ bstrPropertyName = SysAllocString( pszPropertyName );
+ if ( bstrPropertyName == NULL )
+ {
+ hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
+ goto Finished;
+ }
+
+ // Now ask for the property and if it succeeds it is returned directly back
+ hr = pElement->GetPropertyByName( bstrPropertyName, &pProperty );
+ if ( FAILED ( hr ) )
+ {
+ goto Finished;
+ }
+
+ // Now let's get the property and then extract it from the Variant.
+ hr = pProperty->get_Value( &varValue );
+ if ( FAILED ( hr ) )
+ {
+ goto Finished;
+ }
+
+ hr = VariantChangeType( &varValue, &varValue, 0, VT_UI8 );
+ if ( FAILED ( hr ) )
+ {
+ goto Finished;
+ }
+
+ // extract the value
+ *pulonglong = varValue.ullVal;
+
+
+Finished:
+
+ VariantClear( &varValue );
+
+ if ( bstrPropertyName != NULL )
+ {
+ SysFreeString( bstrPropertyName );
+ bstrPropertyName = NULL;
+ }
+
+ if ( pProperty != NULL )
+ {
+ pProperty->Release();
+ pProperty = NULL;
+ }
+
+ return hr;
+
+} // end of Config_GetRawTimeSpanProperty
+
+HRESULT
+DeleteElementFromCollection(
+ IAppHostElementCollection *pCollection,
+ CONST WCHAR * szKeyName,
+ CONST WCHAR * szKeyValue,
+ ULONG BehaviorFlags,
+ BOOL * pfDeleted
+ )
+{
+ HRESULT hr = NOERROR;
+ ULONG index;
+
+ VARIANT varIndex;
+ VariantInit( &varIndex );
+
+ *pfDeleted = FALSE;
+
+ hr = FindElementInCollection(
+ pCollection,
+ szKeyName,
+ szKeyValue,
+ BehaviorFlags,
+ &index
+ );
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ if (hr == S_FALSE)
+ {
+ //
+ // Not found.
+ //
+
+ goto exit;
+ }
+
+ varIndex.vt = VT_UI4;
+ varIndex.ulVal = index;
+
+ hr = pCollection->DeleteElement( varIndex );
+
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ *pfDeleted = TRUE;
+
+exit:
+
+ return hr;
+}
+
+HRESULT
+DeleteAllElementsFromCollection(
+ IAppHostElementCollection *pCollection,
+ CONST WCHAR * szKeyName,
+ CONST WCHAR * szKeyValue,
+ ULONG BehaviorFlags,
+ UINT * pNumDeleted
+ )
+{
+ HRESULT hr = S_OK;
+ UINT numDeleted = 0;
+ BOOL fDeleted = TRUE;
+
+ while (fDeleted)
+ {
+ hr = DeleteElementFromCollection(
+ pCollection,
+ szKeyName,
+ szKeyValue,
+ BehaviorFlags,
+ &fDeleted
+ );
+
+ if (hr == S_FALSE)
+ {
+ hr = S_OK;
+ break;
+ }
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ break;
+ }
+
+ if (fDeleted)
+ {
+ numDeleted++;
+ }
+ }
+
+ *pNumDeleted = numDeleted;
+ return hr;
+}
+
+BOOL
+FindCompareCaseSensitive(
+ CONST WCHAR * szLookupValue,
+ CONST WCHAR * szKeyValue
+ )
+{
+ return !wcscmp(szLookupValue, szKeyValue);
+}
+
+BOOL
+FindCompareCaseInsensitive(
+ CONST WCHAR * szLookupValue,
+ CONST WCHAR * szKeyValue
+ )
+{
+ return !_wcsicmp(szLookupValue, szKeyValue);
+}
+
+typedef
+BOOL
+(*PFN_FIND_COMPARE_PROC)(
+ CONST WCHAR *szLookupValue,
+ CONST WCHAR *szKeyValue
+ );
+
+HRESULT
+FindElementInCollection(
+ IAppHostElementCollection *pCollection,
+ CONST WCHAR * szKeyName,
+ CONST WCHAR * szKeyValue,
+ ULONG BehaviorFlags,
+ OUT ULONG * pIndex
+ )
+{
+ HRESULT hr = NOERROR;
+
+ CComPtr pElement;
+ CComPtr pKeyProperty;
+
+ VARIANT varIndex;
+ VariantInit( &varIndex );
+
+ VARIANT varKeyValue;
+ VariantInit( &varKeyValue );
+
+ DWORD count;
+ DWORD i;
+
+ BSTR bstrKeyName = NULL;
+ PFN_FIND_COMPARE_PROC compareProc;
+
+ compareProc = (BehaviorFlags & FIND_ELEMENT_CASE_INSENSITIVE)
+ ? &FindCompareCaseInsensitive
+ : &FindCompareCaseSensitive;
+
+ bstrKeyName = SysAllocString( szKeyName );
+ if( !bstrKeyName )
+ {
+ hr = E_OUTOFMEMORY;
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = pCollection->get_Count( &count );
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ for( i = 0; i < count; i++ )
+ {
+ varIndex.vt = VT_UI4;
+ varIndex.ulVal = i;
+
+ hr = pCollection->get_Item( varIndex,
+ &pElement );
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto tryNext;
+ }
+
+ hr = pElement->GetPropertyByName( bstrKeyName,
+ &pKeyProperty );
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto tryNext;
+ }
+
+ hr = pKeyProperty->get_Value( &varKeyValue );
+
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto tryNext;
+ }
+
+ if ((compareProc)(szKeyValue, varKeyValue.bstrVal))
+ {
+ *pIndex = i;
+ break;
+ }
+
+tryNext:
+
+ pElement.Release();
+ pKeyProperty.Release();
+
+ VariantClear( &varKeyValue );
+ }
+
+ if (i >= count)
+ {
+ hr = S_FALSE;
+ }
+
+exit:
+
+ SysFreeString( bstrKeyName );
+ VariantClear( &varKeyValue );
+
+ return hr;
+}
+
+HRESULT
+VariantAssign(
+ IN OUT VARIANT * pv,
+ IN CONST WCHAR * sz
+ )
+{
+ if( !pv || !sz )
+ {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr = NOERROR;
+
+ BSTR bstr = SysAllocString( sz );
+ if( !bstr )
+ {
+ hr = E_OUTOFMEMORY;
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+ hr = VariantClear( pv );
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+ pv->vt = VT_BSTR;
+ pv->bstrVal = bstr;
+ bstr = NULL;
+
+exit:
+
+ SysFreeString( bstr );
+
+ return hr;
+}
+
+HRESULT
+GetLocationFromFile(
+ IN IAppHostAdminManager * pAdminMgr,
+ IN CONST WCHAR * szConfigPath,
+ IN CONST WCHAR * szLocationPath,
+ OUT IAppHostConfigLocation ** ppLocation,
+ OUT BOOL * pFound
+ )
+{
+ HRESULT hr = NOERROR;
+
+ CComPtr pLocationCollection;
+ CComPtr pLocation;
+
+ BSTR bstrLocationPath = NULL;
+
+ *ppLocation = NULL;
+ *pFound = FALSE;
+
+ hr = GetLocationCollection( pAdminMgr,
+ szConfigPath,
+ &pLocationCollection );
+
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ DWORD count;
+ DWORD i;
+ VARIANT varIndex;
+ VariantInit( &varIndex );
+
+ hr = pLocationCollection->get_Count( &count );
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ for( i = 0; i < count; i++ )
+ {
+ varIndex.vt = VT_UI4;
+ varIndex.ulVal = i;
+
+ hr = pLocationCollection->get_Item( varIndex,
+ &pLocation );
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = pLocation->get_Path( &bstrLocationPath );
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ if( 0 == wcscmp ( szLocationPath, bstrLocationPath ) )
+ {
+ *pFound = TRUE;
+ *ppLocation = pLocation.Detach();
+ break;
+ }
+
+
+ pLocation.Release();
+
+ SysFreeString( bstrLocationPath );
+ bstrLocationPath = NULL;
+ }
+
+exit:
+
+ SysFreeString( bstrLocationPath );
+
+ return hr;
+}
+
+HRESULT
+GetSectionFromLocation(
+ IN IAppHostConfigLocation * pLocation,
+ IN CONST WCHAR * szSectionName,
+ OUT IAppHostElement ** ppSectionElement,
+ OUT BOOL * pFound
+ )
+{
+ HRESULT hr = NOERROR;
+
+ CComPtr pSectionElement;
+
+ DWORD count;
+ DWORD i;
+
+ VARIANT varIndex;
+ VariantInit( &varIndex );
+
+ BSTR bstrSectionName = NULL;
+
+ *pFound = FALSE;
+ *ppSectionElement = NULL;
+
+ hr = pLocation->get_Count( &count );
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ for( i = 0; i < count; i++ )
+ {
+ varIndex.vt = VT_UI4;
+ varIndex.ulVal = i;
+
+
+ hr = pLocation->get_Item( varIndex,
+ &pSectionElement );
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = pSectionElement->get_Name( &bstrSectionName );
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ if( 0 == wcscmp ( szSectionName, bstrSectionName ) )
+ {
+ *pFound = TRUE;
+ *ppSectionElement = pSectionElement.Detach();
+ break;
+ }
+
+ pSectionElement.Release();
+
+ SysFreeString( bstrSectionName );
+ bstrSectionName = NULL;
+ }
+
+exit:
+
+ SysFreeString( bstrSectionName );
+
+ return hr;
+}
+
+
+HRESULT
+GetAdminElement(
+ IN IAppHostAdminManager * pAdminMgr,
+ IN CONST WCHAR * szConfigPath,
+ IN CONST WCHAR * szElementName,
+ OUT IAppHostElement ** pElement
+)
+{
+ HRESULT hr = S_OK;
+ BSTR bstrConfigPath = NULL;
+ BSTR bstrElementName = NULL;
+
+ bstrConfigPath = SysAllocString(szConfigPath);
+ bstrElementName = SysAllocString(szElementName);
+
+ if (bstrConfigPath == NULL || bstrElementName == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = pAdminMgr->GetAdminSection( bstrElementName,
+ bstrConfigPath,
+ pElement );
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+exit:
+
+ if ( bstrElementName != NULL )
+ {
+ SysFreeString(bstrElementName);
+ bstrElementName = NULL;
+ }
+ if ( bstrConfigPath != NULL )
+ {
+ SysFreeString(bstrConfigPath);
+ bstrConfigPath = NULL;
+ }
+
+ return hr;
+}
+
+
+HRESULT
+ClearAdminElement(
+ IN IAppHostAdminManager * pAdminMgr,
+ IN CONST WCHAR * szConfigPath,
+ IN CONST WCHAR * szElementName
+ )
+{
+ HRESULT hr;
+ CComPtr pElement;
+
+ hr = GetAdminElement(
+ pAdminMgr,
+ szConfigPath,
+ szElementName,
+ &pElement
+ );
+
+ if (FAILED(hr))
+ {
+ if (hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND))
+ {
+ hr = S_OK;
+ }
+ else
+ {
+ DBGERROR_HR(hr);
+ }
+
+ goto exit;
+ }
+
+ hr = pElement->Clear();
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+exit:
+
+ return hr;
+}
+
+
+HRESULT
+ClearElementFromAllSites(
+ IN IAppHostAdminManager * pAdminMgr,
+ IN CONST WCHAR * szConfigPath,
+ IN CONST WCHAR * szElementName
+ )
+{
+ HRESULT hr;
+ CComPtr pSitesCollection;
+ CComPtr pSiteElement;
+ CComPtr pChildCollection;
+ ENUM_INDEX index;
+ BOOL found;
+
+ //
+ // Enumerate the sites, remove the specified elements.
+ //
+
+ hr = GetSitesCollection(
+ pAdminMgr,
+ szConfigPath,
+ &pSitesCollection
+ );
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ for (hr = FindFirstElement(pSitesCollection, &index, &pSiteElement) ;
+ SUCCEEDED(hr) ;
+ hr = FindNextElement(pSitesCollection, &index, &pSiteElement))
+ {
+ if (hr == S_FALSE)
+ {
+ hr = S_OK;
+ break;
+ }
+
+ hr = pSiteElement->get_ChildElements(&pChildCollection);
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ if (pChildCollection)
+ {
+ hr = ClearChildElementsByName(
+ pChildCollection,
+ szElementName,
+ &found
+ );
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+ }
+
+ pSiteElement.Release();
+ }
+
+exit:
+
+ return hr;
+
+}
+
+
+HRESULT
+ClearElementFromAllLocations(
+ IN IAppHostAdminManager * pAdminMgr,
+ IN CONST WCHAR * szConfigPath,
+ IN CONST WCHAR * szElementName
+ )
+{
+ HRESULT hr;
+ CComPtr pLocationCollection;
+ CComPtr pLocation;
+ CComPtr pChildCollection;
+ ENUM_INDEX index;
+
+ //
+ // Enum the tags, remove the specified elements.
+ //
+
+ hr = GetLocationCollection(
+ pAdminMgr,
+ szConfigPath,
+ &pLocationCollection
+ );
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ for (hr = FindFirstLocation(pLocationCollection, &index, &pLocation) ;
+ SUCCEEDED(hr) ;
+ hr = FindNextLocation(pLocationCollection, &index, &pLocation))
+ {
+ if (hr == S_FALSE)
+ {
+ hr = S_OK;
+ break;
+ }
+
+ hr = ClearLocationElements(pLocation, szElementName);
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ pLocation.Release();
+ }
+
+exit:
+
+ return hr;
+
+}
+
+HRESULT
+ClearLocationElements(
+ IN IAppHostConfigLocation * pLocation,
+ IN CONST WCHAR * szElementName
+ )
+{
+ HRESULT hr;
+ CComPtr pElement;
+ ENUM_INDEX index;
+ BOOL matched;
+
+ for (hr = FindFirstLocationElement(pLocation, &index, &pElement) ;
+ SUCCEEDED(hr) ;
+ hr = FindNextLocationElement(pLocation, &index, &pElement))
+ {
+ if (hr == S_FALSE)
+ {
+ hr = S_OK;
+ break;
+ }
+
+ hr = CompareElementName(pElement, szElementName, &matched);
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ if (matched)
+ {
+ pElement->Clear();
+ }
+
+ pElement.Release();
+ }
+
+exit:
+
+ return hr;
+}
+
+HRESULT
+CompareElementName(
+ IN IAppHostElement * pElement,
+ IN CONST WCHAR * szNameToMatch,
+ OUT BOOL * pMatched
+ )
+{
+ HRESULT hr;
+ BSTR bstrElementName = NULL;
+
+ *pMatched = FALSE; // until proven otherwise
+
+ hr = pElement->get_Name(&bstrElementName);
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ if( 0 == wcscmp ( szNameToMatch, bstrElementName ) )
+ {
+ *pMatched = TRUE;
+ }
+
+exit:
+
+ SysFreeString(bstrElementName);
+ return hr;
+}
+
+
+HRESULT
+ClearChildElementsByName(
+ IN IAppHostChildElementCollection * pCollection,
+ IN CONST WCHAR * szElementName,
+ OUT BOOL * pFound
+ )
+{
+ HRESULT hr;
+ CComPtr pElement;
+ ENUM_INDEX index;
+ BOOL matched;
+
+ *pFound = FALSE;
+
+ for (hr = FindFirstChildElement(pCollection, &index, &pElement) ;
+ SUCCEEDED(hr) ;
+ hr = FindNextChildElement(pCollection, &index, &pElement))
+ {
+ if (hr == S_FALSE)
+ {
+ hr = S_OK;
+ break;
+ }
+
+ hr = CompareElementName(pElement, szElementName, &matched);
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ if (matched)
+ {
+ hr = pElement->Clear();
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ *pFound = TRUE;
+ }
+
+ pElement.Release();
+ }
+
+exit:
+
+ return hr;
+}
+
+
+HRESULT
+GetSitesCollection(
+ IN IAppHostAdminManager * pAdminMgr,
+ IN CONST WCHAR * szConfigPath,
+ OUT IAppHostElementCollection ** pSitesCollection
+ )
+{
+ HRESULT hr;
+ CComPtr pSitesElement;
+ BSTR bstrConfigPath;
+ BSTR bstrSitesSectionName;
+
+ bstrConfigPath = SysAllocString(szConfigPath);
+ bstrSitesSectionName = SysAllocString(L"system.applicationHost/sites");
+ *pSitesCollection = NULL;
+
+ if (bstrConfigPath == NULL || bstrSitesSectionName == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ //
+ // Chase down the sites collection.
+ //
+
+ hr = pAdminMgr->GetAdminSection( bstrSitesSectionName,
+ bstrConfigPath,
+ &pSitesElement );
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = pSitesElement->get_Collection(pSitesCollection);
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+exit:
+
+ SysFreeString(bstrSitesSectionName);
+ SysFreeString(bstrConfigPath);
+ return hr;
+}
+
+
+HRESULT
+GetLocationCollection(
+ IN IAppHostAdminManager * pAdminMgr,
+ IN CONST WCHAR * szConfigPath,
+ OUT IAppHostConfigLocationCollection ** pLocationCollection
+ )
+{
+ HRESULT hr;
+ BSTR bstrConfigPath;
+ CComPtr pConfigMgr;
+ CComPtr pConfigFile;
+
+ bstrConfigPath = SysAllocString(szConfigPath);
+ *pLocationCollection = NULL;
+
+ if (bstrConfigPath == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = pAdminMgr->get_ConfigManager(&pConfigMgr);
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = pConfigMgr->GetConfigFile(bstrConfigPath, &pConfigFile);
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = pConfigFile->get_Locations(pLocationCollection);
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+exit:
+
+ SysFreeString(bstrConfigPath);
+ return hr;
+}
+
+
+HRESULT
+FindFirstElement(
+ IN IAppHostElementCollection * pCollection,
+ OUT ENUM_INDEX * pIndex,
+ OUT IAppHostElement ** pElement
+ )
+{
+ HRESULT hr;
+
+ hr = pCollection->get_Count(&pIndex->Count);
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ return hr;
+ }
+
+ VariantInit(&pIndex->Index);
+ pIndex->Index.vt = VT_UI4;
+ pIndex->Index.ulVal = 0;
+
+ return FindNextElement(pCollection, pIndex, pElement);
+}
+
+HRESULT
+FindNextElement(
+ IN IAppHostElementCollection * pCollection,
+ IN OUT ENUM_INDEX * pIndex,
+ OUT IAppHostElement ** pElement
+ )
+{
+ HRESULT hr;
+
+ *pElement = NULL;
+
+ if (pIndex->Index.ulVal >= pIndex->Count)
+ {
+ return S_FALSE;
+ }
+
+ hr = pCollection->get_Item(pIndex->Index, pElement);
+
+ if (SUCCEEDED(hr))
+ {
+ pIndex->Index.ulVal++;
+ }
+
+ return hr;
+}
+
+HRESULT
+FindFirstChildElement(
+ IN IAppHostChildElementCollection * pCollection,
+ OUT ENUM_INDEX * pIndex,
+ OUT IAppHostElement ** pElement
+ )
+{
+ HRESULT hr;
+
+ hr = pCollection->get_Count(&pIndex->Count);
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ return hr;
+ }
+
+ VariantInit(&pIndex->Index);
+ pIndex->Index.vt = VT_UI4;
+ pIndex->Index.ulVal = 0;
+
+ return FindNextChildElement(pCollection, pIndex, pElement);
+}
+
+HRESULT
+FindNextChildElement(
+ IN IAppHostChildElementCollection * pCollection,
+ IN OUT ENUM_INDEX * pIndex,
+ OUT IAppHostElement ** pElement
+ )
+{
+ HRESULT hr;
+
+ *pElement = NULL;
+
+ if (pIndex->Index.ulVal >= pIndex->Count)
+ {
+ return S_FALSE;
+ }
+
+ hr = pCollection->get_Item(pIndex->Index, pElement);
+
+ if (SUCCEEDED(hr))
+ {
+ pIndex->Index.ulVal++;
+ }
+
+ return hr;
+}
+
+HRESULT
+FindFirstLocation(
+ IN IAppHostConfigLocationCollection * pCollection,
+ OUT ENUM_INDEX * pIndex,
+ OUT IAppHostConfigLocation ** pLocation
+ )
+{
+ HRESULT hr;
+
+ hr = pCollection->get_Count(&pIndex->Count);
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ return hr;
+ }
+
+ VariantInit(&pIndex->Index);
+ pIndex->Index.vt = VT_UI4;
+ pIndex->Index.ulVal = 0;
+
+ return FindNextLocation(pCollection, pIndex, pLocation);
+}
+
+HRESULT
+FindNextLocation(
+ IN IAppHostConfigLocationCollection * pCollection,
+ IN OUT ENUM_INDEX * pIndex,
+ OUT IAppHostConfigLocation ** pLocation
+ )
+{
+ HRESULT hr;
+
+ *pLocation = NULL;
+
+ if (pIndex->Index.ulVal >= pIndex->Count)
+ {
+ return S_FALSE;
+ }
+
+ hr = pCollection->get_Item(pIndex->Index, pLocation);
+
+ if (SUCCEEDED(hr))
+ {
+ pIndex->Index.ulVal++;
+ }
+
+ return hr;
+}
+
+HRESULT
+FindFirstLocationElement(
+ IN IAppHostConfigLocation * pLocation,
+ OUT ENUM_INDEX * pIndex,
+ OUT IAppHostElement ** pElement
+ )
+{
+ HRESULT hr;
+
+ hr = pLocation->get_Count(&pIndex->Count);
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ return hr;
+ }
+
+ VariantInit(&pIndex->Index);
+ pIndex->Index.vt = VT_UI4;
+ pIndex->Index.ulVal = 0;
+
+ return FindNextLocationElement(pLocation, pIndex, pElement);
+}
+
+HRESULT
+FindNextLocationElement(
+ IN IAppHostConfigLocation * pLocation,
+ IN OUT ENUM_INDEX * pIndex,
+ OUT IAppHostElement ** pElement
+ )
+{
+ HRESULT hr;
+
+ *pElement = NULL;
+
+ if (pIndex->Index.ulVal >= pIndex->Count)
+ {
+ return S_FALSE;
+ }
+
+ hr = pLocation->get_Item(pIndex->Index, pElement);
+
+ if (SUCCEEDED(hr))
+ {
+ pIndex->Index.ulVal++;
+ }
+
+ return hr;
+}
+
+HRESULT
+GetSharedConfigEnabled(
+ BOOL * pfIsSharedConfig
+)
+/*++
+
+Routine Description:
+ Search the configuration for the shared configuration property.
+
+Arguments:
+
+ pfIsSharedConfig - true if shared configuration is enabled
+
+Return Value:
+ HRESULT
+
+--*/
+{
+ HRESULT hr = S_OK;
+ IAppHostAdminManager *pAdminManager = NULL;
+
+ BSTR bstrSectionName = NULL;
+ BSTR bstrConfigPath = NULL;
+
+ IAppHostElement * pConfigRedirSection = NULL;
+
+
+ bstrSectionName = SysAllocString( L"configurationRedirection" );
+
+ if ( bstrSectionName == NULL )
+ {
+ hr = E_OUTOFMEMORY;
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ bstrConfigPath = SysAllocString( L"MACHINE/REDIRECTION" );
+ if ( bstrConfigPath == NULL )
+ {
+ hr = E_OUTOFMEMORY;
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = CoCreateInstance( CLSID_AppHostAdminManager,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_IAppHostAdminManager,
+ (VOID **)&pAdminManager );
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = pAdminManager->GetAdminSection( bstrSectionName,
+ bstrConfigPath,
+ &pConfigRedirSection );
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = GetElementBoolProperty( pConfigRedirSection,
+ L"enabled",
+ pfIsSharedConfig );
+
+ if ( FAILED( hr ) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ pConfigRedirSection->Release();
+ pConfigRedirSection = NULL;
+
+
+exit:
+
+ //
+ // dump config exception to setup log file (if available)
+ //
+
+ if ( pConfigRedirSection != NULL )
+ {
+ pConfigRedirSection->Release();
+ }
+
+ if ( pAdminManager != NULL )
+ {
+ pAdminManager->Release();
+ }
+
+ if ( bstrConfigPath != NULL )
+ {
+ SysFreeString( bstrConfigPath );
+ }
+
+ if ( bstrSectionName != NULL )
+ {
+ SysFreeString( bstrSectionName );
+ }
+
+ return hr;
+}
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/base64.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/base64.cxx
new file mode 100644
index 0000000000..26e601fac4
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/base64.cxx
@@ -0,0 +1,482 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+DWORD
+Base64Encode(
+ __in_bcount(cbDecodedBufferSize) VOID * pDecodedBuffer,
+ IN DWORD cbDecodedBufferSize,
+ __out_ecount_opt(cchEncodedStringSize) PWSTR pszEncodedString,
+ IN DWORD cchEncodedStringSize,
+ __out_opt DWORD * pcchEncoded
+ )
+/*++
+
+Routine Description:
+
+ Decode a base64-encoded string.
+
+Arguments:
+
+ pDecodedBuffer (IN) - buffer to encode.
+ cbDecodedBufferSize (IN) - size of buffer to encode.
+ cchEncodedStringSize (IN) - size of the buffer for the encoded string.
+ pszEncodedString (OUT) = the encoded string.
+ pcchEncoded (OUT) - size in characters of the encoded string.
+
+Return Values:
+
+ 0 - success.
+ E_OUTOFMEMORY
+
+--*/
+{
+ static WCHAR rgchEncodeTable[64] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
+ };
+
+ DWORD ib;
+ DWORD ich;
+ DWORD cchEncoded;
+ BYTE b0, b1, b2;
+ BYTE * pbDecodedBuffer = (BYTE *) pDecodedBuffer;
+
+ // Calculate encoded string size.
+ cchEncoded = 1 + (cbDecodedBufferSize + 2) / 3 * 4;
+
+ if (NULL != pcchEncoded) {
+ *pcchEncoded = cchEncoded;
+ }
+
+ if (cchEncodedStringSize == 0 && pszEncodedString == NULL) {
+ return ERROR_SUCCESS;
+ }
+
+ if (cchEncodedStringSize < cchEncoded) {
+ // Given buffer is too small to hold encoded string.
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ // Encode data byte triplets into four-byte clusters.
+ ib = ich = 0;
+ while (ib < cbDecodedBufferSize) {
+ b0 = pbDecodedBuffer[ib++];
+ b1 = (ib < cbDecodedBufferSize) ? pbDecodedBuffer[ib++] : 0;
+ b2 = (ib < cbDecodedBufferSize) ? pbDecodedBuffer[ib++] : 0;
+
+ //
+ // The checks below for buffer overflow seems redundant to me.
+ // But it's the only way I can find to keep OACR quiet so it
+ // will have to do.
+ //
+
+ pszEncodedString[ich++] = rgchEncodeTable[b0 >> 2];
+ if ( ich >= cchEncodedStringSize )
+ {
+ DBG_ASSERT( FALSE );
+ return ERROR_BUFFER_OVERFLOW;
+ }
+
+ pszEncodedString[ich++] = rgchEncodeTable[((b0 << 4) & 0x30) | ((b1 >> 4) & 0x0f)];
+ if ( ich >= cchEncodedStringSize )
+ {
+ DBG_ASSERT( FALSE );
+ return ERROR_BUFFER_OVERFLOW;
+ }
+
+ pszEncodedString[ich++] = rgchEncodeTable[((b1 << 2) & 0x3c) | ((b2 >> 6) & 0x03)];
+ if ( ich >= cchEncodedStringSize )
+ {
+ DBG_ASSERT( FALSE );
+ return ERROR_BUFFER_OVERFLOW;
+ }
+
+ pszEncodedString[ich++] = rgchEncodeTable[b2 & 0x3f];
+ if ( ich >= cchEncodedStringSize )
+ {
+ DBG_ASSERT( FALSE );
+ return ERROR_BUFFER_OVERFLOW;
+ }
+ }
+
+ // Pad the last cluster as necessary to indicate the number of data bytes
+ // it represents.
+ switch (cbDecodedBufferSize % 3) {
+ case 0:
+ break;
+ case 1:
+ pszEncodedString[ich - 2] = '=';
+ __fallthrough;
+ case 2:
+ pszEncodedString[ich - 1] = '=';
+ break;
+ }
+
+ // Null-terminate the encoded string.
+ pszEncodedString[ich++] = '\0';
+
+ DBG_ASSERT(ich == cchEncoded);
+
+ return ERROR_SUCCESS;
+}
+
+
+DWORD
+Base64Decode(
+ __in PCWSTR pszEncodedString,
+ __out_opt VOID * pDecodeBuffer,
+ __in DWORD cbDecodeBufferSize,
+ __out_opt DWORD * pcbDecoded
+ )
+/*++
+
+Routine Description:
+
+ Decode a base64-encoded string.
+
+Arguments:
+
+ pszEncodedString (IN) - base64-encoded string to decode.
+ cbDecodeBufferSize (IN) - size in bytes of the decode buffer.
+ pbDecodeBuffer (OUT) - holds the decoded data.
+ pcbDecoded (OUT) - number of data bytes in the decoded data (if success or
+ STATUS_BUFFER_TOO_SMALL).
+
+Return Values:
+
+ 0 - success.
+ E_OUTOFMEMORY
+ E_INVALIDARG
+
+--*/
+{
+#define NA (255)
+#define DECODE(x) (((ULONG)(x) < sizeof(rgbDecodeTable)) ? rgbDecodeTable[x] : NA)
+
+ static BYTE rgbDecodeTable[128] = {
+ NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, // 0-15
+ NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, // 16-31
+ NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 62, NA, NA, NA, 63, // 32-47
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, NA, NA, NA, 0, NA, NA, // 48-63
+ NA, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, NA, NA, NA, NA, NA, // 80-95
+ NA, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, NA, NA, NA, NA, NA, // 112-127
+ };
+
+ DWORD cbDecoded;
+ DWORD cchEncodedSize;
+ DWORD ich;
+ DWORD ib;
+ BYTE b0, b1, b2, b3;
+ BYTE * pbDecodeBuffer = (BYTE *) pDecodeBuffer;
+
+ cchEncodedSize = (DWORD)wcslen(pszEncodedString);
+ if (NULL != pcbDecoded) {
+ *pcbDecoded = 0;
+ }
+
+ if ((0 == cchEncodedSize) || (0 != (cchEncodedSize % 4))) {
+ // Input string is not sized correctly to be base64.
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ // Calculate decoded buffer size.
+ cbDecoded = (cchEncodedSize + 3) / 4 * 3;
+ if (pszEncodedString[cchEncodedSize-1] == '=') {
+ if (pszEncodedString[cchEncodedSize-2] == '=') {
+ // Only one data byte is encoded in the last cluster.
+ cbDecoded -= 2;
+ }
+ else {
+ // Only two data bytes are encoded in the last cluster.
+ cbDecoded -= 1;
+ }
+ }
+
+ if (NULL != pcbDecoded) {
+ *pcbDecoded = cbDecoded;
+ }
+
+ if (cbDecodeBufferSize == 0 && pDecodeBuffer == NULL) {
+ return ERROR_SUCCESS;
+ }
+
+ if (cbDecoded > cbDecodeBufferSize) {
+ // Supplied buffer is too small.
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ // Decode each four-byte cluster into the corresponding three data bytes.
+ ich = ib = 0;
+ while (ich < cchEncodedSize) {
+ b0 = DECODE(pszEncodedString[ich]); ich++;
+ b1 = DECODE(pszEncodedString[ich]); ich++;
+ b2 = DECODE(pszEncodedString[ich]); ich++;
+ b3 = DECODE(pszEncodedString[ich]); ich++;
+
+ if ((NA == b0) || (NA == b1) || (NA == b2) || (NA == b3)) {
+ // Contents of input string are not base64.
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ pbDecodeBuffer[ib++] = (b0 << 2) | (b1 >> 4);
+
+ if (ib < cbDecoded) {
+ pbDecodeBuffer[ib++] = (b1 << 4) | (b2 >> 2);
+
+ if (ib < cbDecoded) {
+ pbDecodeBuffer[ib++] = (b2 << 6) | b3;
+ }
+ }
+ }
+
+ DBG_ASSERT(ib == cbDecoded);
+
+ return ERROR_SUCCESS;
+}
+
+
+DWORD
+Base64Encode(
+ __in_bcount(cbDecodedBufferSize) VOID * pDecodedBuffer,
+ IN DWORD cbDecodedBufferSize,
+ __out_ecount_opt(cchEncodedStringSize) PSTR pszEncodedString,
+ IN DWORD cchEncodedStringSize,
+ __out_opt DWORD * pcchEncoded
+ )
+/*++
+
+Routine Description:
+
+ Decode a base64-encoded string.
+
+Arguments:
+
+ pDecodedBuffer (IN) - buffer to encode.
+ cbDecodedBufferSize (IN) - size of buffer to encode.
+ cchEncodedStringSize (IN) - size of the buffer for the encoded string.
+ pszEncodedString (OUT) = the encoded string.
+ pcchEncoded (OUT) - size in characters of the encoded string.
+
+Return Values:
+
+ 0 - success.
+ E_OUTOFMEMORY
+
+--*/
+{
+ static CHAR rgchEncodeTable[64] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
+ };
+
+ DWORD ib;
+ DWORD ich;
+ DWORD cchEncoded;
+ BYTE b0, b1, b2;
+ BYTE * pbDecodedBuffer = (BYTE *) pDecodedBuffer;
+
+ // Calculate encoded string size.
+ cchEncoded = 1 + (cbDecodedBufferSize + 2) / 3 * 4;
+
+ if (NULL != pcchEncoded) {
+ *pcchEncoded = cchEncoded;
+ }
+
+ if (cchEncodedStringSize == 0 && pszEncodedString == NULL) {
+ return ERROR_SUCCESS;
+ }
+
+ if (cchEncodedStringSize < cchEncoded) {
+ // Given buffer is too small to hold encoded string.
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ // Encode data byte triplets into four-byte clusters.
+ ib = ich = 0;
+ while (ib < cbDecodedBufferSize) {
+ b0 = pbDecodedBuffer[ib++];
+ b1 = (ib < cbDecodedBufferSize) ? pbDecodedBuffer[ib++] : 0;
+ b2 = (ib < cbDecodedBufferSize) ? pbDecodedBuffer[ib++] : 0;
+
+ //
+ // The checks below for buffer overflow seems redundant to me.
+ // But it's the only way I can find to keep OACR quiet so it
+ // will have to do.
+ //
+
+ pszEncodedString[ich++] = rgchEncodeTable[b0 >> 2];
+ if ( ich >= cchEncodedStringSize )
+ {
+ DBG_ASSERT( FALSE );
+ return ERROR_BUFFER_OVERFLOW;
+ }
+
+ pszEncodedString[ich++] = rgchEncodeTable[((b0 << 4) & 0x30) | ((b1 >> 4) & 0x0f)];
+ if ( ich >= cchEncodedStringSize )
+ {
+ DBG_ASSERT( FALSE );
+ return ERROR_BUFFER_OVERFLOW;
+ }
+
+ pszEncodedString[ich++] = rgchEncodeTable[((b1 << 2) & 0x3c) | ((b2 >> 6) & 0x03)];
+ if ( ich >= cchEncodedStringSize )
+ {
+ DBG_ASSERT( FALSE );
+ return ERROR_BUFFER_OVERFLOW;
+ }
+
+ pszEncodedString[ich++] = rgchEncodeTable[b2 & 0x3f];
+ if ( ich >= cchEncodedStringSize )
+ {
+ DBG_ASSERT( FALSE );
+ return ERROR_BUFFER_OVERFLOW;
+ }
+ }
+
+ // Pad the last cluster as necessary to indicate the number of data bytes
+ // it represents.
+ switch (cbDecodedBufferSize % 3) {
+ case 0:
+ break;
+ case 1:
+ pszEncodedString[ich - 2] = '=';
+ __fallthrough;
+ case 2:
+ pszEncodedString[ich - 1] = '=';
+ break;
+ }
+
+ // Null-terminate the encoded string.
+ pszEncodedString[ich++] = '\0';
+
+ DBG_ASSERT(ich == cchEncoded);
+
+ return ERROR_SUCCESS;
+}
+
+
+DWORD
+Base64Decode(
+ __in PCSTR pszEncodedString,
+ __out_opt VOID * pDecodeBuffer,
+ __in DWORD cbDecodeBufferSize,
+ __out_opt DWORD * pcbDecoded
+ )
+/*++
+
+Routine Description:
+
+ Decode a base64-encoded string.
+
+Arguments:
+
+ pszEncodedString (IN) - base64-encoded string to decode.
+ cbDecodeBufferSize (IN) - size in bytes of the decode buffer.
+ pbDecodeBuffer (OUT) - holds the decoded data.
+ pcbDecoded (OUT) - number of data bytes in the decoded data (if success or
+ STATUS_BUFFER_TOO_SMALL).
+
+Return Values:
+
+ 0 - success.
+ E_OUTOFMEMORY
+ E_INVALIDARG
+
+--*/
+{
+#define NA (255)
+#define DECODE(x) (((ULONG)(x) < sizeof(rgbDecodeTable)) ? rgbDecodeTable[x] : NA)
+
+ static BYTE rgbDecodeTable[128] = {
+ NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, // 0-15
+ NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, // 16-31
+ NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 62, NA, NA, NA, 63, // 32-47
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, NA, NA, NA, 0, NA, NA, // 48-63
+ NA, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, NA, NA, NA, NA, NA, // 80-95
+ NA, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, NA, NA, NA, NA, NA, // 112-127
+ };
+
+ DWORD cbDecoded;
+ DWORD cchEncodedSize;
+ DWORD ich;
+ DWORD ib;
+ BYTE b0, b1, b2, b3;
+ BYTE * pbDecodeBuffer = (BYTE *) pDecodeBuffer;
+
+ cchEncodedSize = (DWORD)strlen(pszEncodedString);
+ if (NULL != pcbDecoded) {
+ *pcbDecoded = 0;
+ }
+
+ if ((0 == cchEncodedSize) || (0 != (cchEncodedSize % 4))) {
+ // Input string is not sized correctly to be base64.
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ // Calculate decoded buffer size.
+ cbDecoded = (cchEncodedSize + 3) / 4 * 3;
+ if (pszEncodedString[cchEncodedSize-1] == '=') {
+ if (pszEncodedString[cchEncodedSize-2] == '=') {
+ // Only one data byte is encoded in the last cluster.
+ cbDecoded -= 2;
+ }
+ else {
+ // Only two data bytes are encoded in the last cluster.
+ cbDecoded -= 1;
+ }
+ }
+
+ if (NULL != pcbDecoded) {
+ *pcbDecoded = cbDecoded;
+ }
+
+ if (cbDecodeBufferSize == 0 && pDecodeBuffer == NULL) {
+ return ERROR_SUCCESS;
+ }
+
+ if (cbDecoded > cbDecodeBufferSize) {
+ // Supplied buffer is too small.
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ // Decode each four-byte cluster into the corresponding three data bytes.
+ ich = ib = 0;
+ while (ich < cchEncodedSize) {
+ b0 = DECODE(pszEncodedString[ich]); ich++;
+ b1 = DECODE(pszEncodedString[ich]); ich++;
+ b2 = DECODE(pszEncodedString[ich]); ich++;
+ b3 = DECODE(pszEncodedString[ich]); ich++;
+
+ if ((NA == b0) || (NA == b1) || (NA == b2) || (NA == b3)) {
+ // Contents of input string are not base64.
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ pbDecodeBuffer[ib++] = (b0 << 2) | (b1 >> 4);
+
+ if (ib < cbDecoded) {
+ pbDecodeBuffer[ib++] = (b1 << 4) | (b2 >> 2);
+
+ if (ib < cbDecoded) {
+ pbDecodeBuffer[ib++] = (b2 << 6) | b3;
+ }
+ }
+ }
+
+ DBG_ASSERT(ib == cbDecoded);
+
+ return ERROR_SUCCESS;
+}
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/datetime.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/datetime.cxx
new file mode 100644
index 0000000000..a856b997f1
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/datetime.cxx
@@ -0,0 +1,247 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+static const CHAR* s_rgchMonths[] = {
+ "Jan", "Feb", "Mar", "Apr",
+ "May", "Jun", "Jul", "Aug",
+ "Sep", "Oct", "Nov", "Dec"
+};
+
+// Custom hash table for make_month() for mapping "Apr" to 4
+static const CHAR MonthIndexTable[64] = {
+ -1,'A', 2, 12, -1, -1, -1, 8, // A to G
+ -1, -1, -1, -1, 7, -1,'N', -1, // F to O
+ 9, -1,'R', -1, 10, -1, 11, -1, // P to W
+ -1, 5, -1, -1, -1, -1, -1, -1, // X to Z
+ -1,'A', 2, 12, -1, -1, -1, 8, // a to g
+ -1, -1, -1, -1, 7, -1,'N', -1, // f to o
+ 9, -1,'R', -1, 10, -1, 11, -1, // p to w
+ -1, 5, -1, -1, -1, -1, -1, -1 // x to z
+};
+
+static const BYTE TensDigit[10] = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 };
+
+WORD
+iis_2atoi(
+ __in_ecount(2) PCHAR s
+ )
+/*++
+
+ Converts a 2 character string to integer
+
+ Arguments:
+ s String to convert
+
+ Returns:
+ numeric equivalent, 0 on failure.
+--*/
+{
+
+ DWORD tens = s[0] - '0';
+ DWORD ones = s[1] - '0';
+
+ if ( (tens <= 9) && (ones <= 9) ) {
+ return((WORD)(TensDigit[tens] + ones));
+ }
+ return(0);
+}
+
+WORD
+make_month(
+ __in_ecount(3) PCHAR s
+ )
+{
+ UCHAR monthIndex;
+ UCHAR c;
+ LPCSTR monthString;
+
+ //
+ // use the third character as the index
+ //
+
+ c = (s[2] - 0x40) & 0x3F;
+
+ monthIndex = MonthIndexTable[c];
+
+ if ( monthIndex < 13 ) {
+ goto verify;
+ }
+
+ //
+ // ok, we need to look at the second character
+ //
+
+ if ( monthIndex == 'N' ) {
+
+ //
+ // we got an N which we need to resolve further
+ //
+
+ //
+ // if s[1] is 'u' then Jun, if 'a' then Jan
+ //
+
+ if ( MonthIndexTable[(s[1]-0x40) & 0x3f] == 'A' ) {
+ monthIndex = 1;
+ } else {
+ monthIndex = 6;
+ }
+
+ } else if ( monthIndex == 'R' ) {
+
+ //
+ // if s[1] is 'a' then March, if 'p' then April
+ //
+
+ if ( MonthIndexTable[(s[1]-0x40) & 0x3f] == 'A' ) {
+ monthIndex = 3;
+ } else {
+ monthIndex = 4;
+ }
+ } else {
+ goto error_exit;
+ }
+
+verify:
+
+ monthString = s_rgchMonths[monthIndex-1];
+
+ if ( (s[0] == monthString[0]) &&
+ (s[1] == monthString[1]) &&
+ (s[2] == monthString[2]) ) {
+
+ return(monthIndex);
+
+ } else if ( (toupper(s[0]) == monthString[0]) &&
+ (tolower(s[1]) == monthString[1]) &&
+ (tolower(s[2]) == monthString[2]) ) {
+
+ return monthIndex;
+ }
+
+error_exit:
+ return(0);
+
+} // make_month
+
+BOOL
+StringTimeToFileTime(
+ IN const CHAR * pszTime,
+ OUT ULONGLONG * pulTime
+ )
+/*++
+
+ Converts a string representation of a GMT time (three different
+ varieties) to an NT representation of a file time.
+
+ We handle the following variations:
+
+ Sun, 06 Nov 1994 08:49:37 GMT (RFC 822 updated by RFC 1123)
+ Sunday, 06-Nov-94 08:49:37 GMT (RFC 850)
+ Sun Nov 6 08:49:37 1994 (ANSI C's asctime() format
+
+ Arguments:
+ pszTime String representation of time field
+ pliTime large integer containing the time in NT format.
+
+ Returns:
+ TRUE on success and FALSE on failure.
+
+ History:
+
+ Johnl 24-Jan-1995 Modified from WWW library
+
+--*/
+{
+
+ CHAR * s;
+ SYSTEMTIME st;
+
+ if (pszTime == NULL) {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+
+ st.wMilliseconds = 0;
+
+ if ((s = (CHAR*) strchr(pszTime, ','))) {
+
+ DWORD len;
+
+ //
+ // Thursday, 10-Jun-93 01:29:59 GMT
+ // or: Thu, 10 Jan 1993 01:29:59 GMT */
+ //
+
+ s++;
+
+ while (*s && *s==' ') s++;
+ len = (DWORD)strlen(s);
+
+ if (len < 18) {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+
+ if ( *(s+2) == '-' ) { /* First format */
+
+ st.wDay = (WORD) atoi(s);
+ st.wMonth = (WORD) make_month(s+3);
+ st.wYear = (WORD) atoi(s+7);
+ st.wHour = (WORD) atoi(s+10);
+ st.wMinute = (WORD) atoi(s+13);
+ st.wSecond = (WORD) atoi(s+16);
+
+ } else { /* Second format */
+
+ if (len < 20) {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+
+ st.wDay = iis_2atoi(s);
+ st.wMonth = make_month(s+3);
+ st.wYear = iis_2atoi(s+7) * 100 + iis_2atoi(s+9);
+ st.wHour = iis_2atoi(s+12);
+ st.wMinute = iis_2atoi(s+15);
+ st.wSecond = iis_2atoi(s+18);
+
+ }
+ } else { /* Try the other format: Wed Jun 9 01:29:59 1993 GMT */
+
+ s = (CHAR *) pszTime;
+ while (*s && *s==' ') s++;
+
+ if ((int)strlen(s) < 24) {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+
+ st.wDay = (WORD) atoi(s+8);
+ st.wMonth = (WORD) make_month(s+4);
+ st.wYear = (WORD) atoi(s+20);
+ st.wHour = (WORD) atoi(s+11);
+ st.wMinute = (WORD) atoi(s+14);
+ st.wSecond = (WORD) atoi(s+17);
+ }
+
+ //
+ // Adjust for dates with only two digits
+ //
+
+ if ( st.wYear < 1000 ) {
+ if ( st.wYear < 50 ) {
+ st.wYear += 2000;
+ } else {
+ st.wYear += 1900;
+ }
+ }
+
+ if (!SystemTimeToFileTime(&st, (FILETIME *)pulTime)) {
+ return FALSE;
+ }
+ return(TRUE);
+}
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisz.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisz.cxx
new file mode 100644
index 0000000000..26eacdb244
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisz.cxx
@@ -0,0 +1,480 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+
+//#include
+#include
+//# include
+
+#include
+
+//
+// Private Definitions
+//
+
+#define MAXULONG 4294967295
+#define ISWHITE( ch ) ((ch) == L' ' || (ch) == L'\t' || (ch) == L'\r')
+
+//
+// When appending data, this is the extra amount we request to avoid
+// reallocations
+//
+#define STR_SLOP 128
+
+
+DWORD
+MULTISZ::CalcLength( const WCHAR * str,
+ LPDWORD pcStrings )
+{
+ DWORD count = 0;
+ DWORD total = 1;
+ DWORD len;
+
+ while( *str ) {
+ len = (DWORD)(::wcslen( str ) + 1);
+ total += len;
+ str += len;
+ count++;
+ }
+
+ if( pcStrings != NULL ) {
+ *pcStrings = count;
+ }
+
+ return total;
+
+} // MULTISZ::CalcLength
+
+
+BOOL
+MULTISZ::FindString( const WCHAR * str )
+{
+
+ WCHAR * multisz;
+
+ //
+ // Sanity check.
+ //
+
+ DBG_ASSERT( QueryStr() != NULL );
+ DBG_ASSERT( str != NULL );
+ DBG_ASSERT( *str != '\0' );
+
+ //
+ // Scan it.
+ //
+
+ multisz = QueryStr();
+
+ while( *multisz != '\0' ) {
+
+ if( !::wcscmp( multisz, str ) ) {
+
+ return TRUE;
+
+ }
+
+ multisz += ::wcslen( multisz ) + 1;
+
+ }
+
+ return FALSE;
+
+} // MULTISZ::FindString
+
+
+BOOL
+MULTISZ::FindStringNoCase( const WCHAR * str )
+{
+
+ WCHAR * multisz;
+
+ //
+ // Sanity check.
+ //
+
+ DBG_ASSERT( QueryStr() != NULL );
+ DBG_ASSERT( str != NULL );
+ DBG_ASSERT( *str != '\0' );
+
+ //
+ // Scan it.
+ //
+
+ multisz = QueryStr();
+
+ while( *multisz != '\0' ) {
+
+ if( !_wcsicmp( multisz, str ) ) {
+
+ return TRUE;
+
+ }
+
+ multisz += wcslen( multisz ) + 1;
+
+ }
+
+ return FALSE;
+
+} // MULTISZ::FindStringNoCase
+
+
+VOID
+MULTISZ::AuxInit( const WCHAR * pInit )
+{
+ BOOL fRet;
+
+ if ( pInit )
+ {
+ DWORD cStrings;
+ int cbCopy = CalcLength( pInit, &cStrings ) * sizeof(WCHAR);
+ fRet = Resize( cbCopy );
+
+ if ( fRet ) {
+ CopyMemory( QueryPtr(), pInit, cbCopy );
+ m_cchLen = (cbCopy)/sizeof(WCHAR);
+ m_cStrings = cStrings;
+ } else {
+// BUFFER::SetValid( FALSE);
+ }
+
+ } else {
+
+ Reset();
+
+ }
+
+} // MULTISZ::AuxInit()
+
+
+/*******************************************************************
+
+ NAME: MULTISZ::AuxAppend
+
+ SYNOPSIS: Appends the string onto the multisz.
+
+ ENTRY: Object to append
+********************************************************************/
+
+BOOL MULTISZ::AuxAppend( const WCHAR * pStr, UINT cbStr, BOOL fAddSlop )
+{
+ DBG_ASSERT( pStr != NULL );
+
+ UINT cbThis = QueryCB();
+
+ DBG_ASSERT( cbThis >= 2 );
+
+ if( cbThis == 4 ) {
+
+ //
+ // It's empty, so start at the beginning.
+ //
+
+ cbThis = 0;
+
+ } else {
+
+ //
+ // It's not empty, so back up over the final terminating NULL.
+ //
+
+ cbThis -= sizeof(WCHAR);
+
+ }
+
+ //
+ // Only resize when we have to. When we do resize, we tack on
+ // some extra space to avoid extra reallocations.
+ //
+ // Note: QuerySize returns the requested size of the string buffer,
+ // *not* the strlen of the buffer
+ //
+
+ //AcIncrement( CacMultiszAppend);
+
+ //
+ // Check for the arithmetic overflow
+ //
+ // ( 2 * sizeof( WCHAR ) ) is for the double terminator
+ //
+ ULONGLONG cb64Required = (ULONGLONG)cbThis + cbStr + 2 * sizeof(WCHAR);
+ if ( cb64Required > MAXULONG )
+ {
+ SetLastError( ERROR_ARITHMETIC_OVERFLOW );
+ return FALSE;
+ }
+ if ( QuerySize() < (DWORD) cb64Required )
+ {
+ ULONGLONG cb64AllocSize = cb64Required + (fAddSlop ? STR_SLOP : 0 );
+ //
+ // Check for the arithmetic overflow
+ //
+ if ( cb64AllocSize > MAXULONG )
+ {
+ SetLastError( ERROR_ARITHMETIC_OVERFLOW );
+ return FALSE;
+ }
+ if ( !Resize( (DWORD) cb64AllocSize ) )
+ return FALSE;
+ }
+
+ // copy the exact string and tack on the double terminator
+ memcpy( (BYTE *) QueryPtr() + cbThis,
+ pStr,
+ cbStr);
+ *(WCHAR *)((BYTE *)QueryPtr() + cbThis + cbStr) = L'\0';
+ *(WCHAR *)((BYTE *)QueryPtr() + cbThis + cbStr + sizeof(WCHAR) ) = L'\0';
+
+ m_cchLen = CalcLength( (const WCHAR *)QueryPtr(), &m_cStrings );
+ return TRUE;
+
+} // MULTISZ::AuxAppend()
+
+
+#if 0
+
+BOOL
+MULTISZ::CopyToBuffer( WCHAR * lpszBuffer, LPDWORD lpcch) const
+/*++
+ Description:
+ Copies the string into the WCHAR buffer passed in if the buffer
+ is sufficient to hold the translated string.
+ If the buffer is small, the function returns small and sets *lpcch
+ to contain the required number of characters.
+
+ Arguments:
+ lpszBuffer pointer to WCHAR buffer which on return contains
+ the UNICODE version of string on success.
+ lpcch pointer to DWORD containing the length of the buffer.
+ If *lpcch == 0 then the function returns TRUE with
+ the count of characters required stored in *lpcch.
+ Also in this case lpszBuffer is not affected.
+ Returns:
+ TRUE on success.
+ FALSE on failure. Use GetLastError() for further details.
+
+ History:
+ MuraliK 11-30-94
+--*/
+{
+ BOOL fReturn = TRUE;
+
+ if ( lpcch == NULL) {
+ SetLastError( ERROR_INVALID_PARAMETER);
+ return ( FALSE);
+ }
+
+ if ( *lpcch == 0) {
+
+ //
+ // Inquiring the size of buffer alone
+ //
+ *lpcch = QueryCCH() + 1; // add one character for terminating null
+ } else {
+
+ //
+ // Copy after conversion from ANSI to Unicode
+ //
+ int iRet;
+ iRet = MultiByteToWideChar( CP_ACP,
+ MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
+ QueryStrA(), QueryCCH() + 1,
+ lpszBuffer, (int )*lpcch);
+
+ if ( iRet == 0 || iRet != (int ) *lpcch) {
+
+ //
+ // Error in conversion.
+ //
+ fReturn = FALSE;
+ }
+ }
+
+ return ( fReturn);
+} // MULTISZ::CopyToBuffer()
+#endif
+
+BOOL
+MULTISZ::CopyToBuffer( __out_ecount_opt(*lpcch) WCHAR * lpszBuffer, LPDWORD lpcch) const
+/*++
+ Description:
+ Copies the string into the WCHAR buffer passed in if the buffer
+ is sufficient to hold the translated string.
+ If the buffer is small, the function returns small and sets *lpcch
+ to contain the required number of characters.
+
+ Arguments:
+ lpszBuffer pointer to WCHAR buffer which on return contains
+ the string on success.
+ lpcch pointer to DWORD containing the length of the buffer.
+ If *lpcch == 0 then the function returns TRUE with
+ the count of characters required stored in lpcch.
+ Also in this case lpszBuffer is not affected.
+ Returns:
+ TRUE on success.
+ FALSE on failure. Use GetLastError() for further details.
+
+ History:
+ MuraliK 20-Nov-1996
+--*/
+{
+ BOOL fReturn = TRUE;
+
+ if ( lpcch == NULL) {
+ SetLastError( ERROR_INVALID_PARAMETER);
+ return ( FALSE);
+ }
+
+ register DWORD cch = QueryCCH();
+
+ if ( *lpcch >= cch) {
+
+ DBG_ASSERT( lpszBuffer);
+ memcpy( lpszBuffer, QueryStr(), cch * sizeof(WCHAR));
+ } else {
+ DBG_ASSERT( *lpcch < cch);
+ SetLastError( ERROR_INSUFFICIENT_BUFFER);
+ fReturn = FALSE;
+ }
+
+ *lpcch = cch;
+
+ return ( fReturn);
+} // MULTISZ::CopyToBuffer()
+
+BOOL
+MULTISZ::Equals(
+ MULTISZ* pmszRhs
+)
+//
+// Compares this to pmszRhs, returns TRUE if equal
+//
+{
+ DBG_ASSERT( NULL != pmszRhs );
+
+ PCWSTR pszLhs = First( );
+ PCWSTR pszRhs = pmszRhs->First( );
+
+ if( m_cStrings != pmszRhs->m_cStrings )
+ {
+ return FALSE;
+ }
+
+ while( NULL != pszLhs )
+ {
+ DBG_ASSERT( NULL != pszRhs );
+
+ if( 0 != wcscmp( pszLhs, pszRhs ) )
+ {
+ return FALSE;
+ }
+
+ pszLhs = Next( pszLhs );
+ pszRhs = pmszRhs->Next( pszRhs );
+ }
+
+ return TRUE;
+}
+
+HRESULT
+SplitCommaDelimitedString(
+ PCWSTR pszList,
+ BOOL fTrimEntries,
+ BOOL fRemoveEmptyEntries,
+ MULTISZ * pmszList
+)
+/*++
+
+Routine Description:
+
+ Split comma delimited string into a multisz. Additional leading empty
+ entries after the first are discarded.
+
+Arguments:
+
+ pszList - List to split up
+ fTrimEntries - Whether each entry should be trimmed before added to multisz
+ fRemoveEmptyEntries - Whether empty entires should be discarded
+ pmszList - Filled with MULTISZ list
+
+Return Value:
+
+ HRESULT
+
+--*/
+{
+ HRESULT hr = S_OK;
+
+ if ( pszList == NULL ||
+ pmszList == NULL )
+ {
+ DBG_ASSERT( FALSE );
+ hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
+ goto Finished;
+ }
+
+ pmszList->Reset();
+
+ /*
+ pszCurrent: start of the current entry which may be the comma that
+ precedes the next entry if the entry is empty
+
+ pszNext: the comma that precedes the next entry. If
+ pszCurrent == pszNext, then the entry is empty
+
+ pszEnd: just past the end of the current entry
+ */
+
+ for ( PCWSTR pszCurrent = pszList,
+ pszNext = wcschr( pszCurrent, L',' )
+ ;
+ ;
+ pszCurrent = pszNext + 1,
+ pszNext = wcschr( pszCurrent, L',' ) )
+ {
+ PCWSTR pszEnd = NULL;
+
+ if ( pszNext != NULL )
+ {
+ pszEnd = pszNext;
+ }
+ else
+ {
+ pszEnd = pszCurrent + wcslen( pszCurrent );
+ }
+
+ if ( fTrimEntries )
+ {
+ while ( pszCurrent < pszEnd && ISWHITE( pszCurrent[ 0 ] ) )
+ {
+ pszCurrent++;
+ }
+
+ while ( pszEnd > pszCurrent && ISWHITE( pszEnd[ -1 ] ) )
+ {
+ pszEnd--;
+ }
+ }
+
+ if ( pszCurrent != pszEnd || !fRemoveEmptyEntries )
+ {
+ if ( !pmszList->Append( pszCurrent, (DWORD) ( pszEnd - pszCurrent ) ) )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ goto Finished;
+ }
+ }
+
+ if ( pszNext == NULL )
+ {
+ break;
+ }
+ }
+
+Finished:
+
+ return hr;
+}
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisza.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisza.cxx
new file mode 100644
index 0000000000..e6972534bb
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisza.cxx
@@ -0,0 +1,414 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+
+//#include
+#include
+//# include
+
+#include
+
+//
+// Private Definitions
+//
+
+#define MAXULONG 4294967295
+#define ISWHITE( ch ) ((ch) == L' ' || (ch) == L'\t' || (ch) == L'\r')
+
+//
+// When appending data, this is the extra amount we request to avoid
+// reallocations
+//
+#define STR_SLOP 128
+
+
+DWORD
+MULTISZA::CalcLength( const CHAR * str,
+ LPDWORD pcStrings )
+{
+ DWORD count = 0;
+ DWORD total = 1;
+ DWORD len;
+
+ while( *str ) {
+ len = (DWORD)(::strlen( str ) + 1);
+ total += len;
+ str += len;
+ count++;
+ }
+
+ if( pcStrings != NULL ) {
+ *pcStrings = count;
+ }
+
+ return total;
+
+} // MULTISZA::CalcLength
+
+
+BOOL
+MULTISZA::FindString( const CHAR * str )
+{
+
+ CHAR * multisz;
+
+ //
+ // Sanity check.
+ //
+
+ DBG_ASSERT( QueryStr() != NULL );
+ DBG_ASSERT( str != NULL );
+ DBG_ASSERT( *str != '\0' );
+
+ //
+ // Scan it.
+ //
+
+ multisz = QueryStr();
+
+ while( *multisz != '\0' ) {
+
+ if( !::strcmp( multisz, str ) ) {
+
+ return TRUE;
+
+ }
+
+ multisz += ::strlen( multisz ) + 1;
+
+ }
+
+ return FALSE;
+
+} // MULTISZA::FindString
+
+
+BOOL
+MULTISZA::FindStringNoCase( const CHAR * str )
+{
+
+ CHAR * multisz;
+
+ //
+ // Sanity check.
+ //
+
+ DBG_ASSERT( QueryStr() != NULL );
+ DBG_ASSERT( str != NULL );
+ DBG_ASSERT( *str != '\0' );
+
+ //
+ // Scan it.
+ //
+
+ multisz = QueryStr();
+
+ while( *multisz != '\0' ) {
+
+ if( !_stricmp( multisz, str ) ) {
+
+ return TRUE;
+
+ }
+
+ multisz += strlen( multisz ) + 1;
+
+ }
+
+ return FALSE;
+
+} // MULTISZA::FindStringNoCase
+
+
+VOID
+MULTISZA::AuxInit( const CHAR * pInit )
+{
+ BOOL fRet;
+
+ if ( pInit )
+ {
+ DWORD cStrings;
+ int cbCopy = CalcLength( pInit, &cStrings ) * sizeof(CHAR);
+ fRet = Resize( cbCopy );
+
+ if ( fRet ) {
+ CopyMemory( QueryPtr(), pInit, cbCopy );
+ m_cchLen = (cbCopy)/sizeof(CHAR);
+ m_cStrings = cStrings;
+ } else {
+// BUFFER::SetValid( FALSE);
+ }
+
+ } else {
+
+ Reset();
+
+ }
+
+} // MULTISZA::AuxInit()
+
+
+/*******************************************************************
+
+ NAME: MULTISZA::AuxAppend
+
+ SYNOPSIS: Appends the string onto the MULTISZA.
+
+ ENTRY: Object to append
+********************************************************************/
+
+BOOL MULTISZA::AuxAppend( const CHAR * pStr, UINT cbStr, BOOL fAddSlop )
+{
+ DBG_ASSERT( pStr != NULL );
+
+ UINT cbThis = QueryCB();
+
+ if( cbThis == 2 ) {
+
+ //
+ // It's empty, so start at the beginning.
+ //
+
+ cbThis = 0;
+
+ } else {
+
+ //
+ // It's not empty, so back up over the final terminating NULL.
+ //
+
+ cbThis -= sizeof(CHAR);
+
+ }
+
+ //
+ // Only resize when we have to. When we do resize, we tack on
+ // some extra space to avoid extra reallocations.
+ //
+ // Note: QuerySize returns the requested size of the string buffer,
+ // *not* the strlen of the buffer
+ //
+
+ //AcIncrement( CacMultiszAppend);
+
+ //
+ // Check for the arithmetic overflow
+ //
+ // ( 2 * sizeof( CHAR ) ) is for the double terminator
+ //
+ ULONGLONG cb64Required = (ULONGLONG)cbThis + cbStr + 2 * sizeof(CHAR);
+ if ( cb64Required > MAXULONG )
+ {
+ SetLastError( ERROR_ARITHMETIC_OVERFLOW );
+ return FALSE;
+ }
+ if ( QuerySize() < (DWORD) cb64Required )
+ {
+ ULONGLONG cb64AllocSize = cb64Required + (fAddSlop ? STR_SLOP : 0 );
+ //
+ // Check for the arithmetic overflow
+ //
+ if ( cb64AllocSize > MAXULONG )
+ {
+ SetLastError( ERROR_ARITHMETIC_OVERFLOW );
+ return FALSE;
+ }
+ if ( !Resize( (DWORD) cb64AllocSize ) )
+ return FALSE;
+ }
+
+ // copy the exact string and tack on the double terminator
+ memcpy( (BYTE *) QueryPtr() + cbThis,
+ pStr,
+ cbStr);
+ *(CHAR *)((BYTE *)QueryPtr() + cbThis + cbStr) = L'\0';
+ *(CHAR *)((BYTE *)QueryPtr() + cbThis + cbStr + sizeof(CHAR) ) = L'\0';
+
+ m_cchLen = CalcLength( (const CHAR *)QueryPtr(), &m_cStrings );
+ return TRUE;
+
+} // MULTISZA::AuxAppend()
+
+BOOL
+MULTISZA::CopyToBuffer( __out_ecount_opt(*lpcch) CHAR * lpszBuffer, LPDWORD lpcch) const
+/*++
+ Description:
+ Copies the string into the CHAR buffer passed in if the buffer
+ is sufficient to hold the translated string.
+ If the buffer is small, the function returns small and sets *lpcch
+ to contain the required number of characters.
+
+ Arguments:
+ lpszBuffer pointer to CHAR buffer which on return contains
+ the string on success.
+ lpcch pointer to DWORD containing the length of the buffer.
+ If *lpcch == 0 then the function returns TRUE with
+ the count of characters required stored in lpcch.
+ Also in this case lpszBuffer is not affected.
+ Returns:
+ TRUE on success.
+ FALSE on failure. Use GetLastError() for further details.
+
+ History:
+ MuraliK 20-Nov-1996
+--*/
+{
+ BOOL fReturn = TRUE;
+
+ if ( lpcch == NULL) {
+ SetLastError( ERROR_INVALID_PARAMETER);
+ return ( FALSE);
+ }
+
+ register DWORD cch = QueryCCH();
+
+ if ( *lpcch >= cch) {
+
+ DBG_ASSERT( lpszBuffer);
+ memcpy( lpszBuffer, QueryStr(), cch * sizeof(CHAR));
+ } else {
+ DBG_ASSERT( *lpcch < cch);
+ SetLastError( ERROR_INSUFFICIENT_BUFFER);
+ fReturn = FALSE;
+ }
+
+ *lpcch = cch;
+
+ return ( fReturn);
+} // MULTISZA::CopyToBuffer()
+
+BOOL
+MULTISZA::Equals(
+ MULTISZA* pmszRhs
+)
+//
+// Compares this to pmszRhs, returns TRUE if equal
+//
+{
+ DBG_ASSERT( NULL != pmszRhs );
+
+ PCSTR pszLhs = First( );
+ PCSTR pszRhs = pmszRhs->First( );
+
+ if( m_cStrings != pmszRhs->m_cStrings )
+ {
+ return FALSE;
+ }
+
+ while( NULL != pszLhs )
+ {
+ DBG_ASSERT( NULL != pszRhs );
+
+ if( 0 != strcmp( pszLhs, pszRhs ) )
+ {
+ return FALSE;
+ }
+
+ pszLhs = Next( pszLhs );
+ pszRhs = pmszRhs->Next( pszRhs );
+ }
+
+ return TRUE;
+}
+
+HRESULT
+SplitCommaDelimitedString(
+ PCSTR pszList,
+ BOOL fTrimEntries,
+ BOOL fRemoveEmptyEntries,
+ MULTISZA * pmszList
+)
+/*++
+
+Routine Description:
+
+ Split comma delimited string into a MULTISZA. Additional leading empty
+ entries after the first are discarded.
+
+Arguments:
+
+ pszList - List to split up
+ fTrimEntries - Whether each entry should be trimmed before added to MULTISZA
+ fRemoveEmptyEntries - Whether empty entires should be discarded
+ pmszList - Filled with MULTISZA list
+
+Return Value:
+
+ HRESULT
+
+--*/
+{
+ HRESULT hr = S_OK;
+
+ if ( pszList == NULL ||
+ pmszList == NULL )
+ {
+ DBG_ASSERT( FALSE );
+ hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
+ goto Finished;
+ }
+
+ pmszList->Reset();
+
+ /*
+ pszCurrent: start of the current entry which may be the comma that
+ precedes the next entry if the entry is empty
+
+ pszNext: the comma that precedes the next entry. If
+ pszCurrent == pszNext, then the entry is empty
+
+ pszEnd: just past the end of the current entry
+ */
+
+ for ( PCSTR pszCurrent = pszList,
+ pszNext = strchr( pszCurrent, L',' )
+ ;
+ ;
+ pszCurrent = pszNext + 1,
+ pszNext = strchr( pszCurrent, L',' ) )
+ {
+ PCSTR pszEnd = NULL;
+
+ if ( pszNext != NULL )
+ {
+ pszEnd = pszNext;
+ }
+ else
+ {
+ pszEnd = pszCurrent + strlen( pszCurrent );
+ }
+
+ if ( fTrimEntries )
+ {
+ while ( pszCurrent < pszEnd && ISWHITE( pszCurrent[ 0 ] ) )
+ {
+ pszCurrent++;
+ }
+
+ while ( pszEnd > pszCurrent && ISWHITE( pszEnd[ -1 ] ) )
+ {
+ pszEnd--;
+ }
+ }
+
+ if ( pszCurrent != pszEnd || !fRemoveEmptyEntries )
+ {
+ if ( !pmszList->Append( pszCurrent, (DWORD) ( pszEnd - pszCurrent ) ) )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ goto Finished;
+ }
+ }
+
+ if ( pszNext == NULL )
+ {
+ break;
+ }
+ }
+
+Finished:
+
+ return hr;
+}
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/normalize.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/normalize.cxx
new file mode 100644
index 0000000000..48b41fdd1c
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/normalize.cxx
@@ -0,0 +1,890 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+#include "normalize.h"
+#include "stringa.h"
+
+BOOL g_fEnableNonUTF8;
+BOOL g_fEnableDBCS;
+BOOL g_fIsSystemDBCS;
+static BOOL g_fFavorDBCS;
+
+#ifndef STACK_STRA
+#define STACK_STRA(name, size) CHAR __ach##name[size]; \
+ STRA name(__ach##name, sizeof(__ach##name) / sizeof(CHAR))
+#endif
+
+HRESULT
+InitializeNormalizeUrl(
+ VOID
+)
+{
+ HKEY hKey;
+ DWORD dwType;
+ DWORD dwData;
+ DWORD cbData;
+ WORD wPrimaryLangID;
+
+ //
+ // Read the registry settings on how to handle URLs
+ //
+
+ g_fEnableNonUTF8 = TRUE;
+ g_fEnableDBCS = FALSE;
+ g_fFavorDBCS = FALSE;
+
+ if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ L"System\\CurrentControlSet\\Services\\http\\Parameters",
+ 0,
+ KEY_READ,
+ &hKey ) == ERROR_SUCCESS )
+ {
+ cbData = sizeof( dwData );
+ if ( RegQueryValueEx( hKey,
+ L"EnableNonUTF8",
+ NULL,
+ &dwType,
+ (LPBYTE) &dwData,
+ &cbData ) == ERROR_SUCCESS &&
+ dwType == REG_DWORD )
+ {
+ g_fEnableNonUTF8 = !!dwData;
+ }
+
+ if ( g_fEnableNonUTF8 )
+ {
+ cbData = sizeof( dwData );
+
+ if ( RegQueryValueEx( hKey,
+ L"EnableDBCS",
+ NULL,
+ &dwType,
+ (LPBYTE) &dwData,
+ &cbData ) == ERROR_SUCCESS &&
+ dwType == REG_DWORD )
+ {
+ g_fEnableDBCS = !!dwData;
+ }
+ }
+ else
+ {
+ g_fEnableDBCS = FALSE;
+ }
+
+ if ( g_fEnableDBCS )
+ {
+ cbData = sizeof( dwData );
+
+ if ( RegQueryValueEx( hKey,
+ L"FavorDBCS",
+ NULL,
+ &dwType,
+ (LPBYTE) &dwData,
+ &cbData ) == ERROR_SUCCESS &&
+ dwType == REG_DWORD )
+ {
+ g_fFavorDBCS = !!dwData;
+ }
+ }
+ else
+ {
+ g_fFavorDBCS = FALSE;
+ }
+
+ RegCloseKey( hKey );
+ }
+
+
+ wPrimaryLangID = PRIMARYLANGID( GetSystemDefaultLangID() );
+
+ g_fIsSystemDBCS = ( wPrimaryLangID == LANG_JAPANESE ||
+ wPrimaryLangID == LANG_CHINESE ||
+ wPrimaryLangID == LANG_KOREAN );
+
+ return NO_ERROR;
+}
+
+//
+// Private constants.
+//
+
+#define ACTION_NOTHING 0x00000000
+#define ACTION_EMIT_CH 0x00010000
+#define ACTION_EMIT_DOT_CH 0x00020000
+#define ACTION_EMIT_DOT_DOT_CH 0x00030000
+#define ACTION_BACKUP 0x00040000
+#define ACTION_MASK 0xFFFF0000
+
+
+//
+// Private globals.
+//
+
+INT p_StateTable[16] =
+ {
+ // state 0
+ 0 , // other
+ 0 , // "."
+ 4 , // EOS
+ 1 , // "\"
+
+ // state 1
+ 0 , // other
+ 2 , // "."
+ 4 , // EOS
+ 1 , // "\"
+
+ // state 2
+ 0 , // other
+ 3 , // "."
+ 4 , // EOS
+ 1 , // "\"
+
+ // state 3
+ 0 , // other
+ 0 , // "."
+ 4 , // EOS
+ 1 // "\"
+ };
+
+
+
+INT p_ActionTable[16] =
+ {
+ // state 0
+ ACTION_EMIT_CH, // other
+ ACTION_EMIT_CH, // "."
+ ACTION_EMIT_CH, // EOS
+ ACTION_EMIT_CH, // "\"
+
+ // state 1
+ ACTION_EMIT_CH, // other
+ ACTION_NOTHING, // "."
+ ACTION_EMIT_CH, // EOS
+ ACTION_NOTHING, // "\"
+
+ // state 2
+ ACTION_EMIT_DOT_CH, // other
+ ACTION_NOTHING, // "."
+ ACTION_EMIT_CH, // EOS
+ ACTION_NOTHING, // "\"
+
+ // state 3
+ ACTION_EMIT_DOT_DOT_CH, // other
+ ACTION_EMIT_DOT_DOT_CH, // "."
+ ACTION_BACKUP, // EOS
+ ACTION_BACKUP // "\"
+ };
+
+// since max states = 4, we calculat the index by multiplying with 4.
+# define IndexFromState( st) ( (st) * 4)
+
+
+// the following table provides the index for various ISA Latin1 characters
+// in the incoming URL.
+// It assumes that the URL is ISO Latin1 == ASCII
+INT p_rgIndexForChar[] = {
+
+ 2, // null char
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 thru 10
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 11 thru 20
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 21 thru 30
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 31 thru 40
+ 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, // 41 thru 50 46 = '.' 47 = '/'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 51 thru 60
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 61 thru 70
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 71 thru 80
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 81 thru 90
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, // 91 thru 100 92 = '\\'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 101 thru 110
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 111 thru 120
+ 0, 0, 0, 0, 0, 0, 0, 0 // 121 thru 128
+};
+
+#define IS_UTF8_TRAILBYTE(ch) (((ch) & 0xc0) == 0x80)
+
+
+/*******************************************************************
+
+ NAME: IsUTF8URL
+
+ ENTRY: pszPath - The path to sanitize.
+
+ HISTORY:
+ atsusk 06-Jan-1998 Created.
+
+********************************************************************/
+
+BOOL IsUTF8URL(__in LPSTR pszPath)
+{
+ CHAR ch;
+
+ if ( g_fFavorDBCS )
+ {
+ return ( MultiByteToWideChar( CP_ACP,
+ MB_ERR_INVALID_CHARS,
+ pszPath,
+ -1,
+ NULL,
+ 0) == 0);
+ }
+
+ while (ch = *pszPath++) {
+
+ if (ch & 0x80) {
+ wchar_t wch;
+ int iLen;
+ BOOL bDefault = FALSE;
+ char chTrail1;
+ char chTrail2;
+
+ chTrail1 = *pszPath++;
+ if (chTrail1) {
+ chTrail2 = *pszPath;
+ } else {
+ chTrail2 = 0;
+ }
+
+ if ( ((ch & 0xF0) == 0xE0) &&
+ IS_UTF8_TRAILBYTE(chTrail1) &&
+ IS_UTF8_TRAILBYTE(chTrail2) ) {
+
+ // handle three byte case
+ // 1110xxxx 10xxxxxx 10xxxxxx
+ wch = (wchar_t) (((ch & 0x0f) << 12) |
+ ((chTrail1 & 0x3f) << 6) |
+ (chTrail2 & 0x3f));
+ pszPath++;
+
+ } else
+ if ( ((ch & 0xE0) == 0xC0) &&
+ IS_UTF8_TRAILBYTE(chTrail1) ) {
+
+ // handle two byte case
+ // 110xxxxx 10xxxxxx
+
+ wch = (wchar_t) (((ch & 0x1f) << 6) | (chTrail1 & 0x3f));
+
+ } else
+ return FALSE;
+
+ iLen = WideCharToMultiByte( CP_ACP,
+ WC_NO_BEST_FIT_CHARS,
+ &wch,
+ 1,
+ NULL,
+ 0,
+ NULL,
+ &bDefault );
+
+ if (bDefault == TRUE || iLen == 0 || iLen > 2)
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+} // IsUTF8URL()
+
+
+/*******************************************************************
+
+ NAME: CanonURL
+
+ SYNOPSIS: Sanitizes a path by removing bogus path elements.
+
+ As expected, "/./" entries are simply removed, and
+ "/../" entries are removed along with the previous
+ path element.
+
+ To maintain compatibility with URL path semantics
+ additional transformations are required. All backward
+ slashes "\\" are converted to forward slashes. Any
+ repeated forward slashes (such as "///") are mapped to
+ single backslashes.
+
+ A state table (see the p_StateTable global at the
+ beginning of this file) is used to perform most of
+ the transformations. The table's rows are indexed
+ by current state, and the columns are indexed by
+ the current character's "class" (either slash, dot,
+ NULL, or other). Each entry in the table consists
+ of the new state tagged with an action to perform.
+ See the ACTION_* constants for the valid action
+ codes.
+
+ ENTRY: pszPath - The path to sanitize.
+ fIsDBCSLocale - Indicates the server is in a
+ locale that uses DBCS.
+
+ HISTORY:
+ KeithMo 07-Sep-1994 Created.
+ MuraliK 28-Apr-1995 Adopted this for symbolic paths
+
+********************************************************************/
+INT
+CanonURL(
+ __inout LPSTR pszPath,
+ BOOL fIsDBCSLocale
+ )
+{
+ UCHAR * pszSrc;
+ UCHAR * pszDest;
+ DWORD ch;
+ INT index;
+ BOOL fDBCS = FALSE;
+ DWORD cchMultiByte = 0;
+
+ DBG_ASSERT( pszPath != NULL );
+
+ //
+ // Always look for UTF8 except when DBCS characters are detected
+ //
+ BOOL fScanForUTF8 = IsUTF8URL(pszPath);
+
+ // If fScanForUTF8 is true, this URL is UTF8. don't recognize DBCS.
+ if (fIsDBCSLocale && fScanForUTF8) {
+ fIsDBCSLocale = FALSE;
+ }
+
+ //
+ // Start our scan at the first character
+ //
+
+ pszSrc = pszDest = (UCHAR *) pszPath;
+
+ //
+ // State 0 is the initial state.
+ //
+ index = 0; // State = 0
+
+ //
+ // Loop until we enter state 4 (the final, accepting state).
+ //
+
+ do {
+
+ //
+ // Grab the next character from the path and compute its
+ // next state. While we're at it, map any forward
+ // slashes to backward slashes.
+ //
+
+ index = IndexFromState( p_StateTable[index]); // 4 = # states
+ ch = (DWORD ) *pszSrc++;
+
+ //
+ // If this is a DBCS trailing byte - skip it
+ //
+
+ if ( !fIsDBCSLocale )
+ {
+ index += (( ch >= 0x80) ? 0 : p_rgIndexForChar[ch]);
+ }
+ else
+ {
+ if ( fDBCS )
+ {
+ //
+ // If this is a 0 terminator, we need to set next
+ // state accordingly
+ //
+
+ if ( ch == 0 )
+ {
+ index += p_rgIndexForChar[ ch ];
+ }
+
+ //
+ // fDBCS == TRUE means this byte was a trail byte.
+ // index is implicitly set to zero.
+ //
+ fDBCS = FALSE;
+ }
+ else
+ {
+ index += (( ch >= 0x80) ? 0 : p_rgIndexForChar[ch]);
+
+ if ( IsDBCSLeadByte( (UCHAR)ch ) )
+ {
+ //
+ // This is a lead byte, so the next is a trail.
+ //
+ fDBCS = TRUE;
+ }
+ }
+ }
+
+ //
+ // Interesting UTF8 characters always have the top bit set
+ //
+
+ if ( (ch & 0x80) && fScanForUTF8 )
+ {
+ wchar_t wch;
+ UCHAR mbstr[2];
+
+ //
+ // This is a UTF8 character, convert it here.
+ // index is implicitly set to zero.
+ //
+ if ( cchMultiByte < 2 )
+ {
+ char chTrail1;
+ char chTrail2;
+
+ chTrail1 = *pszSrc;
+ if (chTrail1) {
+ chTrail2 = *(pszSrc+1);
+ } else {
+ chTrail2 = 0;
+ }
+ wch = 0;
+
+ if ((ch & 0xf0) == 0xe0)
+ {
+ // handle three byte case
+ // 1110xxxx 10xxxxxx 10xxxxxx
+
+ wch = (wchar_t) (((ch & 0x0f) << 12) |
+ ((chTrail1 & 0x3f) << 6) |
+ (chTrail2 & 0x3f));
+
+ cchMultiByte = WideCharToMultiByte( CP_ACP,
+ WC_NO_BEST_FIT_CHARS,
+ &wch,
+ 1,
+ (LPSTR) mbstr,
+ 2,
+ NULL,
+ NULL );
+
+ ch = mbstr[0];
+ pszSrc += (3 - cchMultiByte);
+
+ // WinSE 12843: Security Fix, Index should be updated for this character
+ index += (( ch >= 0x80) ? 0 : p_rgIndexForChar[ch]);
+
+ } else if ((ch & 0xe0) == 0xc0)
+ {
+ // handle two byte case
+ // 110xxxxx 10xxxxxx
+
+ wch = (wchar_t) (((ch & 0x1f) << 6) | (chTrail1 & 0x3f));
+
+ cchMultiByte = WideCharToMultiByte( CP_ACP,
+ WC_NO_BEST_FIT_CHARS,
+ &wch,
+ 1,
+ (LPSTR) mbstr,
+ 2,
+ NULL,
+ NULL );
+
+ ch = mbstr[0];
+ pszSrc += (2 - cchMultiByte);
+
+ // WinSE 12843: Security Fix, Index should be updated for this character
+ index += (( ch >= 0x80) ? 0 : p_rgIndexForChar[ch]);
+ }
+
+ } else {
+ //
+ // get ready to emit 2nd byte of converted character
+ //
+ ch = mbstr[1];
+ cchMultiByte = 0;
+ }
+ }
+
+
+ //
+ // Perform the action associated with the state.
+ //
+
+ switch( p_ActionTable[index] )
+ {
+ case ACTION_EMIT_DOT_DOT_CH :
+ *pszDest++ = '.';
+ /* fall through */
+
+ case ACTION_EMIT_DOT_CH :
+ *pszDest++ = '.';
+ /* fall through */
+
+ case ACTION_EMIT_CH :
+ *pszDest++ = (CHAR ) ch;
+ /* fall through */
+
+ case ACTION_NOTHING :
+ break;
+
+ case ACTION_BACKUP :
+ if( (pszDest > ( (UCHAR *) pszPath + 1 ) ) && (*pszPath == '/'))
+ {
+ pszDest--;
+ DBG_ASSERT( *pszDest == '/' );
+
+ *pszDest = '\0';
+ pszDest = (UCHAR *) strrchr( pszPath, '/') + 1;
+ }
+
+ *pszDest = '\0';
+ break;
+
+ default :
+ DBG_ASSERT( !"Invalid action code in state table!" );
+ index = IndexFromState(0) + 2; // move to invalid state
+ DBG_ASSERT( p_StateTable[index] == 4);
+ *pszDest++ = '\0';
+ break;
+ }
+
+ } while( p_StateTable[index] != 4 );
+
+ //
+ // point to terminating nul
+ // only do the check if we aren't about to go outside of the number
+ // of elements in the table.
+ //
+ if ( ( index < ( sizeof(p_ActionTable) / sizeof(p_ActionTable[0]) ) )
+ && p_ActionTable[index] == ACTION_EMIT_CH )
+ {
+ pszDest--;
+ }
+
+ DBG_ASSERT(*pszDest == '\0' && pszDest > (UCHAR*) pszPath);
+
+ return (INT)DIFF(pszDest - (UCHAR*)pszPath);
+} // CanonURL()
+
+
+
+HRESULT
+NormalizeUrl(
+ __inout LPSTR pszStart
+ )
+/*++
+
+Routine Description:
+
+ Normalize URL
+
+Arguments:
+
+ strUrl - URL to be updated to a canonical URI
+
+Return value:
+
+ TRUE if no error, otherwise FALSE
+
+--*/
+{
+ CHAR * pchParams;
+ LPSTR pszSlash;
+ LPSTR pszURL;
+ LPSTR pszValue;
+ STACK_STRA( strChgUrl, MAX_PATH );
+ HRESULT hr;
+ DWORD cchInput;
+
+ if ( pszStart == NULL )
+ {
+ return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
+ }
+
+ cchInput = (DWORD)strlen( pszStart );
+
+ if ( *pszStart != '/' )
+ {
+ //
+ // assume HTTP URL, skip protocol & host name by
+ // searching for 1st '/' following "//"
+ //
+ // We handle this information as a "Host:" header.
+ // It will be overwritten by the real header if it is
+ // present.
+ //
+ // We do not check for a match in this case.
+ //
+
+ if ( (pszSlash = strchr( pszStart, '/' )) && pszSlash[1] == '/' )
+ {
+ pszSlash += 2;
+ if ( pszURL = strchr( pszSlash, '/' ) )
+ {
+ //
+ // update pointer to URL to point to the 1st slash
+ // following host name
+ //
+
+ pszValue = pszURL;
+ }
+ else
+ {
+ //
+ // if no single slash following host name
+ // consider the URL to be empty.
+ //
+
+ pszValue = pszSlash + strlen( pszSlash );
+ }
+
+ memmove( pszStart, pszValue, strlen(pszValue)+1 );
+ }
+
+ //
+ // if no double slash, this is not a fully qualified URL
+ // and we leave it alone.
+ //
+ }
+
+ //
+ // Check for a question mark which indicates this URL contains some
+ // parameters and break the two apart if found
+ //
+
+ if ( (pchParams = strchr( pszStart, '?' )) )
+ {
+ *pchParams = '\0';
+ }
+
+ //
+ // Unescape wants a STR ( sigh )
+ //
+
+ hr = strChgUrl.Copy( (CHAR*)pszStart );
+
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+
+ strChgUrl.Unescape();
+
+ hr = StringCchCopyNA( pszStart, cchInput + 1, strChgUrl.QueryStr(), cchInput );
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+
+ //
+ // Canonicalize the URL
+ //
+
+ CanonURL( pszStart, g_fIsSystemDBCS );
+
+ return NO_ERROR;
+}
+
+
+
+
+HRESULT
+NormalizeUrlOld(
+ __inout LPSTR pszUrl
+)
+/*++
+
+Routine Description:
+
+ NormalizeUrl wrapper (used by ISAPI filter and extension support functions)
+
+Parameters:
+
+ pszUrl - On entry, the URL to be normalized
+ On return, the normalized URL
+ (size of normalized URL is always <= not normalized URL)
+
+Return Value:
+
+ HRESULT
+
+--*/
+{
+ HRESULT hr = NO_ERROR;
+
+ if ( pszUrl )
+ {
+ STACK_BUFFER( buffUrlOutput, MAX_PATH );
+ STACK_STRA( strUrlA, MAX_PATH );
+ LPWSTR szQueryString;
+ DWORD cchData;
+ DWORD cbOutput;
+
+ cchData = (DWORD)strlen( pszUrl );
+
+ //
+ // Prepare the Output string
+ //
+
+ if ( !buffUrlOutput.Resize( ( cchData + 1 ) *sizeof( WCHAR ) ) )
+ {
+ return HRESULT_FROM_WIN32( GetLastError() );
+ }
+
+ //
+ // Normalize it
+ //
+
+ hr = UlCleanAndCopyUrl(
+ pszUrl,
+ cchData,
+ &cbOutput,
+ (WCHAR *) buffUrlOutput.QueryPtr(),
+ &szQueryString
+ );
+
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+
+ //
+ // Terminate the string at the query so that the
+ // query string doesn't appear in the output. IIS 5
+ // truncated in this way.
+ //
+
+ if ( szQueryString != NULL )
+ {
+ ((WCHAR *) buffUrlOutput.QueryPtr())[ cbOutput - wcslen( szQueryString )] = 0;
+ }
+
+ //
+ // Write the normalized URL over the input data
+ //
+
+ hr = strUrlA.CopyW( (WCHAR *) buffUrlOutput.QueryPtr() );
+
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+
+ //
+ // Normalized string will never be longer than the original one
+ //
+
+ DBG_ASSERT( strUrlA.QueryCCH() <= cchData );
+
+ hr = StringCchCopyA( pszUrl, cchData + 1, strUrlA.QueryStr() );
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+
+ hr = NO_ERROR;
+ }
+ else
+ {
+ hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
+ }
+ return hr;
+}
+
+
+HRESULT
+NormalizeUrlW(
+ __inout LPWSTR pszUrl
+)
+/*++
+
+Routine Description:
+
+ unicode version of NormalizeUrl wrapper (used by ISAPI filter and extension support functions)
+
+Parameters:
+
+ pszUrl - On entry, the URL to be normalized
+ On return, the normalized URL
+ (size of normalized URL is always <= not normalized URL)
+
+Return Value:
+
+ HRESULT
+
+--*/
+{
+
+ HRESULT hr = NO_ERROR;
+
+ if ( pszUrl )
+ {
+ STACK_BUFFER( buffUrlOutput, MAX_PATH );
+ STACK_STRA( strUrlA, MAX_PATH );
+ LPWSTR szQueryString;
+ DWORD cchData;
+ DWORD cbOutput;
+
+ cchData = (DWORD)wcslen( pszUrl );
+
+ hr = strUrlA.CopyWToUTF8Escaped( pszUrl );
+
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+
+ //
+ // Prepare Output string
+ //
+
+ if ( !buffUrlOutput.Resize( ( cchData + 1 ) *sizeof( WCHAR ) ) )
+ {
+ return HRESULT_FROM_WIN32( GetLastError() );
+ }
+
+ //
+ // Normalize it
+ //
+
+ hr = UlCleanAndCopyUrl(
+ strUrlA.QueryStr(),
+ strUrlA.QueryCB(),
+ &cbOutput,
+ (WCHAR *) buffUrlOutput.QueryPtr(),
+ &szQueryString
+ );
+
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+
+
+ //
+ // Terminate the string at the query so that the
+ // query string doesn't appear in the output. IIS 5
+ // truncated in this way.
+ //
+
+ if ( szQueryString != NULL )
+ {
+ ((WCHAR *) buffUrlOutput.QueryPtr())[ cbOutput - wcslen( szQueryString )] = 0;
+ }
+
+ //
+ // normalized string will never be longer than the original one
+ //
+
+ DBG_ASSERT( cbOutput <= cchData * sizeof( WCHAR ) );
+
+ //
+ // Write the normalized URL over the input data
+ //
+
+ hr = StringCchCopyW( pszUrl, cchData+1, (WCHAR *) buffUrlOutput.QueryPtr() );
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+
+ hr = NO_ERROR;
+ }
+ else
+ {
+ hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
+ }
+ return hr;
+}
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/packages.config b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/packages.config
new file mode 100644
index 0000000000..21d9344493
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/precomp.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/precomp.h
new file mode 100644
index 0000000000..8f578b2ad3
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/precomp.h
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include
+#include
+#pragma warning( disable:4127 )
+#include
+#include
+#include
+
+#include "macros.h"
+#include "stringu.h"
+#include "stringa.h"
+#include "dbgutil.h"
+#include "ntassert.h"
+#include "ahutil.h"
+#include "acache.h"
+#include "base64.hxx"
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringa.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringa.cpp
new file mode 100644
index 0000000000..6380535473
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringa.cpp
@@ -0,0 +1,1767 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+STRA::STRA(
+ VOID
+) : m_cchLen( 0 )
+{
+ *( QueryStr() ) = '\0';
+}
+
+STRA::STRA(
+ __inout_ecount(cchInit) CHAR* pbInit,
+ __in DWORD cchInit
+) : m_Buff( pbInit, cchInit * sizeof( CHAR ) ),
+ m_cchLen(0)
+/*++
+ Description:
+
+ Used by STACK_STRA. Initially populates underlying buffer with pbInit.
+
+ pbInit is not freed.
+
+ Arguments:
+
+ pbInit - initial memory to use
+ cchInit - count, in characters, of pbInit
+
+ Returns:
+
+ None.
+
+--*/
+{
+ _ASSERTE( NULL != pbInit );
+ _ASSERTE( cchInit > 0 );
+ _ASSERTE( pbInit[0] == '\0' );
+}
+
+BOOL
+STRA::IsEmpty(
+ VOID
+) const
+{
+ return ( m_cchLen == 0 );
+}
+
+BOOL
+STRA::Equals(
+ __in PCSTR pszRhs,
+ __in BOOL fIgnoreCase /*= FALSE*/
+) const
+{
+ _ASSERTE( NULL != pszRhs );
+
+ if( fIgnoreCase )
+ {
+ return ( 0 == _stricmp( QueryStr(), pszRhs ) );
+ }
+
+ return ( 0 == strcmp( QueryStr(), pszRhs ) );
+}
+
+BOOL
+STRA::Equals(
+ __in const STRA * pstrRhs,
+ __in BOOL fIgnoreCase /*= FALSE*/
+) const
+{
+ _ASSERTE( NULL != pstrRhs );
+ return Equals( pstrRhs->QueryStr(), fIgnoreCase );
+}
+
+BOOL
+STRA::Equals(
+ __in const STRA & strRhs,
+ __in BOOL fIgnoreCase /*= FALSE*/
+) const
+{
+ return Equals( strRhs.QueryStr(), fIgnoreCase );
+}
+
+DWORD
+STRA::QueryCB(
+ VOID
+) const
+//
+// Returns the number of bytes in the string excluding the terminating NULL
+//
+{
+ return m_cchLen * sizeof( CHAR );
+}
+
+DWORD
+STRA::QueryCCH(
+ VOID
+) const
+//
+// Returns the number of characters in the string excluding the terminating NULL
+//
+{
+ return m_cchLen;
+}
+
+DWORD
+STRA::QuerySizeCCH(
+ VOID
+) const
+//
+// Returns size of the underlying storage buffer, in characters
+//
+{
+ return m_Buff.QuerySize() / sizeof( CHAR );
+}
+
+DWORD
+STRA::QuerySize(
+ VOID
+) const
+//
+// Returns the size of the storage buffer in bytes
+//
+{
+ return m_Buff.QuerySize();
+}
+
+__nullterminated
+__bcount(this->m_cchLen)
+CHAR *
+STRA::QueryStr(
+ VOID
+) const
+//
+// Return the string buffer
+//
+{
+ return m_Buff.QueryPtr();
+}
+
+VOID
+STRA::Reset(
+ VOID
+)
+//
+// Resets the internal string to be NULL string. Buffer remains cached.
+//
+{
+ _ASSERTE( QueryStr() != NULL );
+ *(QueryStr()) = '\0';
+ m_cchLen = 0;
+}
+
+HRESULT
+STRA::Resize(
+ __in DWORD cchSize
+)
+{
+ if( !m_Buff.Resize( cchSize * sizeof( CHAR ) ) )
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ return S_OK;
+}
+
+HRESULT
+STRA::SyncWithBuffer(
+ VOID
+)
+//
+// Recalculate the length of the string, etc. because we've modified
+// the buffer directly.
+//
+{
+ HRESULT hr;
+ size_t size;
+ hr = StringCchLengthA( QueryStr(),
+ QuerySizeCCH(),
+ &size );
+ if ( SUCCEEDED( hr ) )
+ {
+ m_cchLen = static_cast(size);
+ }
+ return hr;
+}
+
+HRESULT
+STRA::Copy(
+ __in PCSTR pszCopy
+)
+{
+ HRESULT hr;
+ size_t cbLen;
+ hr = StringCbLengthA( pszCopy,
+ STRSAFE_MAX_CCH,
+ &cbLen );
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+ return Copy( pszCopy, cbLen );
+}
+
+
+HRESULT
+STRA::Copy(
+ __in_ecount(cchLen)
+ PCSTR pszCopy,
+ __in SIZE_T cbLen
+)
+//
+// Copy the contents of another string to this one
+//
+{
+ _ASSERTE( cbLen <= MAXDWORD );
+
+ return AuxAppend(
+ pszCopy,
+ static_cast(cbLen),
+ 0
+ );
+}
+
+HRESULT
+STRA::Copy(
+ __in const STRA * pstrRhs
+)
+{
+ _ASSERTE( pstrRhs != NULL );
+ return Copy( pstrRhs->QueryStr(), pstrRhs->QueryCCH() );
+}
+
+HRESULT
+STRA::Copy(
+ __in const STRA & strRhs
+)
+{
+ return Copy( strRhs.QueryStr(), strRhs.QueryCCH() );
+}
+
+HRESULT
+STRA::CopyW(
+ __in PCWSTR pszCopyW
+)
+{
+ HRESULT hr;
+ size_t cchLen;
+ hr = StringCchLengthW( pszCopyW,
+ STRSAFE_MAX_CCH,
+ &cchLen );
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+ return CopyW( pszCopyW, cchLen );
+}
+
+HRESULT
+STRA::CopyWTruncate(
+ __in PCWSTR pszCopyWTruncate
+)
+{
+ HRESULT hr;
+ size_t cchLen;
+ hr = StringCchLengthW( pszCopyWTruncate,
+ STRSAFE_MAX_CCH,
+ &cchLen );
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+ return CopyWTruncate( pszCopyWTruncate, cchLen );
+}
+
+HRESULT
+STRA::CopyWTruncate(
+ __in_ecount(cchLen)
+ PCWSTR pszCopyWTruncate,
+ __in SIZE_T cchLen
+)
+//
+// The "Truncate" methods do not do proper conversion. They do a (CHAR) caste
+//
+{
+ _ASSERTE( cchLen <= MAXDWORD );
+
+ return AuxAppendWTruncate(
+ pszCopyWTruncate,
+ static_cast(cchLen),
+ 0
+ );
+}
+
+HRESULT
+STRA::Append(
+ __in PCSTR pszAppend
+)
+{
+ HRESULT hr;
+ size_t cbLen;
+ hr = StringCbLengthA( pszAppend,
+ STRSAFE_MAX_CCH,
+ &cbLen );
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+ return Append( pszAppend, cbLen );
+}
+
+HRESULT
+STRA::Append(
+ __in_ecount(cchLen)
+ PCSTR pszAppend,
+ __in SIZE_T cbLen
+)
+{
+ _ASSERTE( cbLen <= MAXDWORD );
+ if ( cbLen == 0 )
+ {
+ return S_OK;
+ }
+ return AuxAppend(
+ pszAppend,
+ static_cast(cbLen),
+ QueryCB()
+ );
+}
+
+HRESULT
+STRA::Append(
+ __in const STRA * pstrRhs
+)
+{
+ _ASSERTE( pstrRhs != NULL );
+ return Append( pstrRhs->QueryStr(), pstrRhs->QueryCCH() );
+}
+
+HRESULT
+STRA::Append(
+ __in const STRA & strRhs
+)
+{
+ return Append( strRhs.QueryStr(), strRhs.QueryCCH() );
+}
+
+HRESULT
+STRA::AppendWTruncate(
+ __in PCWSTR pszAppendWTruncate
+)
+{
+ HRESULT hr;
+ size_t cchLen;
+ hr = StringCchLengthW( pszAppendWTruncate,
+ STRSAFE_MAX_CCH,
+ &cchLen );
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+ return AppendWTruncate( pszAppendWTruncate, cchLen );
+}
+
+HRESULT
+STRA::AppendWTruncate(
+ __in_ecount(cchLen)
+ PCWSTR pszAppendWTruncate,
+ __in SIZE_T cchLen
+)
+//
+// The "Truncate" methods do not do proper conversion. They do a (CHAR) caste
+//
+{
+ _ASSERTE( cchLen <= MAXDWORD );
+ if ( cchLen == 0 )
+ {
+ return S_OK;
+ }
+ return AuxAppendWTruncate(
+ pszAppendWTruncate,
+ static_cast(cchLen),
+ QueryCB()
+ );
+}
+
+HRESULT
+STRA::CopyToBuffer(
+ __out_bcount(*pcb) CHAR* pszBuffer,
+ __inout DWORD * pcb
+) const
+//
+// Makes a copy of the stored string into the given buffer
+//
+{
+ _ASSERTE( NULL != pszBuffer );
+ _ASSERTE( NULL != pcb );
+
+ HRESULT hr = S_OK;
+ DWORD cbNeeded = QueryCB() + sizeof( CHAR );
+
+ if( *pcb < cbNeeded )
+ {
+ hr = HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER );
+ goto Finished;
+ }
+
+ memcpy( pszBuffer, QueryStr(), cbNeeded );
+
+Finished:
+
+ *pcb = cbNeeded;
+
+ return hr;
+}
+
+HRESULT
+STRA::SetLen(
+ __in DWORD cchLen
+)
+/*++
+ *
+Routine Description:
+
+ Set the length of the string and null terminate, if there
+ is sufficient buffer already allocated. Will not reallocate.
+
+Arguments:
+
+ cchLen - The number of characters in the new string.
+
+Return Value:
+
+ HRESULT
+
+--*/
+{
+ if( cchLen >= QuerySizeCCH() )
+ {
+ return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
+ }
+
+ *( QueryStr() + cchLen ) = '\0';
+ m_cchLen = cchLen;
+
+ return S_OK;
+}
+
+
+HRESULT
+STRA::SafeSnprintf(
+ __in __format_string
+ PCSTR pszFormatString,
+ ...
+)
+/*++
+
+Routine Description:
+
+ Writes to a STRA, growing it as needed. It arbitrarily caps growth at 64k chars.
+
+Arguments:
+
+ pszFormatString - printf format
+ ... - printf args
+
+Return Value:
+
+ HRESULT
+
+--*/
+{
+ HRESULT hr = S_OK;
+ va_list argsList;
+ va_start( argsList, pszFormatString );
+
+ hr = SafeVsnprintf(pszFormatString, argsList);
+
+ va_end( argsList );
+ return hr;
+}
+
+HRESULT
+STRA::SafeVsnprintf(
+ __in __format_string
+ PCSTR pszFormatString,
+ va_list argsList
+)
+/*++
+
+Routine Description:
+
+ Writes to a STRA, growing it as needed. It arbitrarily caps growth at 64k chars.
+
+Arguments:
+
+ pszFormatString - printf format
+ argsList - printf va_list
+
+Return Value:
+
+ HRESULT
+
+--*/
+{
+ HRESULT hr = S_OK;
+ int cchOutput;
+ int cchNeeded;
+
+ //
+ // Format the incoming message using vsnprintf()
+ // so that the overflows are captured
+ //
+ cchOutput = _vsnprintf_s(
+ QueryStr(),
+ QuerySizeCCH(),
+ QuerySizeCCH() - 1,
+ pszFormatString,
+ argsList
+ );
+
+ if( cchOutput == -1 )
+ {
+ //
+ // Couldn't fit this in the original STRU size.
+ //
+ cchNeeded = _vscprintf( pszFormatString, argsList );
+ if( cchNeeded > 64 * 1024 )
+ {
+ //
+ // If we're trying to produce a string > 64k chars, then
+ // there is probably a problem
+ //
+ hr = HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
+ goto Finished;
+ }
+
+ //
+ // _vscprintf doesn't include terminating null character
+ //
+ cchNeeded++;
+
+ hr = Resize( cchNeeded );
+ if( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+
+ cchOutput = _vsnprintf_s(
+ QueryStr(),
+ QuerySizeCCH(),
+ QuerySizeCCH() - 1,
+ pszFormatString,
+ argsList
+ );
+ if( -1 == cchOutput )
+ {
+ //
+ // This should never happen, cause we should already have correctly sized memory
+ //
+ _ASSERTE( FALSE );
+
+ hr = HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
+ goto Finished;
+ }
+ }
+
+ //
+ // always null terminate at the last WCHAR
+ //
+ QueryStr()[ QuerySizeCCH() - 1 ] = L'\0';
+
+ //
+ // we directly touched the buffer - therefore:
+ //
+ hr = SyncWithBuffer();
+ if( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+
+Finished:
+
+ if( FAILED( hr ) )
+ {
+ Reset();
+ }
+
+ return hr;
+}
+
+bool
+FShouldEscapeUtf8(
+ BYTE ch
+ )
+{
+ if ( ( ch >= 128 ) )
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool
+FShouldEscapeUrl(
+ BYTE ch
+ )
+{
+ if ( ( ch >= 128 ||
+ ch <= 32 ||
+ ch == '<' ||
+ ch == '>' ||
+ ch == '%' ||
+ ch == '?' ||
+ ch == '#' ) &&
+ !( ch == '\n' || ch == '\r' ) )
+ {
+ return true;
+ }
+
+ return false;
+}
+
+HRESULT
+STRA::Escape(
+ VOID
+)
+/*++
+
+Routine Description:
+
+ Escapes a STRA
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ return EscapeInternal( FShouldEscapeUrl );
+}
+
+HRESULT
+STRA::EscapeUtf8(
+ VOID
+)
+/*++
+
+Routine Description:
+
+ Escapes the high-bit chars in a STRA. LWS, CR, LF & controls are untouched.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ return EscapeInternal( FShouldEscapeUtf8 );
+}
+
+
+HRESULT
+STRA::EscapeInternal(
+ PFN_F_SHOULD_ESCAPE pfnFShouldEscape
+)
+/*++
+
+Routine Description:
+
+ Escapes a STRA according to the predicate function passed in
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ LPCSTR pch = QueryStr();
+ __analysis_assume( pch != NULL );
+ int i = 0;
+ BYTE ch;
+ HRESULT hr = S_OK;
+ BOOL fRet = FALSE;
+ SIZE_T NewSize = 0;
+
+ // Set to true if any % escaping occurs
+ BOOL fEscapingDone = FALSE;
+
+ //
+ // If there are any characters that need to be escaped we copy the entire string
+ // character by character into straTemp, escaping as we go, then at the end
+ // copy all of straTemp over. Don't modify InlineBuffer directly.
+ //
+ CHAR InlineBuffer[512];
+ InlineBuffer[0] = '\0';
+ STRA straTemp(InlineBuffer, sizeof(InlineBuffer)/sizeof(*InlineBuffer));
+
+ _ASSERTE( pch );
+
+ while (ch = pch[i])
+ {
+ //
+ // Escape characters that are in the non-printable range
+ // but ignore CR and LF
+ //
+
+ if ( pfnFShouldEscape( ch ) )
+ {
+ if (FALSE == fEscapingDone)
+ {
+ // first character in the string that needed escaping
+ fEscapingDone = TRUE;
+
+ // guess that the size needs to be larger than
+ // what we used to have times two
+ NewSize = QueryCCH() * 2;
+ if ( NewSize > MAXDWORD )
+ {
+ hr = HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW );
+ return hr;
+ }
+
+ hr = straTemp.Resize( static_cast(NewSize) );
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ // Copy all of the previous buffer into buffTemp, only if it is not the first character:
+
+ if ( i > 0)
+ {
+ hr = straTemp.Copy(QueryStr(),
+ i * sizeof(CHAR));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ }
+ }
+
+ // resize the temporary (if needed) with the slop of the entire buffer length
+ // this fixes constant reallocation if the entire string needs to be escaped
+ NewSize = QueryCCH() + 2 * sizeof(CHAR) + 1 * sizeof(CHAR);
+ if ( NewSize > MAXDWORD )
+ {
+ hr = HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW );
+ return hr;
+ }
+
+ fRet = straTemp.m_Buff.Resize( NewSize );
+ if ( !fRet )
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ return hr;
+ }
+
+ //
+ // Create the string to append for the current character
+ //
+
+ CHAR chHex[3];
+ chHex[0] = '%';
+
+ //
+ // Convert the low then the high character to hex
+ //
+
+ UINT nLowDigit = (UINT)(ch % 16);
+ chHex[2] = TODIGIT( nLowDigit );
+
+ ch /= 16;
+
+ UINT nHighDigit = (UINT)(ch % 16);
+
+ chHex[1] = TODIGIT( nHighDigit );
+
+ //
+ // Actually append the converted character to the end of the temporary
+ //
+ hr = straTemp.Append(chHex, 3);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ }
+ else
+ {
+ // if no escaping done, no need to copy
+ if (fEscapingDone)
+ {
+ // if ANY escaping done, copy current character into new buffer
+ straTemp.Append(&pch[i], 1);
+ }
+ }
+
+ // inspect the next character in the string
+ i++;
+ }
+
+ if (fEscapingDone)
+ {
+ // the escaped string is now in straTemp
+ hr = Copy(straTemp);
+ }
+
+ return hr;
+
+} // EscapeInternal()
+
+VOID
+STRA::Unescape(
+ VOID
+)
+/*++
+
+Routine Description:
+
+ Unescapes a STRA
+
+ Supported escape sequences are:
+ %uxxxx unescapes Unicode character xxxx into system codepage
+ %xx unescapes character xx
+ % without following hex digits is ignored
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ CHAR *pScan;
+ CHAR *pDest;
+ CHAR *pNextScan;
+ WCHAR wch;
+ DWORD dwLen;
+ BOOL fChanged = FALSE;
+
+ //
+ // Now take care of any escape characters
+ //
+ pDest = pScan = strchr(QueryStr(), '%');
+
+ while (pScan)
+ {
+ if ((pScan[1] == 'u' || pScan[1] == 'U') &&
+ SAFEIsXDigit(pScan[2]) &&
+ SAFEIsXDigit(pScan[3]) &&
+ SAFEIsXDigit(pScan[4]) &&
+ SAFEIsXDigit(pScan[5]))
+ {
+ wch = TOHEX(pScan[2]) * 4096 + TOHEX(pScan[3]) * 256
+ + TOHEX(pScan[4]) * 16 + TOHEX(pScan[5]);
+
+ dwLen = WideCharToMultiByte(CP_ACP,
+ WC_NO_BEST_FIT_CHARS,
+ &wch,
+ 1,
+ (LPSTR) pDest,
+ 6,
+ NULL,
+ NULL);
+
+ pDest += dwLen;
+ pScan += 6;
+ fChanged = TRUE;
+ }
+ else if (SAFEIsXDigit(pScan[1]) && SAFEIsXDigit(pScan[2]))
+ {
+ *pDest = TOHEX(pScan[1]) * 16 + TOHEX(pScan[2]);
+
+ pDest ++;
+ pScan += 3;
+ fChanged = TRUE;
+ }
+ else // Not an escaped char, just a '%'
+ {
+ if (fChanged)
+ {
+ *pDest = *pScan;
+ }
+
+ pDest++;
+ pScan++;
+ }
+
+ //
+ // Copy all the information between this and the next escaped char
+ //
+ pNextScan = strchr(pScan, '%');
+
+ if (fChanged) // pScan!=pDest, so we have to copy the char's
+ {
+ if (!pNextScan) // That was the last '%' in the string
+ {
+ memmove(pDest,
+ pScan,
+ QueryCCH() - DIFF(pScan - QueryStr()) + 1);
+ }
+ else
+ {
+ // There is another '%', move intermediate chars
+ if ((dwLen = (DWORD)DIFF(pNextScan - pScan)) != 0)
+ {
+ memmove(pDest,
+ pScan,
+ dwLen);
+ pDest += dwLen;
+ }
+ }
+ }
+
+ pScan = pNextScan;
+ }
+
+ if (fChanged)
+ {
+ m_cchLen = (DWORD)strlen(QueryStr()); // for safety recalc the length
+ }
+
+ return;
+}
+
+HRESULT
+STRA::CopyWToUTF8Unescaped(
+ __in LPCWSTR cpchStr
+)
+{
+ return STRA::CopyWToUTF8Unescaped(cpchStr, (DWORD) wcslen(cpchStr));
+}
+
+HRESULT
+STRA::CopyWToUTF8Unescaped(
+ __in_ecount(cch)
+ LPCWSTR cpchStr,
+ __in DWORD cch
+)
+{
+ HRESULT hr = S_OK;
+ int iRet;
+
+ if (cch == 0)
+ {
+ Reset();
+ return S_OK;
+ }
+
+ iRet = ConvertUnicodeToUTF8(cpchStr,
+ &m_Buff,
+ cch);
+ if (-1 == iRet)
+ {
+ // could not convert
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto Finished;
+ }
+
+ m_cchLen = iRet;
+
+ _ASSERTE(strlen(m_Buff.QueryPtr()) == m_cchLen);
+Finished:
+ return hr;
+}
+
+HRESULT
+STRA::CopyWToUTF8Escaped(
+ __in LPCWSTR cpchStr
+)
+{
+ return STRA::CopyWToUTF8Escaped(cpchStr, (DWORD) wcslen(cpchStr));
+}
+
+HRESULT
+STRA::CopyWToUTF8Escaped(
+ __in_ecount(cch)
+ LPCWSTR cpchStr,
+ __in DWORD cch
+)
+{
+ HRESULT hr = S_OK;
+
+ hr = CopyWToUTF8Unescaped(cpchStr, cch);
+ if (FAILED(hr))
+ {
+ goto Finished;
+ }
+
+ hr = Escape();
+ if (FAILED(hr))
+ {
+ goto Finished;
+ }
+
+ hr = S_OK;
+Finished:
+ return hr;
+}
+
+HRESULT
+STRA::AuxAppend(
+ __in_ecount(cbLen)
+ LPCSTR pStr,
+ __in DWORD cbLen,
+ __in DWORD cbOffset
+)
+{
+ _ASSERTE( NULL != pStr );
+ _ASSERTE( cbOffset <= QueryCB() );
+
+ ULONGLONG cb64NewSize = (ULONGLONG)cbOffset + cbLen + sizeof( CHAR );
+ if( cb64NewSize > MAXDWORD )
+ {
+ return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW );
+ }
+
+ if( m_Buff.QuerySize() < cb64NewSize )
+ {
+ if( !m_Buff.Resize( static_cast(cb64NewSize) ) )
+ {
+ return E_OUTOFMEMORY;
+ }
+ }
+
+ memcpy( reinterpret_cast(m_Buff.QueryPtr()) + cbOffset, pStr, cbLen );
+
+ m_cchLen = cbLen + cbOffset;
+
+ *( QueryStr() + m_cchLen ) = '\0';
+
+ return S_OK;
+}
+
+HRESULT
+STRA::AuxAppendW(
+ __in_ecount(cchAppendW)
+ PCWSTR pszAppendW,
+ __in DWORD cchAppendW,
+ __in DWORD cbOffset,
+ __in UINT CodePage,
+ __in BOOL fFailIfNoTranslation,
+ __in DWORD dwFlags
+)
+{
+ HRESULT hr = S_OK;
+ DWORD cbAvailable = 0;
+ DWORD cbRet = 0;
+
+ //
+ // There are only two expect places to append
+ //
+ _ASSERTE( 0 == cbOffset || QueryCB() == cbOffset );
+
+ if ( cchAppendW == 0 )
+ {
+ goto Finished;
+ }
+
+ //
+ // start by assuming 1 char to 1 char will be enough space
+ //
+ if( !m_Buff.Resize( cbOffset + cchAppendW + sizeof( CHAR ) ) )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Finished;
+ }
+
+ cbAvailable = m_Buff.QuerySize() - cbOffset;
+
+ cbRet = WideCharToMultiByte(
+ CodePage,
+ dwFlags,
+ pszAppendW,
+ cchAppendW,
+ QueryStr() + cbOffset,
+ cbAvailable,
+ NULL,
+ NULL
+ );
+ if( 0 != cbRet )
+ {
+ if(!m_Buff.Resize(cbOffset + cbRet + 1))
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ //
+ // not zero --> success, so we're done
+ //
+ goto Finished;
+ }
+
+ //
+ // We only know how to handle ERROR_INSUFFICIENT_BUFFER
+ //
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ if( hr != HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) )
+ {
+ goto Finished;
+ }
+
+ //
+ // Reset HResult because we need to get the number of bytes needed
+ //
+ hr = S_OK;
+ cbRet = WideCharToMultiByte(
+ CodePage,
+ dwFlags,
+ pszAppendW,
+ cchAppendW,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+ if( 0 == cbRet )
+ {
+ //
+ // no idea how we could ever reach here
+ //
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ goto Finished;
+ }
+
+ if( !m_Buff.Resize( cbOffset + cbRet + 1) )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Finished;
+ }
+
+ cbAvailable = m_Buff.QuerySize() - cbOffset;
+
+ cbRet = WideCharToMultiByte(
+ CodePage,
+ dwFlags,
+ pszAppendW,
+ cchAppendW,
+ QueryStr() + cbOffset,
+ cbAvailable,
+ NULL,
+ NULL
+ );
+ if( 0 == cbRet )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ goto Finished;
+ }
+
+Finished:
+
+ if( SUCCEEDED( hr ) && 0 != cbRet )
+ {
+ m_cchLen = cbRet + cbOffset;
+ }
+
+ //
+ // ensure we're still NULL terminated in the right spot
+ // (regardless of success or failure)
+ //
+ QueryStr()[m_cchLen] = '\0';
+
+ return hr;
+}
+
+HRESULT
+STRA::AuxAppendWTruncate(
+ __in_ecount(cchAppendW)
+ __in PCWSTR pszAppendW,
+ __in DWORD cchAppendW,
+ __in DWORD cbOffset
+)
+//
+// Cheesey WCHAR --> CHAR conversion
+//
+{
+ HRESULT hr = S_OK;
+ CHAR* pszBuffer;
+
+ _ASSERTE( NULL != pszAppendW );
+ _ASSERTE( 0 == cbOffset || cbOffset == QueryCB() );
+
+ if( !pszAppendW )
+ {
+ hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
+ goto Finished;
+ }
+
+ ULONGLONG cbNeeded = (ULONGLONG)cbOffset + cchAppendW + sizeof( CHAR );
+ if( cbNeeded > MAXDWORD )
+ {
+ hr = HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW );
+ goto Finished;
+ }
+
+ if( !m_Buff.Resize( static_cast(cbNeeded) ) )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Finished;
+ }
+
+ //
+ // Copy/convert the UNICODE string over (by making two bytes into one)
+ //
+ pszBuffer = QueryStr() + cbOffset;
+ for( DWORD i = 0; i < cchAppendW; i++ )
+ {
+ pszBuffer[i] = static_cast(pszAppendW[i]);
+ }
+
+ m_cchLen = cchAppendW + cbOffset;
+ *( QueryStr() + m_cchLen ) = '\0';
+
+Finished:
+
+ return hr;
+}
+
+// static
+int
+STRA::ConvertUnicodeToCodePage(
+ __in_ecount(dwStringLen)
+ LPCWSTR pszSrcUnicodeString,
+ __inout BUFFER_T * pbufDstAnsiString,
+ __in DWORD dwStringLen,
+ __in UINT uCodePage
+)
+{
+ _ASSERTE(NULL != pszSrcUnicodeString);
+ _ASSERTE(NULL != pbufDstAnsiString);
+
+ BOOL bTemp;
+ int iStrLen = 0;
+ DWORD dwFlags;
+
+ if (uCodePage == CP_ACP)
+ {
+ dwFlags = WC_NO_BEST_FIT_CHARS;
+ }
+ else
+ {
+ dwFlags = 0;
+ }
+
+ iStrLen = WideCharToMultiByte(uCodePage,
+ dwFlags,
+ pszSrcUnicodeString,
+ dwStringLen,
+ (LPSTR)pbufDstAnsiString->QueryPtr(),
+ (int)pbufDstAnsiString->QuerySize(),
+ NULL,
+ NULL);
+ if ((iStrLen == 0) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
+ iStrLen = WideCharToMultiByte(uCodePage,
+ dwFlags,
+ pszSrcUnicodeString,
+ dwStringLen,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ if (iStrLen != 0) {
+ // add one just for the extra NULL
+ bTemp = pbufDstAnsiString->Resize(iStrLen + 1);
+ if (!bTemp)
+ {
+ iStrLen = 0;
+ }
+ else
+ {
+ iStrLen = WideCharToMultiByte(uCodePage,
+ dwFlags,
+ pszSrcUnicodeString,
+ dwStringLen,
+ (LPSTR)pbufDstAnsiString->QueryPtr(),
+ (int)pbufDstAnsiString->QuerySize(),
+ NULL,
+ NULL);
+ }
+
+ }
+ }
+
+ if (0 != iStrLen &&
+ pbufDstAnsiString->Resize(iStrLen + 1))
+ {
+ // insert a terminating NULL into buffer for the dwStringLen+1 in the case that the dwStringLen+1 was not a NULL.
+ ((CHAR*)pbufDstAnsiString->QueryPtr())[iStrLen] = '\0';
+ }
+ else
+ {
+ iStrLen = -1;
+ }
+
+ return iStrLen;
+}
+
+// static
+HRESULT
+STRA::ConvertUnicodeToMultiByte(
+ __in_ecount(dwStringLen)
+ LPCWSTR pszSrcUnicodeString,
+ __in BUFFER_T * pbufDstAnsiString,
+ __in DWORD dwStringLen
+)
+{
+ return ConvertUnicodeToCodePage( pszSrcUnicodeString,
+ pbufDstAnsiString,
+ dwStringLen,
+ CP_ACP );
+}
+
+// static
+HRESULT
+STRA::ConvertUnicodeToUTF8(
+ __in_ecount(dwStringLen)
+ LPCWSTR pszSrcUnicodeString,
+ __in BUFFER_T * pbufDstAnsiString,
+ __in DWORD dwStringLen
+)
+{
+ return ConvertUnicodeToCodePage( pszSrcUnicodeString,
+ pbufDstAnsiString,
+ dwStringLen,
+ CP_UTF8 );
+}
+
+/*++
+
+Routine Description:
+
+ Removes leading and trailing whitespace
+
+--*/
+
+VOID
+STRA::Trim()
+{
+ PSTR pszString = QueryStr();
+ DWORD cchNewLength = m_cchLen;
+ DWORD cchLeadingWhitespace = 0;
+ DWORD cchTempLength = 0;
+
+ for (LONG ixString = m_cchLen - 1; ixString >= 0; ixString--)
+ {
+ if (isspace((unsigned char) pszString[ixString]) != 0)
+ {
+ pszString[ixString] = '\0';
+ cchNewLength--;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ cchTempLength = cchNewLength;
+ for (DWORD ixString = 0; ixString < cchTempLength; ixString++)
+ {
+ if (isspace((unsigned char) pszString[ixString]) != 0)
+ {
+ cchLeadingWhitespace++;
+ cchNewLength--;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (cchNewLength == 0)
+ {
+
+ Reset();
+ }
+ else if (cchLeadingWhitespace > 0)
+ {
+ memmove(pszString, pszString + cchLeadingWhitespace, cchNewLength * sizeof(CHAR));
+ pszString[cchNewLength] = '\0';
+ }
+
+ SyncWithBuffer();
+}
+
+/*++
+
+Routine Description:
+
+ Compares the string to the provided prefix to check for equality
+
+Arguments:
+
+ pStraPrefix - string to compare with
+ fIgnoreCase - indicates whether the string comparison should be case-sensitive
+
+Return Value:
+
+ TRUE if prefix string matches with internal string, FALSE otherwise
+
+--*/
+BOOL
+STRA::StartsWith(
+ __in const STRA * pStraPrefix,
+ __in bool fIgnoreCase) const
+{
+ _ASSERTE( pStraPrefix != NULL );
+ return StartsWith(pStraPrefix->QueryStr(), fIgnoreCase);
+}
+
+/*++
+
+Routine Description:
+
+ Compares the string to the provided prefix to check for equality
+
+Arguments:
+
+ straPrefix - string to compare with
+ fIgnoreCase - indicates whether the string comparison should be case-sensitive
+
+Return Value:
+
+ TRUE if prefix string matches with internal string, FALSE otherwise
+
+--*/
+BOOL
+STRA::StartsWith(
+ __in const STRA & straPrefix,
+ __in bool fIgnoreCase) const
+{
+ return StartsWith(straPrefix.QueryStr(), fIgnoreCase);
+}
+
+/*++
+
+Routine Description:
+
+ Compares the string to the provided prefix to check for equality
+
+Arguments:
+
+ pszPrefix - string to compare with
+ fIgnoreCase - indicates whether the string comparison should be case-sensitive
+
+Return Value:
+
+ TRUE if prefix string matches with internal string, FALSE otherwise
+
+--*/
+BOOL
+STRA::StartsWith(
+ __in PCSTR pszPrefix,
+ __in bool fIgnoreCase) const
+{
+ HRESULT hr = S_OK;
+ BOOL fMatch = FALSE;
+ size_t cchPrefix = 0;
+
+ if (pszPrefix == NULL)
+ {
+ goto Finished;
+ }
+
+ hr = StringCchLengthA( pszPrefix,
+ STRSAFE_MAX_CCH,
+ &cchPrefix );
+ if (FAILED(hr))
+ {
+ goto Finished;
+ }
+
+ _ASSERTE( cchPrefix <= MAXDWORD );
+
+ if (cchPrefix > m_cchLen)
+ {
+ goto Finished;
+ }
+
+ if( fIgnoreCase )
+ {
+ fMatch = ( 0 == _strnicmp( QueryStr(), pszPrefix, cchPrefix ) );
+ }
+ else
+ {
+ fMatch = ( 0 == strncmp( QueryStr(), pszPrefix, cchPrefix ) );
+ }
+
+
+Finished:
+
+ return fMatch;
+}
+
+/*++
+
+Routine Description:
+
+ Compares the string to the provided suffix to check for equality
+
+Arguments:
+
+ pStraSuffix - string to compare with
+ fIgnoreCase - indicates whether the string comparison should be case-sensitive
+
+Return Value:
+
+ TRUE if suffix string matches with internal string, FALSE otherwise
+
+--*/
+BOOL
+STRA::EndsWith(
+ __in const STRA * pStraSuffix,
+ __in bool fIgnoreCase) const
+{
+ _ASSERTE( pStraSuffix != NULL );
+ return EndsWith(pStraSuffix->QueryStr(), fIgnoreCase);
+}
+
+
+/*++
+
+Routine Description:
+
+ Compares the string to the provided suffix to check for equality
+
+Arguments:
+
+ straSuffix - string to compare with
+ fIgnoreCase - indicates whether the string comparison should be case-sensitive
+
+Return Value:
+
+ TRUE if suffix string matches with internal string, FALSE otherwise
+
+--*/
+BOOL
+STRA::EndsWith(
+ __in const STRA & straSuffix,
+ __in bool fIgnoreCase) const
+{
+ return EndsWith(straSuffix.QueryStr(), fIgnoreCase);
+}
+
+
+/*++
+
+Routine Description:
+
+ Compares the string to the provided suffix to check for equality
+
+Arguments:
+
+ pszSuffix - string to compare with
+ fIgnoreCase - indicates whether the string comparison should be case-sensitive
+
+Return Value:
+
+ TRUE if suffix string matches with internal string, FALSE otherwise
+
+--*/
+BOOL
+STRA::EndsWith(
+ __in PCSTR pszSuffix,
+ __in bool fIgnoreCase) const
+{
+ HRESULT hr = S_OK;
+ PSTR pszString = QueryStr();
+ BOOL fMatch = FALSE;
+ size_t cchSuffix = 0;
+ ptrdiff_t ixOffset = 0;
+
+ if (pszSuffix == NULL)
+ {
+ goto Finished;
+ }
+
+ hr = StringCchLengthA( pszSuffix,
+ STRSAFE_MAX_CCH,
+ &cchSuffix );
+ if (FAILED(hr))
+ {
+ goto Finished;
+ }
+
+ _ASSERTE( cchSuffix <= MAXDWORD );
+
+ if (cchSuffix > m_cchLen)
+ {
+ goto Finished;
+ }
+
+ ixOffset = m_cchLen - cchSuffix;
+ _ASSERTE(ixOffset >= 0 && ixOffset <= MAXDWORD);
+
+ if( fIgnoreCase )
+ {
+ fMatch = ( 0 == _strnicmp( pszString + ixOffset, pszSuffix, cchSuffix ) );
+ }
+ else
+ {
+ fMatch = ( 0 == strncmp( pszString + ixOffset, pszSuffix, cchSuffix ) );
+ }
+
+Finished:
+
+ return fMatch;
+}
+
+
+/*++
+
+Routine Description:
+
+ Searches the string for the first occurrence of the specified character.
+
+Arguments:
+
+ charValue - character to find
+ dwStartIndex - the initial index.
+
+Return Value:
+
+ The index for the first character occurence in the string.
+
+ -1 if not found.
+
+--*/
+INT
+STRA::IndexOf(
+ __in CHAR charValue,
+ __in DWORD dwStartIndex
+ ) const
+{
+ INT nIndex = -1;
+
+ // Make sure that there are no buffer overruns.
+ if( dwStartIndex >= QueryCCH() )
+ {
+ goto Finished;
+ }
+
+ const CHAR* pChar = strchr( QueryStr() + dwStartIndex, charValue );
+
+ // Determine the index if found
+ if( pChar )
+ {
+ // nIndex will be set to -1 on failure.
+ (VOID)SizeTToInt( pChar - QueryStr(), &nIndex );
+ }
+
+Finished:
+
+ return nIndex;
+}
+
+
+/*++
+
+Routine Description:
+
+ Searches the string for the first occurrence of the specified substring.
+
+Arguments:
+
+ pszValue - substring to find
+ dwStartIndex - initial index.
+
+Return Value:
+
+ The index for the first character occurence in the string.
+
+ -1 if not found.
+
+--*/
+INT
+STRA::IndexOf(
+ __in PCSTR pszValue,
+ __in DWORD dwStartIndex
+ ) const
+{
+ HRESULT hr = S_OK;
+ INT nIndex = -1;
+ SIZE_T cchValue = 0;
+
+ // Validate input parameters
+ if( dwStartIndex >= QueryCCH() || !pszValue )
+ {
+ goto Finished;
+ }
+
+ const CHAR* pChar = strstr( QueryStr() + dwStartIndex, pszValue );
+
+ // Determine the index if found
+ if( pChar )
+ {
+ // nIndex will be set to -1 on failure.
+ (VOID)SizeTToInt( pChar - QueryStr(), &nIndex );
+ }
+
+Finished:
+
+ return nIndex;
+}
+
+
+/*++
+
+Routine Description:
+
+ Searches the string for the last occurrence of the specified character.
+
+Arguments:
+
+ charValue - character to find
+ dwStartIndex - initial index.
+
+Return Value:
+
+ The index for the last character occurence in the string.
+
+ -1 if not found.
+
+--*/
+INT
+STRA::LastIndexOf(
+ __in CHAR charValue,
+ __in DWORD dwStartIndex
+ ) const
+{
+ INT nIndex = -1;
+
+ // Make sure that there are no buffer overruns.
+ if( dwStartIndex >= QueryCCH() )
+ {
+ goto Finished;
+ }
+
+ const CHAR* pChar = strrchr( QueryStr() + dwStartIndex, charValue );
+
+ // Determine the index if found
+ if( pChar )
+ {
+ // nIndex will be set to -1 on failure.
+ (VOID)SizeTToInt( pChar - QueryStr(), &nIndex );
+ }
+
+Finished:
+
+ return nIndex;
+}
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringu.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringu.cpp
new file mode 100644
index 0000000000..4fd2a052f2
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringu.cpp
@@ -0,0 +1,1289 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+STRU::STRU(
+ VOID
+) : m_cchLen( 0 )
+{
+ *(QueryStr()) = L'\0';
+}
+
+STRU::STRU(
+ __inout_ecount(cchInit) WCHAR* pbInit,
+ __in DWORD cchInit
+) : m_Buff( pbInit, cchInit * sizeof( WCHAR ) ),
+ m_cchLen( 0 )
+/*++
+ Description:
+
+ Used by STACK_STRU. Initially populates underlying buffer with pbInit.
+
+ pbInit is not freed.
+
+ Arguments:
+
+ pbInit - initial memory to use
+ cchInit - count, in characters, of pbInit
+
+ Returns:
+
+ None.
+
+--*/
+{
+ _ASSERTE( cchInit <= (MAXDWORD / sizeof( WCHAR )) );
+ _ASSERTE( NULL != pbInit );
+ _ASSERTE(cchInit > 0 );
+ _ASSERTE(pbInit[0] == L'\0');
+}
+
+BOOL
+STRU::IsEmpty(
+ VOID
+) const
+{
+ return ( m_cchLen == 0 );
+}
+
+DWORD
+STRU::QueryCB(
+ VOID
+) const
+//
+// Returns the number of bytes in the string excluding the terminating NULL
+//
+{
+ return m_cchLen * sizeof( WCHAR );
+}
+
+DWORD
+STRU::QueryCCH(
+ VOID
+) const
+//
+// Returns the number of characters in the string excluding the terminating NULL
+//
+{
+ return m_cchLen;
+}
+
+DWORD
+STRU::QuerySizeCCH(
+ VOID
+) const
+//
+// Returns size of the underlying storage buffer, in characters
+//
+{
+ return m_Buff.QuerySize() / sizeof( WCHAR );
+}
+
+__nullterminated
+__ecount(this->m_cchLen)
+WCHAR*
+STRU::QueryStr(
+ VOID
+) const
+//
+// Return the string buffer
+//
+{
+ return m_Buff.QueryPtr();
+}
+
+VOID
+STRU::Reset(
+ VOID
+)
+//
+// Resets the internal string to be NULL string. Buffer remains cached.
+//
+{
+ _ASSERTE( QueryStr() != NULL );
+ *(QueryStr()) = L'\0';
+ m_cchLen = 0;
+}
+
+HRESULT
+STRU::Resize(
+ DWORD cchSize
+)
+{
+ SIZE_T cbSize = cchSize * sizeof( WCHAR );
+ if ( cbSize > MAXDWORD )
+ {
+ return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW );
+ }
+ if( !m_Buff.Resize( cbSize ) )
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ return S_OK;
+}
+
+HRESULT
+STRU::SyncWithBuffer(
+ VOID
+)
+//
+// Recalculate the length of the string, etc. because we've modified
+// the buffer directly.
+//
+{
+ HRESULT hr;
+ size_t size;
+ hr = StringCchLengthW( QueryStr(),
+ QuerySizeCCH(),
+ &size );
+ if ( SUCCEEDED( hr ) )
+ {
+ m_cchLen = static_cast(size);
+ }
+ return hr;
+}
+
+HRESULT
+STRU::Copy(
+ __in PCWSTR pszCopy
+)
+{
+ HRESULT hr;
+ size_t cbStr;
+
+ hr = StringCchLengthW( pszCopy,
+ STRSAFE_MAX_CCH,
+ &cbStr );
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+
+ _ASSERTE( cbStr <= MAXDWORD );
+ return Copy( pszCopy,
+ cbStr );
+}
+
+HRESULT
+STRU::Copy(
+ __in_ecount(cchLen)
+ PCWSTR pszCopy,
+ SIZE_T cchLen
+)
+//
+// Copy the contents of another string to this one
+//
+{
+ return AuxAppend( pszCopy,
+ cchLen * sizeof(WCHAR),
+ 0);
+}
+
+HRESULT
+STRU::Copy(
+ __in const STRU * pstrRhs
+)
+{
+ _ASSERTE( NULL != pstrRhs );
+ return Copy( pstrRhs->QueryStr(), pstrRhs->QueryCCH() );
+}
+
+HRESULT
+STRU::Copy(
+ __in const STRU & str
+)
+{
+ return Copy( str.QueryStr(), str.QueryCCH() );
+}
+
+HRESULT
+STRU::CopyAndExpandEnvironmentStrings(
+ __in PCWSTR pszSource
+)
+{
+ HRESULT hr = S_OK;
+ DWORD cchDestReqBuff = 0;
+
+ Reset();
+
+ cchDestReqBuff = ExpandEnvironmentStringsW( pszSource,
+ QueryStr(),
+ QuerySizeCCH() );
+ if ( cchDestReqBuff == 0 )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ goto Finished;
+ }
+ else if ( cchDestReqBuff > QuerySizeCCH() )
+ {
+ hr = Resize( cchDestReqBuff );
+ if ( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+
+ cchDestReqBuff = ExpandEnvironmentStringsW( pszSource,
+ QueryStr(),
+ QuerySizeCCH() );
+
+ if ( cchDestReqBuff == 0 || cchDestReqBuff > QuerySizeCCH() )
+ {
+ _ASSERTE( FALSE );
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ goto Finished;
+ }
+ }
+
+ hr = SyncWithBuffer();
+ if ( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+
+Finished:
+
+ return hr;
+
+}
+
+HRESULT
+STRU::CopyA(
+ __in PCSTR pszCopyA
+)
+{
+ HRESULT hr;
+ size_t cbStr;
+
+ hr = StringCbLengthA( pszCopyA,
+ STRSAFE_MAX_CCH,
+ &cbStr );
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+
+ _ASSERTE( cbStr <= MAXDWORD );
+ return CopyA( pszCopyA,
+ cbStr );
+}
+
+HRESULT
+STRU::CopyA(
+ __in_bcount(cchLen)
+ PCSTR pszCopyA,
+ SIZE_T cchLen,
+ UINT CodePage /*= CP_UTF8*/
+)
+{
+ return AuxAppendA(
+ pszCopyA,
+ cchLen,
+ 0,
+ CodePage
+ );
+}
+
+HRESULT
+STRU::Append(
+ __in PCWSTR pszAppend
+)
+{
+ HRESULT hr;
+ size_t cbStr;
+
+ hr = StringCchLengthW( pszAppend,
+ STRSAFE_MAX_CCH,
+ &cbStr );
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+
+ _ASSERTE( cbStr <= MAXDWORD );
+ return Append( pszAppend,
+ cbStr );
+}
+
+HRESULT
+STRU::Append(
+ __in_ecount(cchLen)
+ PCWSTR pszAppend,
+ SIZE_T cchLen
+)
+//
+// Append something to the end of the string
+//
+{
+ if ( cchLen == 0 )
+ {
+ return S_OK;
+ }
+ return AuxAppend( pszAppend,
+ cchLen * sizeof(WCHAR),
+ QueryCB() );
+}
+
+HRESULT
+STRU::Append(
+ __in const STRU * pstrRhs
+)
+{
+ _ASSERTE( NULL != pstrRhs );
+ return Append( pstrRhs->QueryStr(), pstrRhs->QueryCCH() );
+}
+
+HRESULT
+STRU::Append(
+ __in const STRU & strRhs
+)
+{
+ return Append( strRhs.QueryStr(), strRhs.QueryCCH() );
+}
+
+HRESULT
+STRU::AppendA(
+ __in PCSTR pszAppendA
+)
+{
+ HRESULT hr;
+ size_t cbStr;
+
+ hr = StringCbLengthA( pszAppendA,
+ STRSAFE_MAX_CCH,
+ &cbStr );
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+
+ _ASSERTE( cbStr <= MAXDWORD );
+ return AppendA( pszAppendA,
+ cbStr );
+}
+
+HRESULT
+STRU::AppendA(
+ __in_bcount(cchLen)
+ PCSTR pszAppendA,
+ SIZE_T cchLen,
+ UINT CodePage /*= CP_UTF8*/
+)
+{
+ if ( cchLen == 0 )
+ {
+ return S_OK;
+ }
+ return AuxAppendA(
+ pszAppendA,
+ cchLen,
+ QueryCB(),
+ CodePage
+ );
+}
+
+HRESULT
+STRU::CopyToBuffer(
+ __out_bcount(*pcb) WCHAR* pszBuffer,
+ PDWORD pcb
+) const
+//
+// Makes a copy of the stored string into the given buffer
+//
+{
+ _ASSERTE( NULL != pszBuffer );
+ _ASSERTE( NULL != pcb );
+
+ HRESULT hr = S_OK;
+ DWORD cbNeeded = QueryCB() + sizeof( WCHAR );
+
+ if( *pcb < cbNeeded )
+ {
+ hr = HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER );
+ goto Finished;
+ }
+
+ //
+ // BUGBUG: StringCchCopy?
+ //
+ memcpy( pszBuffer, QueryStr(), cbNeeded );
+
+Finished:
+
+ *pcb = cbNeeded;
+
+ return hr;
+}
+
+HRESULT
+STRU::CopyToBufferA(
+ __out_bcount(*pcb) CHAR* pszBuffer,
+ __inout PDWORD pcb
+) const
+{
+ HRESULT hr = S_OK;
+ STACK_STRA( straBuffer, 256 );
+ hr = straBuffer.CopyW( QueryStr() );
+ if ( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+ hr = straBuffer.CopyToBuffer( pszBuffer, pcb );
+ if ( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+Finished:
+ return hr;
+}
+
+HRESULT
+STRU::SetLen(
+ __in DWORD cchLen
+)
+/*++
+ *
+Routine Description:
+
+ Set the length of the string and null terminate, if there
+ is sufficient buffer already allocated. Will not reallocate.
+
+Arguments:
+
+ cchLen - The number of characters in the new string.
+
+Return Value:
+
+ HRESULT
+
+--*/
+{
+ if( cchLen >= QuerySizeCCH() )
+ {
+ return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
+ }
+
+ *( QueryStr() + cchLen ) = L'\0';
+ m_cchLen = cchLen;
+
+ return S_OK;
+}
+
+HRESULT
+STRU::SafeSnwprintf(
+ __in PCWSTR pwszFormatString,
+ ...
+)
+/*++
+
+Routine Description:
+
+ Writes to a STRU, growing it as needed. It arbitrarily caps growth at 64k chars.
+
+Arguments:
+
+ pwszFormatString - printf format
+ ... - printf args
+
+Return Value:
+
+ HRESULT
+
+--*/
+{
+ HRESULT hr = S_OK;
+ va_list argsList;
+ va_start( argsList, pwszFormatString );
+
+ hr = SafeVsnwprintf(pwszFormatString, argsList);
+
+ va_end( argsList );
+ return hr;
+}
+
+HRESULT
+STRU::SafeVsnwprintf(
+ __in PCWSTR pwszFormatString,
+ va_list argsList
+)
+/*++
+
+Routine Description:
+
+ Writes to a STRU, growing it as needed. It arbitrarily caps growth at 64k chars.
+
+Arguments:
+
+ pwszFormatString - printf format
+ argsList - printf va_list
+
+Return Value:
+
+ HRESULT
+
+--*/
+{
+ HRESULT hr = S_OK;
+ int cchOutput;
+ int cchNeeded;
+
+ //
+ // Format the incoming message using vsnprintf()
+ // so that the overflows are captured
+ //
+ cchOutput = _vsnwprintf_s(
+ QueryStr(),
+ QuerySizeCCH(),
+ QuerySizeCCH() - 1,
+ pwszFormatString,
+ argsList
+ );
+
+ if( cchOutput == -1 )
+ {
+ //
+ // Couldn't fit this in the original STRU size.
+ //
+ cchNeeded = _vscwprintf( pwszFormatString, argsList );
+ if( cchNeeded > 64 * 1024 )
+ {
+ //
+ // If we're trying to produce a string > 64k chars, then
+ // there is probably a problem
+ //
+ hr = HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
+ goto Finished;
+ }
+
+ //
+ // _vscprintf doesn't include terminating null character
+ //
+ cchNeeded++;
+
+ hr = Resize( cchNeeded );
+ if( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+
+ cchOutput = _vsnwprintf_s(
+ QueryStr(),
+ QuerySizeCCH(),
+ QuerySizeCCH() - 1,
+ pwszFormatString,
+ argsList
+ );
+ if( -1 == cchOutput )
+ {
+ //
+ // This should never happen, cause we should already have correctly sized memory
+ //
+ _ASSERTE( FALSE );
+
+ hr = HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
+ goto Finished;
+ }
+ }
+
+ //
+ // always null terminate at the last WCHAR
+ //
+ QueryStr()[ QuerySizeCCH() - 1 ] = L'\0';
+
+ //
+ // we directly touched the buffer - therefore:
+ //
+ hr = SyncWithBuffer();
+ if ( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+
+Finished:
+
+ if( FAILED( hr ) )
+ {
+ Reset();
+ }
+
+ return hr;
+}
+
+HRESULT
+STRU::AuxAppend(
+ __in_ecount(cNumStrings)
+ PCWSTR const rgpszStrings[],
+ SIZE_T cNumStrings
+)
+/*++
+
+Routine Description:
+
+ Appends an array of strings of length cNumStrings
+
+Arguments:
+
+ rgStrings - The array of strings to be appened
+ cNumStrings - The count of String
+
+Return Value:
+
+ HRESULT
+
+--*/
+{
+ HRESULT hr = S_OK;
+ size_t cbStringsTotal = sizeof( WCHAR ); // Account for null-terminator
+
+ //
+ // Compute total size of the string.
+ // Resize internal buffer
+ // Copy each array element one by one to backing buffer
+ // Update backing buffer string length
+ //
+ for ( SIZE_T i = 0; i < cNumStrings; i++ )
+ {
+ _ASSERTE( rgpszStrings[ i ] != NULL );
+ if ( NULL == rgpszStrings[ i ] )
+ {
+ return E_INVALIDARG;
+ }
+
+ size_t cbString = 0;
+
+ hr = StringCbLengthW( rgpszStrings[ i ],
+ STRSAFE_MAX_CCH * sizeof( WCHAR ),
+ &cbString );
+ if ( FAILED( hr ) )
+ {
+ return hr;
+ }
+
+ cbStringsTotal += cbString;
+
+ if ( cbStringsTotal > MAXDWORD )
+ {
+ return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW );
+ }
+ }
+
+ size_t cbBufSizeRequired = QueryCB() + cbStringsTotal;
+ if ( cbBufSizeRequired > MAXDWORD )
+ {
+ return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW );
+ }
+
+ if( m_Buff.QuerySize() < cbBufSizeRequired )
+ {
+ if( !m_Buff.Resize( cbBufSizeRequired ) )
+ {
+ return E_OUTOFMEMORY;
+ }
+ }
+
+ STRSAFE_LPWSTR pszStringEnd = QueryStr() + QueryCCH();
+ size_t cchRemaining = QuerySizeCCH() - QueryCCH();
+ for ( SIZE_T i = 0; i < cNumStrings; i++ )
+ {
+ hr = StringCchCopyExW( pszStringEnd, // pszDest
+ cchRemaining, // cchDest
+ rgpszStrings[ i ], // pszSrc
+ &pszStringEnd, // ppszDestEnd
+ &cchRemaining, // pcchRemaining
+ 0 ); // dwFlags
+ if ( FAILED( hr ) )
+ {
+ _ASSERTE( FALSE );
+ HRESULT hr2 = SyncWithBuffer();
+ if ( FAILED( hr2 ) )
+ {
+ return hr2;
+ }
+ return hr;
+ }
+ }
+
+ m_cchLen = static_cast< DWORD >( cbBufSizeRequired ) / sizeof( WCHAR ) - 1;
+
+ return S_OK;
+}
+
+HRESULT
+STRU::AuxAppend(
+ __in_bcount(cbStr)
+ const WCHAR* pStr,
+ SIZE_T cbStr,
+ DWORD cbOffset
+)
+/*++
+
+Routine Description:
+
+ Appends to the string starting at the (byte) offset cbOffset.
+
+Arguments:
+
+ pStr - A unicode string to be appended
+ cbStr - Length, in bytes, of pStr
+ cbOffset - Offset, in bytes, at which to begin the append
+
+Return Value:
+
+ HRESULT
+
+--*/
+{
+ _ASSERTE( NULL != pStr );
+ _ASSERTE( 0 == cbStr % sizeof( WCHAR ) );
+ _ASSERTE( cbOffset <= QueryCB() );
+ _ASSERTE( 0 == cbOffset % sizeof( WCHAR ) );
+
+ ULONGLONG cb64NewSize = (ULONGLONG)cbOffset + cbStr + sizeof( WCHAR );
+ if( cb64NewSize > MAXDWORD )
+ {
+ return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW );
+ }
+
+ if( m_Buff.QuerySize() < cb64NewSize )
+ {
+ if( !m_Buff.Resize( static_cast(cb64NewSize) ) )
+ {
+ return E_OUTOFMEMORY;
+ }
+ }
+
+ memcpy( reinterpret_cast(m_Buff.QueryPtr()) + cbOffset, pStr, cbStr );
+
+ m_cchLen = (static_cast(cbStr) + cbOffset) / sizeof(WCHAR);
+
+ *( QueryStr() + m_cchLen ) = L'\0';
+
+ return S_OK;
+}
+
+HRESULT
+STRU::AuxAppendA(
+ __in_bcount(cbStr)
+ const CHAR* pStr,
+ SIZE_T cbStr,
+ DWORD cbOffset,
+ UINT CodePage
+)
+/*++
+
+Routine Description:
+
+ Convert and append an ANSI string to the string starting at
+ the (byte) offset cbOffset
+
+Arguments:
+
+ pStr - An ANSI string to be appended
+ cbStr - Length, in bytes, of pStr
+ cbOffset - Offset, in bytes, at which to begin the append
+ CodePage - code page to use for conversion
+
+Return Value:
+
+ HRESULT
+
+--*/
+{
+ WCHAR* pszBuffer;
+ DWORD cchBuffer;
+ DWORD cchCharsCopied = 0;
+
+ _ASSERTE( NULL != pStr );
+ _ASSERTE( cbOffset <= QueryCB() );
+ _ASSERTE( 0 == cbOffset % sizeof( WCHAR ) );
+
+ if ( NULL == pStr )
+ {
+ return E_INVALIDARG;
+ }
+
+ if( 0 == cbStr )
+ {
+ return S_OK;
+ }
+
+ //
+ // Only resize when we have to. When we do resize, we tack on
+ // some extra space to avoid extra reallocations.
+ //
+ if( m_Buff.QuerySize() < (ULONGLONG)cbOffset + (cbStr * sizeof( WCHAR )) + sizeof(WCHAR) )
+ {
+ ULONGLONG cb64NewSize = (ULONGLONG)( cbOffset + cbStr * sizeof(WCHAR) + sizeof( WCHAR ) );
+
+ //
+ // Check for the arithmetic overflow
+ //
+ if( cb64NewSize > MAXDWORD )
+ {
+ return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW );
+ }
+
+ if( !m_Buff.Resize( static_cast(cb64NewSize) ) )
+ {
+ return E_OUTOFMEMORY;
+ }
+ }
+
+ pszBuffer = reinterpret_cast(reinterpret_cast(m_Buff.QueryPtr()) + cbOffset);
+ cchBuffer = ( m_Buff.QuerySize() - cbOffset - sizeof( WCHAR ) ) / sizeof( WCHAR );
+
+ cchCharsCopied = MultiByteToWideChar(
+ CodePage,
+ MB_ERR_INVALID_CHARS,
+ pStr,
+ static_cast(cbStr),
+ pszBuffer,
+ cchBuffer
+ );
+ if( 0 == cchCharsCopied )
+ {
+ return HRESULT_FROM_WIN32( GetLastError() );
+ }
+
+ //
+ // set the new length
+ //
+ m_cchLen = cchCharsCopied + cbOffset/sizeof(WCHAR);
+
+ //
+ // Must be less than, cause still need to add NULL
+ //
+ _ASSERTE( m_cchLen < QuerySizeCCH() );
+
+ //
+ // append NULL character
+ //
+ *(QueryStr() + m_cchLen) = L'\0';
+
+ return S_OK;
+}
+
+
+/*++
+
+Routine Description:
+
+ Removes leading and trailing whitespace
+
+--*/
+
+VOID
+STRU::Trim()
+{
+ PWSTR pwszString = QueryStr();
+ DWORD cchNewLength = m_cchLen;
+ DWORD cchLeadingWhitespace = 0;
+ DWORD cchTempLength = 0;
+
+ for (LONG ixString = m_cchLen - 1; ixString >= 0; ixString--)
+ {
+ if (iswspace(pwszString[ixString]) != 0)
+ {
+ pwszString[ixString] = L'\0';
+ cchNewLength--;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ cchTempLength = cchNewLength;
+ for (DWORD ixString = 0; ixString < cchTempLength; ixString++)
+ {
+ if (iswspace(pwszString[ixString]) != 0)
+ {
+ cchLeadingWhitespace++;
+ cchNewLength--;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (cchNewLength == 0)
+ {
+
+ Reset();
+ }
+ else if (cchLeadingWhitespace > 0)
+ {
+ memmove(pwszString, pwszString + cchLeadingWhitespace, cchNewLength * sizeof(WCHAR));
+ pwszString[cchNewLength] = L'\0';
+ }
+
+ SyncWithBuffer();
+}
+
+/*++
+
+Routine Description:
+
+ Compares the string to the provided prefix to check for equality
+
+Arguments:
+
+ pwszPrefix - wide char string to compare with
+ fIgnoreCase - indicates whether the string comparison should be case-sensitive
+
+Return Value:
+
+ TRUE if prefix string matches with internal string, FALSE otherwise
+
+--*/
+
+BOOL
+STRU::StartsWith(
+ __in PCWSTR pwszPrefix,
+ __in bool fIgnoreCase) const
+{
+ HRESULT hr = S_OK;
+ BOOL fMatch = FALSE;
+ size_t cchPrefix = 0;
+
+ if (pwszPrefix == NULL)
+ {
+ goto Finished;
+ }
+
+ hr = StringCchLengthW( pwszPrefix,
+ STRSAFE_MAX_CCH,
+ &cchPrefix );
+ if (FAILED(hr))
+ {
+ goto Finished;
+ }
+
+ _ASSERTE( cchPrefix <= MAXLONG );
+
+ if (cchPrefix > m_cchLen)
+ {
+ goto Finished;
+ }
+
+ #if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN
+
+ fMatch = ( CSTR_EQUAL == CompareStringOrdinal( QueryStr(),
+ (int)cchPrefix,
+ pwszPrefix,
+ (int)cchPrefix,
+ fIgnoreCase ) );
+ #else
+
+ if( fIgnoreCase )
+ {
+ fMatch = ( 0 == _wcsnicmp( QueryStr(), pwszPrefix, cchPrefix ) );
+ }
+ else
+ {
+ fMatch = ( 0 == wcsncmp( QueryStr(), pwszPrefix, cchPrefix ) );
+ }
+
+ #endif
+
+Finished:
+
+ return fMatch;
+}
+
+/*++
+
+Routine Description:
+
+ Compares the string to the provided suffix to check for equality
+
+Arguments:
+
+ pwszSuffix - wide char string to compare with
+ fIgnoreCase - indicates whether the string comparison should be case-sensitive
+
+Return Value:
+
+ TRUE if suffix string matches with internal string, FALSE otherwise
+
+--*/
+
+
+BOOL
+STRU::EndsWith(
+ __in PCWSTR pwszSuffix,
+ __in bool fIgnoreCase) const
+{
+ HRESULT hr = S_OK;
+ PWSTR pwszString = QueryStr();
+ BOOL fMatch = FALSE;
+ size_t cchSuffix = 0;
+ ptrdiff_t ixOffset = 0;
+
+ if (pwszSuffix == NULL)
+ {
+ goto Finished;
+ }
+
+ hr = StringCchLengthW( pwszSuffix,
+ STRSAFE_MAX_CCH,
+ &cchSuffix );
+ if (FAILED(hr))
+ {
+ goto Finished;
+ }
+
+ _ASSERTE( cchSuffix <= MAXLONG );
+
+ if (cchSuffix > m_cchLen)
+ {
+ goto Finished;
+ }
+
+ ixOffset = m_cchLen - cchSuffix;
+ _ASSERTE(ixOffset >= 0 && ixOffset <= MAXDWORD);
+
+ #if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN
+
+ fMatch = ( CSTR_EQUAL == CompareStringOrdinal( pwszString + ixOffset,
+ (int)cchSuffix,
+ pwszSuffix,
+ (int)cchSuffix,
+ fIgnoreCase ) );
+ #else
+
+ if( fIgnoreCase )
+ {
+ fMatch = ( 0 == _wcsnicmp( pwszString + ixOffset, pwszSuffix, cchSuffix ) );
+ }
+ else
+ {
+ fMatch = ( 0 == wcsncmp( pwszString + ixOffset, pwszSuffix, cchSuffix ) );
+ }
+
+ #endif
+
+Finished:
+
+ return fMatch;
+}
+
+/*++
+
+Routine Description:
+
+ Searches the string for the first occurrence of the specified character.
+
+Arguments:
+
+ charValue - character to find
+ dwStartIndex - the initial index.
+
+Return Value:
+
+ The index for the first character occurence in the string.
+
+ -1 if not found.
+
+--*/
+INT
+STRU::IndexOf(
+ __in WCHAR charValue,
+ __in DWORD dwStartIndex
+ ) const
+{
+ INT nIndex = -1;
+
+ // Make sure that there are no buffer overruns.
+ if( dwStartIndex >= QueryCCH() )
+ {
+ goto Finished;
+ }
+
+ const WCHAR* pwChar = wcschr( QueryStr() + dwStartIndex, charValue );
+
+ // Determine the index if found
+ if( pwChar )
+ {
+ // nIndex will be set to -1 on failure.
+ (VOID)SizeTToInt( pwChar - QueryStr(), &nIndex );
+ }
+
+Finished:
+
+ return nIndex;
+}
+
+
+/*++
+
+Routine Description:
+
+ Searches the string for the first occurrence of the specified substring.
+
+Arguments:
+
+ pwszValue - substring to find
+ dwStartIndex - initial index.
+
+Return Value:
+
+ The index for the first character occurence in the string.
+
+ -1 if not found.
+
+--*/
+INT
+STRU::IndexOf(
+ __in PCWSTR pwszValue,
+ __in DWORD dwStartIndex
+ ) const
+{
+ HRESULT hr = S_OK;
+ INT nIndex = -1;
+ SIZE_T cchValue = 0;
+
+ // Validate input parameters
+ if( dwStartIndex >= QueryCCH() || !pwszValue )
+ {
+ goto Finished;
+ }
+
+ const WCHAR* pwChar = wcsstr( QueryStr() + dwStartIndex, pwszValue );
+
+ // Determine the index if found
+ if( pwChar )
+ {
+ // nIndex will be set to -1 on failure.
+ (VOID)SizeTToInt( pwChar - QueryStr(), &nIndex );
+ }
+
+Finished:
+
+ return nIndex;
+}
+
+
+/*++
+
+Routine Description:
+
+ Searches the string for the last occurrence of the specified character.
+
+Arguments:
+
+ charValue - character to find
+ dwStartIndex - initial index.
+
+Return Value:
+
+ The index for the last character occurence in the string.
+
+ -1 if not found.
+
+--*/
+INT
+STRU::LastIndexOf(
+ __in WCHAR charValue,
+ __in DWORD dwStartIndex
+ ) const
+{
+ INT nIndex = -1;
+
+ // Make sure that there are no buffer overruns.
+ if( dwStartIndex >= QueryCCH() )
+ {
+ goto Finished;
+ }
+
+ const WCHAR* pwChar = wcsrchr( QueryStr() + dwStartIndex, charValue );
+
+ // Determine the index if found
+ if( pwChar )
+ {
+ // nIndex will be set to -1 on failure.
+ (VOID)SizeTToInt( pwChar - QueryStr(), &nIndex );
+ }
+
+Finished:
+
+ return nIndex;
+}
+
+//static
+HRESULT
+STRU::ExpandEnvironmentVariables(
+ __in PCWSTR pszString,
+ __out STRU * pstrExpandedString
+ )
+/*++
+
+Routine Description:
+
+ Expand the environment variables in a string
+
+Arguments:
+
+ pszString - String with environment variables to expand
+ pstrExpandedString - Receives expanded string on success
+
+Return Value:
+
+ HRESULT
+
+--*/
+{
+ HRESULT hr = S_OK;
+ DWORD cchNewSize = 0;
+
+ if ( pszString == NULL ||
+ pstrExpandedString == NULL )
+ {
+ DBG_ASSERT( FALSE );
+ hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
+ goto Exit;
+ }
+
+ cchNewSize = ExpandEnvironmentStrings( pszString,
+ pstrExpandedString->QueryStr(),
+ pstrExpandedString->QuerySizeCCH() );
+ if ( cchNewSize == 0 )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ goto Exit;
+ }
+
+ if ( cchNewSize > pstrExpandedString->QuerySizeCCH() )
+ {
+ hr = pstrExpandedString->Resize(
+ ( cchNewSize + 1 ) * sizeof( WCHAR )
+ );
+ if ( FAILED( hr ) )
+ {
+ goto Exit;
+ }
+
+ cchNewSize = ExpandEnvironmentStrings(
+ pszString,
+ pstrExpandedString->QueryStr(),
+ pstrExpandedString->QuerySizeCCH()
+ );
+
+ if ( cchNewSize == 0 ||
+ cchNewSize > pstrExpandedString->QuerySizeCCH() )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ goto Exit;
+ }
+ }
+
+ pstrExpandedString->SyncWithBuffer();
+
+ hr = S_OK;
+
+Exit:
+
+ return hr;
+}
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ulparse.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ulparse.cxx
new file mode 100644
index 0000000000..69b42e6250
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ulparse.cxx
@@ -0,0 +1,1416 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+//
+// BUGBUG: Turn off optimization on ia64 builds due to a compiler bug
+//
+#if (defined(_M_IA64) && (_MSC_FULL_VER == 13009286))
+#pragma optimize("",off)
+#endif
+
+#define LF 0x0A
+#define SP 0x20
+#define HT 0x09
+
+#define HTTP_CHAR 0x001
+#define HTTP_UPCASE 0x002
+#define HTTP_LOCASE 0x004
+#define HTTP_ALPHA (HTTP_UPCASE | HTTP_LOCASE)
+#define HTTP_DIGIT 0x008
+#define HTTP_CTL 0x010
+#define HTTP_LWS 0x020
+#define HTTP_HEX 0x040
+#define HTTP_SEPERATOR 0x080
+#define HTTP_TOKEN 0x100
+
+#define URL_LEGAL 0x200
+#define URL_TOKEN (HTTP_ALPHA | HTTP_DIGIT | URL_LEGAL)
+
+#define IS_HTTP_UPCASE(c) (HttpChars[(UCHAR)(c)] & HTTP_UPCASE)
+#define IS_HTTP_LOCASE(c) (HttpChars[(UCHAR)(c)] & HTTP_UPCASE)
+#define IS_HTTP_ALPHA(c) (HttpChars[(UCHAR)(c)] & HTTP_ALPHA)
+#define IS_HTTP_DIGIT(c) (HttpChars[(UCHAR)(c)] & HTTP_DIGIT)
+#define IS_HTTP_HEX(c) (HttpChars[(UCHAR)(c)] & HTTP_HEX)
+#define IS_HTTP_CTL(c) (HttpChars[(UCHAR)(c)] & HTTP_CTL)
+#define IS_HTTP_LWS(c) (HttpChars[(UCHAR)(c)] & HTTP_LWS)
+#define IS_HTTP_SEPERATOR(c) (HttpChars[(UCHAR)(c)] & HTTP_SEPERATOR)
+#define IS_HTTP_TOKEN(c) (HttpChars[(UCHAR)(c)] & HTTP_TOKEN)
+#define IS_URL_TOKEN(c) (HttpChars[(UCHAR)(c)] & URL_TOKEN)
+
+// Some stuff not defined in VS SDK
+#ifndef NT_SUCCESS
+#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
+#endif
+
+// Copied from ntstatus.h, otherwise we will have double definition for
+// number of macros that are both in ntstatus.h and winnt.h
+#ifndef STATUS_SUCCESS
+#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) // ntsubauth
+#endif
+#ifndef STATUS_OBJECT_PATH_SYNTAX_BAD
+#define STATUS_OBJECT_PATH_SYNTAX_BAD ((NTSTATUS)0xC000003BL)
+#endif
+#ifndef STATUS_OBJECT_PATH_INVALID
+#define STATUS_OBJECT_PATH_INVALID ((NTSTATUS)0xC0000039L)
+#endif
+//
+// Constant Declarations for UTF8 Encoding
+//
+
+#define ASCII 0x007f
+
+#define UTF8_2_MAX 0x07ff // max UTF8 2-byte sequence (32 * 64 =2048)
+#define UTF8_1ST_OF_2 0xc0 // 110x xxxx
+#define UTF8_1ST_OF_3 0xe0 // 1110 xxxx
+#define UTF8_1ST_OF_4 0xf0 // 1111 xxxx
+#define UTF8_TRAIL 0x80 // 10xx xxxx
+
+#define HIGHER_6_BIT(u) ((u) >> 12)
+#define MIDDLE_6_BIT(u) (((u) & 0x0fc0) >> 6)
+#define LOWER_6_BIT(u) ((u) & 0x003f)
+
+#define BIT7(a) ((a) & 0x80)
+#define BIT6(a) ((a) & 0x40)
+
+#define HIGH_SURROGATE_START 0xd800
+#define HIGH_SURROGATE_END 0xdbff
+#define LOW_SURROGATE_START 0xdc00
+#define LOW_SURROGATE_END 0xdfff
+
+#define EMIT_CHAR(ch) \
+ do { \
+ pDest[0] = (ch); \
+ pDest += 1; \
+ BytesCopied += 2; \
+ } while (0)
+
+typedef enum _URL_TYPE
+{
+ UrlTypeUtf8,
+ UrlTypeAnsi,
+ UrlTypeDbcs
+} URL_TYPE;
+
+typedef enum _URL_PART
+{
+ Scheme,
+ HostName,
+ AbsPath,
+ QueryString
+
+} URL_PART;
+
+#define IS_UTF8_TRAILBYTE(ch) (((ch) & 0xc0) == 0x80)
+
+//
+// These are copied from RTL NLS routines.
+//
+
+#define DBCS_TABLE_SIZE 256
+extern PUSHORT NlsLeadByteInfo;
+
+#define LeadByteTable (*(PUSHORT *)NlsLeadByteInfo)
+#define IS_LEAD_BYTE(c) (IsDBCSLeadByte(c))
+
+ULONG HttpChars[256];
+USHORT FastPopChars[256];
+USHORT DummyPopChars[256];
+WCHAR FastUpcaseChars[256];
+BOOL g_UlEnableNonUTF8;
+BOOL g_UlEnableDBCS;
+BOOL g_UlFavorDBCS;
+
+// RtlNtStatusToDosError is nowhere defined, should be used through
+// native code "reflection"
+typedef ULONG (RTL_NT_STATUS_TO_DOS_ERROR_PROC)(NTSTATUS);
+static RTL_NT_STATUS_TO_DOS_ERROR_PROC* rtlNtStatusToDosErrorProc = NULL;
+static HMODULE lib = NULL;
+
+HRESULT
+WIN32_FROM_NTSTATUS(
+ __in NTSTATUS status,
+ __out DWORD * pResult
+ )
+{
+ HRESULT hr = S_OK;
+ if (pResult == NULL)
+ {
+ hr = E_INVALIDARG;
+ goto Finished;
+ }
+ if (lib == NULL)
+ {
+ lib = GetModuleHandle(L"Ntdll.dll");
+ if (lib == NULL)
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
+ goto Finished;
+ }
+ }
+ if (rtlNtStatusToDosErrorProc == NULL)
+ {
+ rtlNtStatusToDosErrorProc =
+ (RTL_NT_STATUS_TO_DOS_ERROR_PROC*)GetProcAddress(
+ lib, "RtlNtStatusToDosError");
+ if (rtlNtStatusToDosErrorProc == NULL)
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
+ goto Finished;
+ }
+ }
+ *pResult = rtlNtStatusToDosErrorProc(status);
+
+Finished:
+ return hr;
+}
+
+NTSTATUS
+Unescape(
+ IN PUCHAR pChar,
+ OUT PUCHAR pOutChar
+ )
+
+{
+ UCHAR Result, Digit;
+
+ if (pChar[0] != '%' ||
+ SAFEIsXDigit(pChar[1]) == FALSE ||
+ SAFEIsXDigit(pChar[2]) == FALSE)
+ {
+ return STATUS_OBJECT_PATH_SYNTAX_BAD;
+ }
+
+ //
+ // HexToChar() inlined
+ //
+
+ // uppercase #1
+ //
+ if (SAFEIsAlpha(pChar[1]))
+ Digit = (UCHAR) toupper(pChar[1]);
+ else
+ Digit = pChar[1];
+
+ Result = ((Digit >= 'A') ? (Digit - 'A' + 0xA) : (Digit - '0')) << 4;
+
+ // uppercase #2
+ //
+ if (SAFEIsAlpha(pChar[2]))
+ Digit = (UCHAR) toupper(pChar[2]);
+ else
+ Digit = pChar[2];
+
+ Result |= (Digit >= 'A') ? (Digit - 'A' + 0xA) : (Digit - '0');
+
+ *pOutChar = Result;
+
+ return STATUS_SUCCESS;
+
+} // Unescape
+
+//
+// PopChar is used only if the string is not UTF-8, or UrlPart != QueryString,
+// or the current character is '%' or its high bit is set. In all other cases,
+// the FastPopChars table is used for fast conversion.
+//
+
+__inline
+NTSTATUS
+PopChar(
+ IN URL_TYPE UrlType,
+ IN URL_PART UrlPart,
+ __in LPSTR pChar,
+ __out WCHAR * pUnicodeChar,
+ __out WCHAR * pUnicodeChar2,
+ OUT PULONG pCharToSkip
+ )
+{
+ NTSTATUS Status;
+ WCHAR UnicodeChar = L'\0';
+ WCHAR UnicodeChar2 = L'\0';
+ UCHAR Char;
+ UCHAR Trail1;
+ UCHAR Trail2;
+ UCHAR Trail3;
+ ULONG CharToSkip;
+
+ //
+ // validate it as a valid url character
+ //
+
+ if (UrlPart != QueryString)
+ {
+ if (IS_URL_TOKEN((UCHAR)pChar[0]) == FALSE)
+ {
+ Status = STATUS_OBJECT_PATH_SYNTAX_BAD;
+ goto end;
+ }
+ }
+ else
+ {
+ //
+ // Allow anything but linefeed in the query string.
+ //
+
+ if (pChar[0] == LF)
+ {
+ Status = STATUS_OBJECT_PATH_SYNTAX_BAD;
+ goto end;
+ }
+
+ UnicodeChar = (USHORT) (UCHAR)pChar[0];
+ CharToSkip = 1;
+
+ // skip all the decoding stuff
+ goto slash;
+ }
+
+ //
+ // need to unescape ?
+ //
+ // can't decode the query string. that would be lossy decodeing
+ // as '=' and '&' characters might be encoded, but have meaning
+ // to the usermode parser.
+ //
+
+ if (pChar[0] == '%')
+ {
+ Status = Unescape((PUCHAR)pChar, &Char);
+ if (NT_SUCCESS(Status) == FALSE)
+ goto end;
+ CharToSkip = 3;
+ }
+ else
+ {
+ Char = pChar[0];
+ CharToSkip = 1;
+ }
+
+ if (UrlType == UrlTypeUtf8)
+ {
+ //
+ // convert to unicode, checking for utf8 .
+ //
+ // 3 byte runs are the largest we can have. 16 bits in UCS-2 =
+ // 3 bytes of (4+4,2+6,2+6) where it's code + char.
+ // for a total of 6+6+4 char bits = 16 bits.
+ //
+
+ //
+ // NOTE: we'll only bother to decode utf if it was escaped
+ // thus the (CharToSkip == 3)
+ //
+ if ((CharToSkip == 3) && ((Char & 0xf8) == 0xf0))
+ {
+ // 4 byte run
+ //
+
+ // Unescape the next 3 trail bytes
+ //
+
+ Status = Unescape((PUCHAR)pChar+CharToSkip, &Trail1);
+ if (NT_SUCCESS(Status) == FALSE)
+ goto end;
+
+ CharToSkip += 3; // %xx
+
+ Status = Unescape((PUCHAR)pChar+CharToSkip, &Trail2);
+ if (NT_SUCCESS(Status) == FALSE)
+ goto end;
+
+ CharToSkip += 3; // %xx
+
+ Status = Unescape((PUCHAR)pChar+CharToSkip, &Trail3);
+ if (NT_SUCCESS(Status) == FALSE)
+ goto end;
+
+ CharToSkip += 3; // %xx
+
+ if (IS_UTF8_TRAILBYTE(Trail1) == FALSE ||
+ IS_UTF8_TRAILBYTE(Trail2) == FALSE ||
+ IS_UTF8_TRAILBYTE(Trail3) == FALSE)
+ {
+ // bad utf!
+ //
+ Status = STATUS_OBJECT_PATH_SYNTAX_BAD;
+ goto end;
+ }
+
+ // handle four byte case - convert to utf-16
+ // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+
+ UnicodeChar = ((USHORT) ((Char & 0x07) << 8) |
+ ((Trail1 & 0x3f) << 2) |
+ ((Trail2 & 0x30) >> 4)) + 0xD7C0;
+ UnicodeChar2 = ((USHORT) ((Trail2 & 0x0f) << 6) |
+ (Trail3 & 0x3f)) | 0xDC00;
+ }
+ else if ((CharToSkip == 3) && ((Char & 0xf0) == 0xe0))
+ {
+ // 3 byte run
+ //
+
+ // Unescape the next 2 trail bytes
+ //
+
+ Status = Unescape((PUCHAR)pChar+CharToSkip, &Trail1);
+ if (NT_SUCCESS(Status) == FALSE)
+ goto end;
+
+ CharToSkip += 3; // %xx
+
+ Status = Unescape((PUCHAR)pChar+CharToSkip, &Trail2);
+ if (NT_SUCCESS(Status) == FALSE)
+ goto end;
+
+ CharToSkip += 3; // %xx
+
+ if (IS_UTF8_TRAILBYTE(Trail1) == FALSE ||
+ IS_UTF8_TRAILBYTE(Trail2) == FALSE)
+ {
+ // bad utf!
+ //
+ Status = STATUS_OBJECT_PATH_SYNTAX_BAD;
+ goto end;
+ }
+
+ // handle three byte case
+ // 1110xxxx 10xxxxxx 10xxxxxx
+
+ UnicodeChar = (USHORT) (((Char & 0x0f) << 12) |
+ ((Trail1 & 0x3f) << 6) |
+ (Trail2 & 0x3f));
+
+ }
+ else if ((CharToSkip == 3) && ((Char & 0xe0) == 0xc0))
+ {
+ // 2 byte run
+ //
+
+ // Unescape the next 1 trail byte
+ //
+
+ Status = Unescape((PUCHAR)pChar+CharToSkip, &Trail1);
+ if (NT_SUCCESS(Status) == FALSE)
+ goto end;
+
+ CharToSkip += 3; // %xx
+
+ if (IS_UTF8_TRAILBYTE(Trail1) == FALSE)
+ {
+ // bad utf!
+ //
+ Status = STATUS_OBJECT_PATH_SYNTAX_BAD;
+ goto end;
+ }
+
+ // handle two byte case
+ // 110xxxxx 10xxxxxx
+
+ UnicodeChar = (USHORT) (((Char & 0x1f) << 6) |
+ (Trail1 & 0x3f));
+
+ }
+
+ // now this can either be unescaped high-bit (bad)
+ // or escaped high-bit. (also bad)
+ //
+ // thus not checking CharToSkip
+ //
+
+ else if ((Char & 0x80) == 0x80)
+ {
+ // high bit set ! bad utf!
+ //
+ Status = STATUS_OBJECT_PATH_SYNTAX_BAD;
+ goto end;
+
+ }
+ //
+ // Normal character (again either escaped or unescaped)
+ //
+ else
+ {
+ //
+ // Simple conversion to unicode, it's 7-bit ascii.
+ //
+
+ UnicodeChar = (USHORT)Char;
+ }
+
+ }
+ else // UrlType != UrlTypeUtf8
+ {
+ UCHAR AnsiChar[2];
+ ULONG AnsiCharSize;
+
+ //
+ // Convert ANSI character to Unicode.
+ // If the UrlType is UrlTypeDbcs, then we may have
+ // a DBCS lead/trail pair.
+ //
+
+ if (UrlType == UrlTypeDbcs && IS_LEAD_BYTE(Char))
+ {
+ UCHAR SecondByte;
+
+ //
+ // This is a double-byte character.
+ //
+
+ SecondByte = *(pChar+CharToSkip);
+
+ AnsiCharSize = 2;
+ AnsiChar[0] = Char;
+
+ if (SecondByte == '%')
+ {
+ Status = Unescape((PUCHAR)pChar+CharToSkip, &AnsiChar[1]);
+ if (!NT_SUCCESS(Status))
+ {
+ goto end;
+ }
+
+ CharToSkip += 3; // %xx
+ }
+ else
+ {
+ AnsiChar[1] = SecondByte;
+ CharToSkip += 1;
+ }
+
+ }
+ else
+ {
+ //
+ // This is a single-byte character.
+ //
+
+ AnsiCharSize = 1;
+ AnsiChar[0] = Char;
+
+ }
+ /*
+ Status = RtlMultiByteToUnicodeN(
+ &UnicodeChar,
+ sizeof(WCHAR),
+ NULL,
+ (PCHAR) &AnsiChar[0],
+ AnsiCharSize
+ );
+ */
+ Status = MultiByteToWideChar(
+ CP_ACP,
+ 0,
+ (PCHAR) &AnsiChar[0],
+ AnsiCharSize,
+ &UnicodeChar,
+ sizeof(WCHAR)
+ );
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto end;
+ }
+ }
+
+
+slash:
+ //
+ // turn backslashes into forward slashes
+ //
+
+ if (UrlPart != QueryString && UnicodeChar == L'\\')
+ {
+ UnicodeChar = L'/';
+ }
+ else if (UnicodeChar == UNICODE_NULL)
+ {
+ //
+ // we pop'd a NULL. bad!
+ //
+ Status = STATUS_OBJECT_PATH_SYNTAX_BAD;
+ goto end;
+ }
+
+ *pCharToSkip = CharToSkip;
+ *pUnicodeChar = UnicodeChar;
+ *pUnicodeChar2 = UnicodeChar2;
+
+ Status = STATUS_SUCCESS;
+
+end:
+ return Status;
+
+} // PopChar
+
+
+//
+// Private constants.
+//
+
+#define ACTION_NOTHING 0x00000000
+#define ACTION_EMIT_CH 0x00010000
+#define ACTION_EMIT_DOT_CH 0x00020000
+#define ACTION_EMIT_DOT_DOT_CH 0x00030000
+#define ACTION_BACKUP 0x00040000
+#define ACTION_MASK 0xFFFF0000
+
+//
+// Private globals
+//
+
+//
+// this table says what to do based on the current state and the current
+// character
+//
+ULONG pActionTable[16] =
+{
+ //
+ // state 0 = fresh, seen nothing exciting yet
+ //
+ ACTION_EMIT_CH, // other = emit it state = 0
+ ACTION_EMIT_CH, // "." = emit it state = 0
+ ACTION_NOTHING, // EOS = normal finish state = 4
+ ACTION_EMIT_CH, // "/" = we saw the "/", emit it state = 1
+
+ //
+ // state 1 = we saw a "/" !
+ //
+ ACTION_EMIT_CH, // other = emit it, state = 0
+ ACTION_NOTHING, // "." = eat it, state = 2
+ ACTION_NOTHING, // EOS = normal finish state = 4
+ ACTION_NOTHING, // "/" = extra slash, eat it, state = 1
+
+ //
+ // state 2 = we saw a "/" and ate a "." !
+ //
+ ACTION_EMIT_DOT_CH, // other = emit the dot we ate. state = 0
+ ACTION_NOTHING, // "." = eat it, a .. state = 3
+ ACTION_NOTHING, // EOS = normal finish state = 4
+ ACTION_NOTHING, // "/" = we ate a "/./", swallow it state = 1
+
+ //
+ // state 3 = we saw a "/" and ate a ".." !
+ //
+ ACTION_EMIT_DOT_DOT_CH, // other = emit the "..". state = 0
+ ACTION_EMIT_DOT_DOT_CH, // "." = 3 dots, emit the ".." state = 0
+ ACTION_BACKUP, // EOS = we have a "/..\0", backup! state = 4
+ ACTION_BACKUP // "/" = we have a "/../", backup! state = 1
+};
+
+//
+// this table says which newstate to be in given the current state and the
+// character we saw
+//
+ULONG pNextStateTable[16] =
+{
+ // state 0
+ 0 , // other
+ 0 , // "."
+ 4 , // EOS
+ 1 , // "\"
+
+ // state 1
+ 0 , // other
+ 2 , // "."
+ 4 , // EOS
+ 1 , // "\"
+
+ // state 2
+ 0 , // other
+ 3 , // "."
+ 4 , // EOS
+ 1 , // "\"
+
+ // state 3
+ 0 , // other
+ 0 , // "."
+ 4 , // EOS
+ 1 // "\"
+};
+
+//
+// this says how to index into pNextStateTable given our current state.
+//
+// since max states = 4, we calculate the index by multiplying with 4.
+//
+#define IndexFromState( st) ( (st) * 4)
+
+
+/***************************************************************************++
+
+Routine Description:
+
+ This function can be told to clean up UTF-8, ANSI, or DBCS URLs.
+
+ Unescape
+ Convert backslash to forward slash
+ Remove double slashes (empty directiories names) - e.g. // or \\
+ Handle /./
+ Handle /../
+ Convert to unicode
+ computes the case insensitive hash
+
+Arguments:
+
+
+Return Value:
+
+ NTSTATUS - Completion status.
+
+
+--***************************************************************************/
+NTSTATUS
+UlpCleanAndCopyUrlByType(
+ IN URL_TYPE UrlType,
+ IN URL_PART UrlPart,
+ __inout PWSTR pDestination,
+ __in_ecount(SourceLength) LPSTR pSource,
+ IN ULONG SourceLength,
+ OUT PULONG pBytesCopied,
+ __deref_opt_out_opt PWSTR * ppQueryString
+ )
+{
+ NTSTATUS Status;
+ PWSTR pDest;
+ PUCHAR pChar;
+ ULONG CharToSkip;
+ ULONG BytesCopied;
+ PWSTR pQueryString;
+ ULONG StateIndex;
+ WCHAR UnicodeChar;
+ WCHAR UnicodeChar2 = L'\0';
+ BOOLEAN MakeCanonical;
+ PUSHORT pFastPopChar;
+
+ pDest = pDestination;
+ pQueryString = NULL;
+ BytesCopied = 0;
+
+ pChar = (PUCHAR)pSource;
+ CharToSkip = 0;
+
+ StateIndex = 0;
+
+ MakeCanonical = (UrlPart == AbsPath) ? TRUE : FALSE;
+
+ if (UrlType == UrlTypeUtf8 && UrlPart != QueryString)
+ {
+ pFastPopChar = FastPopChars;
+ }
+ else
+ {
+ pFastPopChar = DummyPopChars;
+ }
+
+ while (SourceLength > 0)
+ {
+ //
+ // advance ! it's at the top of the loop to enable ANSI_NULL to
+ // come through ONCE
+ //
+
+ pChar += CharToSkip;
+ SourceLength -= CharToSkip;
+
+ //
+ // well? have we hit the end?
+ //
+
+ if (SourceLength == 0)
+ {
+ UnicodeChar = UNICODE_NULL;
+ UnicodeChar2 = UNICODE_NULL;
+ }
+ else
+ {
+ //
+ // Nope. Peek briefly to see if we hit the query string
+ //
+
+ if (UrlPart == AbsPath && pChar[0] == '?')
+ {
+ DBG_ASSERT(pQueryString == NULL);
+
+ //
+ // remember it's location
+ //
+
+ pQueryString = pDest;
+
+ //
+ // let it fall through ONCE to the canonical
+ // in order to handle a trailing "/.." like
+ // "http://hostname:80/a/b/..?v=1&v2"
+ //
+
+ UnicodeChar = L'?';
+ UnicodeChar2 = UNICODE_NULL;
+ CharToSkip = 1;
+
+ //
+ // now we are cleaning the query string
+ //
+
+ UrlPart = QueryString;
+
+ //
+ // cannot use fast path for PopChar anymore
+ //
+
+ pFastPopChar = DummyPopChars;
+ }
+ else
+ {
+ USHORT NextUnicodeChar = pFastPopChar[*pChar];
+
+ //
+ // Grab the next character. Try to be fast for the
+ // normal character case. Otherwise call PopChar.
+ //
+
+ if (NextUnicodeChar == 0)
+ {
+ Status = PopChar(
+ UrlType,
+ UrlPart,
+ (LPSTR)pChar,
+ &UnicodeChar,
+ &UnicodeChar2,
+ &CharToSkip
+ );
+
+ if (NT_SUCCESS(Status) == FALSE)
+ goto end;
+ }
+ else
+ {
+#if DBG
+ Status = PopChar(
+ UrlType,
+ UrlPart,
+ (LPSTR)pChar,
+ &UnicodeChar,
+ &UnicodeChar2,
+ &CharToSkip
+ );
+
+ DBG_ASSERT(NT_SUCCESS(Status));
+ DBG_ASSERT(UnicodeChar == NextUnicodeChar);
+ DBG_ASSERT(CharToSkip == 1);
+#endif
+ UnicodeChar = NextUnicodeChar;
+ UnicodeChar2 = UNICODE_NULL;
+ CharToSkip = 1;
+ }
+ }
+ }
+
+ if (MakeCanonical)
+ {
+ //
+ // now use the state machine to make it canonical .
+ //
+
+ //
+ // from the old value of StateIndex, figure out our new base StateIndex
+ //
+ StateIndex = IndexFromState(pNextStateTable[StateIndex]);
+
+ //
+ // did we just hit the query string? this will only happen once
+ // that we take this branch after hitting it, as we stop
+ // processing after hitting it.
+ //
+
+ if (UrlPart == QueryString)
+ {
+ //
+ // treat this just like we hit a NULL, EOS.
+ //
+
+ StateIndex += 2;
+ }
+ else
+ {
+ //
+ // otherwise based the new state off of the char we
+ // just popped.
+ //
+
+ switch (UnicodeChar)
+ {
+ case UNICODE_NULL: StateIndex += 2; break;
+ case L'.': StateIndex += 1; break;
+ case L'/': StateIndex += 3; break;
+ default: StateIndex += 0; break;
+ }
+ }
+
+ }
+ else
+ {
+ StateIndex = (UnicodeChar == UNICODE_NULL) ? 2 : 0;
+ }
+
+ //
+ // Perform the action associated with the state.
+ //
+
+ switch (pActionTable[StateIndex])
+ {
+ case ACTION_EMIT_DOT_DOT_CH:
+
+ EMIT_CHAR(L'.');
+
+ // fall through
+
+ case ACTION_EMIT_DOT_CH:
+
+ EMIT_CHAR(L'.');
+
+ // fall through
+
+ case ACTION_EMIT_CH:
+
+ EMIT_CHAR(UnicodeChar);
+ if (UnicodeChar2 != UNICODE_NULL)
+ {
+ EMIT_CHAR(UnicodeChar2);
+ }
+
+ // fall through
+
+ case ACTION_NOTHING:
+ break;
+
+ case ACTION_BACKUP:
+
+ //
+ // pDest currently points 1 past the last '/'. backup over it and
+ // find the preceding '/', set pDest to 1 past that one.
+ //
+
+ //
+ // backup to the '/'
+ //
+
+ pDest -= 1;
+ BytesCopied -= 2;
+
+ DBG_ASSERT(pDest[0] == L'/');
+
+ //
+ // are we at the start of the string? that's bad, can't go back!
+ //
+
+ if (pDest == pDestination)
+ {
+ DBG_ASSERT(BytesCopied == 0);
+ Status = STATUS_OBJECT_PATH_INVALID;
+ goto end;
+ }
+
+ //
+ // back up over the '/'
+ //
+
+ pDest -= 1;
+ BytesCopied -= 2;
+
+ DBG_ASSERT(pDest > pDestination);
+
+ //
+ // now find the previous slash
+ //
+
+ while (pDest > pDestination && pDest[0] != L'/')
+ {
+ pDest -= 1;
+ BytesCopied -= 2;
+ }
+
+ //
+ // we already have a slash, so don't have to store 1.
+ //
+
+ DBG_ASSERT(pDest[0] == L'/');
+
+ //
+ // simply skip it, as if we had emitted it just now
+ //
+
+ pDest += 1;
+ BytesCopied += 2;
+
+ break;
+
+ default:
+ DBG_ASSERT(!"http!UlpCleanAndCopyUrl: Invalid action code in state table!");
+ Status = STATUS_OBJECT_PATH_SYNTAX_BAD;
+ goto end;
+ }
+
+ //
+ // Just hit the query string ?
+ //
+
+ if (MakeCanonical && UrlPart == QueryString)
+ {
+ //
+ // Stop canonical processing
+ //
+
+ MakeCanonical = FALSE;
+
+ //
+ // Need to emit the '?', it wasn't emitted above
+ //
+
+ DBG_ASSERT(pActionTable[StateIndex] != ACTION_EMIT_CH);
+
+ EMIT_CHAR(L'?');
+
+ }
+
+ }
+
+ //
+ // terminate the string, it hasn't been done in the loop
+ //
+
+ DBG_ASSERT((pDest-1)[0] != UNICODE_NULL);
+
+ pDest[0] = UNICODE_NULL;
+ *pBytesCopied = BytesCopied;
+
+ if (ppQueryString != NULL)
+ {
+ *ppQueryString = pQueryString;
+ }
+
+ Status = STATUS_SUCCESS;
+
+
+end:
+ return Status;
+
+} // UlpCleanAndCopyUrlByType
+
+
+/***************************************************************************++
+
+Routine Description:
+
+
+ Unescape
+ Convert backslash to forward slash
+ Remove double slashes (empty directiories names) - e.g. // or \\
+ Handle /./
+ Handle /../
+ Convert to unicode
+
+Arguments:
+
+Return Value:
+
+ HRESULT
+
+
+--***************************************************************************/
+HRESULT
+UlCleanAndCopyUrl(
+ __in LPSTR pSource,
+ IN ULONG SourceLength,
+ OUT PULONG pBytesCopied,
+ __inout PWSTR pDestination,
+ __deref_opt_out_opt PWSTR * ppQueryString OPTIONAL
+ )
+{
+ NTSTATUS Status;
+ URL_TYPE AnsiUrlType = g_UlEnableDBCS ? UrlTypeDbcs : UrlTypeAnsi;
+
+ if (!g_UlEnableNonUTF8)
+ {
+ //
+ // Only accept UTF-8 URLs.
+ //
+
+ Status = UlpCleanAndCopyUrlByType(
+ UrlTypeUtf8,
+ AbsPath,
+ pDestination,
+ pSource,
+ SourceLength,
+ pBytesCopied,
+ ppQueryString
+ );
+
+ }
+ else if (!g_UlFavorDBCS)
+ {
+ //
+ // The URL may be either UTF-8 or ANSI. First
+ // try UTF-8, and if that fails go for ANSI.
+ //
+
+ Status = UlpCleanAndCopyUrlByType(
+ UrlTypeUtf8,
+ AbsPath,
+ pDestination,
+ pSource,
+ SourceLength,
+ pBytesCopied,
+ ppQueryString
+ );
+
+ if (!NT_SUCCESS(Status))
+ {
+ Status = UlpCleanAndCopyUrlByType(
+ AnsiUrlType,
+ AbsPath,
+ pDestination,
+ pSource,
+ SourceLength,
+ pBytesCopied,
+ ppQueryString
+ );
+
+ }
+
+ }
+ else
+ {
+ //
+ // The URL may be either ANSI or UTF-8. First
+ // try the ANSI interpretation, and if that fails
+ // go for UTF-8.
+ //
+ Status = UlpCleanAndCopyUrlByType(
+ AnsiUrlType,
+ AbsPath,
+ pDestination,
+ pSource,
+ SourceLength,
+ pBytesCopied,
+ ppQueryString
+ );
+
+ if (!NT_SUCCESS(Status))
+ {
+ Status = UlpCleanAndCopyUrlByType(
+ UrlTypeUtf8,
+ AbsPath,
+ pDestination,
+ pSource,
+ SourceLength,
+ pBytesCopied,
+ ppQueryString
+ );
+
+ }
+ }
+
+ //
+ // Convert NTSTATUS to HRESULT
+ //
+
+ if ( Status == STATUS_SUCCESS )
+ {
+ return S_OK;
+ }
+ else
+ {
+ DWORD dwErr = 0;
+ if (SUCCEEDED(WIN32_FROM_NTSTATUS( Status, &dwErr )))
+ {
+ return HRESULT_FROM_WIN32( dwErr );
+ }
+ else
+ {
+ return Status;
+ }
+ }
+}
+
+HRESULT
+UlInitializeParsing(
+ VOID
+)
+{
+ ULONG i;
+ UCHAR c;
+ HKEY hKey;
+ DWORD dwType;
+ DWORD dwData;
+ DWORD cbData;
+
+ //
+ // First read the HTTP registry settings on how to handle URLs
+ //
+
+ g_UlEnableNonUTF8 = TRUE;
+ g_UlEnableDBCS = FALSE;
+ g_UlFavorDBCS = FALSE;
+
+ if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ L"System\\CurrentControlSet\\Services\\http\\Parameters",
+ 0,
+ KEY_READ,
+ &hKey ) == ERROR_SUCCESS )
+ {
+ cbData = sizeof( dwData );
+
+ if ( RegQueryValueEx( hKey,
+ L"EnableNonUTF8",
+ NULL,
+ &dwType,
+ (LPBYTE) &dwData,
+ &cbData ) == ERROR_SUCCESS &&
+ dwType == REG_DWORD )
+ {
+ g_UlEnableNonUTF8 = !!dwData;
+ }
+
+ cbData = sizeof( dwData );
+
+ if ( g_UlEnableNonUTF8 )
+ {
+ if ( RegQueryValueEx( hKey,
+ L"EnableDBCS",
+ NULL,
+ &dwType,
+ (LPBYTE) &dwData,
+ &cbData ) == ERROR_SUCCESS &&
+ dwType == REG_DWORD )
+ {
+ g_UlEnableDBCS = !!dwData;
+ }
+ }
+ else
+ {
+ g_UlEnableDBCS = FALSE;
+ }
+
+ cbData = sizeof( dwData );
+
+ if ( g_UlEnableDBCS )
+ {
+ if ( RegQueryValueEx( hKey,
+ L"FavorDBCS",
+ NULL,
+ &dwType,
+ (LPBYTE) &dwData,
+ &cbData ) == ERROR_SUCCESS &&
+ dwType == REG_DWORD )
+ {
+ g_UlFavorDBCS = !!dwData;
+ }
+ }
+ else
+ {
+ g_UlFavorDBCS = FALSE;
+ }
+
+ RegCloseKey( hKey );
+ }
+
+
+ // Initialize the HttpChars array appropriately.
+
+ for (i = 0; i < 128; i++)
+ {
+ HttpChars[i] = HTTP_CHAR;
+ }
+
+ for (i = 'A'; i <= 'Z'; i++)
+ {
+ HttpChars[i] |= HTTP_UPCASE;
+ }
+
+ for (i = 'a'; i <= 'z'; i++)
+ {
+ HttpChars[i] |= HTTP_LOCASE;
+ }
+
+ for (i = '0'; i <= '9'; i++)
+ {
+ HttpChars[i] |= (HTTP_DIGIT | HTTP_HEX);
+ }
+
+
+ for (i = 0; i <= 31; i++)
+ {
+ HttpChars[i] |= HTTP_CTL;
+ }
+
+ HttpChars[127] |= HTTP_CTL;
+
+ HttpChars[SP] |= HTTP_LWS;
+ HttpChars[HT] |= HTTP_LWS;
+
+
+ for (i = 'A'; i <= 'F'; i++)
+ {
+ HttpChars[i] |= HTTP_HEX;
+ }
+
+ for (i = 'a'; i <= 'f'; i++)
+ {
+ HttpChars[i] |= HTTP_HEX;
+ }
+
+ HttpChars['('] |= HTTP_SEPERATOR;
+ HttpChars[')'] |= HTTP_SEPERATOR;
+ HttpChars['<'] |= HTTP_SEPERATOR;
+ HttpChars['>'] |= HTTP_SEPERATOR;
+ HttpChars['@'] |= HTTP_SEPERATOR;
+ HttpChars[','] |= HTTP_SEPERATOR;
+ HttpChars[';'] |= HTTP_SEPERATOR;
+ HttpChars[':'] |= HTTP_SEPERATOR;
+ HttpChars['\\'] |= HTTP_SEPERATOR;
+ HttpChars['"'] |= HTTP_SEPERATOR;
+ HttpChars['/'] |= HTTP_SEPERATOR;
+ HttpChars['['] |= HTTP_SEPERATOR;
+ HttpChars[']'] |= HTTP_SEPERATOR;
+ HttpChars['?'] |= HTTP_SEPERATOR;
+ HttpChars['='] |= HTTP_SEPERATOR;
+ HttpChars['{'] |= HTTP_SEPERATOR;
+ HttpChars['}'] |= HTTP_SEPERATOR;
+ HttpChars[SP] |= HTTP_SEPERATOR;
+ HttpChars[HT] |= HTTP_SEPERATOR;
+
+
+ //
+ // URL "reserved" characters (rfc2396)
+ //
+
+ HttpChars[';'] |= URL_LEGAL;
+ HttpChars['/'] |= URL_LEGAL;
+ HttpChars['\\'] |= URL_LEGAL;
+ HttpChars['?'] |= URL_LEGAL;
+ HttpChars[':'] |= URL_LEGAL;
+ HttpChars['@'] |= URL_LEGAL;
+ HttpChars['&'] |= URL_LEGAL;
+ HttpChars['='] |= URL_LEGAL;
+ HttpChars['+'] |= URL_LEGAL;
+ HttpChars['$'] |= URL_LEGAL;
+ HttpChars[','] |= URL_LEGAL;
+
+
+ //
+ // URL escape character
+ //
+
+ HttpChars['%'] |= URL_LEGAL;
+
+ //
+ // URL "mark" characters (rfc2396)
+ //
+
+ HttpChars['-'] |= URL_LEGAL;
+ HttpChars['_'] |= URL_LEGAL;
+ HttpChars['.'] |= URL_LEGAL;
+ HttpChars['!'] |= URL_LEGAL;
+ HttpChars['~'] |= URL_LEGAL;
+ HttpChars['*'] |= URL_LEGAL;
+ HttpChars['\''] |= URL_LEGAL;
+ HttpChars['('] |= URL_LEGAL;
+ HttpChars[')'] |= URL_LEGAL;
+
+
+ //
+ // RFC2396 describes these characters as `unwise' "because gateways and
+ // other transport agents are known to sometimes modify such characters,
+ // or they are used as delimiters". However, for compatibility with
+ // IIS 5.0 and DAV, we must allow these unwise characters in URLs.
+ //
+
+ HttpChars['{'] |= URL_LEGAL;
+ HttpChars['}'] |= URL_LEGAL;
+ HttpChars['|'] |= URL_LEGAL;
+ HttpChars['^'] |= URL_LEGAL;
+ HttpChars['['] |= URL_LEGAL;
+ HttpChars[']'] |= URL_LEGAL;
+ HttpChars['`'] |= URL_LEGAL;
+
+ //
+ // '#', '%', and '"' are not considered URL_LEGAL, according to the RFC.
+ // However, IIS 5.0 allowed them, so we should too.
+ //
+
+ HttpChars['#'] |= URL_LEGAL;
+ HttpChars['%'] |= URL_LEGAL;
+ HttpChars['"'] |= URL_LEGAL;
+
+ //
+ // In DBCS locales we need to explicitly accept lead bytes which
+ // we would normally reject.
+ //
+
+ if (0) // BUGBUG
+ {
+ for (i = 0; i < DBCS_TABLE_SIZE; i++)
+ {
+ if (IS_LEAD_BYTE((BYTE)i))
+ {
+ HttpChars[i] |= URL_LEGAL;
+ }
+ }
+ }
+
+ //
+ // These US-ASCII characters are "excluded"; i.e. not URL_LEGAL (see RFC):
+ // '<' | '>' | ' ' (0x20)
+ // In addition, control characters (0x00-0x1F and 0x7F) and
+ // non US-ASCII characters (0x80-0xFF) are not URL_LEGAL.
+ //
+
+ for (i = 0; i < 128; i++)
+ {
+ if (!IS_HTTP_SEPERATOR(i) && !IS_HTTP_CTL(i))
+ {
+ HttpChars[i] |= HTTP_TOKEN;
+ }
+ }
+
+
+ //
+ // Fast path for PopChar
+ //
+
+ RtlZeroMemory(FastPopChars, 256 * sizeof(USHORT));
+ RtlZeroMemory(DummyPopChars, 256 * sizeof(USHORT));
+
+ for (i = 0; i < 256; i++)
+ {
+ c = (UCHAR)i;
+
+ if (IS_URL_TOKEN(c) && c != '%' && (c & 0x80) != 0x80)
+ {
+ FastPopChars[i] = (USHORT)c;
+ }
+ }
+
+ //
+ // Turn backslashes into forward slashes
+ //
+
+ FastPopChars['\\'] = L'/';
+
+
+ //
+ // Fast path for UpcaseUnicodeChar
+ //
+
+ for (i = 0; i < 256; i++)
+ {
+ FastUpcaseChars[i] = towupper((WCHAR)i);
+ }
+
+
+ return S_OK;
+}
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/util.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/util.cxx
new file mode 100644
index 0000000000..22c31a0ed2
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/util.cxx
@@ -0,0 +1,74 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+HRESULT
+MakePathCanonicalizationProof(
+ IN PCWSTR pszName,
+ OUT STRU * pstrPath
+)
+/*++
+
+Routine Description:
+
+ This functions adds a prefix
+ to the string, which is "\\?\UNC\" for a UNC path, and "\\?\" for
+ other paths. This prefix tells Windows not to parse the path.
+
+Arguments:
+
+ IN pszName - The path to be converted
+ OUT pstrPath - Output path created
+
+Return Values:
+
+ HRESULT
+
+--*/
+{
+ HRESULT hr;
+
+ if (pszName[0] == L'\\' && pszName[1] == L'\\')
+ {
+ //
+ // If the path is already canonicalized, just return
+ //
+
+ if ((pszName[2] == '?' || pszName[2] == '.') &&
+ pszName[3] == '\\')
+ {
+ hr = pstrPath->Copy(pszName);
+
+ if (SUCCEEDED(hr))
+ {
+ //
+ // If the path was in DOS form ("\\.\"),
+ // we need to change it to Win32 from ("\\?\")
+ //
+
+ pstrPath->QueryStr()[2] = L'?';
+ }
+
+ return hr;
+ }
+
+ pszName += 2;
+
+
+ if (FAILED(hr = pstrPath->Copy(L"\\\\?\\UNC\\")))
+ {
+ return hr;
+ }
+ }
+ else
+ {
+ if (FAILED(hr = pstrPath->Copy(L"\\\\?\\")))
+ {
+ return hr;
+ }
+ }
+
+ return pstrPath->Append(pszName);
+}
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stbuff.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stbuff.h
new file mode 100644
index 0000000000..04e13789f0
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stbuff.h
@@ -0,0 +1,1013 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef _STBUFF_H
+#define _STBUFF_H
+
+#include
+#include
+
+#define STB_INLINE_SIZE 64
+#define STB_MAX_ALLOC 16*1024
+
+#define TO_UPPER(ch) (isupper(ch) ? ch : toupper(ch))
+
+class STBUFF
+{
+public:
+
+ STBUFF(
+ BOOL fZeroInit = TRUE
+ ) : _pData( _Inline ),
+ _cbData( 0 ),
+ _cbBuffer( STB_INLINE_SIZE ),
+ _cbMaxAlloc( STB_MAX_ALLOC )
+ {
+ if ( fZeroInit )
+ {
+ ZeroInit();
+ }
+
+ _Inline[STB_INLINE_SIZE] = 0;
+ _Inline[STB_INLINE_SIZE+1] = 0;
+ }
+
+ virtual
+ ~STBUFF()
+ {
+ Reset( TRUE );
+ }
+
+ VOID
+ Reset(
+ BOOL fFreeAlloc = FALSE
+ )
+ {
+ //
+ // If we are supposed to free any heap
+ // allocations, do so now.
+ //
+
+ if ( fFreeAlloc &&
+ _pData != _Inline )
+ {
+ LocalFree( _pData );
+ _pData = _Inline;
+ _cbBuffer = STB_INLINE_SIZE;
+ }
+
+ //
+ // Reset the data size
+ //
+
+ _cbData = 0;
+ }
+
+ HRESULT
+ Resize(
+ DWORD cbSize
+ )
+ {
+ HRESULT hr = S_OK;
+ BYTE * pTemp;
+
+ //
+ // If the buffer is large enough, just return
+ //
+
+ if ( cbSize < _cbBuffer )
+ {
+ goto Finished;
+ }
+
+ //
+ // If the requested size exceeds our maximum
+ // allocation, then fail this call.
+ //
+
+ if ( cbSize > _cbMaxAlloc )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Finished;
+ }
+
+ //
+ // Adjust the allocation size so that we allocate
+ // in chunks of MINITOOLS_INLINE_SIZE. Don't
+ // exeed _cbMaxAlloc.
+ //
+
+ if ( cbSize % STB_INLINE_SIZE )
+ {
+ cbSize = ( cbSize / STB_INLINE_SIZE + 1 ) *
+ STB_INLINE_SIZE;
+ }
+
+ if ( cbSize > _cbMaxAlloc )
+ {
+ cbSize = _cbMaxAlloc;
+ }
+
+ //
+ // Allocate the new storage and copy any existing
+ // data into it.
+ //
+ // Allocate two extra bytes so that we can guarantee
+ // NULL termination when someone queries the data
+ // pointer as a string.
+ //
+
+ pTemp = (BYTE*)LocalAlloc( LPTR, cbSize + 2 );
+
+ if ( !pTemp )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Finished;
+ }
+
+ if ( _cbData )
+ {
+ CopyMemory( pTemp, _pData, _cbData );
+ }
+
+ //
+ // If the original buffer is not the inline
+ // storage, then free it.
+ //
+
+ if ( _pData != _Inline )
+ {
+ LocalFree( _pData );
+ }
+
+ //
+ // Save the new storage pointer
+ //
+
+ _pData = pTemp;
+ _cbBuffer = cbSize;
+
+ //
+ // Set the extra two bytes as 0
+ //
+
+ _pData[_cbBuffer] = 0;
+ _pData[_cbBuffer+1] = 0;
+
+Finished:
+ return hr;
+ }
+
+ HRESULT
+ AppendData(
+ VOID * pData,
+ DWORD cbData,
+ DWORD Offset = 0xffffffff
+ )
+ {
+ DWORD cbNeeded;
+ HRESULT hr = S_OK;
+
+ //
+ // Resize the buffer if necessary
+ //
+
+ cbNeeded = Offset + cbData;
+
+ hr = Resize( cbNeeded );
+
+ if ( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+
+ //
+ // Copy the new data
+ //
+
+ if ( cbData )
+ {
+ CopyMemory( _pData + Offset, pData, cbData );
+ }
+
+ _cbData = cbNeeded;
+
+ //
+ // NULL terminate the data
+ //
+
+ GuaranteeNullTermination();
+
+Finished:
+
+ return hr;
+ }
+
+
+ HRESULT
+ AppendData(
+ LPCSTR szData,
+ DWORD cchData = 0xffffffff,
+ DWORD Offset = 0xffffffff
+ )
+ {
+ //
+ // If cchData is 0xffffffff, then calculate size
+ //
+
+ if ( cchData == 0xffffffff )
+ {
+ cchData = (DWORD)strlen( szData );
+ }
+
+ //
+ // If offset is 0xffffffff, then assume
+ // that we are appending to the end of the
+ // string.
+ //
+
+ if ( Offset == 0xffffffff )
+ {
+ Offset = _cbData;
+ }
+
+ return AppendData( (VOID*)szData,
+ cchData,
+ Offset );
+ }
+
+ HRESULT
+ AppendData(
+ LPCWSTR szData,
+ DWORD cchData = 0xffffffff,
+ DWORD cchOffset = 0xffffffff
+ )
+ {
+ DWORD cbData;
+ DWORD cbOffset;
+ //
+ // If cchData is 0xffffffff, then calculate size
+ //
+
+ if ( cchData == 0xffffffff )
+ {
+ cchData = (DWORD)wcslen( szData );
+ }
+
+ cbData = cchData * sizeof(WCHAR);
+
+ //
+ // If offset is 0xffffffff, then assume
+ // that we are appending to the end of the
+ // string.
+ //
+
+ if ( cchOffset == 0xffffffff )
+ {
+ cchOffset = _cbData;
+ }
+
+ cbOffset = cchOffset * sizeof(WCHAR);
+
+ return AppendData( (VOID*)szData,
+ cbData,
+ cbOffset );
+ }
+
+ HRESULT
+ AppendData(
+ STBUFF *pbuff
+ )
+ {
+ return AppendData( pbuff->QueryPtr(),
+ pbuff->QueryDataSize() );
+ }
+
+ HRESULT
+ SetData(
+ VOID * pData,
+ DWORD cbData
+ )
+ {
+ //
+ // Set data is just an append to offset zero
+ //
+
+ return AppendData( pData,
+ cbData,
+ 0 );
+ }
+
+ HRESULT
+ SetData(
+ LPCSTR pData,
+ DWORD cchData = 0xffffffff
+ )
+ {
+ //
+ // If cbData is 0xffffffff, then assume that
+ // pData is a NULL terminated string.
+ //
+
+ if ( cchData == 0xffffffff )
+ {
+ cchData = (DWORD)strlen( (LPSTR)pData );
+ }
+
+ return SetData( (VOID*)pData, cchData );
+ }
+
+ HRESULT
+ SetData(
+ LPCWSTR pData,
+ DWORD cchData = 0xffffffff
+ )
+ {
+ //
+ // If cbData is 0xffffffff, then assume that
+ // pData is a NULL terminated string.
+ //
+
+ if ( cchData == 0xffffffff )
+ {
+ cchData = (DWORD)wcslen( (LPWSTR)pData );
+ }
+
+ return SetData( (VOID*)pData, cchData * sizeof(WCHAR) );
+ }
+
+
+ HRESULT
+ SetData(
+ STBUFF *pbuff
+ )
+ {
+ return AppendData( pbuff->QueryPtr(),
+ pbuff->QueryDataSize(),
+ 0 );
+ }
+
+ HRESULT
+ AnsiToUnicode(
+ LPCSTR szString,
+ UINT codepage = CP_UTF8
+ )
+ {
+ DWORD cchString = (DWORD)strlen( szString );
+ HRESULT hr = S_OK;
+
+ hr = Resize( cchString * sizeof(WCHAR) );
+
+ if ( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+
+ if ( !MultiByteToWideChar( codepage,
+ MB_ERR_INVALID_CHARS,
+ szString,
+ cchString,
+ (LPWSTR)_pData,
+ cchString ) )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ goto Finished;
+ }
+
+ _cbData = cchString * sizeof(WCHAR);
+
+Finished:
+
+ return hr;
+ }
+
+ HRESULT
+ UnicodeToAnsi(
+ LPCWSTR szStringW,
+ UINT codepage = CP_UTF8
+ )
+ {
+ DWORD cchString = (DWORD)wcslen( szStringW );
+ HRESULT hr = S_OK;
+
+ hr = Resize( cchString );
+
+ if ( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+
+ if ( !WideCharToMultiByte( codepage,
+ 0,
+ szStringW,
+ cchString,
+ (LPSTR)_pData,
+ cchString,
+ NULL,
+ NULL ) )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ goto Finished;
+ }
+
+ _cbData = cchString;
+
+Finished:
+
+ return hr;
+ }
+
+ HRESULT
+ ExpandEnvironmentStrings(
+ VOID
+ )
+ {
+ STBUFF Temp;
+ DWORD cbNeeded;
+ HRESULT hr = S_OK;
+
+ cbNeeded = ::ExpandEnvironmentStringsA( QueryStr(),
+ Temp.QueryStr(),
+ Temp.QueryBufferSize() );
+
+ if ( cbNeeded > Temp.QueryBufferSize() )
+ {
+ hr = Temp.Resize ( cbNeeded );
+ if ( FAILED (hr) )
+ {
+ goto Finished;
+ }
+
+ cbNeeded = ::ExpandEnvironmentStringsA( QueryStr(),
+ Temp.QueryStr(),
+ Temp.QueryBufferSize() );
+
+ }
+
+ Temp.CalcDataSize();
+
+ hr = SetData( &Temp );
+ if ( FAILED (hr) )
+ {
+ goto Finished;
+ }
+
+ Finished:
+
+ return hr;
+ }
+
+ HRESULT
+ Vsprintf(
+ LPCSTR szFormat,
+ va_list args
+ )
+ {
+ DWORD cchWritten;
+ HRESULT hr = S_OK;
+
+ DWORD cbNeeded = _vscprintf( szFormat, args );
+
+ hr = Resize( cbNeeded + 1 );
+
+ if ( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+
+ cchWritten = _vsnprintf_s( QueryStr(),
+ QueryBufferSize(),
+ QueryBufferSize(),
+ szFormat,
+ args );
+
+ _cbData = cchWritten;
+
+Finished:
+
+ return hr;
+ }
+
+ HRESULT
+ Vsprintf(
+ LPCWSTR szFormat,
+ va_list args
+ )
+ {
+ DWORD cchWritten;
+ HRESULT hr = S_OK;
+
+ DWORD cbNeeded = _vscwprintf( szFormat, args ) * sizeof(WCHAR);
+
+ hr = Resize( cbNeeded + 1 );
+
+ if ( FAILED( hr ) )
+ {
+ goto Finished;
+ }
+
+ cchWritten = _vsnwprintf_s( QueryStrW(),
+ QueryBufferSize() / sizeof(WCHAR),
+ _TRUNCATE,
+ szFormat,
+ args );
+
+ _cbData = cchWritten * sizeof(WCHAR);
+
+Finished:
+
+ return hr;
+ }
+
+ HRESULT
+ Printf(
+ LPCSTR szFormat,
+ ...
+ )
+ {
+ HRESULT hr;
+
+ //
+ // Let Vsprintf do the work
+ //
+
+ va_list args;
+
+ va_start( args, szFormat );
+
+ hr = Vsprintf( szFormat,
+ args );
+
+ va_end( args );
+
+ return hr;
+ }
+
+ HRESULT
+ Printf(
+ LPCWSTR szFormat,
+ ...
+ )
+ {
+ HRESULT hr;
+
+ //
+ // Let Vsprintf do the work
+ //
+
+ va_list args;
+
+ va_start( args, szFormat );
+
+ hr = Vsprintf( szFormat,
+ args );
+
+ va_end( args );
+
+ return hr;
+ }
+
+ VOID *
+ QueryPtr()
+ {
+ return (VOID*)_pData;
+ }
+
+ LPSTR
+ QueryStr()
+ {
+ GuaranteeNullTermination();
+
+ return (LPSTR)_pData;
+ }
+
+ LPWSTR
+ QueryStrW()
+ {
+ GuaranteeNullTermination();
+
+ return (LPWSTR)_pData;
+ }
+
+ DWORD
+ QueryDataSize()
+ {
+ return _cbData;
+ }
+
+ HRESULT
+ SetDataSize(
+ DWORD cbData
+ )
+ {
+ HRESULT hr = S_OK;
+
+ if ( cbData > _cbBuffer )
+ {
+ hr = HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER );
+ goto Finished;
+ }
+
+ _cbData = cbData;
+
+ Finished:
+ return hr;
+ }
+
+ VOID
+ CalcDataSize()
+ {
+ _cbData = (DWORD)strlen( (LPSTR)_pData );
+ }
+
+ VOID
+ CalcDataSizeW()
+ {
+ _cbData = (DWORD)wcslen( (LPWSTR)_pData );
+ }
+
+ DWORD
+ QueryBufferSize()
+ {
+ return _cbBuffer;
+ }
+
+ DWORD
+ QueryMaxAlloc()
+ {
+ return _cbMaxAlloc;
+ }
+
+ VOID
+ SetMaxAlloc(
+ DWORD cbMaxAlloc
+ )
+ {
+ _cbMaxAlloc = cbMaxAlloc;
+ }
+
+ VOID
+ ZeroInit(
+ VOID
+ )
+ {
+ FillMemory( _Inline, STB_INLINE_SIZE, 0x00 );
+
+ if ( _pData != _Inline )
+ {
+ FillMemory( _pData, _cbBuffer, 0x00 );
+ }
+ }
+
+ HRESULT
+ Escape(
+ BOOL fAllowDoubleEscaping = FALSE
+ )
+ {
+ STBUFF Temp;
+ DWORD dwNumEscapes = 0;
+ CHAR szHex[3] = {0};
+ BYTE * pRead;
+ BYTE * pWrite;
+ HRESULT hr = S_OK;
+
+ //
+ // Walk through the string once. If there
+ // are no escapes, then we can just return.
+ //
+
+ GuaranteeNullTermination();
+
+ pRead = (BYTE*)_pData;
+
+ while ( *pRead != '\0' )
+ {
+ if ( ( fAllowDoubleEscaping ||
+ !IsEscapeSequence( (CHAR*)pRead ) ) &&
+ ShouldEscape( *pRead ) )
+ {
+ dwNumEscapes++;
+ }
+
+ pRead++;
+ }
+
+ if ( dwNumEscapes == 0 )
+ {
+ goto Finished;
+ }
+
+ //
+ // Make sure that our cooked string buffer is big enough, so
+ // we can manipulate its pointer directly.
+ //
+
+ hr = Temp.Resize( _cbData + dwNumEscapes * 2 );
+ if ( FAILED (hr) )
+ {
+ goto Finished;
+ }
+
+ pRead = (BYTE*)_pData;
+ pWrite = (BYTE*)Temp.QueryStr();
+
+ while ( *pRead != '\0' )
+ {
+ if ( ( fAllowDoubleEscaping ||
+ !IsEscapeSequence( (CHAR*)pRead ) ) &&
+ ShouldEscape( *pRead ) )
+ {
+ _snprintf_s( szHex, 3, 2, "%02x", *pRead );
+
+ *pWrite = '%';
+ *(pWrite+1) = szHex[0];
+ *(pWrite+2) = szHex[1];
+
+ pRead++;
+ pWrite += 3;
+
+ continue;
+ }
+
+ *pWrite = *pRead;
+
+ pRead++;
+ pWrite++;
+ }
+
+ *pWrite = '\0';
+
+ Temp.CalcDataSize();
+
+ hr = SetData( Temp.QueryStr() );
+ if ( FAILED (hr) )
+ {
+ goto Finished;
+ }
+
+ Finished:
+
+ return hr;
+ }
+
+ VOID
+ Unescape(
+ VOID
+ )
+ {
+ CHAR * pRead;
+ CHAR * pWrite;
+ CHAR szHex[3] = {0};
+ BYTE c;
+
+ pRead = (CHAR*)_pData;
+ pWrite = pRead;
+
+ while ( *pRead )
+ {
+ if ( IsEscapeSequence( pRead ) )
+ {
+ szHex[0] = *(pRead+1);
+ szHex[1] = *(pRead+2);
+
+ c = (BYTE)strtoul( szHex, NULL, 16 );
+
+ *pWrite = c;
+
+ pRead += 3;
+ pWrite++;
+
+ continue;
+ }
+
+ *pWrite = *pRead;
+
+ pRead++;
+ pWrite++;
+ }
+
+ *pWrite = '\0';
+
+ CalcDataSize();
+
+ return;
+ }
+
+ VOID
+ MoveToFront(
+ DWORD cbOffset
+ )
+ {
+ if ( cbOffset >= _cbData )
+ {
+ Reset();
+
+ return;
+ }
+
+ MoveMemory( _pData, _pData + cbOffset, _cbData - cbOffset );
+
+ _cbData -= cbOffset;
+ }
+
+ BOOL
+ IsWildcardMatch(
+ LPCSTR szExpr
+ )
+ {
+ LPCSTR pExpr = szExpr;
+ LPCSTR pString = QueryStr();
+ LPCSTR pSubMatch;
+ DWORD cchSubMatch;
+
+ if ( !pExpr )
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+
+ while ( *pExpr )
+ {
+ switch ( *pExpr )
+ {
+ case '*':
+
+ //
+ // Eat '*' characters
+ //
+
+ while ( *pExpr == '*' )
+ {
+ pExpr++;
+ }
+
+ //
+ // Find the next wildcard
+ //
+
+ pSubMatch = strchr( pExpr, '*' );
+
+ cchSubMatch = (DWORD)(pSubMatch ?
+ pSubMatch - pExpr :
+ strlen( pExpr ));
+
+ if ( cchSubMatch == 0 )
+ {
+ //
+ // No submatch. The rest of
+ // pString automatically matches
+ //
+
+ return TRUE;
+ }
+
+ //
+ // Ensure that the current submatch exists
+ //
+
+ while ( _strnicmp( pString, pExpr, cchSubMatch ) )
+ {
+ pString++;
+
+ if ( *pString == '\0' )
+ {
+ //
+ // Not found
+ //
+
+ return FALSE;
+ }
+ }
+
+ pExpr += cchSubMatch;
+ pString += cchSubMatch;
+
+ break;
+
+ default:
+
+ if ( TO_UPPER( *pExpr ) != TO_UPPER( *pString ) )
+ {
+ return FALSE;
+ }
+
+ pExpr++;
+ pString++;
+ }
+ }
+
+ if ( *pString != '\0' )
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+private:
+
+ LPBYTE _pData;
+ DWORD _cbData;
+ DWORD _cbBuffer;
+ DWORD _cbMaxAlloc;
+ BYTE _Inline[STB_INLINE_SIZE+2];
+
+ VOID
+ GuaranteeNullTermination()
+ {
+ _pData[_cbData] = 0;
+ _pData[_cbData+1] = 0;
+ }
+
+ BOOL
+ IsEscapeSequence(
+ CHAR * str
+ )
+ {
+ if ( *str == '%' &&
+ isxdigit( *(str+1) ) &&
+ isxdigit( *(str+2) ) )
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ BOOL
+ ShouldEscape(
+ BYTE c
+ )
+ {
+ //
+ // If the character is listed in RFC2396, section
+ // 2.4.3 as control, space, delims or unwise, we
+ // should escape it. Also, we should escape characters
+ // with the high bit set.
+ //
+
+ if ( c <= 0x1f ||
+ c == 0x7f )
+ {
+ //
+ // Control character
+ //
+
+ goto ReturnTrue;
+ }
+
+ if ( c >= 0x80 )
+ {
+ //
+ // High bit set
+ //
+
+ goto ReturnTrue;
+ }
+
+ switch ( c )
+ {
+
+ //
+ // space
+ //
+ case ' ':
+
+ //
+ // delims
+ //
+ case '<':
+ case '>':
+ case '#':
+ case '%':
+ case '\"':
+
+ //
+ // unwise
+ //
+ case '{':
+ case '}':
+ case '|':
+ case '\\':
+ case '^':
+ case '[':
+ case ']':
+ case '`':
+
+ goto ReturnTrue;
+ }
+
+ //
+ // If we get here, then the character should not be
+ // escaped
+ //
+
+ return FALSE;
+
+ ReturnTrue:
+
+ return TRUE;
+ }
+};
+
+#endif // _STBUFF_H
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlist.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlist.h
new file mode 100644
index 0000000000..916c8576a8
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlist.h
@@ -0,0 +1,87 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef _STLIST_H
+#define _STLIST_H
+
+#ifndef IsListEmpty
+
+#include
+
+#define IsListEmpty(ListHead) ((ListHead)->Flink == (ListHead))
+
+VOID
+inline
+InitializeListHead(
+ LIST_ENTRY * ListHead
+ )
+{
+ ListHead->Flink = ListHead->Blink = ListHead;
+}
+
+BOOL
+inline
+RemoveEntryList(
+ LIST_ENTRY * Entry
+ )
+{
+ LIST_ENTRY * Blink;
+ LIST_ENTRY * Flink;
+
+ Flink = Entry->Flink;
+ Blink = Entry->Blink;
+ Blink->Flink = Flink;
+ Flink->Blink = Blink;
+ return (Flink == Blink);
+}
+
+PLIST_ENTRY
+inline
+RemoveHeadList(
+ LIST_ENTRY * ListHead
+ )
+{
+ LIST_ENTRY * Flink;
+ LIST_ENTRY * Entry;
+
+ Entry = ListHead->Flink;
+ Flink = Entry->Flink;
+ ListHead->Flink = Flink;
+ Flink->Blink = ListHead;
+ return Entry;
+}
+
+VOID
+inline
+InsertHeadList(
+ LIST_ENTRY * ListHead,
+ LIST_ENTRY * Entry
+ )
+{
+ LIST_ENTRY * Flink;
+
+ Flink = ListHead->Flink;
+ Entry->Flink = Flink;
+ Entry->Blink = ListHead;
+ Flink->Blink = Entry;
+ ListHead->Flink = Entry;
+}
+
+VOID
+inline
+InsertTailList(
+ LIST_ENTRY * ListHead,
+ LIST_ENTRY * Entry
+ )
+{
+ LIST_ENTRY * Blink;
+
+ Blink = ListHead->Blink;
+ Entry->Flink = ListHead;
+ Entry->Blink = Blink;
+ Blink->Flink = Entry;
+ ListHead->Blink = Entry;
+}
+
+#endif // IsListEmpty
+#endif // _STLIST_H
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlock.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlock.h
new file mode 100644
index 0000000000..6571489187
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlock.h
@@ -0,0 +1,149 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef _STLOCK_H
+#define _STLOCK_H
+
+class STLOCK
+{
+public:
+
+ STLOCK()
+ : _fInitialized( FALSE )
+ {
+ }
+
+ ~STLOCK()
+ {
+ if ( _fInitialized )
+ {
+ DeleteCriticalSection( &_cs );
+ CloseHandle( _hReadersDone );
+ }
+ }
+
+ HRESULT
+ Initialize(
+ VOID
+ )
+ {
+ HRESULT hr = S_OK;
+ BOOL fResult = FALSE;
+
+ if ( !_fInitialized )
+ {
+ _fWriterWaiting = FALSE;
+ _cReaders = 0;
+
+ fResult = InitializeCriticalSectionAndSpinCount( &_cs, 100 );
+
+ if ( !fResult )
+ {
+ hr = E_FAIL;
+ goto Finished;
+ }
+
+ _hReadersDone = CreateEvent( NULL,
+ FALSE,
+ FALSE,
+ NULL );
+
+ if ( !_hReadersDone )
+ {
+ DeleteCriticalSection( &_cs );
+ hr = E_FAIL;
+ goto Finished;
+ }
+
+ _fInitialized = TRUE;
+ }
+
+Finished:
+ return hr;
+ }
+
+ BOOL
+ QueryInitialized() const
+ {
+ return _fInitialized;
+ }
+
+ void SharedAcquire()
+ {
+ EnterCriticalSection( &_cs );
+ InterlockedIncrement( &_cReaders );
+ LeaveCriticalSection( &_cs );
+ }
+
+ void SharedRelease()
+ {
+ ReleaseInternal();
+ }
+
+ void ExclusiveAcquire()
+ {
+ EnterCriticalSection( &_cs );
+
+ _fWriterWaiting = TRUE;
+
+ //
+ // If there are any readers, wait for them
+ // to release
+ //
+
+ if ( InterlockedExchangeAdd( &_cReaders, 0 ) > 0 )
+ {
+ WaitForSingleObject( _hReadersDone, INFINITE );
+ }
+
+ //
+ // Reader count -1 indicates that a writer has the lock
+ //
+
+ _cReaders = -1;
+ }
+
+ void ExclusiveRelease()
+ {
+ ReleaseInternal();
+ }
+
+private:
+
+ BOOL _fInitialized;
+ BOOL _fWriterWaiting;
+ LONG _cReaders;
+ CRITICAL_SECTION _cs;
+ HANDLE _hReadersDone;
+
+ void ReleaseInternal()
+ {
+ LONG cReaders = InterlockedDecrement( &_cReaders );
+
+ if ( cReaders >= 0 )
+ {
+ //
+ // Released a read lock. If this was the last
+ // reader and writers are waiting, set the
+ // readers done event
+ //
+
+ if ( ( _fWriterWaiting ) && ( cReaders == 0 ) )
+ {
+ SetEvent( _hReadersDone );
+ }
+ }
+ else
+ {
+ //
+ // Released a write lock
+ //
+
+ _cReaders = 0;
+ _fWriterWaiting = FALSE;
+ LeaveCriticalSection( &_cs );
+ }
+ }
+};
+
+#endif // _STLOCK_H
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttable.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttable.h
new file mode 100644
index 0000000000..0fd629af3d
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttable.h
@@ -0,0 +1,599 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef _STTABLE_H
+#define _STTABLE_H
+
+#include
+#include
+#include "stbuff.h"
+#include "stlock.h"
+#include "stlist.h"
+
+#define DEFAULT_BUCKETS 97 // largest prime under 100
+
+class ITEM;
+class STTABLE_ITEM;
+
+typedef DWORD (WINAPI * PFN_HASH)(STBUFF*);
+typedef BOOL (WINAPI * PFN_COMPARE_KEYS)(STBUFF*,STBUFF*);
+typedef VOID (WINAPI * PFN_ITER)(STTABLE_ITEM*, BOOL*);
+
+class STTABLE_ITEM
+{
+public:
+
+ STTABLE_ITEM()
+ : _cRefs( 1 )
+ {
+ InitializeListHead( &le );
+ }
+
+ VOID
+ Reference()
+ {
+ InterlockedIncrement( &_cRefs );
+ }
+
+ VOID
+ Dereference()
+ {
+ LONG cRefs = InterlockedDecrement( &_cRefs );
+
+ if ( cRefs == 0 )
+ {
+ delete this;
+ }
+ }
+
+ HRESULT
+ Initialize(
+ STBUFF * pKey
+ )
+ {
+ return _buffKey.SetData( pKey->QueryPtr(),
+ pKey->QueryDataSize() );
+ }
+
+ STBUFF *
+ QueryKey()
+ {
+ return &_buffKey;
+ }
+
+ virtual
+ ~STTABLE_ITEM()
+ {}
+
+ LIST_ENTRY le;
+
+private:
+
+ LONG _cRefs;
+ STBUFF _buffKey;
+};
+
+class STTABLE_BUCKET
+{
+public:
+
+ STTABLE_BUCKET()
+ : _pfnCompareKeys( NULL )
+ {}
+
+ virtual
+ ~STTABLE_BUCKET()
+ {
+ LIST_ENTRY * pEntry;
+ STTABLE_ITEM * pItem;
+
+ while ( !IsListEmpty( &_Head ) )
+ {
+ pEntry = RemoveHeadList( &_Head );
+
+ pItem = CONTAINING_RECORD( pEntry,
+ STTABLE_ITEM,
+ le );
+
+ pItem->Dereference();
+ pItem = NULL;
+ }
+ }
+
+ HRESULT
+ Initialize(
+ PFN_COMPARE_KEYS pfnCompareKeys = NULL
+ )
+ {
+ InitializeListHead( &_Head );
+
+ _pfnCompareKeys = pfnCompareKeys;
+
+ return _BucketLock.Initialize();
+ }
+
+ HRESULT
+ Insert(
+ STTABLE_ITEM * pNewItem
+ )
+ {
+ LIST_ENTRY * pEntry;
+ STTABLE_ITEM * pItem;
+ HRESULT hr = S_OK;
+
+ _BucketLock.ExclusiveAcquire();
+
+ //
+ // Check to see if the item is already in the list
+ //
+
+ pEntry = _Head.Flink;
+
+ while ( pEntry != &_Head )
+ {
+ pItem = CONTAINING_RECORD( pEntry,
+ STTABLE_ITEM,
+ le );
+
+ if ( CompareKeys( pNewItem->QueryKey(),
+ pItem->QueryKey() ) )
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
+ goto Finished;
+ }
+
+ pEntry = pEntry->Flink;
+ }
+
+ //
+ // It's not in the list. Add it now
+ //
+
+ pNewItem->Reference();
+ InsertTailList( &_Head, &pNewItem->le );
+
+Finished:
+
+ _BucketLock.ExclusiveRelease();
+
+ return hr;
+ }
+
+ HRESULT
+ Remove(
+ STTABLE_ITEM * pItemToRemove
+ )
+ {
+ LIST_ENTRY * pEntry;
+ STTABLE_ITEM * pItem;
+
+ _BucketLock.ExclusiveAcquire();
+
+ //
+ // Find the item in the list
+ //
+
+ pEntry = _Head.Flink;
+
+ while ( pEntry != &_Head )
+ {
+ pItem = CONTAINING_RECORD( pEntry,
+ STTABLE_ITEM,
+ le );
+
+ if ( CompareKeys( pItemToRemove->QueryKey(),
+ pItem->QueryKey() ) )
+ {
+ RemoveEntryList( &pItemToRemove->le );
+ pItemToRemove->Dereference();
+ pItemToRemove = NULL;
+
+ goto Finished;
+ }
+
+ pEntry = pEntry->Flink;
+ }
+
+ //
+ // Item was not found. Set error code, but
+ // don't fail function.
+ //
+
+ SetLastError (ERROR_FILE_NOT_FOUND);
+
+Finished:
+
+ _BucketLock.ExclusiveRelease();
+
+ return S_OK;
+ }
+
+ HRESULT
+ GetItem(
+ STBUFF * pKey,
+ STTABLE_ITEM **ppItem
+ )
+ {
+ LIST_ENTRY * pEntry;
+ STTABLE_ITEM * pItem;
+ HRESULT hr = S_OK;
+
+ _BucketLock.SharedAcquire();
+
+ //
+ // Find the item in the list
+ //
+
+ pEntry = _Head.Flink;
+
+ while ( pEntry != &_Head )
+ {
+ pItem = CONTAINING_RECORD( pEntry,
+ STTABLE_ITEM,
+ le );
+
+ if ( CompareKeys( pKey,
+ pItem->QueryKey() ) )
+ {
+ pItem->Reference();
+ goto Finished;
+ }
+
+ pEntry = pEntry->Flink;
+ }
+
+ //
+ // Item was not found.
+ //
+
+ pItem = NULL;
+
+ hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+
+Finished:
+
+ _BucketLock.SharedRelease();
+
+ *ppItem = pItem;
+
+ return hr;
+ }
+
+ VOID
+ Iterate(
+ PFN_ITER pIterFunction
+ )
+ {
+ LIST_ENTRY * pEntry;
+ STTABLE_ITEM * pItem;
+ BOOL fRemoveItem;
+
+ ////////////////////////////////////////
+ //
+ // It is assumed that this function will
+ // be called under a write lock
+ //
+ ////////////////////////////////////////
+
+ //
+ // Walk the list and call the provided
+ // function on each item
+ //
+
+ pEntry = _Head.Flink;
+
+ while ( pEntry != &_Head )
+ {
+ pItem = CONTAINING_RECORD( pEntry,
+ STTABLE_ITEM,
+ le );
+
+ //
+ // The iterator function might remove
+ // the item from the list, so we need
+ // to get the next link first
+ //
+
+ pEntry = pEntry->Flink;
+
+ pItem->Reference();
+ pIterFunction( pItem, &fRemoveItem );
+
+ if ( fRemoveItem )
+ {
+ RemoveEntryList( &pItem->le );
+ pItem->Dereference();
+ pItem = NULL;
+ }
+ }
+
+ }
+
+private:
+
+ LIST_ENTRY _Head;
+ STLOCK _BucketLock;
+ PFN_COMPARE_KEYS _pfnCompareKeys;
+
+ BOOL
+ CompareKeys(
+ STBUFF * pKey1,
+ STBUFF * pKey2
+ )
+ {
+ if ( _pfnCompareKeys )
+ {
+ return _pfnCompareKeys( pKey1,
+ pKey2 );
+ }
+
+ return ( strcmp( pKey1->QueryStr(),
+ pKey2->QueryStr() ) == 0 );
+ }
+};
+
+
+class STTABLE
+{
+public:
+
+ STTABLE()
+ : _cBuckets( 0 ),
+ _pfnHash( NULL )
+ {}
+
+ virtual
+ ~STTABLE()
+ {
+ STTABLE_BUCKET ** rgBuckets;
+ STTABLE_BUCKET * pBucket;
+ DWORD n;
+
+ rgBuckets = (STTABLE_BUCKET**)_buffBucketPtrs.QueryPtr();
+
+ for( n = 0; n < _cBuckets; n++ )
+ {
+ pBucket = rgBuckets[n];
+
+ delete pBucket;
+ pBucket = NULL;
+ }
+ }
+
+ HRESULT
+ Initialize(
+ DWORD cBuckets = DEFAULT_BUCKETS,
+ PFN_HASH pfnHash = NULL,
+ PFN_COMPARE_KEYS pfnCompareKeys = NULL
+ )
+ {
+ STTABLE_BUCKET ** rgBuckets;
+ DWORD n;
+ HRESULT hr = S_OK;
+
+ //
+ // Create a buffer for the bucket array
+ //
+
+ hr = _buffBucketPtrs.Resize( cBuckets * sizeof(STTABLE_BUCKET*) );
+
+ if ( FAILED (hr) )
+ {
+ goto Finished;
+ }
+
+ rgBuckets = (STTABLE_BUCKET**)_buffBucketPtrs.QueryPtr();
+
+ //
+ // Create the buckets
+ //
+
+ for ( n = 0; n < cBuckets; n++ )
+ {
+ STTABLE_BUCKET * pNewBucket = new STTABLE_BUCKET;
+
+ if ( !pNewBucket )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Finished;
+ }
+
+ hr = pNewBucket->Initialize( pfnCompareKeys );
+
+ if ( FAILED (hr) )
+ {
+ delete pNewBucket;
+ pNewBucket = NULL;
+
+ goto Finished;
+ }
+
+ rgBuckets[n] = pNewBucket;
+ pNewBucket = NULL;
+
+ _cBuckets++;
+ }
+
+ //
+ // Initialize the table lock
+ //
+
+ _TableLock.Initialize();
+
+ //
+ // Set the hash function
+ //
+
+ _pfnHash = pfnHash;
+
+Finished:
+ return hr;
+ }
+
+ HRESULT
+ Insert(
+ STTABLE_ITEM * pNewItem
+ )
+ {
+
+ DWORD dwHash;
+ STTABLE_BUCKET * pBucket;
+ HRESULT hr = S_OK;
+
+ dwHash = ComputeHash( pNewItem->QueryKey() );
+
+ pBucket = GetBucket( dwHash );
+
+ _TableLock.SharedAcquire();
+
+ hr = pBucket->Insert( pNewItem );
+
+ _TableLock.SharedRelease();
+
+ return hr;
+ }
+
+ HRESULT
+ Remove(
+ STTABLE_ITEM * pItemToRemove
+ )
+ {
+ DWORD dwHash;
+ STTABLE_BUCKET * pBucket;
+ HRESULT hr = S_OK;
+
+ dwHash = ComputeHash( pItemToRemove->QueryKey() );
+
+ pBucket = GetBucket( dwHash );
+
+ _TableLock.SharedAcquire();
+
+ hr = pBucket->Remove( pItemToRemove );
+
+ _TableLock.SharedRelease();
+
+ return hr;
+ }
+
+ HRESULT
+ GetItem(
+ STBUFF * pKey,
+ STTABLE_ITEM **ppItem
+ )
+ {
+ DWORD dwHash;
+ STTABLE_BUCKET * pBucket;
+ STTABLE_ITEM * pRet;
+ HRESULT hr = S_OK;
+
+ dwHash = ComputeHash( pKey );
+
+ pBucket = GetBucket( dwHash );
+
+ _TableLock.SharedAcquire();
+
+ hr = pBucket->GetItem( pKey, &pRet );
+ if(FAILED( hr))
+ {
+ pRet = NULL;
+ goto Finished;
+ }
+
+ Finished:
+
+ _TableLock.SharedRelease();
+
+ *ppItem = pRet;
+
+ return hr;
+ }
+
+ VOID
+ Iterate(
+ PFN_ITER pIterFunction
+ )
+ {
+ STTABLE_BUCKET ** rgBuckets;
+ DWORD n;
+
+ _TableLock.ExclusiveAcquire();
+
+ rgBuckets = (STTABLE_BUCKET**)_buffBucketPtrs.QueryPtr();
+
+ //
+ // Iterate each bucket
+ //
+
+ for ( n = 0; n < _cBuckets; n++ )
+ {
+ STTABLE_BUCKET * pBucket;
+
+ pBucket = rgBuckets[n];
+
+ pBucket->Iterate( pIterFunction );
+
+ pBucket = NULL;
+ }
+
+ _TableLock.ExclusiveRelease();
+ }
+
+private:
+
+ STBUFF _buffBucketPtrs;
+ DWORD _cBuckets;
+ STLOCK _TableLock;
+ PFN_HASH _pfnHash;
+
+ DWORD
+ ComputeHash(
+ STBUFF * pKey
+ )
+ {
+ if ( _pfnHash )
+ {
+ return _pfnHash( pKey );
+ }
+
+ return HashString( pKey->QueryStr() );
+ }
+
+ STTABLE_BUCKET *
+ GetBucket(
+ DWORD dwHash
+ )
+ {
+ STTABLE_BUCKET ** rgBuckets;
+
+ rgBuckets = (STTABLE_BUCKET**)_buffBucketPtrs.QueryPtr();
+
+ return rgBuckets[dwHash % _cBuckets];
+ }
+
+ DWORD
+ WINAPI
+ HashString(
+ LPCSTR szString
+ )
+ {
+ DWORD dwRet = 0;
+
+ //
+ // Create a hash by adding up the ascii values
+ // of each character in a case-insensitive manner
+ //
+
+ if ( szString )
+ {
+ while ( *szString )
+ {
+ dwRet += ( (*szString) | 0x20 );
+ szString++;
+ }
+ }
+
+ return dwRet;
+ }
+};
+
+#endif // _STTABLE_H
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttimer.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttimer.h
new file mode 100644
index 0000000000..f5a10817a5
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttimer.h
@@ -0,0 +1,232 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef _STTIMER_H
+#define _STTIMER_H
+
+class STTIMER
+{
+public:
+
+ STTIMER()
+ : _pTimer( NULL )
+ {
+ }
+
+ virtual
+ ~STTIMER()
+ {
+ if ( _pTimer )
+ {
+ CancelTimer();
+
+ CloseThreadpoolTimer( _pTimer );
+
+ _pTimer = NULL;
+ }
+ }
+
+ HRESULT
+ InitializeTimer(
+ PTP_TIMER_CALLBACK pfnCallback,
+ VOID * pContext,
+ DWORD dwInitialWait = 0,
+ DWORD dwPeriod = 0
+ )
+ {
+ _pTimer = CreateThreadpoolTimer( pfnCallback,
+ pContext,
+ NULL );
+
+ if ( !_pTimer )
+ {
+ return HRESULT_FROM_WIN32( GetLastError() );
+ }
+
+ if ( dwInitialWait )
+ {
+ SetTimer( dwInitialWait,
+ dwPeriod );
+ }
+
+ return S_OK;
+ }
+
+ VOID
+ SetTimer(
+ DWORD dwInitialWait,
+ DWORD dwPeriod = 0
+ )
+ {
+ FILETIME ftInitialWait;
+
+ if ( dwInitialWait == 0 && dwPeriod == 0 )
+ {
+ //
+ // Special case. We are preventing new callbacks
+ // from being queued. Any existing callbacks in the
+ // queue will still run.
+ //
+ // This effectively disables the timer. It can be
+ // re-enabled by setting non-zero initial wait or
+ // period values.
+ //
+
+ SetThreadpoolTimer( _pTimer, NULL, 0, 0 );
+ return;
+ }
+
+ InitializeRelativeFileTime( &ftInitialWait, dwInitialWait );
+
+ SetThreadpoolTimer( _pTimer,
+ &ftInitialWait,
+ dwPeriod,
+ 0 );
+ }
+
+ VOID
+ CancelTimer()
+ {
+ //
+ // Disable the timer
+ //
+
+ SetTimer( 0 );
+
+ //
+ // Wait until any callbacks queued prior to disabling
+ // have completed.
+ //
+
+ WaitForThreadpoolTimerCallbacks( _pTimer, TRUE );
+ }
+
+private:
+
+ VOID
+ InitializeRelativeFileTime(
+ FILETIME * pft,
+ DWORD dwMilliseconds
+ )
+ {
+ LARGE_INTEGER li;
+
+ //
+ // The pftDueTime parameter expects the time to be
+ // expressed as the number of 100 nanosecond intervals
+ // times -1.
+ //
+ // To convert from milliseconds, we'll multiply by
+ // -10000
+ //
+
+ li.QuadPart = (LONGLONG)dwMilliseconds * -10000;
+
+ pft->dwHighDateTime = li.HighPart;
+ pft->dwLowDateTime = li.LowPart;
+ };
+
+ TP_TIMER * _pTimer;
+};
+
+class STELAPSED
+{
+public:
+
+ STELAPSED()
+ : _dwInitTime( 0 ),
+ _dwInitTickCount( 0 ),
+ _dwPerfCountsPerMillisecond( 0 ),
+ _fUsingHighResolution( FALSE )
+ {
+ LARGE_INTEGER li;
+ BOOL fResult;
+
+ _dwInitTickCount = GetTickCount64();
+
+ fResult = QueryPerformanceFrequency( &li );
+
+ if ( !fResult )
+ {
+ goto Finished;
+ }
+
+ _dwPerfCountsPerMillisecond = li.QuadPart / 1000;
+
+ fResult = QueryPerformanceCounter( &li );
+
+ if ( !fResult )
+ {
+ goto Finished;
+ }
+
+ _dwInitTime = li.QuadPart / _dwPerfCountsPerMillisecond;
+
+ _fUsingHighResolution = TRUE;
+
+Finished:
+
+ return;
+ }
+
+ virtual
+ ~STELAPSED()
+ {
+ }
+
+ LONGLONG
+ QueryElapsedTime()
+ {
+ LARGE_INTEGER li;
+
+ if ( _fUsingHighResolution && QueryPerformanceCounter( &li ) )
+ {
+ DWORD64 dwCurrentTime = li.QuadPart / _dwPerfCountsPerMillisecond;
+
+ if ( dwCurrentTime < _dwInitTime )
+ {
+ //
+ // It's theoretically possible that QueryPerformanceCounter
+ // may return slightly different values on different CPUs.
+ // In this case, we don't want to return an unexpected value
+ // so we'll return zero. This is acceptable because
+ // presumably such a case would only happen for a very short
+ // time window.
+ //
+ // It would be possible to prevent this by ensuring processor
+ // affinity for all calls to QueryPerformanceCounter, but that
+ // would be undesirable in the general case because it could
+ // introduce unnecessary context switches and potentially a
+ // CPU bottleneck.
+ //
+ // Note that this issue also applies to callers doing rapid
+ // calls to this function. If a caller wants to mitigate
+ // that, they could enforce the affinitization, or they
+ // could implement a similar sanity check when comparing
+ // returned values from this function.
+ //
+
+ return 0;
+ }
+
+ return dwCurrentTime - _dwInitTime;
+ }
+
+ return GetTickCount64() - _dwInitTickCount;
+ }
+
+ BOOL
+ QueryUsingHighResolution()
+ {
+ return _fUsingHighResolution;
+ }
+
+private:
+
+ DWORD64 _dwInitTime;
+ DWORD64 _dwInitTickCount;
+ DWORD64 _dwPerfCountsPerMillisecond;
+ BOOL _fUsingHighResolution;
+};
+
+#endif // _STTIMER_H
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/dbgutil2.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/dbgutil2.h
new file mode 100644
index 0000000000..1c4d2d4381
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/dbgutil2.h
@@ -0,0 +1,49 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+# ifndef _DBGUTIL_H_
+# define _DBGUTIL_H_
+
+
+// begin_user_modifiable
+
+//
+// define DEBUG_FLAGS_VAR to assure that DebugFlags will stay private to
+// iisutil. This is important in the case when iisutil is linked as static library
+//
+#define DEBUG_FLAGS_VAR g_dwDebugFlagsIISUtil
+
+//
+// Modify the following flags if necessary
+//
+
+# define DEFAULT_OUTPUT_FLAGS ( DbgOutputKdb )
+
+
+// end_user_modifiable
+// begin_user_unmodifiable
+
+
+
+/************************************************************
+ * Include Headers
+ ************************************************************/
+
+# include
+
+
+//
+// Define the debugging constants
+//
+
+# define DEBUG_ALLOC_CACHE 0x01000000
+# define DEBUG_SCHED 0x02000000
+# define DEBUG_RESOURCE 0x04000000
+# define DEBUG_INET_MONITOR 0x08000000
+# define DEBUG_PIPEDATA 0x10000000
+
+// Use the default constants from pudebug.h
+
+# endif /* _DBGUTIL_H_ */
+
+/************************ End of File ***********************/
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtldbg.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtldbg.h
new file mode 100644
index 0000000000..3c6c48e7b1
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtldbg.h
@@ -0,0 +1,154 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef __IRTLDBG_H__
+#define __IRTLDBG_H__
+
+#ifndef __IRTLMISC_H__
+# include
+#endif
+
+/* Ensure that MessageBoxes can popup */
+# define RUNNING_AS_SERVICE 1
+
+
+#ifdef _AFX
+ /* Assure compatiblity with MFC */
+
+# define IRTLASSERT(x) ASSERT(x)
+# define IRTLVERIFY(x) VERIFY(x)
+
+#else /* !_AFX */
+
+# if DBG || defined(_DEBUG)
+# define IRTLDEBUG
+# endif
+
+# if defined(IRTLDEBUG)
+# ifndef USE_DEBUG_CRTS
+ /* IIS (and NT) do not ship msvcrtD.dll, per the VC license,
+ * so we can't use the assertion code from . Use similar
+ * macros from instead. */
+# include
+
+ /* workaround for /W4 warnings about 'constant expressions' */
+# define IRTLASSERT(f) \
+ ((void) ((f) || (PuDbgAssertFailed(DBG_CONTEXT, #f, ""), 0) ))
+
+# elif defined(_MSC_VER) && (_MSC_VER >= 1000)
+ /* Use the new debugging tools in Visual C++ 4.x */
+# include
+ /* _ASSERTE will give a more meaningful message, but the string takes
+ * space. Use _ASSERT if this is an issue. */
+# define IRTLASSERT(f) _ASSERTE(f)
+# else
+# include
+# define IRTLASSERT(f) assert(f)
+# endif
+
+# ifdef _PREFAST_
+# undef IRTLASSERT
+# define IRTLASSERT(f) ((void)0)
+# endif
+
+# define IRTLVERIFY(f) IRTLASSERT(f)
+# define DEBUG_ONLY(f) (f)
+# define TRACE IrtlTrace
+# define TRACE0(psz) IrtlTrace(_T("%s"), _T(psz))
+# define TRACE1(psz, p1) IrtlTrace(_T(psz), p1)
+# define TRACE2(psz, p1, p2) IrtlTrace(_T(psz), p1, p2)
+# define TRACE3(psz, p1, p2, p3) IrtlTrace(_T(psz), p1, p2, p3)
+# define ASSERT_VALID(pObj) \
+ do {IRTLASSERT((pObj) != NULL); (pObj)->AssertValid();} while (0)
+# define DUMP(pObj) \
+ do {IRTLASSERT((pObj) != NULL); (pObj)->Dump();} while (0)
+
+# else /* !_DEBUG */
+
+ /* These macros should all compile away to nothing */
+# define IRTLASSERT(f) ((void)0)
+# define IRTLVERIFY(f) ((void)(f))
+# define DEBUG_ONLY(f) ((void)0)
+# define TRACE 1 ? (void)0 : IrtlTrace
+# define TRACE0(psz)
+# define TRACE1(psz, p1)
+# define TRACE2(psz, p1, p2)
+# define TRACE3(psz, p1, p2, p3)
+# define ASSERT_VALID(pObj) ((void)0)
+# define DUMP(pObj) ((void)0)
+
+# endif /* !_DEBUG */
+
+
+# define ASSERT_POINTER(p, type) \
+ IRTLASSERT((p) != NULL)
+
+#define ASSERT_STRING(s) \
+ IRTLASSERT(((s) != NULL))
+
+/* Declarations for non-Windows apps */
+
+# ifndef _WINDEF_
+typedef void* LPVOID;
+typedef const void* LPCVOID;
+typedef unsigned int UINT;
+typedef int BOOL;
+typedef const char* LPCTSTR;
+# endif /* _WINDEF_ */
+
+# ifndef TRUE
+# define FALSE 0
+# define TRUE 1
+# endif
+
+#endif /* !_AFX */
+
+
+#ifdef __cplusplus
+
+// Compile-time (not run-time) assertion. Code will not compile if
+// expr is false. Note: there is no non-debug version of this; we
+// want this for all builds. The compiler optimizes the code away.
+template struct static_checker;
+template <> struct static_checker {}; // specialize only for `true'
+#define STATIC_ASSERT(expr) static_checker< (expr) >()
+
+#endif /* !__cplusplus */
+
+/* Writes trace messages to debug stream */
+extern
+#ifdef __cplusplus
+"C"
+#endif /* !__cplusplus */
+IRTL_DLLEXP
+void __cdecl
+IrtlTrace(
+ LPCTSTR pszFormat,
+ ...);
+
+
+#ifdef _DEBUG
+# define IRTL_DEBUG_INIT() IrtlDebugInit()
+# define IRTL_DEBUG_TERM() IrtlDebugTerm()
+#else /* !_DEBUG */
+# define IRTL_DEBUG_INIT() ((void)0)
+# define IRTL_DEBUG_TERM() ((void)0)
+#endif /* !_DEBUG */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* should be called from main(), WinMain(), or DllMain() */
+IRTL_DLLEXP void
+IrtlDebugInit();
+
+IRTL_DLLEXP void
+IrtlDebugTerm();
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __IRTLDBG_H__ */
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtlmisc.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtlmisc.h
new file mode 100644
index 0000000000..02bfa2d065
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtlmisc.h
@@ -0,0 +1,131 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef __IRTLMISC_H__
+#define __IRTLMISC_H__
+
+#include
+
+//--------------------------------------------------------------------
+// These declarations are needed to export the template classes from
+// IisRtl.DLL and import them into other modules.
+
+// DEBGUDEBUG
+/**
+#ifndef IRTL_DLLEXP
+# ifdef DLL_IMPLEMENTATION
+# define IRTL_DLLEXP __declspec(dllexport)
+# ifdef IMPLEMENTATION_EXPORT
+# define IRTL_EXPIMP
+# else
+# undef IRTL_EXPIMP
+# endif
+# elif defined LIB_IMPLEMENTATION
+# define IRTL_DLLEXP
+# define IRTL_EXPIMP extern
+# else
+# define IRTL_DLLEXP __declspec(dllimport)
+# define IRTL_EXPIMP extern
+# endif // !DLL_IMPLEMENTATION
+#endif // !IRTL_DLLEXP
+*/
+
+#define IRTL_DLLEXP
+#define IRTL_EXPIMP
+
+
+
+
+
+//--------------------------------------------------------------------
+// Miscellaneous functions
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+
+// Heap routines
+
+// Private IIS heap
+HANDLE
+WINAPI
+IisHeap();
+
+// Allocate dwBytes
+LPVOID
+WINAPI
+IisMalloc(
+ IN SIZE_T dwBytes);
+
+// Allocate dwBytes. Memory is zeroed
+LPVOID
+WINAPI
+IisCalloc(
+ IN SIZE_T dwBytes);
+
+// Reallocate lpMem to dwBytes
+LPVOID
+WINAPI
+IisReAlloc(
+ IN LPVOID lpMem,
+ IN SIZE_T dwBytes);
+
+// Free lpMem
+BOOL
+WINAPI
+IisFree(
+ IN LPVOID lpMem);
+
+// additional IISRTL initialization
+BOOL
+WINAPI
+InitializeIISRTL();
+
+// call before unloading IISRTL
+void
+WINAPI
+TerminateIISRTL();
+
+// case-insensitive strstr
+IRTL_DLLEXP const char* stristr(const char* pszString, const char* pszSubString);
+
+// how many CPUs on this machine?
+inline int NumProcessors()
+{
+ static int s_nCPUs = 0;
+
+ if (s_nCPUs == 0)
+ {
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ s_nCPUs = si.dwNumberOfProcessors;
+ }
+ return s_nCPUs;
+}
+
+
+// how many CPUs on this machine?
+inline int ProcessorType()
+{
+ static int s_nProcessorType = 0;
+
+ if (s_nProcessorType == 0)
+ {
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ s_nProcessorType = si.dwProcessorType;
+ }
+ return s_nProcessorType;
+}
+
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#define HRESULT_FROM_GLE() ( GetLastError() != NO_ERROR ) \
+ ? HRESULT_FROM_WIN32( GetLastError() ) \
+ : E_FAIL
+
+#endif // __IRTLMISC_H__
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/memorylog.hxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/memorylog.hxx
new file mode 100644
index 0000000000..effa543259
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/memorylog.hxx
@@ -0,0 +1,67 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef _MEMORYLOG_HXX_
+#define _MEMORYLOG_HXX_
+
+//#include "buffer.hxx"
+
+class CMemoryLog
+{
+public:
+ CMemoryLog(DWORD dwMaxByteSize);
+ ~CMemoryLog();
+
+ //
+ // Override the new and delete operator to make them
+ // use LocalAlloc so that CMemoryLog
+ // can be safely constructed and deleted
+ // in the DllMain()
+ //
+
+ VOID *
+ operator new(
+ size_t size
+ )
+ {
+ return LocalAlloc( LPTR, size );
+ }
+
+ VOID
+ operator delete(
+ VOID * pMemoryLog
+ )
+ {
+ DBG_ASSERT( pMemoryLog != NULL );
+ LocalFree( pMemoryLog );
+ }
+
+ // appends to memory log
+ DWORD Append(LPCSTR pszOutput,
+ DWORD cchLen
+ );
+private:
+ CMemoryLog();
+
+ // pointer to the beginning of the memory buffer
+ CHAR *m_pBufferBegin;
+ // pointer to the byte 1 beyond the end of the last message
+ CHAR *m_pLastMessageEnd;
+ // pointer to the end of the memory buffer
+ CHAR *m_pBufferEnd;
+
+ // Used for storage
+ BUFFER m_buf;
+
+ // TRUE if storage could be allocated, otherwise FALSE
+ BOOL m_fValid;
+
+ CRITICAL_SECTION m_cs;
+
+ // to be able to tell if the critsec was initialized successfully
+ BOOL m_fCritSecInitialized;
+
+};
+
+#endif // _MEMORYLOG_HXX_
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/precomp.hxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/precomp.hxx
new file mode 100644
index 0000000000..d012c7ee29
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/precomp.hxx
@@ -0,0 +1,9 @@
+#include
+#include "tchar.h"
+#include "dbgutil.h"
+#include "ntassert.h"
+#include "buffer.h"
+#include "stringa.h"
+#include "stringu.h"
+#include "stdlib.h"
+#include "stdio.h"
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/pudebug.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/pudebug.h
new file mode 100644
index 0000000000..d42153d457
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/pudebug.h
@@ -0,0 +1,748 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#if !defined(BUILD_PUDEBUG)
+//
+// if we are not using this header for building the pudebug library
+// then better this be used with dbgutil.h
+//
+ # ifndef _DBGUTIL_H_
+ // error Please make sure you included dbgutil.h!
+ // error Do not include pudebug.h directly
+ #include
+ # endif // _DBGUTIL_H_
+#endif
+
+# ifndef _PUDEBUG_H_
+# define _PUDEBUG_H_
+
+#ifndef _NO_TRACING_
+# define _NO_TRACING_
+#endif // _NO_TRACING_
+
+/************************************************************
+ * Include Headers
+ ************************************************************/
+
+# ifdef __cplusplus
+extern "C" {
+# endif // __cplusplus
+
+# include
+
+# ifndef dllexp
+# define dllexp __declspec( dllexport)
+# endif // dllexp
+
+#include
+
+#ifndef IN_OUT
+#define IN_OUT __inout
+#endif
+
+/***********************************************************
+ * Macros
+ ************************************************************/
+
+enum PRINT_REASONS {
+ PrintNone = 0x0, // Nothing to be printed
+ PrintError = 0x1, // An error message
+ PrintWarning = 0x2, // A warning message
+ PrintLog = 0x3, // Just logging. Indicates a trace of where ...
+ PrintMsg = 0x4, // Echo input message
+ PrintCritical = 0x5, // Print and Exit
+ PrintAssertion= 0x6 // Printing for an assertion failure
+ };
+
+
+enum DEBUG_OUTPUT_FLAGS {
+ DbgOutputNone = 0x0, // None
+ DbgOutputKdb = 0x1, // Output to Kernel Debugger
+ DbgOutputLogFile = 0x2, // Output to LogFile
+ DbgOutputTruncate = 0x4, // Truncate Log File if necessary
+ DbgOutputStderr = 0x8, // Send output to std error
+ DbgOutputBackup = 0x10, // Make backup of debug file ?
+ DbgOutputMemory = 0x20, // Dump to memory buffer
+ DbgOutputAll = 0xFFFFFFFF // All the bits set.
+ };
+
+
+# define MAX_LABEL_LENGTH ( 100)
+
+
+// The following flags are used internally to track what level of tracing we
+// are currently using. Bitmapped for extensibility.
+#define DEBUG_FLAG_ODS 0x00000001
+//#define DEBUG_FLAG_INFO 0x00000002
+//#define DEBUG_FLAG_WARN 0x00000004
+//#define DEBUG_FLAG_ERROR 0x00000008
+// The following are used internally to determine whether to log or not based
+// on what the current state is
+//#define DEBUG_FLAGS_INFO (DEBUG_FLAG_ODS | DEBUG_FLAG_INFO)
+//#define DEBUG_FLAGS_WARN (DEBUG_FLAG_ODS | DEBUG_FLAG_INFO | DEBUG_FLAG_WARN)
+//#define DEBUG_FLAGS_ERROR (DEBUG_FLAG_ODS | DEBUG_FLAG_INFO | DEBUG_FLAG_WARN | DEBUG_FLAG_ERROR)
+
+#define DEBUG_FLAGS_ANY (DEBUG_FLAG_INFO | DEBUG_FLAG_WARN | DEBUG_FLAG_ERROR)
+
+//
+// user of DEBUG infrastructure may choose unique variable name for DEBUG_FLAGS
+// that's specially useful for cases where DEBUG infrastructure is used within
+// static library (static library may prefer to maintain it's own DebugFlags independent
+// on the main program it links to
+//
+#ifndef DEBUG_FLAGS_VAR
+#define DEBUG_FLAGS_VAR g_dwDebugFlags
+#endif
+
+extern
+#ifdef __cplusplus
+"C"
+# endif // _cplusplus
+ DWORD DEBUG_FLAGS_VAR ; // Debugging Flags
+
+# define DECLARE_DEBUG_VARIABLE()
+
+# define SET_DEBUG_FLAGS( dwFlags) DEBUG_FLAGS_VAR = dwFlags
+# define GET_DEBUG_FLAGS() ( DEBUG_FLAGS_VAR )
+
+# define LOAD_DEBUG_FLAGS_FROM_REG(hkey, dwDefault) \
+ DEBUG_FLAGS_VAR = PuLoadDebugFlagsFromReg((hkey), (dwDefault))
+
+# define LOAD_DEBUG_FLAGS_FROM_REG_STR(pszRegKey, dwDefault) \
+ DEBUG_FLAGS_VAR = PuLoadDebugFlagsFromRegStr((pszRegKey), (dwDefault))
+
+# define SAVE_DEBUG_FLAGS_IN_REG(hkey, dwDbg) \
+ PuSaveDebugFlagsInReg((hkey), (dwDbg))
+
+# define DEBUG_IF( arg, s) if ( DEBUG_ ## arg & GET_DEBUG_FLAGS()) { \
+ s \
+ } else {}
+
+# define IF_DEBUG( arg) if ( DEBUG_## arg & GET_DEBUG_FLAGS())
+
+
+/*++
+ class DEBUG_PRINTS
+
+ This class is responsible for printing messages to log file / kernel debugger
+
+ Currently the class supports only member functions for char.
+ ( not unicode-strings).
+
+--*/
+
+
+typedef struct _DEBUG_PRINTS {
+
+ CHAR m_rgchLabel[MAX_LABEL_LENGTH];
+ CHAR m_rgchLogFilePath[MAX_PATH];
+ CHAR m_rgchLogFileName[MAX_PATH];
+ HANDLE m_LogFileHandle;
+ HANDLE m_StdErrHandle;
+ BOOL m_fInitialized;
+ BOOL m_fBreakOnAssert;
+ DWORD m_dwOutputFlags;
+ VOID *m_pMemoryLog;
+} DEBUG_PRINTS, FAR * LPDEBUG_PRINTS;
+
+
+LPDEBUG_PRINTS
+PuCreateDebugPrintsObject(
+ IN const char * pszPrintLabel,
+ IN DWORD dwOutputFlags);
+
+//
+// frees the debug prints object and closes any file if necessary.
+// Returns NULL on success or returns pDebugPrints on failure.
+//
+LPDEBUG_PRINTS
+PuDeleteDebugPrintsObject(
+ IN_OUT LPDEBUG_PRINTS pDebugPrints);
+
+
+VOID
+PuDbgPrint(
+ IN_OUT LPDEBUG_PRINTS pDebugPrints,
+ IN const char * pszFilePath,
+ IN int nLineNum,
+ IN const char * pszFunctionName,
+ IN const char * pszFormat,
+ ...);
+ // arglist
+VOID
+PuDbgPrintW(
+ IN_OUT LPDEBUG_PRINTS pDebugPrints,
+ IN const char * pszFilePath,
+ IN int nLineNum,
+ IN const char * pszFunctionName,
+ IN const WCHAR * pszFormat,
+ ...); // arglist
+
+// PuDbgPrintError is similar to PuDbgPrint() but allows
+// one to print error code in friendly manner
+VOID
+PuDbgPrintError(
+ IN_OUT LPDEBUG_PRINTS pDebugPrints,
+ IN const char * pszFilePath,
+ IN int nLineNum,
+ IN const char * pszFunctionName,
+ IN DWORD dwError,
+ IN const char * pszFormat,
+ ...); // arglist
+
+/*++
+ PuDbgDump() does not do any formatting of output.
+ It just dumps the given message onto the debug destinations.
+--*/
+VOID
+PuDbgDump(
+ IN_OUT LPDEBUG_PRINTS pDebugPrints,
+ IN const char * pszFilePath,
+ IN int nLineNum,
+ IN const char * pszFunctionName,
+ IN const char * pszDump
+ );
+
+//
+// PuDbgAssertFailed() *must* be __cdecl to properly capture the
+// thread context at the time of the failure.
+//
+
+INT
+__cdecl
+PuDbgAssertFailed(
+ IN_OUT LPDEBUG_PRINTS pDebugPrints,
+ IN const char * pszFilePath,
+ IN int nLineNum,
+ IN const char * pszFunctionName,
+ IN const char * pszExpression,
+ IN const char * pszMessage);
+
+INT
+WINAPI
+PuDbgPrintAssertFailed(
+ IN_OUT LPDEBUG_PRINTS pDebugPrints,
+ IN const char * pszFilePath,
+ IN int nLineNum,
+ IN const char * pszFunctionName,
+ IN const char * pszExpression,
+ IN const char * pszMessage);
+
+VOID
+PuDbgCaptureContext (
+ OUT PCONTEXT ContextRecord
+ );
+
+VOID
+PuDbgPrintCurrentTime(
+ IN_OUT LPDEBUG_PRINTS pDebugPrints,
+ IN const char * pszFilePath,
+ IN int nLineNum,
+ IN const char * pszFunctionName
+ );
+
+VOID
+PuSetDbgOutputFlags(
+ IN_OUT LPDEBUG_PRINTS pDebugPrints,
+ IN DWORD dwFlags);
+
+DWORD
+PuGetDbgOutputFlags(
+ IN const LPDEBUG_PRINTS pDebugPrints);
+
+
+//
+// Following functions return Win32 error codes.
+// NO_ERROR if success
+//
+
+DWORD
+PuOpenDbgPrintFile(
+ IN_OUT LPDEBUG_PRINTS pDebugPrints,
+ IN const char * pszFileName,
+ IN const char * pszPathForFile);
+
+DWORD
+PuReOpenDbgPrintFile(
+ IN_OUT LPDEBUG_PRINTS pDebugPrints);
+
+DWORD
+PuCloseDbgPrintFile(
+ IN_OUT LPDEBUG_PRINTS pDebugPrints);
+
+DWORD
+PuOpenDbgMemoryLog(
+ IN_OUT LPDEBUG_PRINTS pDebugPrints);
+
+DWORD
+PuCloseDbgMemoryLog(
+ IN_OUT LPDEBUG_PRINTS pDebugPrints);
+
+DWORD
+PuLoadDebugFlagsFromReg(IN HKEY hkey, IN DWORD dwDefault);
+
+DWORD
+PuLoadDebugFlagsFromRegStr(IN LPCSTR pszRegKey, IN DWORD dwDefault);
+
+DWORD
+PuSaveDebugFlagsInReg(IN HKEY hkey, IN DWORD dwDbg);
+
+
+# define PuPrintToKdb( pszOutput) \
+ if ( pszOutput != NULL) { \
+ OutputDebugString( pszOutput); \
+ } else {}
+
+
+
+# ifdef __cplusplus
+};
+# endif // __cplusplus
+
+// begin_user_unmodifiable
+
+
+
+/***********************************************************
+ * Macros
+ ************************************************************/
+
+
+extern
+#ifdef __cplusplus
+"C"
+# endif // _cplusplus
+DEBUG_PRINTS * g_pDebug; // define a global debug variable
+
+# if DBG
+
+// For the CHK build we want ODS enabled. For an explanation of these flags see
+// the comment just after the definition of DBG_CONTEXT
+# define DECLARE_DEBUG_PRINTS_OBJECT() \
+ DEBUG_PRINTS * g_pDebug = NULL; \
+ DWORD DEBUG_FLAGS_VAR = DEBUG_FLAG_ERROR;
+
+#else // !DBG
+
+# define DECLARE_DEBUG_PRINTS_OBJECT() \
+ DEBUG_PRINTS * g_pDebug = NULL; \
+ DWORD DEBUG_FLAGS_VAR = 0;
+
+#endif // !DBG
+
+
+//
+// Call the following macro as part of your initialization for program
+// planning to use the debugging class.
+//
+/** DEBUGDEBUG
+# define CREATE_DEBUG_PRINT_OBJECT( pszLabel) \
+ g_pDebug = PuCreateDebugPrintsObject( pszLabel, DEFAULT_OUTPUT_FLAGS);\
+ if ( g_pDebug == NULL) { \
+ OutputDebugStringA( "Unable to Create Debug Print Object \n"); \
+ }
+*/
+
+//
+// Call the following macro once as part of the termination of program
+// which uses the debugging class.
+//
+# define DELETE_DEBUG_PRINT_OBJECT( ) \
+ g_pDebug = PuDeleteDebugPrintsObject( g_pDebug);
+
+
+# define VALID_DEBUG_PRINT_OBJECT() \
+ ( ( g_pDebug != NULL) && g_pDebug->m_fInitialized)
+
+
+//
+// Use the DBG_CONTEXT without any surrounding braces.
+// This is used to pass the values for global DebugPrintObject
+// and File/Line information
+//
+//# define DBG_CONTEXT g_pDebug, __FILE__, __LINE__, __FUNCTION__
+
+// The 3 main tracing macros, each one corresponds to a different level of
+// tracing
+
+// The 3 main tracing macros, each one corresponds to a different level of
+// tracing
+//# define DBGINFO(args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_INFO) { PuDbgPrint args; }}
+//# define DBGWARN(args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_WARN) { PuDbgPrint args; }}
+//# define DBGERROR(args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_ERROR) { PuDbgPrint args; }}
+
+# define DBGINFOW(args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_INFO) { PuDbgPrintW args; }}
+# define DBGWARNW(args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_WARN) { PuDbgPrintW args; }}
+# define DBGERRORW(args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_ERROR) { PuDbgPrintW args; }}
+
+
+//
+// DBGPRINTF() is printing function ( much like printf) but always called
+// with the DBG_CONTEXT as follows
+// DBGPRINTF( ( DBG_CONTEXT, format-string, arguments for format list));
+//
+# define DBGPRINTF DBGINFO
+
+//
+// DPERROR() is printing function ( much like printf) but always called
+// with the DBG_CONTEXT as follows
+// DPERROR( ( DBG_CONTEXT, error, format-string,
+// arguments for format list));
+//
+# define DPERROR( args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_ERROR) { PuDbgPrintError args; }}
+
+# if DBG
+
+# define DBG_CODE(s) s /* echoes code in debugging mode */
+
+// The same 3 main tracing macros however in this case the macros are only compiled
+// into the CHK build. This is necessary because some tracing info used functions or
+// variables which are not compiled into the FRE build.
+# define CHKINFO(args) { PuDbgPrint args; }
+# define CHKWARN(args) { PuDbgPrint args; }
+# define CHKERROR(args) { PuDbgPrint args; }
+
+# define CHKINFOW(args) { PuDbgPrintW args; }
+# define CHKWARNW(args) { PuDbgPrintW args; }
+# define CHKERRORW(args) { PuDbgPrintW args; }
+
+
+#ifndef DBG_ASSERT
+# ifdef _PREFAST_
+# define DBG_ASSERT(exp) ((void)0) /* Do Nothing */
+# define DBG_ASSERT_MSG(exp, pszMsg) ((void)0) /* Do Nothing */
+# define DBG_REQUIRE( exp) ((void) (exp))
+# else // !_PREFAST_
+# define DBG_ASSERT( exp ) \
+ ( (VOID)( ( exp ) || ( DebugBreak(), \
+ PuDbgPrintAssertFailed( DBG_CONTEXT, #exp, "" ) ) ) )
+
+# define DBG_ASSERT_MSG( exp, pszMsg) \
+ ( (VOID)( ( exp ) || ( DebugBreak(), \
+ PuDbgPrintAssertFailed( DBG_CONTEXT, #exp, pszMsg ) ) ) )
+
+# define DBG_REQUIRE( exp ) \
+ DBG_ASSERT( exp )
+# endif // !_PREFAST_
+#endif
+
+
+# define DBG_LOG() PuDbgPrint( DBG_CONTEXT, "\n" )
+
+# define DBG_OPEN_LOG_FILE( pszFile, pszPath ) \
+ PuOpenDbgPrintFile( g_pDebug, (pszFile), (pszPath) )
+
+# define DBG_CLOSE_LOG_FILE( ) \
+ PuCloseDbgPrintFile( g_pDebug )
+
+# define DBG_OPEN_MEMORY_LOG( ) \
+ PuOpenDbgMemoryLog( g_pDebug )
+
+
+# define DBGDUMP( args ) PuDbgDump args
+
+# define DBGPRINT_CURRENT_TIME() PuDbgPrintCurrentTime( DBG_CONTEXT )
+
+# else // !DBG
+
+# define DBG_CODE(s) ((void)0) /* Do Nothing */
+
+# define CHKINFO(args) ((void)0) /* Do Nothing */
+# define CHKWARN(args) ((void)0) /* Do Nothing */
+# define CHKERROR(args) ((void)0) /* Do Nothing */
+
+# define CHKINFOW(args) ((void)0) /* Do Nothing */
+# define CHKWARNW(args) ((void)0) /* Do Nothing */
+# define CHKERRORW(args) ((void)0) /* Do Nothing */
+
+#ifndef DBG_ASSERT
+# define DBG_ASSERT(exp) ((void)0) /* Do Nothing */
+
+# define DBG_ASSERT_MSG(exp, pszMsg) ((void)0) /* Do Nothing */
+
+# define DBG_REQUIRE( exp) ((void) (exp))
+#endif // !DBG_ASSERT
+
+# define DBGDUMP( args) ((void)0) /* Do nothing */
+
+# define DBG_LOG() ((void)0) /* Do Nothing */
+
+# define DBG_OPEN_LOG_FILE( pszFile, pszPath) ((void)0) /* Do Nothing */
+
+# define DBG_OPEN_MEMORY_LOG() ((void)0) /* Do Nothing */
+
+# define DBG_CLOSE_LOG_FILE() ((void)0) /* Do Nothing */
+
+# define DBGPRINT_CURRENT_TIME() ((void)0) /* Do Nothing */
+
+# endif // !DBG
+
+
+// end_user_unmodifiable
+
+// begin_user_unmodifiable
+
+
+#ifdef ASSERT
+# undef ASSERT
+#endif
+
+
+# define ASSERT( exp) DBG_ASSERT( exp)
+
+
+// end_user_unmodifiable
+
+// begin_user_modifiable
+
+//
+// Debugging constants consist of two pieces.
+// All constants in the range 0x0 to 0x8000 are reserved
+// User extensions may include additional constants (bit flags)
+//
+
+# define DEBUG_API_ENTRY 0x00000001L
+# define DEBUG_API_EXIT 0x00000002L
+# define DEBUG_INIT_CLEAN 0x00000004L
+# define DEBUG_ERROR 0x00000008L
+
+ // End of Reserved Range
+# define DEBUG_RESERVED 0x00000FFFL
+
+// end_user_modifiable
+
+
+
+/***********************************************************
+ * Platform Type related variables and macros
+ ************************************************************/
+
+//
+// Enum for product types
+//
+
+typedef enum _PLATFORM_TYPE {
+
+ PtInvalid = 0, // Invalid
+ PtNtWorkstation = 1, // NT Workstation
+ PtNtServer = 2, // NT Server
+
+} PLATFORM_TYPE;
+
+//
+// IISGetPlatformType is the function used to the platform type
+//
+
+extern
+#ifdef __cplusplus
+"C"
+# endif // _cplusplus
+PLATFORM_TYPE
+IISGetPlatformType(
+ VOID
+ );
+
+//
+// External Macros
+//
+
+#define InetIsNtServer( _pt ) ((_pt) == PtNtServer)
+#define InetIsNtWksta( _pt ) ((_pt) == PtNtWorkstation)
+#define InetIsValidPT(_pt) ((_pt) != PtInvalid)
+
+extern
+#ifdef __cplusplus
+"C"
+# endif // _cplusplus
+PLATFORM_TYPE g_PlatformType;
+
+
+// Use the DECLARE_PLATFORM_TYPE macro to declare the platform type
+#define DECLARE_PLATFORM_TYPE() \
+ PLATFORM_TYPE g_PlatformType = PtInvalid;
+
+// Use the INITIALIZE_PLATFORM_TYPE to init the platform type
+// This should typically go inside the DLLInit or equivalent place.
+#define INITIALIZE_PLATFORM_TYPE() \
+ g_PlatformType = IISGetPlatformType();
+
+//
+// Additional Macros to use the Platform Type
+//
+
+#define TsIsNtServer( ) InetIsNtServer(g_PlatformType)
+#define TsIsNtWksta( ) InetIsNtWksta(g_PlatformType)
+#define IISIsValidPlatform() InetIsValidPT(g_PlatformType)
+#define IISPlatformType() (g_PlatformType)
+
+
+/***********************************************************
+ * Some utility functions for Critical Sections
+ ************************************************************/
+
+//
+// IISSetCriticalSectionSpinCount() provides a thunk for the
+// original NT4.0sp3 API SetCriticalSectionSpinCount() for CS with Spin counts
+// Users of this function should definitely dynlink with kernel32.dll,
+// Otherwise errors will surface to a large extent
+//
+extern
+# ifdef __cplusplus
+"C"
+# endif // _cplusplus
+DWORD
+IISSetCriticalSectionSpinCount(
+ LPCRITICAL_SECTION lpCriticalSection,
+ DWORD dwSpinCount
+);
+
+
+//
+// Macro for the calls to SetCriticalSectionSpinCount()
+//
+# define SET_CRITICAL_SECTION_SPIN_COUNT( lpCS, dwSpins) \
+ IISSetCriticalSectionSpinCount( (lpCS), (dwSpins))
+
+//
+// IIS_DEFAULT_CS_SPIN_COUNT is the default value of spins used by
+// Critical sections defined within IIS.
+// NYI: We should have to switch the individual values based on experiments!
+// Current value is an arbitrary choice
+//
+# define IIS_DEFAULT_CS_SPIN_COUNT (1000)
+
+//
+// Initializes a critical section and sets its spin count
+// to IIS_DEFAULT_CS_SPIN_COUNT. Equivalent to
+// InitializeCriticalSectionAndSpinCount(lpCS, IIS_DEFAULT_CS_SPIN_COUNT),
+// but provides a safe thunking layer for older systems that don't provide
+// this API.
+//
+extern
+# ifdef __cplusplus
+"C"
+# endif // _cplusplus
+BOOL
+IISInitializeCriticalSection(
+ LPCRITICAL_SECTION lpCriticalSection
+);
+
+//
+// Macro for the calls to InitializeCriticalSection()
+//
+# define INITIALIZE_CRITICAL_SECTION(lpCS) IISInitializeCriticalSection(lpCS)
+
+# endif /* _DEBUG_HXX_ */
+
+//
+// The following macros allow the automatic naming of certain Win32 objects.
+// See IIS\SVCS\IISRTL\WIN32OBJ.C for details on the naming convention.
+//
+// Set IIS_NAMED_WIN32_OBJECTS to a non-zero value to enable named events,
+// semaphores, and mutexes.
+//
+
+#if DBG
+#define IIS_NAMED_WIN32_OBJECTS 1
+#else
+#define IIS_NAMED_WIN32_OBJECTS 0
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HANDLE
+PuDbgCreateEvent(
+ __in LPSTR FileName,
+ IN ULONG LineNumber,
+ __in LPSTR MemberName,
+ IN PVOID Address,
+ IN BOOL ManualReset,
+ IN BOOL InitialState
+ );
+
+HANDLE
+PuDbgCreateSemaphore(
+ __in LPSTR FileName,
+ IN ULONG LineNumber,
+ __in LPSTR MemberName,
+ IN PVOID Address,
+ IN LONG InitialCount,
+ IN LONG MaximumCount
+ );
+
+HANDLE
+PuDbgCreateMutex(
+ __in LPSTR FileName,
+ IN ULONG LineNumber,
+ __in LPSTR MemberName,
+ IN PVOID Address,
+ IN BOOL InitialOwner
+ );
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#if IIS_NAMED_WIN32_OBJECTS
+
+#define IIS_CREATE_EVENT( membername, address, manual, state ) \
+ PuDbgCreateEvent( \
+ (LPSTR)__FILE__, \
+ (ULONG)__LINE__, \
+ (membername), \
+ (PVOID)(address), \
+ (manual), \
+ (state) \
+ )
+
+#define IIS_CREATE_SEMAPHORE( membername, address, initial, maximum ) \
+ PuDbgCreateSemaphore( \
+ (LPSTR)__FILE__, \
+ (ULONG)__LINE__, \
+ (membername), \
+ (PVOID)(address), \
+ (initial), \
+ (maximum) \
+ )
+
+#define IIS_CREATE_MUTEX( membername, address, initial ) \
+ PuDbgCreateMutex( \
+ (LPSTR)__FILE__, \
+ (ULONG)__LINE__, \
+ (membername), \
+ (PVOID)(address), \
+ (initial) \
+ )
+
+#else // !IIS_NAMED_WIN32_OBJECTS
+
+#define IIS_CREATE_EVENT( membername, address, manual, state ) \
+ CreateEventA( \
+ NULL, \
+ (manual), \
+ (state), \
+ NULL \
+ )
+
+#define IIS_CREATE_SEMAPHORE( membername, address, initial, maximum ) \
+ CreateSemaphoreA( \
+ NULL, \
+ (initial), \
+ (maximum), \
+ NULL \
+ )
+
+#define IIS_CREATE_MUTEX( membername, address, initial ) \
+ CreateMutexA( \
+ NULL, \
+ (initial), \
+ NULL \
+ )
+
+#endif // IIS_NAMED_WIN32_OBJECTS
+
+
+/************************ End of File ***********************/
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj
new file mode 100644
index 0000000000..257df53c47
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 15.0
+ {A2599642-CBE5-4230-8511-3DC2D81874BE}
+ Win32Proj
+ reftrace
+
+
+
+ StaticLibrary
+ v141
+
+
+ true
+
+
+
+ $(ProjectDir)include;$(IIS-Common)Include;$(IncludePath)
+
+
+
+ true
+ precomp.hxx
+ _LIB;%(PreprocessorDefinitions)
+
+
+ Windows
+
+
+
+
+
+ This project is trying to import a missing file: {0}.
+
+
+
+
+
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj.filters b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj.filters
new file mode 100644
index 0000000000..b77ab9c7c1
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj.filters
@@ -0,0 +1,54 @@
+
+
+
+
+ {aaa5bb99-ba5c-4b8d-9ef9-a406282e05a6}
+
+
+ {85a83b74-9536-44d0-a7f7-96e1475f21e9}
+
+
+
+
+ src
+
+
+ src
+
+
+ src
+
+
+ src
+
+
+ src
+
+
+ src
+
+
+ src
+
+
+
+
+ include
+
+
+ include
+
+
+ include
+
+
+ include
+
+
+ include
+
+
+ include
+
+
+
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/irtldbg.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/irtldbg.cpp
new file mode 100644
index 0000000000..06ce025bbe
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/irtldbg.cpp
@@ -0,0 +1,150 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.hxx"
+
+#include
+#include
+#include
+#include
+#include
+
+#define IMPLEMENTATION_EXPORT
+#include
+
+
+void __cdecl
+IrtlTrace(
+ LPCTSTR ptszFormat,
+ ...)
+{
+ TCHAR tszBuff[2048];
+ va_list args;
+
+ va_start(args, ptszFormat);
+ _vsntprintf_s(tszBuff, sizeof(tszBuff) / sizeof(tszBuff[0]), _TRUNCATE, ptszFormat, args);
+ va_end(args);
+
+ DBGPRINTF(( DBG_CONTEXT, "%ls", tszBuff ));
+}
+
+
+
+#ifdef IRTLDEBUG
+
+# if defined(USE_DEBUG_CRTS) && defined(_MSC_VER) && (_MSC_VER >= 1000)
+
+
+# ifdef IRTLDBG_RUNNING_AS_SERVICE
+
+// The default assertion mechanism set up by Visual C++ 4 will not
+// work with Active Server Pages because it's running inside a service
+// and there is no desktop to interact with.
+
+// Note: for this to work properly, #define _WIN32_WINNT 0x400 before
+// including or MB_SERVICE_NOTIFICATION won't be #define'd.
+
+int __cdecl
+AspAssertHandler(
+ int nReportType,
+ char* pszErrorText,
+ int* pnReturn)
+{
+ const char szInfo[] = " (Press ABORT to terminate IIS,"
+ " RETRY to debug this failure,"
+ " or IGNORE to continue.)";
+ char* pszMessageTitle = NULL;
+ int nResult = FALSE;
+
+ *pnReturn = 0; // nothing for _CrtDbgReport to do
+
+ // These flags enable message boxes to show up on the user's console
+ switch (nReportType)
+ {
+ case _CRT_WARN:
+ // If using MFC's TRACE macro (AfxTrace), the report hook
+ // (AspAssertHandler) will get called with _CRT_WARN. Ignore.
+ pszMessageTitle = "Warning";
+ *pnReturn = 0;
+ return FALSE;
+
+ case _CRT_ERROR:
+ pszMessageTitle = "Fatal Error";
+ break;
+
+ case _CRT_ASSERT:
+ pszMessageTitle = "Assertion Failed";
+ break;
+ }
+
+ char* pszMessageText =
+ static_cast(malloc(strlen(pszErrorText) + strlen(szInfo) + 1));
+
+ if (NULL == pszMessageText)
+ return FALSE;
+
+ strcpy(pszMessageText, pszErrorText);
+ strcat(pszMessageText, szInfo);
+
+ const int n = MessageBoxA(NULL, pszMessageText, pszMessageTitle,
+ (MB_SERVICE_NOTIFICATION | MB_TOPMOST
+ | MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION));
+
+ if (n == IDABORT)
+ {
+ exit(1);
+ }
+ else if (n == IDRETRY)
+ {
+ *pnReturn = 1; // tell _CrtDbgReport to start the debugger
+ nResult = TRUE; // tell _CrtDbgReport to run
+ }
+
+ free(pszMessageText);
+
+ return nResult;
+}
+# endif // IRTLDBG_RUNNING_AS_SERVICE
+# endif // _MSC_VER >= 1000
+
+
+
+void
+IrtlDebugInit()
+{
+# if defined(USE_DEBUG_CRTS) && defined(_MSC_VER) && (_MSC_VER >= 1000)
+# ifdef IRTLDBG_RUNNING_AS_SERVICE
+ // If we end up in _CrtDbgReport, don't put up a message box
+ // _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
+ _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
+ _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
+
+ // Use AspAssertHandler to put up a message box instead
+ _CrtSetReportHook(AspAssertHandler);
+# endif // IRTLDBG_RUNNING_AS_SERVICE
+
+
+ // Enable debug heap allocations & check for memory leaks at program exit
+ // The memory leak check will not be performed if inetinfo.exe is
+ // run directly under a debugger, only if it is run as a service.
+ _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF
+ | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
+# endif // _MSC_VER >= 1000
+}
+
+
+
+void
+IrtlDebugTerm()
+{
+# if defined(USE_DEBUG_CRTS) && defined(_MSC_VER) && (_MSC_VER >= 1000)
+# ifdef IRTLDBG_RUNNING_AS_SERVICE
+ // Turn off AspAssertHandler, so that we don't get numerous message boxes
+ // if there are memory leaks on shutdown
+ _CrtSetReportHook(NULL);
+# endif // IRTLDBG_RUNNING_AS_SERVICE
+# endif // _MSC_VER >= 1000
+}
+
+#endif //IRTLDEBUG
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/isplat.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/isplat.cxx
new file mode 100644
index 0000000000..eb13b3edde
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/isplat.cxx
@@ -0,0 +1,63 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.hxx"
+#include "pudebug.h"
+
+#define IMPLEMENTATION_EXPORT
+
+extern "C"
+PLATFORM_TYPE
+IISGetPlatformType(
+ VOID
+)
+/*++
+
+ This function consults the registry and determines the platform type
+ for this machine.
+
+ Arguments:
+
+ None
+
+ Returns:
+ Platform type
+
+--*/
+{
+ OSVERSIONINFOEX osVersionInfoEx = { 0 };
+ DWORDLONG dwlConditionMask = 0;
+ BOOL fReturn = FALSE;
+
+ osVersionInfoEx.dwOSVersionInfoSize = sizeof( osVersionInfoEx );
+
+ //
+ // If we are not workstation (Client)
+ // that means that we are a server or domain controller (Server)
+ //
+ osVersionInfoEx.wProductType = VER_NT_WORKSTATION;
+ VER_SET_CONDITION( dwlConditionMask, VER_PRODUCT_TYPE, VER_EQUAL );
+
+ fReturn = VerifyVersionInfo(
+ &osVersionInfoEx,
+ VER_PRODUCT_TYPE,
+ dwlConditionMask );
+
+ //
+ // VerifyVersionInfo fails if the return value is zero
+ // and GetLastError returns an error code other than ERROR_OLD_WIN_VERSION
+ //
+ if ( !fReturn && GetLastError() != ERROR_OLD_WIN_VERSION )
+ {
+ DPERROR(( DBG_CONTEXT,
+ HRESULT_FROM_WIN32 ( GetLastError() ),
+ "VerifyVersionInfo failed\n" ));
+
+ return PtInvalid;
+ }
+
+ return ( fReturn ) ? PtNtWorkstation : PtNtServer;
+}
+
+
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/memorylog.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/memorylog.cxx
new file mode 100644
index 0000000000..6f303f94e0
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/memorylog.cxx
@@ -0,0 +1,123 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.hxx"
+#include "memorylog.hxx"
+#include "pudebug.h"
+
+CMemoryLog::CMemoryLog(DWORD dwMaxByteSize) :
+ m_fValid(FALSE),
+ m_fCritSecInitialized(FALSE)
+{
+ BOOL fRet;
+
+ fRet = m_buf.Resize(dwMaxByteSize);
+ if (fRet)
+ {
+ m_fValid = TRUE;
+ }
+
+ m_pBufferBegin = (CHAR*) m_buf.QueryPtr();
+ m_pLastMessageEnd = (CHAR*) m_buf.QueryPtr();
+ m_pBufferEnd = ((CHAR*) m_buf.QueryPtr()) + m_buf.QuerySize();
+
+ fRet = InitializeCriticalSectionAndSpinCount(&m_cs,
+ 0x80000000 /* precreate event */ |
+ IIS_DEFAULT_CS_SPIN_COUNT );
+ if (FALSE != fRet)
+ {
+ m_fCritSecInitialized = TRUE;
+ }
+
+}
+
+CMemoryLog::~CMemoryLog()
+{
+ m_pBufferBegin = NULL;
+ m_pLastMessageEnd = NULL;
+ m_pBufferEnd = NULL;
+ m_fValid = FALSE;
+
+ if (m_fCritSecInitialized)
+ {
+ DeleteCriticalSection(&m_cs);
+ m_fCritSecInitialized = FALSE;
+ }
+}
+
+//
+// Appends to end of the circular memory log.
+//
+DWORD
+CMemoryLog::Append(LPCSTR pszOutput,
+ DWORD cchLen
+ )
+{
+ // make sure internal state can accept this request
+ if (FALSE == m_fValid ||
+ FALSE == m_fCritSecInitialized )
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // make sure that we won't think we need less
+ // memory than we do. We are going to add 1 to
+ // this value next, so if it is MAX_UINT then
+ // we will wrap on the add. Don't allow strings
+ // that are that long.
+ if ( (ULONGLONG)cchLen + 1 > MAXDWORD )
+ {
+ return ERROR_ARITHMETIC_OVERFLOW;
+ }
+
+ // make sure the string length will fit inside the buffer
+ if ( cchLen + 1 > m_buf.QuerySize())
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ CHAR * pWhereToWriteMessage = NULL;
+
+ // need to synchronize access to m_pLastMessageEnd
+ EnterCriticalSection(&m_cs);
+
+ // check if the new message will fit into the remaining space in the buffer
+ // previous end (+1) + new length + 1 for NULL
+ if (m_pLastMessageEnd + cchLen + 1 < m_pBufferEnd)
+ {
+ // it will fit in remaining space
+ pWhereToWriteMessage = m_pLastMessageEnd;
+ }
+ else
+ {
+ // start over at the beginning
+ pWhereToWriteMessage = (CHAR*)m_buf.QueryPtr();
+
+ // don't leave extra old goo sitting around in the buffer
+ ZeroMemory(m_pLastMessageEnd, m_pBufferEnd - m_pLastMessageEnd);
+ }
+
+ // set end of message to pWhere + length + 1 for NULL
+ m_pLastMessageEnd = pWhereToWriteMessage + cchLen + 1;
+
+ LeaveCriticalSection(&m_cs);
+
+ // the following memcpy is outside of the criticalsection -
+ // this introduces a race between leaving the criticalsection and
+ // looping back through the buffer before we finish writing.
+ // how likely is this? Not very.
+ //
+ // In addition - moving the memcpy inside of the critsec makes the time spent
+ // quite a bit larger than some simple load/stores that are currently there.
+ //
+ // Plus this is a debugging aid - life isn't fair.
+
+ // actually do the copy
+ memcpy(pWhereToWriteMessage, pszOutput, cchLen);
+
+ // write out a NULL to indicate end of message
+ *(pWhereToWriteMessage + cchLen) = NULL;
+
+ return NO_ERROR;
+}
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/pudebug.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/pudebug.cxx
new file mode 100644
index 0000000000..44e42a21b1
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/pudebug.cxx
@@ -0,0 +1,1164 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+/************************************************************
+ * Include Headers
+ ************************************************************/
+# include "precomp.hxx"
+
+
+# include
+# include
+# include
+# include
+# include
+
+
+# include "pudebug.h"
+# include "memorylog.hxx"
+
+
+/*************************************************************
+ * Global Variables and Default Values
+ *************************************************************/
+
+//
+// TRUE if we're in a test process.
+// There are a few noisy assertions that fire frequently cause of test code issues. These noisy asserts are masking
+// real ones, drastically reducing the value of CHK bits.
+//
+BOOL g_fTestProcess = FALSE;
+
+//
+// HACK HACK
+// suppress shutdown asserts under some hosts
+//
+BOOL g_fAvoidShutdownAsserts = FALSE;
+
+# define MAX_PRINTF_OUTPUT ( 10240)
+
+# define DEFAULT_DEBUG_FLAGS_VALUE ( 0)
+# define DEBUG_FLAGS_REGISTRY_LOCATION_A "DebugFlags"
+# define DEBUG_BREAK_ENABLED_REGKEYNAME_A "BreakOnAssert"
+
+/*************************************************************
+ * Functions
+ *************************************************************/
+
+/********************************************************************++
+
+Routine Description:
+ This function creates a new DEBUG_PRINTS object for the required
+ program.
+
+Arguments:
+ pszPrintLabel pointer to null-terminated string containing
+ the label for program's debugging output
+ dwOutputFlags DWORD containing the output flags to be used.
+
+Returns:
+ pointer to a new DEBUG_PRINTS object on success.
+ Returns NULL on failure.
+--*********************************************************************/
+LPDEBUG_PRINTS
+PuCreateDebugPrintsObject(
+ IN const char * pszPrintLabel,
+ IN DWORD dwOutputFlags)
+{
+
+ LPDEBUG_PRINTS pDebugPrints;
+
+ pDebugPrints = (LPDEBUG_PRINTS ) GlobalAlloc( GPTR, sizeof( DEBUG_PRINTS));
+
+ if ( pDebugPrints != NULL) {
+
+ if ( strlen( pszPrintLabel) < MAX_LABEL_LENGTH) {
+
+ strcpy_s( pDebugPrints->m_rgchLabel,
+ sizeof( pDebugPrints->m_rgchLabel ) / sizeof( pDebugPrints->m_rgchLabel[0]),
+ pszPrintLabel);
+ } else {
+ strncpy_s( pDebugPrints->m_rgchLabel,
+ sizeof( pDebugPrints->m_rgchLabel ) / sizeof( pDebugPrints->m_rgchLabel[0]),
+ pszPrintLabel,
+ MAX_LABEL_LENGTH - 1);
+ }
+
+ memset( pDebugPrints->m_rgchLogFilePath, 0, MAX_PATH);
+ memset( pDebugPrints->m_rgchLogFileName, 0, MAX_PATH);
+
+ pDebugPrints->m_LogFileHandle = INVALID_HANDLE_VALUE;
+
+ pDebugPrints->m_dwOutputFlags = dwOutputFlags;
+ pDebugPrints->m_StdErrHandle = GetStdHandle( STD_ERROR_HANDLE);
+
+ if ( pDebugPrints->m_StdErrHandle == NULL )
+ {
+ pDebugPrints->m_StdErrHandle = INVALID_HANDLE_VALUE;
+ }
+
+ pDebugPrints->m_fInitialized = TRUE;
+ pDebugPrints->m_fBreakOnAssert= TRUE;
+ pDebugPrints->m_pMemoryLog = NULL;
+ }
+
+
+ return ( pDebugPrints);
+} // PuCreateDebugPrintsObject()
+
+
+
+
+/********************************************************************++
+
+Routine Description:
+ This function cleans up the pDebugPrints object and
+ frees the allocated memory.
+
+ Arguments:
+ pDebugPrints poitner to the DEBUG_PRINTS object.
+
+ Returns:
+ NULL on success.
+ pDebugPrints() if the deallocation failed.
+
+--*********************************************************************/
+LPDEBUG_PRINTS
+PuDeleteDebugPrintsObject(
+ IN OUT LPDEBUG_PRINTS pDebugPrints)
+{
+ if ( pDebugPrints != NULL) {
+
+ PuCloseDbgMemoryLog(pDebugPrints);
+ DWORD dwError = PuCloseDbgPrintFile( pDebugPrints);
+
+ if ( dwError != NO_ERROR) {
+
+ SetLastError( dwError);
+ } else {
+
+ // returns NULL on success
+ pDebugPrints =
+ (LPDEBUG_PRINTS ) GlobalFree( pDebugPrints);
+ }
+ }
+
+ return ( pDebugPrints);
+
+} // PuDeleteDebugPrintsObject()
+
+
+
+
+VOID
+PuSetDbgOutputFlags(
+ IN OUT LPDEBUG_PRINTS pDebugPrints,
+ IN DWORD dwFlags)
+{
+
+ if ( pDebugPrints == NULL) {
+
+ SetLastError( ERROR_INVALID_PARAMETER);
+ } else {
+
+ pDebugPrints->m_dwOutputFlags = dwFlags;
+ }
+
+ return;
+} // PuSetDbgOutputFlags()
+
+
+
+DWORD
+PuGetDbgOutputFlags(
+ IN const LPDEBUG_PRINTS pDebugPrints)
+{
+ return ( pDebugPrints != NULL) ? pDebugPrints->m_dwOutputFlags : 0;
+
+} // PuGetDbgOutputFlags()
+
+
+static DWORD
+PuOpenDbgFileLocal(
+ IN OUT LPDEBUG_PRINTS pDebugPrints)
+{
+ if ( pDebugPrints == NULL)
+ return ERROR_INVALID_PARAMETER;
+
+ if ( pDebugPrints->m_LogFileHandle != INVALID_HANDLE_VALUE) {
+
+ //
+ // Silently return as a file handle exists.
+ //
+ return ( NO_ERROR);
+ }
+
+ pDebugPrints->m_LogFileHandle =
+ CreateFileA( pDebugPrints->m_rgchLogFileName,
+ GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if ( pDebugPrints->m_LogFileHandle == INVALID_HANDLE_VALUE) {
+
+ CHAR pchBuffer[1024];
+ DWORD dwError = GetLastError();
+
+ sprintf_s( pchBuffer,
+ sizeof( pchBuffer ) / sizeof( pchBuffer[0] ),
+ " Critical Error: Unable to Open File %s. Error = %d\n",
+ pDebugPrints->m_rgchLogFileName, dwError);
+ OutputDebugStringA( pchBuffer);
+
+ return ( dwError);
+ }
+
+ return ( NO_ERROR);
+} // PuOpenDbgFileLocal()
+
+
+
+
+
+DWORD
+PuOpenDbgPrintFile(
+ IN OUT LPDEBUG_PRINTS pDebugPrints,
+ IN const char * pszFileName,
+ IN const char * pszPathForFile)
+/********************************************************************++
+
+ Opens a Debugging log file. This function can be called to set path
+ and name of the debugging file.
+
+ Arguments:
+ pszFileName pointer to null-terminated string containing
+ the name of the file.
+
+ pszPathForFile pointer to null-terminated string containing the
+ path for the given file.
+ If NULL, then the old place where dbg files were
+ stored is used or if none,
+ default windows directory will be used.
+
+ Returns:
+ Win32 error codes. NO_ERROR on success.
+
+--*********************************************************************/
+
+{
+ if ( pszFileName == NULL || pDebugPrints == NULL) {
+
+ return ( ERROR_INVALID_PARAMETER);
+ }
+
+ //
+ // Setup the Path information. if necessary.
+ //
+
+ if ( pszPathForFile != NULL) {
+
+ // Path is being changed.
+
+ if ( strlen( pszPathForFile) < MAX_PATH) {
+
+ strcpy_s( pDebugPrints->m_rgchLogFilePath,
+ sizeof( pDebugPrints->m_rgchLogFilePath ) / sizeof( pDebugPrints->m_rgchLogFilePath[0] ),
+ pszPathForFile);
+ } else {
+
+ return ( ERROR_INVALID_PARAMETER);
+ }
+ } else {
+
+ if ( pDebugPrints->m_rgchLogFilePath[0] == '\0' && // no old path
+ !GetWindowsDirectoryA( pDebugPrints->m_rgchLogFilePath, MAX_PATH)) {
+
+ //
+ // Unable to get the windows default directory. Use current dir
+ //
+
+ strcpy_s( pDebugPrints->m_rgchLogFilePath,
+ sizeof( pDebugPrints->m_rgchLogFilePath ) / sizeof( pDebugPrints->m_rgchLogFilePath[0] ),
+ ".");
+ }
+ }
+
+ //
+ // Should need be, we need to create this directory for storing file
+ //
+
+
+ //
+ // Form the complete Log File name and open the file.
+ //
+ if ( (strlen( pszFileName) + strlen( pDebugPrints->m_rgchLogFilePath))
+ >= MAX_PATH) {
+
+ return ( ERROR_NOT_ENOUGH_MEMORY);
+ }
+
+ // form the complete path
+ strcpy_s( pDebugPrints->m_rgchLogFileName,
+ sizeof( pDebugPrints->m_rgchLogFileName ) / sizeof( pDebugPrints->m_rgchLogFileName[0] ),
+ pDebugPrints->m_rgchLogFilePath);
+
+ if ( pDebugPrints->m_rgchLogFileName[ strlen(pDebugPrints->m_rgchLogFileName) - 1]
+ != '\\') {
+ // Append a \ if necessary
+ strcat_s( pDebugPrints->m_rgchLogFileName,
+ sizeof( pDebugPrints->m_rgchLogFileName ) / sizeof( pDebugPrints->m_rgchLogFileName[0] ),
+ "\\");
+ };
+ strcat_s( pDebugPrints->m_rgchLogFileName,
+ sizeof( pDebugPrints->m_rgchLogFileName ) / sizeof( pDebugPrints->m_rgchLogFileName[0] ),
+ pszFileName);
+
+ return PuOpenDbgFileLocal( pDebugPrints);
+
+} // PuOpenDbgPrintFile()
+
+
+
+
+DWORD
+PuReOpenDbgPrintFile(
+ IN OUT LPDEBUG_PRINTS pDebugPrints)
+/********************************************************************++
+
+ This function closes any open log file and reopens a new copy.
+ If necessary. It makes a backup copy of the file.
+
+--*********************************************************************/
+
+{
+ if ( pDebugPrints == NULL) {
+ return ( ERROR_INVALID_PARAMETER);
+ }
+
+ PuCloseDbgPrintFile( pDebugPrints); // close any existing file.
+
+ if ( pDebugPrints->m_dwOutputFlags & DbgOutputBackup) {
+
+ // MakeBkupCopy();
+
+ OutputDebugStringA( " Error: MakeBkupCopy() Not Yet Implemented\n");
+ }
+
+ return PuOpenDbgFileLocal( pDebugPrints);
+
+} // PuReOpenDbgPrintFile()
+
+
+
+
+DWORD
+PuCloseDbgPrintFile(
+ IN OUT LPDEBUG_PRINTS pDebugPrints)
+{
+ DWORD dwError = NO_ERROR;
+
+ if ( pDebugPrints == NULL ) {
+ dwError = ERROR_INVALID_PARAMETER;
+ } else {
+
+ if ( pDebugPrints->m_LogFileHandle != INVALID_HANDLE_VALUE) {
+
+ FlushFileBuffers( pDebugPrints->m_LogFileHandle);
+
+ if ( !CloseHandle( pDebugPrints->m_LogFileHandle)) {
+
+ CHAR pchBuffer[1024];
+
+ dwError = GetLastError();
+
+ sprintf_s( pchBuffer,
+ sizeof( pchBuffer ) / sizeof( pchBuffer[0] ),
+ "CloseDbgPrintFile() : CloseHandle( %p) failed."
+ " Error = %d\n",
+ pDebugPrints->m_LogFileHandle,
+ dwError);
+ OutputDebugStringA( pchBuffer);
+ }
+
+ pDebugPrints->m_LogFileHandle = INVALID_HANDLE_VALUE;
+ }
+ }
+
+ return ( dwError);
+} // DEBUG_PRINTS::CloseDbgPrintFile()
+
+DWORD
+PuOpenDbgMemoryLog(IN OUT LPDEBUG_PRINTS pDebugPrints)
+{
+ DWORD dwError;
+ CMemoryLog * pLog = NULL;
+
+ if (NULL == pDebugPrints)
+ {
+ dwError = ERROR_INVALID_PARAMETER;
+ goto done;
+ }
+
+ if (NULL != pDebugPrints->m_pMemoryLog)
+ {
+ dwError = ERROR_SUCCESS;
+ goto done;
+ }
+
+ pLog = new CMemoryLog(1024 * 512); // max size of 512 K
+ if (NULL == pLog)
+ {
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+
+ // save away the pointer
+ pDebugPrints->m_pMemoryLog = pLog;
+
+ // make sure output gets to the log
+ pDebugPrints->m_dwOutputFlags |= DbgOutputMemory;
+
+ dwError = NO_ERROR;
+done:
+ return dwError;
+}
+
+DWORD
+PuCloseDbgMemoryLog(IN OUT LPDEBUG_PRINTS pDebugPrints)
+{
+ DWORD dwError;
+
+ if (NULL == pDebugPrints)
+ {
+ dwError = ERROR_INVALID_PARAMETER;
+ goto done;
+ }
+ if (NULL != pDebugPrints->m_pMemoryLog)
+ {
+ CMemoryLog * pLog = (CMemoryLog*) (pDebugPrints->m_pMemoryLog);
+ delete pLog;
+ pDebugPrints->m_pMemoryLog = NULL;
+ }
+
+ dwError = NO_ERROR;
+done:
+ return dwError;
+}
+
+VOID
+PupOutputMessage(
+ IN LPDEBUG_PRINTS pDebugPrints,
+ IN STRA *straOutput
+ )
+{
+ if ( pDebugPrints != NULL)
+ {
+ if ( ( pDebugPrints->m_dwOutputFlags & DbgOutputStderr) &&
+ ( pDebugPrints->m_StdErrHandle != INVALID_HANDLE_VALUE ) ) {
+
+ DWORD nBytesWritten;
+
+ ( VOID) WriteFile( pDebugPrints->m_StdErrHandle,
+ straOutput->QueryStr(),
+ straOutput->QueryCCH(),
+ &nBytesWritten,
+ NULL);
+ }
+
+ if ( pDebugPrints->m_dwOutputFlags & DbgOutputLogFile &&
+ pDebugPrints->m_LogFileHandle != INVALID_HANDLE_VALUE) {
+
+ DWORD nBytesWritten;
+
+ //
+ // Truncation of log files. Not yet implemented.
+
+ ( VOID) WriteFile( pDebugPrints->m_LogFileHandle,
+ straOutput->QueryStr(),
+ straOutput->QueryCCH(),
+ &nBytesWritten,
+ NULL);
+
+ }
+
+ if ( (pDebugPrints->m_dwOutputFlags & DbgOutputMemory) &&
+ (NULL != pDebugPrints->m_pMemoryLog) )
+ {
+ CMemoryLog* pLog = (CMemoryLog*) (pDebugPrints->m_pMemoryLog);
+ pLog->Append(straOutput->QueryStr(), straOutput->QueryCCH());
+ }
+
+ }
+
+
+ if ( pDebugPrints == NULL ||
+ pDebugPrints->m_dwOutputFlags & DbgOutputKdb)
+ {
+ OutputDebugStringA( straOutput->QueryStr() );
+ }
+
+ return;
+}
+
+void
+FormatMsgToBuffer( IN OUT STRA * pSTRAOutput,
+ IN LPDEBUG_PRINTS pDebugPrints,
+ IN LPCSTR pszFilePath,
+ IN DWORD nLineNum,
+ IN LPCSTR pszFunctionName,
+ IN LPCSTR pszFormat,
+ IN va_list * pargsList)
+{
+ LPCSTR pszFileName = strrchr( pszFilePath, '\\');
+ int cchPrologue = 0;
+ HRESULT hr = S_OK;
+ DWORD cchOutput = 0;
+
+ //
+ // Skip the complete path name and retain file name in pszName
+ //
+
+ if ( pszFileName== NULL) {
+
+ // if skipping \\ yields nothing use whole path.
+ pszFileName = pszFilePath;
+ }
+ else
+ {
+ // skip past the '\'
+ ++pszFileName;
+ }
+
+ // Format the message header as: tid label!function [file @ line number]:message
+ cchPrologue = sprintf_s( pSTRAOutput->QueryStr(),
+ pSTRAOutput->QuerySize(),
+ "%lu %hs!%hs [%hs @ %d]:",
+ GetCurrentThreadId(),
+ pDebugPrints ? pDebugPrints->m_rgchLabel : "??",
+ pszFunctionName,
+ pszFileName,
+ nLineNum);
+
+ // we directly touched the buffer - however, wait to SyncWithBuffer
+ // until the rest of the operations are done. Do NOT call QueryCCH() it will be WRONG.
+
+
+ // Format the incoming message using vsnprintf() so that the overflows are
+ // captured
+
+ cchOutput = _vsnprintf_s( pSTRAOutput->QueryStr() + cchPrologue,
+ pSTRAOutput->QuerySize() - cchPrologue,
+ pSTRAOutput->QuerySize() - cchPrologue - 1,
+ pszFormat, *pargsList);
+
+ if ( cchOutput == -1 )
+ {
+ // couldn't fit this in the original STRA size. Try a heap allocation.
+ hr = pSTRAOutput->Resize(MAX_PRINTF_OUTPUT);
+ if (FAILED(hr))
+ {
+ // Can't allocate, therefore don't give back half done results
+ pSTRAOutput->Reset();
+ return;
+ }
+
+ cchOutput = _vsnprintf_s( pSTRAOutput->QueryStr() + cchPrologue,
+ pSTRAOutput->QuerySize() - cchPrologue,
+ pSTRAOutput->QuerySize() - cchPrologue - 1,
+ pszFormat, *pargsList);
+ if (cchOutput == -1)
+ {
+ // we need to NULL terminate, as _vsnprintf failed to do that for us.
+ pSTRAOutput->QueryStr()[pSTRAOutput->QuerySize() - 1] = '\0';
+ }
+ }
+
+ // we directly touched the buffer - therefore:
+ pSTRAOutput->SyncWithBuffer();
+
+ return;
+} // FormatMsgToBuffer()
+
+
+/********************************************************************++
+Routine Description:
+ Main function that examines the incoming message and prints out a header
+ and the message.
+
+Arguments:
+ pDebugPrints - pointer to the debug print object
+ pszFilePaht - pointer to the file from where this function is called
+ nLineNum - Line number within the file
+ pszFormat - formatting string to use.
+
+Returns:
+ None
+--*********************************************************************/
+
+VOID
+PuDbgPrint(
+ IN OUT LPDEBUG_PRINTS pDebugPrints,
+ IN const char * pszFilePath,
+ IN int nLineNum,
+ IN const char * pszFunctionName,
+ IN const char * pszFormat,
+ ...)
+{
+ STACK_STRA(straOutput, 256);
+ va_list argsList;
+ DWORD dwErr;
+
+ // get a local copy of the error code so that it is not lost
+ dwErr = GetLastError();
+
+ va_start( argsList, pszFormat);
+ FormatMsgToBuffer( &straOutput,
+ pDebugPrints,
+ pszFilePath,
+ nLineNum,
+ pszFunctionName,
+ pszFormat,
+ &argsList);
+
+ va_end( argsList);
+
+ //
+ // Send the outputs to respective files.
+ //
+ PupOutputMessage( pDebugPrints, &straOutput);
+
+
+ SetLastError( dwErr );
+
+ return;
+} // PuDbgPrint()
+
+void
+FormatMsgToBufferW( IN OUT STRU * pSTRUOutput,
+ IN LPDEBUG_PRINTS pDebugPrints,
+ IN LPCSTR pszFilePath,
+ IN DWORD nLineNum,
+ IN LPCSTR pszFunctionName,
+ IN LPCWSTR pszFormat,
+ IN va_list * pargsList)
+{
+ LPCSTR pszFileName = strrchr( pszFilePath, '\\');
+ int cchPrologue = 0;
+ HRESULT hr = S_OK;
+ DWORD cchOutput = 0;
+
+ //
+ // Skip the complete path name and retain file name in pszName
+ //
+
+ if ( pszFileName== NULL) {
+
+ // if skipping \\ yields nothing use whole path.
+ pszFileName = pszFilePath;
+ }
+ else
+ {
+ // skip past the '\'
+ ++pszFileName;
+ }
+
+ // Format the message header as: tid label!function [file @ line number]:message
+ cchPrologue = swprintf_s( pSTRUOutput->QueryStr(),
+ pSTRUOutput->QuerySizeCCH(),
+ L"%lu %hs!%hs [%hs @ %d]:",
+ GetCurrentThreadId(),
+ pDebugPrints ? pDebugPrints->m_rgchLabel : "??",
+ pszFunctionName,
+ pszFileName,
+ nLineNum);
+
+ // we directly touched the buffer - however, wait to SyncWithBuffer
+ // until the rest of the operations are done. Do NOT call QueryCCH() it will be WRONG.
+
+ // Format the incoming message using vsnprintf() so that the overflows are
+ // captured
+
+ cchOutput = _vsnwprintf_s( pSTRUOutput->QueryStr() + cchPrologue,
+ pSTRUOutput->QuerySizeCCH() - cchPrologue,
+ // DEBUGDEBUG
+ //pSTRUOutput->QueryBuffer()->QuerySize() / sizeof(WCHAR) - cchPrologue - 1, // this is a count of characters
+ pSTRUOutput->QuerySizeCCH() - cchPrologue - 1,
+ pszFormat, *pargsList);
+
+ if ( cchOutput == -1 )
+ {
+ // couldn't fit this in the original STRA size. Try a heap allocation.
+ hr = pSTRUOutput->Resize(MAX_PRINTF_OUTPUT);
+ if (FAILED(hr))
+ {
+ // Can't allocate, therefore don't give back half done results
+ pSTRUOutput->Reset();
+ return;
+ }
+
+ cchOutput = _vsnwprintf_s( pSTRUOutput->QueryStr() + cchPrologue,
+ pSTRUOutput->QuerySizeCCH() - cchPrologue,
+ //DEBUGDEBUG
+ //pSTRUOutput->QueryBuffer()->QuerySize() / sizeof(WCHAR) - cchPrologue - 1, // this is a count of characters
+ pSTRUOutput->QuerySizeCCH() - cchPrologue - 1,
+ pszFormat, *pargsList);
+ if (cchOutput == -1)
+ {
+ // we need to NULL terminate, as _vsnprintf failed to do that for us.
+ //DEBUGDEBUG
+ pSTRUOutput->QueryStr()[pSTRUOutput->QuerySizeCCH() - 1] = L'\0';
+
+ }
+ }
+
+ // we directly touched the buffer - therefore:
+ pSTRUOutput->SyncWithBuffer();
+
+ return;
+} // FormatMsgToBuffer()
+
+extern "C"
+VOID
+PuDbgPrintW(
+ IN OUT LPDEBUG_PRINTS pDebugPrints,
+ IN const char * pszFilePath,
+ IN int nLineNum,
+ IN const char * pszFunctionName,
+ IN const WCHAR * pszFormat,
+ ...
+)
+{
+ STACK_STRU(struOutput, 256);
+ va_list argsList;
+ DWORD dwErr;
+ HRESULT hr;
+ // get a local copy of the error code so that it is not lost
+ dwErr = GetLastError();
+
+ va_start( argsList, pszFormat);
+ FormatMsgToBufferW( &struOutput,
+ pDebugPrints,
+ pszFilePath,
+ nLineNum,
+ pszFunctionName,
+ pszFormat,
+ &argsList);
+
+ va_end( argsList);
+
+ //
+ // Send the outputs to respective files.
+ //
+ STACK_STRA(straOutput, 256);
+ hr = straOutput.CopyWTruncate(struOutput.QueryStr(), struOutput.QueryCCH());
+ if (FAILED(hr))
+ {
+ goto done;
+ }
+
+ PupOutputMessage( pDebugPrints, &straOutput);
+
+done:
+
+ SetLastError( dwErr );
+
+ return;
+}
+
+/********************************************************************++
+Routine Description:
+ This function behaves like PuDbgPrint() but also prints out formatted
+ Error message indicating what failed.
+
+Arguments:
+ pDebugPrints - pointer to the debug print object
+ pszFilePaht - pointer to the file from where this function is called
+ nLineNum - Line number within the file
+ dwError - Error code for which the formatted error message should
+ be printed
+ pszFormat - formatting string to use.
+
+Returns:
+ None
+--*********************************************************************/
+VOID
+PuDbgPrintError(
+ IN OUT LPDEBUG_PRINTS pDebugPrints,
+ IN const char * pszFilePath,
+ IN int nLineNum,
+ IN const char * pszFunctionName,
+ IN DWORD dwError,
+ IN const char * pszFormat,
+ ...) // argsList
+{
+ STACK_STRA(straOutput, 256);
+ va_list argsList;
+ DWORD dwErr;
+
+ // get a local copy of the error code so that it is not lost
+ dwErr = GetLastError();
+
+ va_start( argsList, pszFormat);
+ FormatMsgToBuffer( &straOutput,
+ pDebugPrints,
+ pszFilePath,
+ nLineNum,
+ pszFunctionName,
+ pszFormat,
+ &argsList);
+
+ va_end( argsList);
+
+
+ //
+ // obtain the formatted error message for error code
+ //
+
+ LPSTR lpErrorBuffer = NULL;
+ DWORD nRet;
+#pragma prefast(suppress: __WARNING_ANSI_APICALL,"debug spew is ansi")
+ nRet =
+ FormatMessageA((FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM),
+ NULL, // lpSource
+ dwError,
+ LANG_NEUTRAL,
+ (LPSTR ) &lpErrorBuffer, // pointer to store buffer allocated
+ 0, // size of buffer
+ NULL // lpArguments
+ );
+
+ if (lpErrorBuffer)
+ {
+ CHAR pszErrorOut[64]; // 64 from: (/t=)4 + (Error(=)7 + (%x=)18 (0x + 16hex on 64 bit systems) + (): =)3 == 32 + some more slop
+ _snprintf_s( pszErrorOut,
+ sizeof( pszErrorOut ) / sizeof( pszErrorOut[0] ),
+ sizeof(pszErrorOut) / sizeof(CHAR) - 1, // leave space for NULL.
+ "\tError(%x): ",
+ dwError);
+ pszErrorOut[63] = '\0';
+
+ // if these appends fail, nothing to be done about it therefore just ignore the return values
+ straOutput.Append(pszErrorOut);
+
+ straOutput.Append(lpErrorBuffer);
+ straOutput.Append("\n");
+ }
+
+ //
+ // Send the outputs to respective files.
+ //
+ PupOutputMessage( pDebugPrints, &straOutput);
+
+ // free the buffer if any was allocated
+ if ( lpErrorBuffer != NULL) {
+ LocalFree (lpErrorBuffer);
+ }
+
+ SetLastError( dwErr );
+
+ return;
+} // PuDbgPrintError()
+
+
+
+VOID
+PuDbgDump(
+ IN OUT LPDEBUG_PRINTS pDebugPrints,
+ IN const char * pszFilePath,
+ IN int nLineNum,
+ IN const char * pszFunctionName,
+ IN const char * pszDump
+ )
+{
+ UNREFERENCED_PARAMETER( pszFunctionName );
+ UNREFERENCED_PARAMETER( nLineNum );
+
+ LPCSTR pszFileName = strrchr( pszFilePath, '\\');
+ DWORD dwErr;
+ DWORD cbDump;
+
+
+ //
+ // Skip the complete path name and retain file name in pszName
+ //
+
+ if ( pszFileName== NULL) {
+
+ pszFileName = pszFilePath;
+ }
+
+ dwErr = GetLastError();
+
+ // No message header for this dump
+ cbDump = (DWORD)strlen( pszDump);
+
+ //
+ // Send the outputs to respective files.
+ //
+
+ if ( pDebugPrints != NULL)
+ {
+ if ( ( pDebugPrints->m_dwOutputFlags & DbgOutputStderr) &&
+ ( pDebugPrints->m_StdErrHandle != INVALID_HANDLE_VALUE ) ) {
+
+ DWORD nBytesWritten;
+
+ ( VOID) WriteFile( pDebugPrints->m_StdErrHandle,
+ pszDump,
+ cbDump,
+ &nBytesWritten,
+ NULL);
+ }
+
+ if ( pDebugPrints->m_dwOutputFlags & DbgOutputLogFile &&
+ pDebugPrints->m_LogFileHandle != INVALID_HANDLE_VALUE) {
+
+ DWORD nBytesWritten;
+
+ //
+ // Truncation of log files. Not yet implemented.
+
+ ( VOID) WriteFile( pDebugPrints->m_LogFileHandle,
+ pszDump,
+ cbDump,
+ &nBytesWritten,
+ NULL);
+
+ }
+
+ if ( (pDebugPrints->m_dwOutputFlags & DbgOutputMemory) &&
+ (NULL != pDebugPrints->m_pMemoryLog) )
+ {
+ CMemoryLog * pLog = (CMemoryLog*)(pDebugPrints->m_pMemoryLog);
+ pLog->Append(pszDump, cbDump);
+ }
+ }
+
+ if ( pDebugPrints == NULL
+ || pDebugPrints->m_dwOutputFlags & DbgOutputKdb)
+ {
+ OutputDebugStringA( pszDump);
+ }
+
+ SetLastError( dwErr );
+
+ return;
+} // PuDbgDump()
+
+//
+// N.B. For PuDbgCaptureContext() to work properly, the calling function
+// *must* be __cdecl, and must have a "normal" stack frame. So, we decorate
+// PuDbgAssertFailed() with the __cdecl modifier and disable the frame pointer
+// omission (FPO) optimization.
+//
+
+// DEBUGDEBUG
+//#pragma optimize( "y", off ) // disable frame pointer omission (FPO)
+#pragma optimize( "", off )
+
+INT
+__cdecl
+PuDbgAssertFailed(
+ IN OUT LPDEBUG_PRINTS pDebugPrints,
+ IN const char * pszFilePath,
+ IN int nLineNum,
+ IN const char * pszFunctionName,
+ IN const char * pszExpression,
+ IN const char * pszMessage)
+/********************************************************************++
+ This function calls assertion failure and records assertion failure
+ in log file.
+
+--*********************************************************************/
+
+{
+ PuDbgPrintAssertFailed( pDebugPrints, pszFilePath, nLineNum, pszFunctionName,
+ pszExpression,
+ pszMessage );
+ if ( !g_fAvoidShutdownAsserts )
+ {
+ DebugBreak();
+ }
+
+ return 0;
+} // PuDbgAssertFailed()
+
+#pragma optimize( "", on ) // restore frame pointer omission (FPO)
+
+INT
+WINAPI
+PuDbgPrintAssertFailed(
+ IN OUT LPDEBUG_PRINTS pDebugPrints,
+ IN const char * pszFilePath,
+ IN int nLineNum,
+ IN const char * pszFunctionName,
+ IN const char * pszExpression,
+ IN const char * pszMessage)
+/********************************************************************++
+ This function calls assertion failure and records assertion failure
+ in log file.
+
+--*********************************************************************/
+
+{
+ PuDbgPrint( pDebugPrints, pszFilePath, nLineNum, pszFunctionName,
+ " Assertion (%s) Failed: %s\n",
+ pszExpression,
+ pszMessage );
+ return 0;
+} // PuDbgPrintAssertFailed()
+
+
+
+VOID
+PuDbgPrintCurrentTime(
+ IN OUT LPDEBUG_PRINTS pDebugPrints,
+ IN const char * pszFilePath,
+ IN int nLineNum,
+ IN const char * pszFunctionName
+ )
+/********************************************************************++
+ This function generates the current time and prints it out to debugger
+ for tracing out the path traversed, if need be.
+
+ Arguments:
+ pszFile pointer to string containing the name of the file
+ lineNum line number within the file where this function is called.
+
+ Returns:
+ NO_ERROR always.
+--*********************************************************************/
+
+{
+ PuDbgPrint( pDebugPrints, pszFilePath, nLineNum, pszFunctionName,
+ " TickCount = %u\n",
+ GetTickCount()
+ );
+
+ return;
+} // PrintOutCurrentTime()
+
+
+
+
+DWORD
+PuLoadDebugFlagsFromReg(IN HKEY hkey, IN DWORD dwDefault)
+/********************************************************************++
+ This function reads the debug flags assumed to be stored in
+ the location "DebugFlags" under given key.
+ If there is any error the default value is returned.
+--*********************************************************************/
+
+{
+ DWORD err;
+ DWORD dwDebug = dwDefault;
+ DWORD dwBuffer;
+ DWORD cbBuffer = sizeof(dwBuffer);
+ DWORD dwType;
+
+ if( hkey != NULL )
+ {
+ err = RegQueryValueExA( hkey,
+ DEBUG_FLAGS_REGISTRY_LOCATION_A,
+ NULL,
+ &dwType,
+ (LPBYTE)&dwBuffer,
+ &cbBuffer );
+
+ if( ( err == NO_ERROR ) && ( dwType == REG_DWORD ) )
+ {
+ dwDebug = dwBuffer;
+ }
+ }
+
+ return dwDebug;
+} // PuLoadDebugFlagsFromReg()
+
+
+
+
+DWORD
+PuLoadDebugFlagsFromRegStr(IN LPCSTR pszRegKey, IN DWORD dwDefault)
+/********************************************************************++
+Description:
+ This function reads the debug flags assumed to be stored in
+ the location "DebugFlags" under given key location in registry.
+ If there is any error the default value is returned.
+
+Arguments:
+ pszRegKey - pointer to registry key location from where to read the key from
+ dwDefault - default values in case the read from registry fails
+
+Returns:
+ Newly read value on success
+ If there is any error the dwDefault is returned.
+--*********************************************************************/
+
+{
+ HKEY hkey = NULL;
+
+ DWORD dwVal = dwDefault;
+
+ DWORD dwError = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
+ pszRegKey,
+ 0,
+ KEY_READ,
+ &hkey);
+ if ( dwError == NO_ERROR) {
+ dwVal = PuLoadDebugFlagsFromReg( hkey, dwDefault);
+ RegCloseKey( hkey);
+ hkey = NULL;
+ }
+
+ return ( dwVal);
+} // PuLoadDebugFlagsFromRegStr()
+
+
+
+
+
+DWORD
+PuSaveDebugFlagsInReg(IN HKEY hkey, IN DWORD dwDbg)
+/********************************************************************++
+ Saves the debug flags in registry. On failure returns the error code for
+ the operation that failed.
+
+--*********************************************************************/
+{
+ DWORD err;
+
+ if( hkey == NULL ) {
+
+ err = ERROR_INVALID_PARAMETER;
+ } else {
+
+ err = RegSetValueExA(hkey,
+ DEBUG_FLAGS_REGISTRY_LOCATION_A,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&dwDbg,
+ sizeof(dwDbg) );
+ }
+
+ return (err);
+} // PuSaveDebugFlagsInReg()
+
+
+VOID
+PuDbgCaptureContext (
+ OUT PCONTEXT ContextRecord
+ )
+{
+ //
+ // This space intentionally left blank.
+ //
+ UNREFERENCED_PARAMETER( ContextRecord );
+} // PuDbgCaptureContext
+
+
+/****************************** End of File ******************************/
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/reftrace.c b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/reftrace.c
new file mode 100644
index 0000000000..bfb78aa717
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/reftrace.c
@@ -0,0 +1,232 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+//#include
+//#include
+//#include
+#include
+#include
+#include
+#include
+
+
+PTRACE_LOG
+CreateRefTraceLog(
+ IN LONG LogSize,
+ IN LONG ExtraBytesInHeader
+ )
+/*++
+
+Routine Description:
+
+ Creates a new (empty) ref count trace log buffer.
+
+Arguments:
+
+ LogSize - The number of entries in the log.
+
+ ExtraBytesInHeader - The number of extra bytes to include in the
+ log header. This is useful for adding application-specific
+ data to the log.
+
+Return Value:
+
+ PTRACE_LOG - Pointer to the newly created log if successful,
+ NULL otherwise.
+
+--*/
+{
+
+ return CreateTraceLog(
+ LogSize,
+ ExtraBytesInHeader,
+ sizeof(REF_TRACE_LOG_ENTRY)
+ );
+
+} // CreateRefTraceLog
+
+
+VOID
+DestroyRefTraceLog(
+ IN PTRACE_LOG Log
+ )
+/*++
+
+Routine Description:
+
+ Destroys a ref count trace log buffer created with CreateRefTraceLog().
+
+Arguments:
+
+ Log - The ref count trace log buffer to destroy.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ DestroyTraceLog( Log );
+
+} // DestroyRefTraceLog
+
+
+//
+// N.B. For RtlCaptureBacktrace() to work properly, the calling function
+// *must* be __cdecl, and must have a "normal" stack frame. So, we decorate
+// WriteRefTraceLog[Ex]() with the __cdecl modifier and disable the frame
+// pointer omission (FPO) optimization.
+//
+
+//#pragma optimize( "y", off ) // disable frame pointer omission (FPO)
+#pragma optimize( "", off ) // disable frame pointer omission (FPO)
+
+LONG
+__cdecl
+WriteRefTraceLog(
+ IN PTRACE_LOG Log,
+ IN LONG NewRefCount,
+ IN CONST VOID * Context
+ )
+/*++
+
+Routine Description:
+
+ Writes a new entry to the specified ref count trace log. The entry
+ written contains the updated reference count and a stack backtrace
+ leading up to the current caller.
+
+Arguments:
+
+ Log - The log to write to.
+
+ NewRefCount - The updated reference count.
+
+ Context - An uninterpreted context to associate with the log entry.
+
+Return Value:
+
+ Index of entry in log.
+
+--*/
+{
+
+ return WriteRefTraceLogEx(
+ Log,
+ NewRefCount,
+ Context,
+ REF_TRACE_EMPTY_CONTEXT, // suppress use of optional extra contexts
+ REF_TRACE_EMPTY_CONTEXT,
+ REF_TRACE_EMPTY_CONTEXT
+ );
+
+} // WriteRefTraceLog
+
+
+
+
+LONG
+__cdecl
+WriteRefTraceLogEx(
+ IN PTRACE_LOG Log,
+ IN LONG NewRefCount,
+ IN CONST VOID * Context,
+ IN CONST VOID * Context1, // optional extra context
+ IN CONST VOID * Context2, // optional extra context
+ IN CONST VOID * Context3 // optional extra context
+ )
+/*++
+
+Routine Description:
+
+ Writes a new "extended" entry to the specified ref count trace log.
+ The entry written contains the updated reference count, stack backtrace
+ leading up to the current caller and extra context information.
+
+Arguments:
+
+ Log - The log to write to.
+
+ NewRefCount - The updated reference count.
+
+ Context - An uninterpreted context to associate with the log entry.
+ Context1 - An uninterpreted context to associate with the log entry.
+ Context2 - An uninterpreted context to associate with the log entry.
+ Context3 - An uninterpreted context to associate with the log entry.
+
+ NOTE Context1/2/3 are "optional" in that the caller may suppress
+ debug display of these values by passing REF_TRACE_EMPTY_CONTEXT
+ for each of them.
+
+Return Value:
+
+ Index of entry in log.
+
+--*/
+{
+
+ REF_TRACE_LOG_ENTRY entry;
+ ULONG hash;
+ DWORD cStackFramesSkipped;
+
+ //
+ // Initialize the entry.
+ //
+
+ RtlZeroMemory(
+ &entry,
+ sizeof(entry)
+ );
+
+ //
+ // Set log entry members.
+ //
+
+ entry.NewRefCount = NewRefCount;
+ entry.Context = Context;
+ entry.Thread = GetCurrentThreadId();
+ entry.Context1 = Context1;
+ entry.Context2 = Context2;
+ entry.Context3 = Context3;
+
+ //
+ // Capture the stack backtrace. Normally, we skip two stack frames:
+ // one for this routine, and one for RtlCaptureBacktrace() itself.
+ // For non-Ex callers who come in via WriteRefTraceLog,
+ // we skip three stack frames.
+ //
+
+ if ( entry.Context1 == REF_TRACE_EMPTY_CONTEXT
+ && entry.Context2 == REF_TRACE_EMPTY_CONTEXT
+ && entry.Context3 == REF_TRACE_EMPTY_CONTEXT
+ ) {
+
+ cStackFramesSkipped = 2;
+
+ } else {
+
+ cStackFramesSkipped = 1;
+
+ }
+
+ RtlCaptureStackBackTrace(
+ cStackFramesSkipped,
+ REF_TRACE_LOG_STACK_DEPTH,
+ entry.Stack,
+ &hash
+ );
+
+ //
+ // Write it to the log.
+ //
+
+ return WriteTraceLog(
+ Log,
+ &entry
+ );
+
+} // WriteRefTraceLogEx
+
+#pragma optimize( "", on ) // restore frame pointer omission (FPO)
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/tracelog.c b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/tracelog.c
new file mode 100644
index 0000000000..58eeb4863f
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/tracelog.c
@@ -0,0 +1,239 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+//#include
+//#include
+//#include
+#include
+#include
+#include
+#include
+#include
+
+
+#define ALLOC_MEM(cb) (PVOID)LocalAlloc( LPTR, (cb) )
+#define FREE_MEM(ptr) (VOID)LocalFree( (HLOCAL)(ptr) )
+
+
+
+PTRACE_LOG
+CreateTraceLog(
+ IN LONG LogSize,
+ IN LONG ExtraBytesInHeader,
+ IN LONG EntrySize
+ )
+/*++
+
+Routine Description:
+
+ Creates a new (empty) trace log buffer.
+
+Arguments:
+
+ LogSize - The number of entries in the log.
+
+ ExtraBytesInHeader - The number of extra bytes to include in the
+ log header. This is useful for adding application-specific
+ data to the log.
+
+ EntrySize - The size (in bytes) of each entry.
+
+Return Value:
+
+ PTRACE_LOG - Pointer to the newly created log if successful,
+ NULL otherwise.
+
+--*/
+{
+
+ ULONG ulTotalSize = 0;
+ ULONG ulLogSize = 0;
+ ULONG ulEntrySize = 0;
+ ULONG ulTmpResult = 0;
+ ULONG ulExtraBytesInHeader = 0;
+ PTRACE_LOG log = NULL;
+ HRESULT hr = S_OK;
+
+ //
+ // Sanity check the parameters.
+ //
+
+ //DBG_ASSERT( LogSize > 0 );
+ //DBG_ASSERT( EntrySize > 0 );
+ //DBG_ASSERT( ExtraBytesInHeader >= 0 );
+ //DBG_ASSERT( ( EntrySize & 3 ) == 0 );
+
+ //
+ // converting to unsigned long. Since all these values are positive
+ // so its safe to cast them to their unsigned equivalent directly.
+ //
+ ulLogSize = (ULONG) LogSize;
+ ulEntrySize = (ULONG) EntrySize;
+ ulExtraBytesInHeader = (ULONG) ExtraBytesInHeader;
+
+ //
+ // Check if the multiplication operation will overflow a LONG
+ // ulTotalSize = LogSize * EntrySize;
+ //
+ hr = ULongMult( ulLogSize, ulEntrySize, &ulTotalSize );
+ if ( FAILED(hr) )
+ {
+ SetLastError( ERROR_ARITHMETIC_OVERFLOW );
+ return NULL;
+ }
+
+ //
+ // check for overflow in addition operation.
+ // ulTmpResult = sizeof(TRACE_LOG) + ulExtraBytesInHeader
+ //
+ hr = ULongAdd( (ULONG) sizeof(TRACE_LOG), ulExtraBytesInHeader, &ulTmpResult );
+ if ( FAILED(hr) )
+ {
+ SetLastError( ERROR_ARITHMETIC_OVERFLOW );
+ return NULL;
+ }
+
+ //
+ // check for overflow in addition operation.
+ // ulTotalSize = ulTotalSize + ulTmpResult;
+ //
+ hr = ULongAdd( ulTmpResult, ulTotalSize, &ulTotalSize );
+ if ( FAILED(hr) )
+ {
+ SetLastError( ERROR_ARITHMETIC_OVERFLOW );
+ return NULL;
+ }
+
+ if ( ulTotalSize > (ULONG) 0x7FFFFFFF )
+ {
+ SetLastError( ERROR_ARITHMETIC_OVERFLOW );
+ return NULL;
+ }
+
+ //
+ // Allocate & initialize the log structure.
+ //
+
+ log = (PTRACE_LOG)ALLOC_MEM( ulTotalSize );
+
+ //
+ // Initialize it.
+ //
+
+ if( log != NULL ) {
+
+ RtlZeroMemory( log, ulTotalSize );
+
+ log->Signature = TRACE_LOG_SIGNATURE;
+ log->LogSize = LogSize;
+ log->NextEntry = -1;
+ log->EntrySize = EntrySize;
+ log->LogBuffer = (PUCHAR)( log + 1 ) + ExtraBytesInHeader;
+ }
+
+ return log;
+
+} // CreateTraceLog
+
+
+VOID
+DestroyTraceLog(
+ IN PTRACE_LOG Log
+ )
+/*++
+
+Routine Description:
+
+ Destroys a trace log buffer created with CreateTraceLog().
+
+Arguments:
+
+ Log - The trace log buffer to destroy.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ if ( Log != NULL ) {
+ //DBG_ASSERT( Log->Signature == TRACE_LOG_SIGNATURE );
+
+ Log->Signature = TRACE_LOG_SIGNATURE_X;
+ FREE_MEM( Log );
+ }
+
+} // DestroyTraceLog
+
+
+LONG
+WriteTraceLog(
+ IN PTRACE_LOG Log,
+ IN PVOID Entry
+ )
+/*++
+
+Routine Description:
+
+ Writes a new entry to the specified trace log.
+
+Arguments:
+
+ Log - The log to write to.
+
+ Entry - Pointer to the data to write. This buffer is assumed to be
+ Log->EntrySize bytes long.
+
+Return Value:
+
+ Index of entry in log. This is useful for correlating the output
+ of !inetdbg.ref to a particular point in the output debug stream
+
+--*/
+{
+
+ PUCHAR target;
+ ULONG index;
+
+ //DBG_ASSERT( Log != NULL );
+ //DBG_ASSERT( Log->Signature == TRACE_LOG_SIGNATURE );
+ //DBG_ASSERT( Entry != NULL );
+
+ //
+ // Find the next slot, copy the entry to the slot.
+ //
+
+ index = ( (ULONG) InterlockedIncrement( &Log->NextEntry ) ) % (ULONG) Log->LogSize;
+
+ //DBG_ASSERT( index < (ULONG) Log->LogSize );
+
+ target = Log->LogBuffer + ( index * Log->EntrySize );
+
+ RtlCopyMemory(
+ target,
+ Entry,
+ Log->EntrySize
+ );
+
+ return index;
+} // WriteTraceLog
+
+
+VOID
+ResetTraceLog(
+ IN PTRACE_LOG Log
+ )
+{
+
+ //DBG_ASSERT( Log != NULL );
+ //DBG_ASSERT( Log->Signature == TRACE_LOG_SIGNATURE );
+
+ RtlZeroMemory(
+ ( Log + 1 ),
+ Log->LogSize * Log->EntrySize
+ );
+
+ Log->NextEntry = -1;
+
+} // ResetTraceLog
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/win32obj.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/win32obj.cxx
new file mode 100644
index 0000000000..cd6987d860
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/win32obj.cxx
@@ -0,0 +1,348 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.hxx"
+#include "pudebug.h"
+
+#define MAX_OBJECT_NAME 256 // chars
+
+
+LONG g_PuDbgEventsCreated = 0;
+LONG g_PuDbgSemaphoresCreated = 0;
+LONG g_PuDbgMutexesCreated = 0;
+
+
+
+LPSTR
+PuDbgpBuildObjectName(
+ __in LPSTR ObjectNameBuffer,
+ IN ULONG ObjectNameBufferCch,
+ __in LPSTR FileName,
+ IN ULONG LineNumber,
+ __in LPSTR MemberName,
+ IN PVOID Address
+ )
+
+/*++
+
+Routine Description:
+
+ Internal routine that builds an appropriate object name based on
+ the file name, line number, member name, address, and process ID.
+
+Arguments:
+
+ ObjectNameBuffer - Pointer to the target buffer for the name.
+
+ FileName - The filename of the source creating the object. This
+ is __FILE__ of the caller.
+
+ LineNumber - The line number within the source. This is __LINE__
+ of the caller.
+
+ MemberName - The member/global variable name where the object handle
+ is to be stored.
+
+ Address - The address of the containing structure/class or of the
+ global itself.
+
+Return Value:
+
+ LPSTR - Pointer to ObjectNameBuffer if successful, NULL otherwise.
+
+ N.B. This routine always returns NULL when running under Win9x.
+
+--*/
+
+{
+
+ PLATFORM_TYPE platformType;
+ LPSTR fileNamePart;
+ LPSTR result;
+
+ //
+ // We have no convenient way to dump objects w/ names from
+ // Win9x, so we'll only enable this functionality under NT.
+ //
+
+ // platformType = IISGetPlatformType();
+
+ //
+ // By default IIS-Duct-tape will only run on NT platforms. So
+ // do not worry about getting the platform types yet.
+ //
+ platformType = PtNtServer;
+ result = NULL;
+
+ if( platformType == PtNtServer ||
+ platformType == PtNtWorkstation ) {
+
+ //
+ // Find the filename part of the incoming source file name.
+ //
+
+ fileNamePart = strrchr( FileName, '\\' );
+
+ if( fileNamePart == NULL ) {
+ fileNamePart = strrchr( FileName, '/' );
+ }
+
+ if( fileNamePart == NULL ) {
+ fileNamePart = strrchr( FileName, ':' );
+ }
+
+ if( fileNamePart == NULL ) {
+ fileNamePart = FileName;
+ } else {
+ fileNamePart++;
+ }
+
+ //
+ // Ensure we don't overwrite our object name buffer.
+ //
+
+ if( ( sizeof(":1234567890 :12345678 PID:1234567890") +
+ strlen( fileNamePart ) +
+ strlen( MemberName ) ) < MAX_OBJECT_NAME ) {
+
+ sprintf_s(
+ ObjectNameBuffer,
+ ObjectNameBufferCch,
+ "%s:%lu %s:%08p PID:%lu",
+ fileNamePart,
+ LineNumber,
+ MemberName,
+ Address,
+ GetCurrentProcessId()
+ );
+
+ result = ObjectNameBuffer;
+
+ }
+
+ }
+
+ return result;
+
+} // PuDbgpBuildObjectName
+
+
+HANDLE
+PuDbgCreateEvent(
+ __in LPSTR FileName,
+ IN ULONG LineNumber,
+ __in LPSTR MemberName,
+ IN PVOID Address,
+ IN BOOL ManualReset,
+ IN BOOL InitialState
+ )
+
+/*++
+
+Routine Description:
+
+ Creates a new event object.
+
+Arguments:
+
+ FileName - The filename of the source creating the object. This
+ is __FILE__ of the caller.
+
+ LineNumber - The line number within the source. This is __LINE__
+ of the caller.
+
+ MemberName - The member/global variable name where the object handle
+ is to be stored.
+
+ Address - The address of the containing structure/class or of the
+ global itself.
+
+ ManualReset - TRUE to create a manual reset event, FALSE to create
+ an automatic reset event.
+
+ InitialState - The intitial state of the event object.
+
+Return Value:
+
+ HANDLE - Handle to the object if successful, NULL otherwise.
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER( Address );
+ UNREFERENCED_PARAMETER( MemberName );
+ UNREFERENCED_PARAMETER( LineNumber );
+ UNREFERENCED_PARAMETER( FileName );
+
+ LPSTR objName = NULL;
+ HANDLE objHandle;
+ //CHAR objNameBuffer[MAX_OBJECT_NAME];
+
+/*
+ disable passing names to event creation
+ Longhorn forces some security checks that
+ prevent hostable webcore to work on checked builds
+ (at least ASP requests are failing when
+ trying to create event)
+
+ objName = PuDbgpBuildObjectName(
+ objNameBuffer,
+ FileName,
+ LineNumber,
+ MemberName,
+ Address
+ );
+*/
+ objHandle = CreateEventA(
+ NULL, // lpEventAttributes
+ ManualReset, // bManualReset
+ InitialState, // bInitialState
+ objName // lpName
+ );
+
+ if( objHandle != NULL ) {
+ InterlockedIncrement( &g_PuDbgEventsCreated );
+ }
+
+ return objHandle;
+
+} // PuDbgCreateEvent
+
+
+HANDLE
+PuDbgCreateSemaphore(
+ __in LPSTR FileName,
+ IN ULONG LineNumber,
+ __in LPSTR MemberName,
+ IN PVOID Address,
+ IN LONG InitialCount,
+ IN LONG MaximumCount
+ )
+
+/*++
+
+Routine Description:
+
+ Creates a new semaphore object.
+
+Arguments:
+
+ FileName - The filename of the source creating the object. This
+ is __FILE__ of the caller.
+
+ LineNumber - The line number within the source. This is __LINE__
+ of the caller.
+
+ MemberName - The member/global variable name where the object handle
+ is to be stored.
+
+ Address - The address of the containing structure/class or of the
+ global itself.
+
+ InitialCount - The initial count of the semaphore.
+
+ MaximumCount - The maximum count of the semaphore.
+
+Return Value:
+
+ HANDLE - Handle to the object if successful, NULL otherwise.
+
+--*/
+
+{
+
+ LPSTR objName;
+ HANDLE objHandle;
+ CHAR objNameBuffer[MAX_OBJECT_NAME];
+
+ objName = PuDbgpBuildObjectName(
+ objNameBuffer,
+ sizeof( objNameBuffer) / sizeof( objNameBuffer[0] ),
+ FileName,
+ LineNumber,
+ MemberName,
+ Address
+ );
+
+ objHandle = CreateSemaphoreA(
+ NULL, // lpSemaphoreAttributes
+ InitialCount, // lInitialCount
+ MaximumCount, // lMaximumCount
+ objName // lpName
+ );
+
+ if( objHandle != NULL ) {
+ InterlockedIncrement( &g_PuDbgSemaphoresCreated );
+ }
+
+ return objHandle;
+
+} // PuDbgCreateSemaphore
+
+
+HANDLE
+PuDbgCreateMutex(
+ __in LPSTR FileName,
+ IN ULONG LineNumber,
+ __in LPSTR MemberName,
+ IN PVOID Address,
+ IN BOOL InitialOwner
+ )
+
+/*++
+
+Routine Description:
+
+ Creates a new mutex object.
+
+Arguments:
+
+ FileName - The filename of the source creating the object. This
+ is __FILE__ of the caller.
+
+ LineNumber - The line number within the source. This is __LINE__
+ of the caller.
+
+ MemberName - The member/global variable name where the object handle
+ is to be stored.
+
+ Address - The address of the containing structure/class or of the
+ global itself.
+
+ InitialOwner - TRUE if the mutex should be created "owned".
+
+Return Value:
+
+ HANDLE - Handle to the object if successful, NULL otherwise.
+
+--*/
+
+{
+
+ LPSTR objName;
+ HANDLE objHandle;
+ CHAR objNameBuffer[MAX_OBJECT_NAME];
+
+ objName = PuDbgpBuildObjectName(
+ objNameBuffer,
+ sizeof( objNameBuffer) / sizeof( objNameBuffer[0] ),
+ FileName,
+ LineNumber,
+ MemberName,
+ Address
+ );
+
+ objHandle = CreateMutexA(
+ NULL, // lpMutexAttributes
+ InitialOwner, // bInitialOwner,
+ objName // lpName
+ );
+
+ if( objHandle != NULL ) {
+ InterlockedIncrement( &g_PuDbgMutexesCreated );
+ }
+
+ return objHandle;
+
+} // PuDbgCreateMutex
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.h
new file mode 100644
index 0000000000..63a67d68f4
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.h
@@ -0,0 +1,64 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#ifndef _BLDVER_H_
+#define _BLDVER_H_
+
+#define STR_HELPER(x) #x
+#define WSTR_HELPER(x) L#x
+#define NUM_TO_STR(x) STR_HELPER(x)
+#define NUM_TO_WSTR(x) WSTR_HELPER(x)
+
+//
+// Build versions are properties of the build system but can be overwritten below
+//
+// #define PRODUCT_MAJOR 7
+// #define PRODUCT_MINOR 1
+// #define BUILD_MAJOR 1972
+// #define BUILD_MINOR 0
+
+#define PRODUCT_MAJOR_STRING NUM_TO_STR(PRODUCT_MAJOR)
+#define PRODUCT_MAJOR_STRING_L NUM_TO_WSTR(PRODUCT_MAJOR)
+#define PRODUCT_MAJOR_NUMBER PRODUCT_MAJOR
+
+#define PRODUCT_MINOR_STRING NUM_TO_STR(PRODUCT_MINOR)
+#define PRODUCT_MINOR_STRING_L NUM_TO_WSTR(PRODUCT_MINOR)
+#define PRODUCT_MINOR_NUMBER PRODUCT_MINOR
+
+#define BUILD_MAJOR_STRING NUM_TO_STR(BUILD_MAJOR)
+#define BUILD_MAJOR_STRING_L NUM_TO_WSTR(BUILD_MAJOR)
+#define BUILD_MAJOR_NUMBER BUILD_MAJOR
+
+#define BUILD_MINOR_STRING NUM_TO_STR(BUILD_MINOR)
+#define BUILD_MINOR_STRING_L NUM_TO_WSTR(BUILD_MINOR)
+#define BUILD_MINOR_NUMBER BUILD_MINOR
+
+#define BUILD_NUMBER BUILD_MAJOR_STRING "." BUILD_MINOR_STRING
+#define BUILD_NUM BUILD_MAJOR , BUILD_MINOR
+#define PRODUCT_NUMBER PRODUCT_MAJOR_STRING "." PRODUCT_MINOR_STRING
+#define PRODUCT_NUM PRODUCT_MAJOR , PRODUCT_MINOR
+#define INET_VERSION PRODUCT_MAJOR_STRING "." PRODUCT_MINOR_STRING "." BUILD_MAJOR_STRING "." BUILD_MINOR_STRING
+#define INET_VERSION_L PRODUCT_MAJOR_STRING_L L"." PRODUCT_MINOR_STRING_L L"." BUILD_MAJOR_STRING_L L"." BUILD_MINOR_STRING_L
+#define INET_VER PRODUCT_MAJOR , PRODUCT_MINOR , BUILD_MAJOR , BUILD_MINOR
+
+#define BUILD_PRIVATE "Built by IISBLD on IISBLD.\0"
+
+#undef VER_PRODUCTVERSION
+#undef VER_PRODUCTVERSION_STR
+#undef VER_PRODUCTMAJORVERSION
+#undef VER_PRODUCTMINORVERSION
+#undef VER_PRODUCTBUILD
+#undef VER_PRODUCTBUILD_QFE
+#undef VER_PRODUCTNAME_STR
+#undef VER_COMPANYNAME_STR
+
+#define VER_PRODUCTVERSION PRODUCT_MAJOR,PRODUCT_MINOR,BUILD_MAJOR,BUILD_MINOR
+#define VER_PRODUCTVERSION_STR PRODUCT_MAJOR_STRING "." PRODUCT_MINOR_STRING "." BUILD_MAJOR_STRING "." BUILD_MINOR_STRING
+#define VER_PRODUCTMAJORVERSION PRODUCT_MAJOR
+#define VER_PRODUCTMINORVERSION PRODUCT_MINOR
+#define VER_PRODUCTBUILD BUILD_MAJOR
+#define VER_PRODUCTBUILD_QFE BUILD_MINOR
+#define VER_PRODUCTNAME_STR "Microsoft Web Platform Extensions"
+#define VER_COMPANYNAME_STR "Microsoft Corporation"
+
+#endif
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.rc b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.rc
new file mode 100644
index 0000000000..30a96499ec
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.rc
@@ -0,0 +1,73 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+// BLDVER.RC - Standard version resource for CoreXT applications.
+
+// Before including this file into your .rc, define the following
+// macros for your application (don't forget the \0's):
+// #define RC_VERSION_FILE_DESCRIPTION "Test DLL\0"
+// #define RC_VERSION_INTERNAL_NAME "Test\0"
+// #define RC_VERSION_ORIGINAL_FILE_NAME "Test.DLL\0"
+
+#include
+#include
+
+VS_VERSION_INFO VERSIONINFO
+
+FILEVERSION INET_VER
+PRODUCTVERSION INET_VER
+
+FILEFLAGSMASK 0x3fL
+#ifdef DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+
+//
+// Global definitions
+//
+#ifndef RC_VERSION_COMPANY_NAME
+ #define RC_VERSION_COMPANY_NAME "Microsoft Corporation\0"
+#endif
+
+#ifndef RC_VERSION_PRODUCT_NAME
+ #define RC_VERSION_PRODUCT_NAME "Microsoft\256 Web Platform Extensions\0"
+#endif
+
+#ifndef RC_VERSION_LEGAL_COPYRIGHT
+ #define RC_VERSION_LEGAL_COPYRIGHT "Copyright \251 Microsoft Corporation\0"
+#endif
+
+#ifndef RC_VERSION_LEGAL_TRADEMARKS
+ #define RC_VERSION_LEGAL_TRADEMARKS "Microsoft\256 is a registered trademark of Microsoft Corporation.\0"
+#endif
+
+FILEOS 0x4L
+FILETYPE 0x1L
+FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", RC_VERSION_COMPANY_NAME
+ VALUE "FileDescription", RC_VERSION_FILE_DESCRIPTION
+ VALUE "InternalName", RC_VERSION_INTERNAL_NAME
+ VALUE "LegalCopyright", RC_VERSION_LEGAL_COPYRIGHT
+ VALUE "LegalTrademarks", RC_VERSION_LEGAL_TRADEMARKS
+ VALUE "OriginalFilename", RC_VERSION_ORIGINAL_FILE_NAME
+ VALUE "ProductName", RC_VERSION_PRODUCT_NAME
+ VALUE "FileVersion", INET_VERSION
+ VALUE "ProductVersion", INET_VERSION
+ VALUE "PrivateBuild", BUILD_PRIVATE
+#ifdef OLEREGISTER
+ VALUE "OLESelfRegister","\0"
+#endif
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Setup.sln b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Setup.sln
new file mode 100644
index 0000000000..4ec3c19636
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Setup.sln
@@ -0,0 +1,41 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26730.12
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iisca", "iisca\lib\iisca.vcxproj", "{7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CommonLib", "IIS-Common\lib\CommonLib.vcxproj", "{B54A8F61-60DE-4AD9-87CA-D102F230678E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Debug|x64.ActiveCfg = Debug|x64
+ {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Debug|x64.Build.0 = Debug|x64
+ {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Debug|x86.ActiveCfg = Debug|Win32
+ {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Debug|x86.Build.0 = Debug|Win32
+ {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Release|x64.ActiveCfg = Release|x64
+ {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Release|x64.Build.0 = Release|x64
+ {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Release|x86.ActiveCfg = Release|Win32
+ {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Release|x86.Build.0 = Release|Win32
+ {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x64.ActiveCfg = Debug|x64
+ {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x64.Build.0 = Debug|x64
+ {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x86.ActiveCfg = Debug|Win32
+ {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x86.Build.0 = Debug|Win32
+ {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x64.ActiveCfg = Release|x64
+ {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x64.Build.0 = Release|x64
+ {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x86.ActiveCfg = Release|Win32
+ {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {3DC22D38-F38B-420A-9AD1-77F2512B35FF}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/LICENSE b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/LICENSE
new file mode 100644
index 0000000000..21071075c2
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/LICENSE
@@ -0,0 +1,21 @@
+ MIT License
+
+ Copyright (c) Microsoft Corporation. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/README.md b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/README.md
new file mode 100644
index 0000000000..22e594aa6c
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/README.md
@@ -0,0 +1,18 @@
+Microsoft IIS Setup
+--------------------------------
+
+The repository contains setup resources shared by IIS Out-Of-Band (OOB) products.
+
+### Contributing
+
+This project welcomes contributions and suggestions. Most contributions require you to agree to a
+Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
+the rights to use your contribution. For details, visit https://cla.microsoft.com.
+
+When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
+a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
+provided by the bot. You will only need to do this once across all repos using our CLA.
+
+This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
+For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
+contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/appsearch/appsearch.wxi b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/appsearch/appsearch.wxi
new file mode 100644
index 0000000000..820cc86f4e
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/appsearch/appsearch.wxi
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/build/exports.props b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/build/exports.props
new file mode 100644
index 0000000000..94f411d056
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/build/exports.props
@@ -0,0 +1,23 @@
+
+
+
+
+
+ $(MSBuildThisFileDirectory)..\
+
+
+
+
+
+ <_IIS-CommonExportsPath>$(IIS-Setup)\IIS-Common\build\exports.props
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/build/submodule.props b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/build/submodule.props
new file mode 100644
index 0000000000..d51d7f8d8e
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/build/submodule.props
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.cpp
new file mode 100644
index 0000000000..883a228a33
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.cpp
@@ -0,0 +1,59 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+
+HRESULT
+CheckInstallToSharedConfig(
+ IN MSIHANDLE hInstall,
+ BOOL * pbShouldInstall
+ )
+{
+ HRESULT hr = S_OK;
+ STRU strShared;
+ STRU strWriteToShared;
+
+ *pbShouldInstall = FALSE;
+
+ //Check if config is shared
+ hr = MsiUtilGetProperty( hInstall, L"IISCONFIGISSHARED", &strShared );
+ if ( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+ if( 0 != wcscmp( strShared.QueryStr(), L"1" ) )
+ {
+ //config is not shared, tell caller to schedule executeCA for config
+ IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"IIS Configuration is NOT shared. Setup will schedule the deferred custom action.");
+ *pbShouldInstall = TRUE;
+ goto exit;
+ }
+
+ //
+ //config is shared lets check IIUSESHAREDCONFIG Property
+ //
+ hr = MsiUtilGetProperty( hInstall, L"IIUSESHAREDCONFIG", &strWriteToShared );
+ if ( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+ if( 0 == wcscmp( strWriteToShared.QueryStr(), L"1" ) )
+ {
+ //Config is shared but property is set
+ //tell caller to schedule executeCA for config
+ //
+ IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"IIS Configuration IS shared. IIUSESHAREDCONFIG property indicated that setup SHOULD schedule the deferred custom action..");
+ *pbShouldInstall = TRUE;
+ }
+ else
+ {
+ IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"IIS Configuration IS shared. IIUSESHAREDCONFIG property indicated that setup should NOT schedule the deferred custom action.");
+ }
+
+exit:
+ return hr;
+}
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.h
new file mode 100644
index 0000000000..0ac0ea9852
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.h
@@ -0,0 +1,8 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+HRESULT
+CheckInstallToSharedConfig(
+ IN MSIHANDLE hInstall,
+ BOOL * pbShouldInstall
+ );
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/CustomAction.def b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/CustomAction.def
new file mode 100644
index 0000000000..8ba47da929
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/CustomAction.def
@@ -0,0 +1,15 @@
+; Copyright (c) Microsoft Corporation. All rights reserved.
+; Licensed under the MIT license.
+
+LIBRARY iisca
+
+EXPORTS
+
+ ; IIS Common Config custom actions
+
+ IISScheduleInstallCA
+ IISScheduleUninstallCA
+ IISExecuteCA
+ IISBeginTransactionCA
+ IISRollbackTransactionCA
+ IISCommitTransactionCA
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.cpp
new file mode 100644
index 0000000000..b57a5d3037
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.cpp
@@ -0,0 +1,271 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+//
+// Public functions
+//
+
+HRESULT
+RegisterCgiRestriction(
+ IN IAppHostAdminManager * pAdminMgr,
+ IN CONST WCHAR * szConfigPath,
+ IN CONST WCHAR * szPath,
+ IN BOOL fAllowed,
+ IN OPTIONAL CONST WCHAR * szGroupId,
+ IN OPTIONAL CONST WCHAR * szDescription
+ )
+{
+ HRESULT hr = NOERROR;
+
+ CComPtr pCgiRestrictionSection;
+ CComPtr pCgiRestrictionCollection;
+ CComPtr pNewCgiRestrictionElement;
+
+ BSTR bstrAppHostConfigPath = SysAllocString(szConfigPath);
+ BSTR bstrCgiRestriction = SysAllocString( L"system.webServer/security/isapiCgiRestriction" );
+ BSTR bstrAdd = SysAllocString( L"add" );
+
+ if( !bstrAppHostConfigPath ||
+ !bstrCgiRestriction ||
+ !bstrAdd )
+ {
+ hr = E_OUTOFMEMORY;
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+ //
+ // Remove any existing web service first,
+ // ignore any resulting errors.
+ //
+
+ hr = UnRegisterCgiRestriction(
+ pAdminMgr,
+ szConfigPath,
+ szPath,
+ FALSE // do NOT expand environment strings
+ );
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ // press on regardless
+ }
+
+ hr = UnRegisterCgiRestriction(
+ pAdminMgr,
+ szConfigPath,
+ szPath,
+ TRUE // DO expand environment strings
+ );
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ // press on regardless
+ }
+
+ //
+ // Get the ISAPI CGI Restriction collection
+ //
+
+ hr = pAdminMgr->GetAdminSection( bstrCgiRestriction,
+ bstrAppHostConfigPath,
+ &pCgiRestrictionSection );
+
+
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+ hr = pCgiRestrictionSection->get_Collection( &pCgiRestrictionCollection );
+
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+ //
+ // Create a new element
+ //
+
+ hr = pCgiRestrictionCollection->CreateNewElement( bstrAdd,
+ &pNewCgiRestrictionElement );
+
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+ hr = SetElementStringProperty(
+ pNewCgiRestrictionElement,
+ L"path",
+ szPath
+ );
+
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+ hr = SetElementStringProperty(
+ pNewCgiRestrictionElement,
+ L"allowed",
+ fAllowed ? L"true" : L"false"
+ );
+
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+ if( szGroupId && *szGroupId )
+ {
+ hr = SetElementStringProperty(
+ pNewCgiRestrictionElement,
+ L"groupId",
+ szGroupId
+ );
+
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+ }
+
+ if( szDescription && *szDescription )
+ {
+ hr = SetElementStringProperty(
+ pNewCgiRestrictionElement,
+ L"description",
+ szDescription
+ );
+
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+ }
+
+ //
+ // Add the new element
+ //
+
+ hr = pCgiRestrictionCollection->AddElement( pNewCgiRestrictionElement );
+
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+exit:
+
+ SysFreeString( bstrAppHostConfigPath );
+ SysFreeString( bstrCgiRestriction );
+ SysFreeString( bstrAdd );
+
+ return hr;
+}
+
+HRESULT
+UnRegisterCgiRestriction(
+ IN IAppHostAdminManager * pAdminMgr,
+ IN CONST WCHAR * szConfigPath,
+ IN CONST WCHAR * szPath,
+ IN BOOL fExpandPath
+ )
+{
+ HRESULT hr = NOERROR;
+
+ CComPtr pCgiRestrictionSection;
+ CComPtr pCgiRestrictionCollection;
+
+ BSTR bstrAppHostConfigPath = SysAllocString(szConfigPath);
+ BSTR bstrCgiRestriction = SysAllocString( L"system.webServer/security/isapiCgiRestriction" );
+
+ UINT numDeleted;
+
+ STRU expandedPath;
+
+ if( !bstrAppHostConfigPath ||
+ !bstrCgiRestriction )
+ {
+ hr = E_OUTOFMEMORY;
+ DBGERROR_HR( hr );
+ goto exit;
+ }
+
+ if (fExpandPath)
+ {
+ hr = expandedPath.CopyAndExpandEnvironmentStrings(szPath);
+
+ if (FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ szPath = expandedPath.QueryStr();
+ }
+
+ //
+ // Remove from the ISAPI CGI Restriction collection
+ //
+
+ hr = pAdminMgr->GetAdminSection( bstrCgiRestriction,
+ bstrAppHostConfigPath,
+ &pCgiRestrictionSection );
+
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = pCgiRestrictionSection->get_Collection( &pCgiRestrictionCollection );
+
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = DeleteAllElementsFromCollection( pCgiRestrictionCollection,
+ L"path",
+ szPath,
+ FIND_ELEMENT_CASE_INSENSITIVE,
+ &numDeleted
+ );
+
+ if( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ if( numDeleted == 0 )
+ {
+ DBGWARN(( DBG_CONTEXT,
+ "Expected to find %S in ISAPI CGI Restriction collection\n",
+ szPath ));
+ }
+
+exit:
+
+ SysFreeString( bstrAppHostConfigPath );
+ SysFreeString( bstrCgiRestriction );
+
+ return hr;
+}
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.h
new file mode 100644
index 0000000000..68ae838d07
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.h
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+
+#ifndef _CGI_RESTRICTIONS_H_
+#define _CGI_RESTRICTIONS_H_
+
+
+HRESULT
+RegisterCgiRestriction(
+ IN IAppHostAdminManager * pAdminMgr,
+ IN CONST WCHAR * szConfigPath,
+ IN CONST WCHAR * szPath,
+ IN BOOL fAllowed,
+ IN OPTIONAL CONST WCHAR * szGroupId,
+ IN OPTIONAL CONST WCHAR * szDescription
+ );
+
+
+HRESULT
+UnRegisterCgiRestriction(
+ IN IAppHostAdminManager * pAdminMgr,
+ IN CONST WCHAR * szConfigPath,
+ IN CONST WCHAR * szPath,
+ IN BOOL fExpandPath = FALSE
+ );
+
+
+#endif
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.cpp
new file mode 100644
index 0000000000..8d44a69506
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.cpp
@@ -0,0 +1,72 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+UINT
+__stdcall
+CheckForSharedConfigurationCA(
+ MSIHANDLE hInstall
+)
+{
+ HRESULT hr = S_OK;
+ UINT status = ERROR_SUCCESS;
+ BOOL fIsSharedConfig = FALSE;
+ STRU strWriteToShared;
+
+ IISLogInitialize(hInstall, UNITEXT(__FUNCTION__));
+
+ hr = GetSharedConfigEnabled( &fIsSharedConfig );
+ if ( FAILED( hr ) )
+ {
+ IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Unable to detect whether shared configuration is in use.");
+ status = LogMsiCustomActionError( hInstall, 30001 );
+ goto exit;
+ }
+ if ( fIsSharedConfig )
+ {
+ //set config shared property.
+ //will be used by other CAs via CheckInstallToSharedConfig
+ hr = MsiSetProperty( hInstall, L"IISCONFIGISSHARED", L"1" );
+ if ( FAILED( hr ) )
+ {
+ goto exit;
+ }
+ //
+ //config is shared lets check if user
+ //set public property IIUSESHAREDCONFIG
+ //
+ hr = MsiUtilGetProperty( hInstall, L"IIUSESHAREDCONFIG", &strWriteToShared );
+ if ( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+ if( 0 == wcscmp( strWriteToShared.QueryStr(), L"1" ) )
+ {
+ //Config is shared but property is set
+ //tell caller to schedule executeCA for config
+ //
+ IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"IIS Configuration IS shared. IIUSESHAREDCONFIG property indicated that setup SHOULD schedule the deferred custom action..");
+ }
+ else
+ {
+ //
+ //public property not set error-out install
+ //
+ IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Shared Configuration detected.");
+ status = LogMsiCustomActionError( hInstall, 30002 );
+ goto exit;
+ }
+ }
+ else
+ {
+ IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"No Shared Configuration detected.");
+ }
+
+exit:
+
+ IISLogClose();
+ return status;
+}
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.h
new file mode 100644
index 0000000000..f69b0101c4
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.h
@@ -0,0 +1,16 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+
+#ifndef _CONFIG_CUSTOM_H_
+#define _CONFIG_CUSTOM_H_
+
+
+UINT
+__stdcall
+CheckForSharedConfigurationCA(
+ MSIHANDLE hInstall
+);
+
+#endif
+
diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/consoleprops.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/consoleprops.cpp
new file mode 100644
index 0000000000..ed39ca6af6
--- /dev/null
+++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/consoleprops.cpp
@@ -0,0 +1,594 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+#include "precomp.h"
+
+#define CheckAndGoToExit(hr,sev,msg,prop) if (FAILED(hr)) { DBGERROR_HR(hr); IISLogWrite(sev, msg, prop, hr);goto exit;}
+#define CheckAndReturnHr(hr,sev,msg,prop) if (FAILED(hr)) { DBGERROR_HR(hr); IISLogWrite(sev, msg, prop, hr);return hr;}
+
+
+HRESULT
+GetConsoleIntProperty(
+ IN MSIHANDLE hRecord,
+ IN UINT field,
+ __inout CA_DATA_WRITER * cadata)
+{
+ HRESULT hr = S_OK;
+
+ UINT dwValue = 0;
+ hr = MsiUtilRecordGetInteger( hRecord,
+ field,
+ &dwValue );
+ if ( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", field, hr);
+ return hr;
+ }
+
+ hr = cadata->Write(dwValue);
+ if ( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr);
+ return hr;
+ }
+
+ return hr;
+}
+
+HRESULT
+GetConsoleProperties(
+ IN MSIHANDLE hRecord,
+ __inout CA_DATA_WRITER * cadata)
+{
+ HRESULT hr = S_OK;
+
+ /*STACK_STRU( strTextColour, 128 );
+ STACK_STRU( strBackgroundColour, 128 );*/
+
+ enum {
+ CA_CONSOLEPROPS_QUCIKEDIT = 5,
+ CA_CONSOLEPROPS_INSERTMODE,
+ CA_CONSOLEPROPS_WINDOWWIDTH,
+ CA_CONSOLEPROPS_WINDOWHEIGHT,
+ CA_CONSOLEPROPS_BUFFERWIDTH,
+ CA_CONSOLEPROPS_BUFFERHEIGHT,
+ /* CA_CONSOLEPROPS_TEXTCOLOUR,
+ CA_CONSOLEPROPS_BACKGROUNDCOLOUR*/
+ };
+
+ // GET QuickEdit int
+ hr = GetConsoleIntProperty( hRecord,
+ CA_CONSOLEPROPS_QUCIKEDIT,
+ cadata );
+ if ( FAILED(hr) ) { return hr;}
+
+ // GET InsertMode
+ hr = GetConsoleIntProperty( hRecord,
+ CA_CONSOLEPROPS_INSERTMODE,
+ cadata );
+ if ( FAILED(hr) ) { return hr;}
+
+
+ // GET WindowWidth
+ hr = GetConsoleIntProperty( hRecord,
+ CA_CONSOLEPROPS_WINDOWWIDTH,
+ cadata );
+ if ( FAILED(hr) ) { return hr;}
+
+
+ // GET WindowHeight
+ hr = GetConsoleIntProperty( hRecord,
+ CA_CONSOLEPROPS_WINDOWHEIGHT,
+ cadata );
+ if ( FAILED(hr) ) { return hr;}
+
+
+ // GET BufferWidth
+ hr = GetConsoleIntProperty( hRecord,
+ CA_CONSOLEPROPS_BUFFERWIDTH,
+ cadata );
+ if ( FAILED(hr) ) { return hr;}
+
+
+ // GET BufferHeight
+ hr = GetConsoleIntProperty( hRecord,
+ CA_CONSOLEPROPS_BUFFERHEIGHT,
+ cadata );
+ if ( FAILED(hr) ) { return hr;}
+
+ //// Get Text colours
+ //hr = MsiUtilRecordGetString( hRecord,
+ // CA_CONSOLEPROPS_TEXTCOLOUR,
+ // &strTextColour );
+
+ //CheckAndReturnHr(hr, SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_CONSOLEPROPS_TEXTCOLOUR);
+
+ //hr = cadata->Write( strTextColour.QueryStr(), strTextColour.QueryCCH() );
+ //if ( FAILED(hr) )
+ //{
+ // DBGERROR_HR(hr);
+ // IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr);
+ // return hr;
+ //}
+
+ //// Get Background colours
+ //hr = MsiUtilRecordGetString( hRecord,
+ // CA_CONSOLEPROPS_BACKGROUNDCOLOUR,
+ // &strBackgroundColour );
+
+ //CheckAndReturnHr(hr, SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_CONSOLEPROPS_TEXTCOLOUR);
+
+ //hr = cadata->Write( strBackgroundColour.QueryStr(), strBackgroundColour.QueryCCH() );
+ //if ( FAILED(hr) )
+ //{
+ // DBGERROR_HR(hr);
+ // IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr);
+ // return hr;
+ //}
+
+ return hr;
+}
+
+UINT
+WINAPI
+ScheduleSetConsolePropertiesCA(
+ IN MSIHANDLE hInstall
+ )
+{
+ HRESULT hr = S_OK;
+ UINT status = ERROR_SUCCESS;
+
+ MSIHANDLE hDatabase = NULL;
+ MSIHANDLE hView = NULL;
+ MSIHANDLE hRecord = NULL;
+
+ STACK_STRU( strShortcut, 128 );
+ STACK_STRU( strDirectoryId, 256 ); // Directory Identifier
+ STACK_STRU( strDirectoryName, 256 );
+ STACK_STRU( strComponent, 128 );
+ STACK_STRU( strShortcutName, 256 );
+ STACK_STRU( strData, 256);
+
+
+ CONST WCHAR * szQuery =
+ L"SELECT "
+ L"`IISShortcutConsoleProperties`.`Shortcut_`, "
+ L"`Shortcut`.`Component_`, "
+ L"`Shortcut`.`Name`, "
+ L"`Directory`.`Directory`, "
+ L"`IISShortcutConsoleProperties`.`QuickEdit`, "
+ L"`IISShortcutConsoleProperties`.`InsertMode`, "
+ L"`IISShortcutConsoleProperties`.`WindowWidth`, "
+ L"`IISShortcutConsoleProperties`.`WindowHeight`, "
+ L"`IISShortcutConsoleProperties`.`BufferWidth`, "
+ L"`IISShortcutConsoleProperties`.`BufferHeight` "
+ /*L"`IISShortcutConsoleProperties`.`TextColor`, "
+ L"`IISShortcutConsoleProperties`.`BackgroundColor` "*/
+ L"FROM `IISShortcutConsoleProperties`, `Shortcut`, `Directory` "
+ L"WHERE `IISShortcutConsoleProperties`.`Shortcut_`=`Shortcut`.`Shortcut` "
+ L"AND `Shortcut`.`Directory_`=`Directory`.`Directory`";
+
+
+ CA_DATA_WRITER cadata;
+ INSTALLSTATE installStateCurrent;
+ INSTALLSTATE installStateAction;
+
+ BOOL scheduleDefferedCA = FALSE;
+
+ enum {
+ CA_CONSOLEPROPS_SHORTCUT = 1,
+ CA_CONSOLEPROPS_COMPONENT,
+ CA_CONSOLEPROPS_SHORTCUTNAME,
+ CA_CONSOLEPROPS_DIRECTORY,
+ };
+
+ IISLogInitialize(hInstall, UNITEXT(__FUNCTION__));
+
+ hDatabase = MsiGetActiveDatabase( hInstall );
+ if ( !hDatabase )
+ {
+ hr = E_UNEXPECTED;
+ IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting MSI database, hr=0x%x", hr);
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView );
+ if ( ERROR_SUCCESS != status )
+ {
+ hr = HRESULT_FROM_WIN32( status );
+ IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error opening View, hr=0x%x", hr);
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ status = MsiViewExecute( hView, NULL );
+ if ( ERROR_SUCCESS != status )
+ {
+ hr = HRESULT_FROM_WIN32( status );
+ IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error executing view, hr=0x%x", hr);
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) )
+ {
+ hr = MsiUtilRecordGetString( hRecord,
+ CA_CONSOLEPROPS_COMPONENT,
+ &strComponent );
+ CheckAndGoToExit(hr, SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_CONSOLEPROPS_COMPONENT);
+
+ status = MsiGetComponentStateW( hInstall,
+ strComponent.QueryStr(),
+ &installStateCurrent,
+ &installStateAction );
+
+ if ( ERROR_SUCCESS != status )
+ {
+ hr = HRESULT_FROM_WIN32(status);
+ DBGERROR_HR(hr);
+ IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting state for component %s, hr=0x%x", strComponent.QueryStr(), hr);
+ goto exit;
+ }
+
+ // Only run if the comonent is installing or reinstalling
+ if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) ||
+ MsiUtilIsReInstalling( installStateCurrent, installStateAction ) )
+ {
+ // Get Shortcut location
+ {
+ // GET: directory where shortcut is
+ // Get the directory id for the shortcut
+ hr = MsiUtilRecordGetString( hRecord,
+ CA_CONSOLEPROPS_DIRECTORY,
+ &strDirectoryId );
+
+ CheckAndGoToExit(hr, SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_CONSOLEPROPS_DIRECTORY);
+
+ // Get directory path
+ hr = MsiUtilGetProperty(hInstall, strDirectoryId.QueryStr(), &strDirectoryName );
+
+ CheckAndGoToExit(hr, SETUP_LOG_SEVERITY_ERROR, L"Error getting value for directory record %s, hr=0x%x", strDirectoryId.QueryStr());
+
+ IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION,
+ L"Shortcut Directory: '%s'.",
+ strDirectoryName.QueryStr());
+ // ENDGET: directory where shortcut is
+
+
+ // GET: Short and Long names of shortcuts
+ hr = MsiUtilRecordGetString( hRecord,
+ CA_CONSOLEPROPS_SHORTCUTNAME,
+ &strShortcutName );
+
+ CheckAndGoToExit(hr, SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_CONSOLEPROPS_SHORTCUTNAME);
+
+
+ // strShortcutName contains the short and long file names of the shortcut
+ PCWSTR pszPrevious = strShortcutName.QueryStr();
+ // Append the shortcut name to the directory and write to cadata
+ // Write the short and long shortcut paths
+ for ( DWORD i = 0; i < strShortcutName.QueryCCH() + 1; i++ )
+ {
+ if ( strShortcutName.QueryStr()[ i ] == L'|' ||
+ strShortcutName.QueryStr()[ i ] == L'\0' )
+ {
+ strShortcutName.QueryStr()[ i ] = L'\0';
+
+ strData.Copy( strDirectoryName );
+ strData.Append(L"\\");
+ strData.Append(pszPrevious);
+ strData.Append(L".lnk");
+
+ IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION,
+ L"Potential shortcut path: %s",
+ strData.QueryStr());
+
+ hr = cadata.Write( strData.QueryStr(), strData.QueryCCH() );
+ if ( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr);
+ goto exit;
+ }
+
+ pszPrevious = strShortcutName.QueryStr() + i + 1;
+
+ // Get the console properties
+ hr = GetConsoleProperties(hRecord, &cadata);
+ if( FAILED(hr))
+ {
+ DBGERROR_HR(hr);
+ IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting console properties, hr=0x%x", hr);
+ goto exit;
+ }
+
+ // Only schedule custom action if needed
+ scheduleDefferedCA = TRUE;
+ }
+ }
+ // ENDGET: Short and Long names of shortcuts
+ }
+ // End OF getting shortcut location
+ }
+
+ if ( hRecord )
+ {
+ MsiCloseHandle( hRecord );
+ hRecord = NULL;
+ }
+
+ }
+
+ if ( scheduleDefferedCA )
+ {
+ hr = MsiUtilScheduleDeferredAction( hInstall,
+ L"ExecuteSetConsoleProperties",
+ cadata.QueryData() );
+ if ( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error scheduling custom action, hr=0x%x", hr);
+ goto exit;
+ }
+
+ IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION,
+ L"Custom action ExecuteSetConsoleProperties scheduled");
+ }
+
+exit:
+
+ if ( hRecord )
+ {
+ MsiCloseHandle( hRecord );
+ hRecord = NULL;
+ }
+
+ if ( hView )
+ {
+ MsiCloseHandle( hView );
+ hView = NULL;
+ }
+
+ if ( hDatabase )
+ {
+ MsiCloseHandle( hDatabase );
+ hDatabase = NULL;
+ }
+
+ IISLogClose();
+
+ return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_SUCCESS;
+}
+
+void IntializeConsoleProps(
+ IN NT_CONSOLE_PROPS* pConsoleProps
+ )
+{
+ if (!pConsoleProps)
+ {
+ return;
+ }
+
+ pConsoleProps->dbh.cbSize = sizeof(NT_CONSOLE_PROPS);
+ pConsoleProps->dbh.dwSignature = NT_CONSOLE_PROPS_SIG;
+ pConsoleProps->bFullScreen = false;
+ pConsoleProps->uHistoryBufferSize = 50;
+ pConsoleProps->uNumberOfHistoryBuffers = 4;
+ pConsoleProps->uCursorSize = 25;
+
+ pConsoleProps->ColorTable[0] = RGB(0,0,0);
+ pConsoleProps->ColorTable[1] = RGB(0,0,128);
+ pConsoleProps->ColorTable[2] = RGB(0,128,0);
+ pConsoleProps->ColorTable[3] = RGB(0,128,128);
+ pConsoleProps->ColorTable[4] = RGB(128,0,0);
+ pConsoleProps->ColorTable[5] = RGB(128,0,128);
+ pConsoleProps->ColorTable[6] = RGB(128,128,0);
+ pConsoleProps->ColorTable[7] = RGB(192,192,192);
+ pConsoleProps->ColorTable[8] = RGB(128,128,128);
+ pConsoleProps->ColorTable[9] = RGB(0,0,255);
+ pConsoleProps->ColorTable[10] = RGB(0,255,0);
+ pConsoleProps->ColorTable[11] = RGB(0,255,255);
+ pConsoleProps->ColorTable[12] = RGB(255,0,0);
+ pConsoleProps->ColorTable[13] = RGB(255,0,255);
+ pConsoleProps->ColorTable[14] = RGB(255,255,0);
+ pConsoleProps->ColorTable[15] = RGB(255,255,255);
+
+ pConsoleProps->wPopupFillAttribute = ((15 << 4) | 3);
+}
+
+
+UINT
+WINAPI
+ExecuteSetConsolePropertiesCA(
+ IN MSIHANDLE hInstall
+ )
+{
+ HRESULT hr = S_OK;
+
+ BOOL fCoInit = FALSE;
+
+ WCHAR * szShortcutFile = NULL;
+ /*WCHAR * szTextColour = NULL;
+ WCHAR * szBackgroundColour = NULL;*/
+ INT dwQuickEdit = 0;
+ INT dwInsertMode = 0;
+ INT dwWindowWidth = 120;
+ INT dwWindowHeight = 50;
+ INT dwBufferWidth = 120;
+ INT dwBufferHeight = 3000;
+
+
+ CA_DATA_READER cadata;
+
+ IISLogInitialize(hInstall, UNITEXT(__FUNCTION__));
+
+ //
+ // Retrieve parameters from ca data
+ //
+
+ hr = cadata.LoadDeferredCAData( hInstall );
+ if ( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error retrieving custom action data, hr=0x%x", hr);
+ goto exit;
+ }
+
+ if ( SUCCEEDED( hr = CoInitialize(NULL) ) )
+ {
+ fCoInit = TRUE;
+ }
+
+ while ( SUCCEEDED(hr = cadata.Read( &szShortcutFile )) )
+ {
+ hr = cadata.Read( &dwQuickEdit);
+ if ( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = cadata.Read( &dwInsertMode);
+ if ( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = cadata.Read( &dwWindowWidth);
+ if ( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = cadata.Read( &dwWindowHeight);
+ if ( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = cadata.Read( &dwBufferWidth);
+ if ( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = cadata.Read( &dwBufferHeight);
+ if ( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ /*hr = cadata.Read( &szTextColour);
+ if ( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }
+
+ hr = cadata.Read( &szBackgroundColour);
+ if ( FAILED(hr) )
+ {
+ DBGERROR_HR(hr);
+ goto exit;
+ }*/
+
+ // Check to see if file exists
+ if(GetFileAttributes(szShortcutFile) != 0xFFFFFFFF)
+ {
+ IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION,
+ L"Shortcut %s exists", szShortcutFile);
+
+ // Get shell
+ CComPtr