Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1945 lines
47 KiB

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
setup.cpp
Abstract:
Setup code called from regsvr32
--*/
#include "precomp.h"
BSTR g_PropertyBSTR = NULL;
BSTR g_SyntaxBSTR = NULL;
BSTR g_UserTypeBSTR = NULL;
BSTR g_InheritBSTR = NULL;
BSTR g_ClassBSTR = NULL;
BSTR g_IsapiRestrictionListBSTR = NULL;
BSTR g_RestrictionListCustomDescBSTR = NULL;
BSTR g_FilterLoadOrderBSTR = NULL;
BSTR g_IIsFilterBSTR = NULL;
BSTR g_InProcessIsapiAppsBSTR = NULL;
BSTR g_bitsserverBSTR = NULL;
BSTR g_bitserverBSTR = NULL;
HRESULT
InitializeSetup()
{
g_PropertyBSTR = SysAllocString( L"Property" );
g_SyntaxBSTR = SysAllocString( L"Syntax" );
g_UserTypeBSTR = SysAllocString( L"UserType" );
g_InheritBSTR = SysAllocString( L"Inherit" );
g_ClassBSTR = SysAllocString( L"Class" );
g_IsapiRestrictionListBSTR = SysAllocString( L"IsapiRestrictionList" );
g_RestrictionListCustomDescBSTR = SysAllocString( L"RestrictionListCustomDesc" );
g_FilterLoadOrderBSTR = SysAllocString( L"FilterLoadOrder" );
g_IIsFilterBSTR = SysAllocString( L"IIsFilter" );
g_InProcessIsapiAppsBSTR = SysAllocString( L"InProcessIsapiApps" );
g_bitsserverBSTR = SysAllocString( L"bitsserver" );
g_bitserverBSTR = SysAllocString( L"bitserver" );
if ( !g_PropertyBSTR || !g_SyntaxBSTR || !g_UserTypeBSTR ||
!g_InheritBSTR | !g_ClassBSTR || !g_IsapiRestrictionListBSTR ||
!g_RestrictionListCustomDescBSTR || !g_FilterLoadOrderBSTR || !g_IIsFilterBSTR ||
!g_InProcessIsapiAppsBSTR || !g_bitsserverBSTR || !g_bitserverBSTR )
{
SysFreeString( g_PropertyBSTR );
SysFreeString( g_SyntaxBSTR );
SysFreeString( g_UserTypeBSTR );
SysFreeString( g_InheritBSTR );
SysFreeString( g_ClassBSTR );
SysFreeString( g_IsapiRestrictionListBSTR );
SysFreeString( g_RestrictionListCustomDescBSTR );
SysFreeString( g_FilterLoadOrderBSTR );
SysFreeString( g_IIsFilterBSTR );
SysFreeString( g_InProcessIsapiAppsBSTR );
SysFreeString( g_bitsserverBSTR );
SysFreeString( g_bitserverBSTR );
g_PropertyBSTR = g_SyntaxBSTR = g_UserTypeBSTR =
g_InheritBSTR = g_ClassBSTR = g_IsapiRestrictionListBSTR =
g_RestrictionListCustomDescBSTR = g_FilterLoadOrderBSTR = g_IIsFilterBSTR =
g_InProcessIsapiAppsBSTR = g_bitsserverBSTR = g_bitserverBSTR = NULL;
return E_OUTOFMEMORY;
}
return S_OK;
}
void
CleanupSetup()
{
SysFreeString( g_PropertyBSTR );
SysFreeString( g_SyntaxBSTR );
SysFreeString( g_UserTypeBSTR );
SysFreeString( g_InheritBSTR );
SysFreeString( g_ClassBSTR );
SysFreeString( g_IsapiRestrictionListBSTR );
SysFreeString( g_RestrictionListCustomDescBSTR );
SysFreeString( g_FilterLoadOrderBSTR );
SysFreeString( g_IIsFilterBSTR );
SysFreeString( g_InProcessIsapiAppsBSTR );
SysFreeString( g_bitsserverBSTR );
SysFreeString( g_bitserverBSTR );
g_PropertyBSTR = g_SyntaxBSTR = g_UserTypeBSTR =
g_InheritBSTR = g_ClassBSTR = g_IsapiRestrictionListBSTR =
g_RestrictionListCustomDescBSTR = g_FilterLoadOrderBSTR = g_IIsFilterBSTR =
g_InProcessIsapiAppsBSTR = g_bitsserverBSTR = NULL;
}
void RemoveFilterHelper(
WCHAR * Buffer,
const WCHAR * const ToRemove )
{
WCHAR *ToReplace;
SIZE_T FragmentLength = wcslen( ToRemove );
while( ToReplace = wcsstr( Buffer, ToRemove ) )
{
WCHAR *Next = ToReplace + FragmentLength;
memmove( ToReplace, Next, sizeof(WCHAR) * ( wcslen( Next ) + 1 ) );
Buffer = ToReplace;
}
}
DWORD
BITSGetStartupInfoFilter(
DWORD Status )
{
//
// The following exceptions are documented
// to be thrown by GetStartupInfoA
//
switch( Status )
{
case STATUS_NO_MEMORY:
case STATUS_INVALID_PARAMETER_2:
case STATUS_BUFFER_OVERFLOW:
return EXCEPTION_EXECUTE_HANDLER;
default:
return EXCEPTION_CONTINUE_SEARCH;
}
}
HRESULT
BITSGetStartupInfo(
LPSTARTUPINFO lpStartupInfo )
{
__try
{
GetStartupInfoA( lpStartupInfo );
}
__except( BITSGetStartupInfoFilter( GetExceptionCode() ) )
{
return E_OUTOFMEMORY;
}
return S_OK;
}
HRESULT RestartIIS()
{
//
// Restarts IIS by calling "iisreset /restart" at the commandline.
//
STARTUPINFO StartupInfo;
HRESULT Hr = BITSGetStartupInfo( &StartupInfo );
if ( FAILED( Hr ) )
return Hr;
#define IISRESET_EXE "iisreset.exe"
#define IISRESET_CMDLINE "iisreset /RESTART"
PROCESS_INFORMATION ProcessInfo;
CHAR sApplicationPath[MAX_PATH];
CHAR *pApplicationName = NULL;
CHAR sCmdLine[MAX_PATH];
DWORD dwLen = MAX_PATH;
DWORD dwCount;
dwCount = SearchPath(NULL, // Search Path, NULL is PATH
IISRESET_EXE, // Application
NULL, // Extension (already specified)
dwLen, // Length (char's) of sApplicationPath
sApplicationPath, // Path + Name for application
&pApplicationName ); // File part of sApplicationPath
if (dwCount == 0)
{
return HRESULT_FROM_WIN32( GetLastError() );
}
if (dwCount > dwLen)
{
return HRESULT_FROM_WIN32( ERROR_BUFFER_OVERFLOW );
}
StringCbCopyA(sCmdLine, MAX_PATH, IISRESET_CMDLINE);
BOOL RetVal = CreateProcess(
sApplicationPath, // name of executable module
sCmdLine, // command line string
NULL, // SD
NULL, // SD
FALSE, // handle inheritance option
CREATE_NO_WINDOW, // creation flags
NULL, // new environment block
NULL, // current directory name
&StartupInfo, // startup information
&ProcessInfo // process information
);
if ( !RetVal )
return HRESULT_FROM_WIN32( GetLastError() );
WaitForSingleObject( ProcessInfo.hProcess, INFINITE );
DWORD Status;
GetExitCodeProcess( ProcessInfo.hProcess, &Status );
CloseHandle( ProcessInfo.hProcess );
CloseHandle( ProcessInfo.hThread );
return HRESULT_FROM_WIN32( Status );
}
HRESULT InstallPropertySchema( )
{
//
// Installs the ADSI schema with the new metabase properties.
//
HRESULT Hr;
VARIANT var;
VariantInit( &var );
IADsContainer *MbSchemaContainer = NULL;
Hr = ADsGetObject(
L"IIS://LocalHost/Schema",
__uuidof( *MbSchemaContainer),
reinterpret_cast<void**>( &MbSchemaContainer ) );
if ( FAILED( Hr ) )
return Hr;
BSTR PropertyNameBSTR = NULL;
BSTR PropertyClassBSTR = NULL;
IDispatch *Dispatch = NULL;
IADs *MbProperty = NULL;
IADsClass *MbClass = NULL;
for ( SIZE_T i = 0; i < g_NumberOfProperties; i++ )
{
PropertyNameBSTR = SysAllocString( g_Properties[i].PropertyName );
PropertyClassBSTR = SysAllocString( g_Properties[i].ClassName );
Hr = MbSchemaContainer->Create(
g_PropertyBSTR,
PropertyNameBSTR,
&Dispatch );
if ( Hr == E_ADS_OBJECT_EXISTS )
continue;
if ( FAILED( Hr ) )
goto failed;
Hr = Dispatch->QueryInterface( __uuidof( *MbProperty ),
reinterpret_cast<void**>( &MbProperty ) );
if ( FAILED( Hr ) )
goto failed;
Dispatch->Release();
Dispatch = NULL;
var.bstrVal = SysAllocString( g_Properties[i].Syntax );
var.vt = VT_BSTR;
if ( !var.bstrVal )
{
Hr = E_OUTOFMEMORY;
goto failed;
}
Hr = MbProperty->Put( g_SyntaxBSTR, var );
if ( FAILED(Hr) )
goto failed;
VariantClear( &var );
var.ulVal = g_Properties[i].UserType;
var.vt = VT_UI4;
Hr = MbProperty->Put( g_UserTypeBSTR, var );
if ( FAILED( Hr ) )
goto failed;
var.boolVal = true;
var.vt = VT_BOOL;
Hr = MbProperty->Put( g_InheritBSTR, var );
if ( FAILED(Hr) )
goto failed;
Hr = MbProperty->SetInfo();
if ( FAILED(Hr) )
goto failed;
VariantClear( &var );
MbProperty->Release();
MbProperty = NULL;
Hr = MbSchemaContainer->GetObject( g_ClassBSTR, PropertyClassBSTR, &Dispatch );
if ( FAILED(Hr) )
goto failed;
Hr = Dispatch->QueryInterface( __uuidof( *MbClass ),
reinterpret_cast<void**>( &MbClass ) );
if ( FAILED( Hr ) )
goto failed;
Dispatch->Release();
Dispatch = NULL;
Hr = MbClass->get_OptionalProperties( &var );
if ( FAILED( Hr ) )
goto failed;
SAFEARRAY* Array = var.parray;
long LBound;
long UBound;
Hr = SafeArrayGetLBound( Array, 1, &LBound );
if ( FAILED( Hr ) )
goto failed;
Hr = SafeArrayGetUBound( Array, 1, &UBound );
if ( FAILED( Hr ) )
goto failed;
UBound++; // Add one to the upper bound
SAFEARRAYBOUND SafeBounds;
SafeBounds.lLbound = LBound;
SafeBounds.cElements = UBound - LBound + 1;
Hr = SafeArrayRedim( Array, &SafeBounds );
if ( FAILED( Hr ) )
goto failed;
VARIANT bstrvar;
VariantInit( &bstrvar );
bstrvar.vt = VT_BSTR;
bstrvar.bstrVal = SysAllocString( g_Properties[i].PropertyName );
if ( !bstrvar.bstrVal )
{
Hr = E_OUTOFMEMORY;
goto failed;
}
long Dim = (long)UBound;
Hr = SafeArrayPutElement( Array, &Dim, &bstrvar );
VariantClear( &bstrvar );
if ( FAILED(Hr) )
goto failed;
Hr = MbClass->put_OptionalProperties( var );
if ( FAILED(Hr) )
goto failed;
Hr = MbClass->SetInfo();
if ( FAILED(Hr) )
goto failed;
MbClass->Release();
MbClass = NULL;
SysFreeString( PropertyNameBSTR );
SysFreeString( PropertyClassBSTR );
PropertyNameBSTR = PropertyClassBSTR = NULL;
}
Hr = S_OK;
failed:
VariantClear( &var );
if ( Dispatch )
Dispatch->Release();
if ( MbProperty )
MbProperty->Release();
if ( MbClass )
MbClass->Release();
if ( MbSchemaContainer )
MbSchemaContainer->Release();
SysFreeString( PropertyNameBSTR );
SysFreeString( PropertyClassBSTR );
return Hr;
}
HRESULT RemovePropertySchema( )
{
// Removes our properties from the metabase schema
HRESULT Hr;
VARIANT var;
VariantInit( &var );
IADsContainer *MbSchemaContainer = NULL;
Hr = ADsGetObject(
L"IIS://LocalHost/Schema",
__uuidof( *MbSchemaContainer ),
reinterpret_cast<void**>( &MbSchemaContainer ) );
if ( FAILED( Hr ) )
return Hr;
BSTR PropertyNameBSTR = NULL;
BSTR PropertyClassBSTR = NULL;
IDispatch *Dispatch = NULL;
IADsClass *MbClass = NULL;
IADs *Object = NULL;
for ( SIZE_T i = 0; i < g_NumberOfProperties; i++ )
{
PropertyNameBSTR = SysAllocString( g_Properties[i].PropertyName );
PropertyClassBSTR = SysAllocString( g_Properties[i].ClassName );
if ( !PropertyNameBSTR || !PropertyClassBSTR )
{
Hr = E_OUTOFMEMORY;
goto failed;
}
MbSchemaContainer->Delete( g_PropertyBSTR, PropertyNameBSTR );
Hr = MbSchemaContainer->QueryInterface( __uuidof(*Object), reinterpret_cast<void**>( &Object ) );
if ( FAILED( Hr ) )
goto failed;
Object->SetInfo();
Object->Release();
Object = NULL;
Hr = MbSchemaContainer->GetObject( g_ClassBSTR, PropertyClassBSTR, &Dispatch );
if ( FAILED( Hr ) )
goto failed;
Hr = Dispatch->QueryInterface( __uuidof( *MbClass ), reinterpret_cast<void**>( &MbClass ) );
if ( FAILED( Hr ) )
goto failed;
Dispatch->Release();
Dispatch = NULL;
if ( FAILED( Hr ) )
goto failed;
Hr = MbClass->get_OptionalProperties( &var );
SAFEARRAY* Array = var.parray;
Hr = SafeArrayLock( Array );
if ( FAILED( Hr ) )
goto failed;
ULONG NewSize = 0;
SIZE_T j = Array->rgsabound[0].lLbound;
SIZE_T k = Array->rgsabound[0].lLbound + Array->rgsabound[0].cElements;
while( j < k )
{
VARIANT & JElem = ((VARIANT*)Array->pvData)[j];
// This element is fine, keep it
if ( 0 != _wcsicmp( (WCHAR*)JElem.bstrVal, BSTR( g_Properties[i].PropertyName ) ) )
{
NewSize++;
j++;
}
else
{
// find a suitable element to replace the bad element with
while( j < --k )
{
VARIANT & KElem = ((VARIANT*)Array->pvData)[k];
if ( 0 != _wcsicmp( (WCHAR*)KElem.bstrVal, BSTR( g_Properties[i].PropertyName ) ) )
{
// found element. move it
VARIANT temp = JElem;
JElem = KElem;
KElem = temp;
break;
}
}
}
}
SAFEARRAYBOUND ArrayBounds;
ArrayBounds = Array->rgsabound[0];
ArrayBounds.cElements = NewSize;
SafeArrayUnlock( Array );
Hr = SafeArrayRedim( Array, &ArrayBounds );
if ( FAILED( Hr ) )
goto failed;
Hr = MbClass->put_OptionalProperties( var );
if ( FAILED( Hr ) )
goto failed;
Hr = MbClass->SetInfo();
if ( FAILED( Hr ) )
goto failed;
MbClass->Release();
MbClass = NULL;
VariantClear( &var );
continue;
failed:
SysFreeString( PropertyNameBSTR );
SysFreeString( PropertyClassBSTR );
PropertyNameBSTR = PropertyClassBSTR = NULL;
if ( MbClass )
{
MbClass->Release();
MbClass = NULL;
}
if ( Dispatch )
{
Dispatch->Release();
Dispatch = NULL;
}
if ( Object )
{
Object->Release();
Object = NULL;
}
VariantClear( &var );
}
return S_OK;
}
HRESULT InstallDefaultValues( )
{
//
// Install default values for the configuration. Do this at the top and let inheritance deal with it.
//
HRESULT Hr = S_OK;
METADATA_RECORD mdr;
METADATA_HANDLE mdHandle = NULL;
DWORD Value;
IMSAdminBase * IISAdminBase = NULL;
class PropertyIDManager *PropertyMan =
new PropertyIDManager();
if ( !PropertyMan )
return E_OUTOFMEMORY;
Hr = PropertyMan->LoadPropertyInfo();
if ( FAILED(Hr) )
goto error;
Hr = CoCreateInstance(
GETAdminBaseCLSID(TRUE),
NULL,
CLSCTX_SERVER,
__uuidof( *IISAdminBase ),
(LPVOID*)&IISAdminBase );
if ( FAILED(Hr) )
goto error;
Hr = IISAdminBase->OpenKey(
METADATA_MASTER_ROOT_HANDLE,
L"/LM/W3SVC",
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
10000, // 10 seconds
&mdHandle );
if ( FAILED(Hr) )
goto error;
mdr.dwMDIdentifier = PropertyMan->GetPropertyMetabaseID( MD_BITS_CONNECTION_DIR );
mdr.dwMDAttributes = METADATA_INHERIT;
mdr.dwMDUserType = PropertyMan->GetPropertyUserType( MD_BITS_CONNECTION_DIR );
mdr.dwMDDataType = STRING_METADATA;
mdr.pbMDData = (PBYTE)MD_DEFAULT_BITS_CONNECTION_DIR;
mdr.dwMDDataLen = sizeof(WCHAR) * ( wcslen( MD_DEFAULT_BITS_CONNECTION_DIR ) + 1 );
mdr.dwMDDataTag = 0;
Hr = IISAdminBase->SetData(
mdHandle,
NULL,
&mdr );
if ( FAILED(Hr) )
goto error;
mdr.dwMDIdentifier = PropertyMan->GetPropertyMetabaseID( MD_BITS_MAX_FILESIZE );
mdr.dwMDAttributes = METADATA_INHERIT;
mdr.dwMDUserType = PropertyMan->GetPropertyUserType( MD_BITS_MAX_FILESIZE );
mdr.dwMDDataType = STRING_METADATA;
mdr.pbMDData = (PBYTE)MD_DEFAULT_BITS_MAX_FILESIZE;
mdr.dwMDDataLen = sizeof(WCHAR) * ( wcslen( MD_DEFAULT_BITS_MAX_FILESIZE ) + 1 );
mdr.dwMDDataTag = 0;
Hr = IISAdminBase->SetData(
mdHandle,
NULL,
&mdr );
if ( FAILED(Hr) )
goto error;
Value = MD_DEFAULT_NO_PROGESS_TIMEOUT;
mdr.dwMDIdentifier = PropertyMan->GetPropertyMetabaseID( MD_BITS_NO_PROGRESS_TIMEOUT );
mdr.dwMDAttributes = METADATA_INHERIT;
mdr.dwMDUserType = PropertyMan->GetPropertyUserType( MD_BITS_NO_PROGRESS_TIMEOUT );
mdr.dwMDDataType = DWORD_METADATA;
mdr.pbMDData = (PBYTE)&Value;
mdr.dwMDDataLen = sizeof(Value);
mdr.dwMDDataTag = 0;
Hr = IISAdminBase->SetData(
mdHandle,
NULL,
&mdr );
if ( FAILED(Hr) )
goto error;
Value = (DWORD)MD_DEFAULT_BITS_NOTIFICATION_URL_TYPE;
mdr.dwMDIdentifier = PropertyMan->GetPropertyMetabaseID( MD_BITS_NOTIFICATION_URL_TYPE );
mdr.dwMDAttributes = METADATA_INHERIT;
mdr.dwMDUserType = PropertyMan->GetPropertyUserType( MD_BITS_NOTIFICATION_URL_TYPE );
mdr.dwMDDataType = DWORD_METADATA;
mdr.pbMDData = (PBYTE)&Value;
mdr.dwMDDataLen = sizeof(Value);
mdr.dwMDDataTag = 0;
Hr = IISAdminBase->SetData(
mdHandle,
NULL,
&mdr );
if ( FAILED(Hr) )
goto error;
mdr.dwMDIdentifier = PropertyMan->GetPropertyMetabaseID( MD_BITS_NOTIFICATION_URL );
mdr.dwMDAttributes = METADATA_INHERIT;
mdr.dwMDUserType = PropertyMan->GetPropertyUserType( MD_BITS_NOTIFICATION_URL );
mdr.dwMDDataType = STRING_METADATA;
mdr.pbMDData = (PBYTE)MD_DEFAULT_BITS_NOTIFICATION_URL;
mdr.dwMDDataLen = sizeof(WCHAR) * ( wcslen( MD_DEFAULT_BITS_NOTIFICATION_URL ) + 1 );;
mdr.dwMDDataTag = 0;
Hr = IISAdminBase->SetData(
mdHandle,
NULL,
&mdr );
if ( FAILED(Hr) )
goto error;
mdr.dwMDIdentifier = PropertyMan->GetPropertyMetabaseID( MD_BITS_HOSTID );
mdr.dwMDAttributes = METADATA_INHERIT;
mdr.dwMDUserType = PropertyMan->GetPropertyUserType( MD_BITS_HOSTID );
mdr.dwMDDataType = STRING_METADATA;
mdr.pbMDData = (PBYTE)MD_DEFAULT_BITS_HOSTID;
mdr.dwMDDataLen = sizeof(WCHAR) * ( wcslen( MD_DEFAULT_BITS_HOSTID ) + 1 );
mdr.dwMDDataTag = 0;
Hr = IISAdminBase->SetData(
mdHandle,
NULL,
&mdr );
if ( FAILED(Hr) )
goto error;
Value = MD_DEFAULT_HOSTID_FALLBACK_TIMEOUT;
mdr.dwMDIdentifier = PropertyMan->GetPropertyMetabaseID( MD_BITS_HOSTID_FALLBACK_TIMEOUT );
mdr.dwMDAttributes = METADATA_INHERIT;
mdr.dwMDUserType = PropertyMan->GetPropertyUserType( MD_BITS_HOSTID_FALLBACK_TIMEOUT );
mdr.dwMDDataType = DWORD_METADATA;
mdr.pbMDData = (PBYTE)&Value;
mdr.dwMDDataLen = sizeof(Value);
mdr.dwMDDataTag = 0;
Hr = IISAdminBase->SetData(
mdHandle,
NULL,
&mdr );
if ( FAILED(Hr) )
goto error;
error:
if ( PropertyMan )
delete PropertyMan;
if ( mdHandle )
IISAdminBase->CloseKey( mdHandle );
if ( IISAdminBase )
IISAdminBase->Release();
return Hr;
}
HRESULT
AddDllToIISList(
SAFEARRAY* Array )
{
//
// Add the ISAPI to the IIS list.
//
HRESULT Hr;
WCHAR ExtensionPath[ MAX_PATH ];
DWORD dwRet =
GetModuleFileNameW(
g_hinst,
ExtensionPath,
MAX_PATH );
if ( !dwRet )
return HRESULT_FROM_WIN32( GetLastError() );
// Search for the DLL. If its already in the list, do nothing
Hr = SafeArrayLock( Array );
if ( FAILED( Hr ) )
return Hr;
for ( unsigned int i = Array->rgsabound[0].lLbound;
i < Array->rgsabound[0].lLbound + Array->rgsabound[0].cElements; i++ )
{
VARIANT & IElem = ((VARIANT*)Array->pvData)[i];
if ( _wcsicmp( (WCHAR*)IElem.bstrVal, ExtensionPath ) == 0 )
{
SafeArrayUnlock( Array );
return S_OK;
}
}
// Need to add the DLL
SAFEARRAYBOUND SafeBounds;
SafeBounds.lLbound = Array->rgsabound[0].lLbound;
SafeBounds.cElements = Array->rgsabound[0].cElements+1;
SafeArrayUnlock( Array );
Hr = SafeArrayRedim( Array, &SafeBounds );
if ( FAILED( Hr ) )
return Hr;
VARIANT bstrvar;
VariantInit( &bstrvar );
bstrvar.vt = VT_BSTR;
bstrvar.bstrVal = SysAllocString( ExtensionPath );
long Index = SafeBounds.lLbound + SafeBounds.cElements - 1;
Hr = SafeArrayPutElement( Array, &Index, (void*)&bstrvar );
VariantClear( &bstrvar );
if ( FAILED( Hr ) )
return Hr;
return S_OK;
}
HRESULT
RemoveDllFromIISList(
SAFEARRAY *Array )
{
// Remove the DLL from the IIS list
HRESULT Hr;
WCHAR ExtensionPath[ MAX_PATH ];
DWORD dwRet =
GetModuleFileNameW(
g_hinst,
ExtensionPath,
MAX_PATH );
if ( !dwRet )
return HRESULT_FROM_WIN32( GetLastError() );
Hr = SafeArrayLock( Array );
if ( FAILED( Hr ) )
return Hr;
ULONG NewSize = 0;
SIZE_T j = Array->rgsabound[0].lLbound;
SIZE_T k = Array->rgsabound[0].lLbound + Array->rgsabound[0].cElements;
while( j < k )
{
VARIANT & JElem = ((VARIANT*)Array->pvData)[j];
// This element is fine, keep it
if ( 0 != _wcsicmp( (WCHAR*)JElem.bstrVal, ExtensionPath ) )
{
NewSize++;
j++;
}
else
{
// find a suitable element to replace the bad element with
while( j < --k )
{
VARIANT & KElem = ((VARIANT*)Array->pvData)[k];
if ( 0 != _wcsicmp( (WCHAR*)KElem.bstrVal, ExtensionPath ) )
{
// found element. move it
VARIANT temp = JElem;
JElem = KElem;
KElem = temp;
break;
}
}
}
}
SAFEARRAYBOUND ArrayBounds;
ArrayBounds = Array->rgsabound[0];
ArrayBounds.cElements = NewSize;
SafeArrayUnlock( Array );
Hr = SafeArrayRedim( Array, &ArrayBounds );
if ( FAILED( Hr ) )
return Hr;
return S_OK;
}
HRESULT
ModifyLockdownList( bool Add )
{
// Toplevel function to modify the IIS lockdown list.
// If Add is 1, then the ISAPI is added. If Add is 0, then the ISAPI is removed.
HRESULT Hr;
IADs *Service = NULL;
SAFEARRAY* Array = NULL;
bool ArrayLocked = false;
VARIANT var;
VariantInit( &var );
Hr = ADsGetObject( BSTR( L"IIS://LocalHost/W3SVC" ), __uuidof( IADs ), (void**)&Service );
if ( FAILED( Hr ) )
return Hr;
Hr = Service->Get( g_IsapiRestrictionListBSTR, &var );
if ( FAILED(Hr) )
{
// This property doesn't exist on IIS5 or IIS5.1 don't install it
Hr = S_OK;
goto cleanup;
}
Array = var.parray;
Hr = SafeArrayLock( Array );
if ( FAILED( Hr ) )
goto cleanup;
ArrayLocked = true;
if ( !Array->rgsabound[0].cElements )
{
// The array has no elements which means no restrictions.
Hr = S_OK;
goto cleanup;
}
VARIANT & FirstElem = ((VARIANT*)Array->pvData)[ Array->rgsabound[0].lLbound ];
if ( _wcsicmp(L"0", (WCHAR*)FirstElem.bstrVal ) == 0 )
{
//
// According to the IIS6 spec, a 0 means that all ISAPIs are denied except
// those that are explicitly listed.
//
// If installing: add to the list.
// If uninstalling: remove from the list
//
SafeArrayUnlock( Array );
ArrayLocked = false;
if ( Add )
Hr = AddDllToIISList( Array );
else
Hr = RemoveDllFromIISList( Array );
if ( FAILED( Hr ) )
goto cleanup;
}
else if ( _wcsicmp( L"1", (WCHAR*)FirstElem.bstrVal ) == 0 )
{
//
// According to the IIS6 spec, a 1 means that all ISAPIs are allowed except
// those that are explicitly denied.
//
// If installing: remove from the list
// If uninstalling: Do nothing
//
SafeArrayUnlock( Array );
ArrayLocked = false;
if ( Add )
{
Hr = RemoveDllFromIISList( Array );
if ( FAILED( Hr ) )
goto cleanup;
}
}
else
{
Hr = E_FAIL;
goto cleanup;
}
Hr = Service->Put( g_IsapiRestrictionListBSTR, var );
if ( FAILED( Hr ) )
goto cleanup;
Hr = Service->SetInfo();
if ( FAILED( Hr ) )
goto cleanup;
Hr = S_OK;
cleanup:
if ( Array && ArrayLocked )
SafeArrayUnlock( Array );
if ( Service )
Service->Release();
VariantClear( &var );
return Hr;
}
HRESULT
AddToLockdownListDisplayPutString(
SAFEARRAY *Array,
unsigned long Position,
const WCHAR *String )
{
HRESULT Hr;
VARIANT Var;
VariantInit( &Var );
Var.vt = VT_BSTR;
Var.bstrVal = SysAllocString( String );
if ( !Var.bstrVal )
return E_OUTOFMEMORY;
long Index = (unsigned long)Position;
Hr = SafeArrayPutElement( Array, &Index, (void*)&Var );
VariantClear( &Var );
return Hr;
}
HRESULT
AddToLockdownListDisplay( SAFEARRAY *Array )
{
HRESULT Hr;
WCHAR FilterPath[ MAX_PATH ];
DWORD dwRet =
GetModuleFileNameW(
g_hinst,
FilterPath,
MAX_PATH );
if ( !dwRet )
return HRESULT_FROM_WIN32( GetLastError() );
WCHAR ExtensionName[ MAX_PATH ];
if (! LoadStringW(g_hinst, // handle to resource module
IDS_EXTENSION_NAME, // resource identifier
ExtensionName, // resource buffer
MAX_PATH ) ) // size of buffer
return HRESULT_FROM_WIN32( GetLastError() );
//
// Check to see if the ISAPI is already in the list. If it is, don't modify
// list.
//
Hr = SafeArrayLock( Array );
if ( FAILED( Hr ) )
return Hr;
for( unsigned long i = Array->rgsabound[0].lLbound;
i < Array->rgsabound[0].lLbound + Array->rgsabound[0].cElements;
i++ )
{
VARIANT & CurrentElement = ((VARIANT*)Array->pvData)[ i ];
BSTR BSTRString = CurrentElement.bstrVal;
if ( _wcsicmp( (WCHAR*)BSTRString, FilterPath ) == 0 )
{
// ISAPI is already in the list, don't do anything
SafeArrayUnlock( Array );
return S_OK;
}
}
SAFEARRAYBOUND SafeArrayBound = Array->rgsabound[0];
unsigned long OldSize = SafeArrayBound.cElements;
SafeArrayBound.cElements += 3;
SafeArrayUnlock( Array );
Hr = SafeArrayRedim( Array, &SafeArrayBound );
if ( FAILED( Hr ) )
return Hr;
Hr = AddToLockdownListDisplayPutString( Array, OldSize, L"1" );
if ( FAILED( Hr ) )
return Hr;
Hr = AddToLockdownListDisplayPutString( Array, OldSize + 1, FilterPath );
if ( FAILED( Hr ) )
return Hr;
Hr = AddToLockdownListDisplayPutString( Array, OldSize + 2, ExtensionName );
if ( FAILED( Hr ) )
return Hr;
return S_OK;
}
HRESULT
SafeArrayRemoveSlice(
SAFEARRAY *Array,
unsigned long lBound,
unsigned long uBound )
{
// Remove a slice of an array.
SIZE_T ElementsToRemove = uBound - lBound + 1;
HRESULT Hr = SafeArrayLock( Array );
if ( FAILED( Hr ) )
return Hr;
if ( uBound + 1 < Array->rgsabound[0].cElements )
{
// At least one element exists above this element
// Step 1, move slice to temp storage
VARIANT *Temp = (VARIANT*)new BYTE[ sizeof(VARIANT) * ElementsToRemove ];
if ( !Temp )
{
SafeArrayUnlock( Array );
return E_OUTOFMEMORY;
}
memcpy( Temp, &((VARIANT*)Array->pvData)[ lBound ], sizeof(VARIANT)*ElementsToRemove );
// Step 2, collapse hole left by slice
memmove( &((VARIANT*)Array->pvData)[ lBound ],
&((VARIANT*)Array->pvData)[ uBound + 1 ],
sizeof(VARIANT) * ( Array->rgsabound[0].cElements - ( uBound + 1 ) ) );
// Step 3, move slice to end of array
memcpy( &((VARIANT*)Array->pvData)[ Array->rgsabound[0].cElements - ElementsToRemove ],
Temp,
sizeof(VARIANT)*ElementsToRemove );
}
SAFEARRAYBOUND SafeArrayBound = Array->rgsabound[0];
SafeArrayBound.cElements -= (ULONG)ElementsToRemove;
SafeArrayUnlock( Array );
return SafeArrayRedim( Array, &SafeArrayBound );
}
HRESULT
RemoveFromLockdownListDisplay(
SAFEARRAY *Array )
{
HRESULT Hr;
WCHAR FilterPath[ MAX_PATH ];
DWORD dwRet =
GetModuleFileNameW(
g_hinst,
FilterPath,
MAX_PATH );
if ( !dwRet )
return HRESULT_FROM_WIN32( GetLastError() );
Hr = SafeArrayLock( Array );
if ( FAILED( Hr ) )
return Hr;
for( unsigned int i = Array->rgsabound[0].lLbound;
i < Array->rgsabound[0].lLbound + Array->rgsabound[0].cElements;
i++ )
{
VARIANT & CurrentElement = ((VARIANT*)Array->pvData)[ i ];
BSTR BSTRString = CurrentElement.bstrVal;
if ( _wcsicmp( (WCHAR*)BSTRString, FilterPath ) == 0 )
{
// ISAPI is in the list, remove it
Hr = SafeArrayUnlock( Array );
if ( FAILED( Hr ) )
return Hr;
Hr = SafeArrayRemoveSlice(
Array,
(i == 0) ? 0 : i - 1,
min( i + 1, Array->rgsabound[0].cElements - 1 ) );
return Hr;
}
}
// ISAPI wasn't found. Nothing to do.
SafeArrayUnlock( Array );
return S_OK;
}
HRESULT
ModifyLockdownListDisplay( bool Add )
{
HRESULT Hr;
SAFEARRAY* Array = NULL;
IADs *Service = NULL;
VARIANT var;
VariantInit( &var );
Hr = ADsGetObject( BSTR( L"IIS://LocalHost/W3SVC" ), __uuidof( IADs ), (void**)&Service );
if ( FAILED( Hr ) )
return Hr;
Hr = Service->Get( g_RestrictionListCustomDescBSTR, &var );
if ( FAILED(Hr) )
{
// This property doesn't exist on IIS5 or IIS5.1 don't install or uninstall it
Hr = S_OK;
goto cleanup;
}
Array = var.parray;
if ( Add )
Hr = AddToLockdownListDisplay( Array );
else
Hr = RemoveFromLockdownListDisplay( Array );
if ( FAILED( Hr ) )
goto cleanup;
Hr = Service->Put( g_RestrictionListCustomDescBSTR, var );
if ( FAILED( Hr ) )
goto cleanup;
Hr = Service->SetInfo();
if ( FAILED( Hr ) )
goto cleanup;
cleanup:
VariantClear( &var );
if ( Service )
Service->Release();
return Hr;
}
HRESULT
RemoveFilterIfNeeded()
{
HRESULT Hr;
VARIANT var;
VariantInit( &var );
WCHAR *LoadOrder = NULL;
IADsContainer *MbFiltersContainer = NULL;
IADs *Object = NULL;
Hr = ADsGetObject( BSTR( L"IIS://LocalHost/W3SVC/Filters" ), __uuidof( IADsContainer), (void**)&MbFiltersContainer );
if ( FAILED( Hr ) )
return Hr;
// Remove bits from the load path
Hr = MbFiltersContainer->QueryInterface( __uuidof(*Object), (void**)&Object );
if ( FAILED( Hr ) )
goto failed;
Hr = Object->Get( g_FilterLoadOrderBSTR, &var );
if ( FAILED( Hr ) )
goto failed;
Hr = VariantChangeType( &var, &var, 0, VT_BSTR );
if ( FAILED( Hr ) )
goto failed;
SIZE_T LoadOrderLength = wcslen( (WCHAR*)var.bstrVal ) + 1;
LoadOrder = new WCHAR[ LoadOrderLength ];
if ( !LoadOrder )
{
Hr = E_OUTOFMEMORY;
goto failed;
}
memcpy( LoadOrder, (WCHAR*)var.bstrVal, LoadOrderLength * sizeof( WCHAR ) );
// remove any old bitsserver entries
RemoveFilterHelper( LoadOrder, L",bitsserver" );
RemoveFilterHelper( LoadOrder, L"bitsserver," );
RemoveFilterHelper( LoadOrder, L"bitsserver" );
RemoveFilterHelper( LoadOrder, L",bitserver" );
RemoveFilterHelper( LoadOrder, L"bitserver," );
RemoveFilterHelper( LoadOrder, L"bitserver" );
VariantClear( &var );
var.vt = VT_BSTR;
var.bstrVal = SysAllocString( LoadOrder );
if ( !var.bstrVal )
goto failed;
Hr = Object->Put( g_FilterLoadOrderBSTR, var );
if ( FAILED( Hr ) )
goto failed;
Hr = Object->SetInfo();
if ( FAILED( Hr ) )
goto failed;
MbFiltersContainer->Delete( g_IIsFilterBSTR, g_bitsserverBSTR );
MbFiltersContainer->Delete( g_IIsFilterBSTR, g_bitserverBSTR );
Object->SetInfo();
Hr = S_OK;
failed:
if ( MbFiltersContainer )
{
MbFiltersContainer->Release();
MbFiltersContainer = NULL;
}
if ( Object )
{
Object->Release();
Object = NULL;
}
return Hr;
}
HRESULT
ModifyInProcessList( bool Add )
{
// Toplevel function to modify the IIS inprocess list.
// If Add is 1, then the ISAPI is added. If Add is 0, then the ISAPI is removed.
HRESULT Hr;
IADs *Service = NULL;
VARIANT var;
VariantInit( &var );
Hr = ADsGetObject( BSTR( L"IIS://LocalHost/W3SVC" ), __uuidof( IADs ), (void**)&Service );
if ( FAILED( Hr ) )
return Hr;
Hr = Service->Get( g_InProcessIsapiAppsBSTR, &var );
if ( FAILED(Hr) )
{
goto cleanup;
}
if ( Add )
Hr = AddDllToIISList( var.parray );
else
Hr = RemoveDllFromIISList( var.parray );
Hr = Service->Put( g_InProcessIsapiAppsBSTR, var );
if ( FAILED( Hr ) )
goto cleanup;
Hr = Service->SetInfo();
if ( FAILED( Hr ) )
goto cleanup;
Hr = S_OK;
cleanup:
if ( Service )
Service->Release();
VariantClear( &var );
return Hr;
}
HRESULT
StartupMSTask()
{
HRESULT Hr;
SC_HANDLE hSC = NULL;
SC_HANDLE hSchSvc = NULL;
BYTE* ConfigBuffer = NULL;
DWORD BytesNeeded = 0;
hSC = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (hSC == NULL)
{
Hr = HRESULT_FROM_WIN32( GetLastError() );
goto exit;
}
hSchSvc = OpenService(hSC,
"Schedule",
SERVICE_ALL_ACCESS );
if ( !hSchSvc )
{
Hr = HRESULT_FROM_WIN32( GetLastError() );
goto exit;
}
SERVICE_STATUS SvcStatus;
if (QueryServiceStatus(hSchSvc, &SvcStatus) == FALSE)
{
Hr = HRESULT_FROM_WIN32( GetLastError() );
goto exit;
}
if (SvcStatus.dwCurrentState == SERVICE_RUNNING)
{
// Service is already running
Hr = S_OK;
goto exit;
}
SetLastError( ERROR_SUCCESS );
QueryServiceConfig(
hSchSvc,
NULL,
0,
&BytesNeeded );
if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
{
Hr = HRESULT_FROM_WIN32( GetLastError() );
goto exit;
}
ConfigBuffer = new BYTE[ BytesNeeded ];
if ( !ConfigBuffer )
{
Hr = E_OUTOFMEMORY;
goto exit;
}
if ( !QueryServiceConfig(
hSchSvc,
(LPQUERY_SERVICE_CONFIG)ConfigBuffer,
BytesNeeded,
&BytesNeeded ) )
{
Hr = HRESULT_FROM_WIN32( GetLastError() );
goto exit;
}
if ( ((LPQUERY_SERVICE_CONFIG)ConfigBuffer)->dwStartType != SERVICE_AUTO_START )
{
if ( !ChangeServiceConfig(
hSchSvc,
SERVICE_NO_CHANGE, // type of service
SERVICE_AUTO_START, // when to start service
SERVICE_NO_CHANGE, // severity of start failure
NULL, // service binary file name
NULL, // load ordering group name
NULL, // tag identifier
NULL, // array of dependency names
NULL, // account name
NULL, // account password
NULL // display name
) )
{
Hr = HRESULT_FROM_WIN32( GetLastError() );
goto exit;
}
}
if ( StartService(hSchSvc, 0, NULL) == FALSE )
{
Hr = HRESULT_FROM_WIN32( GetLastError() );
goto exit;
}
// Poll for the service to enter the running or error state
Hr = S_OK;
while( 1 )
{
if (QueryServiceStatus(hSchSvc, &SvcStatus) == FALSE)
{
Hr = HRESULT_FROM_WIN32( GetLastError() );
goto exit;
}
if ( SvcStatus.dwCurrentState == SERVICE_STOPPED ||
SvcStatus.dwCurrentState == SERVICE_PAUSED )
{
// Service is already running
Hr = HRESULT_FROM_WIN32( SvcStatus.dwCurrentState );
goto exit;
}
if ( SvcStatus.dwCurrentState == SERVICE_RUNNING )
{
Hr = S_OK;
goto exit;
}
}
exit:
if ( ConfigBuffer )
delete[] ConfigBuffer;
if ( hSchSvc )
CloseServiceHandle( hSC );
if ( hSC )
CloseServiceHandle( hSchSvc );
return Hr;
}
#if 0
HRESULT
ProcessVerbsInIniSection(
WCHAR *Section,
WCHAR *Verb,
WCHAR *FileName,
bool Add )
{
HRESULT Hr = S_OK;
WCHAR *SectionData = (WCHAR*)new WCHAR[ 32768 ];
if ( !SectionData )
return E_OUTOFMEMORY;
WCHAR *NewSectionData = (WCHAR*)new WCHAR[ 32768 * 2 ];
if ( !NewSectionData )
{
Hr = E_OUTOFMEMORY;
goto exit;
}
DWORD Result =
GetPrivateProfileSectionW(
Section, // section name
SectionData, // return buffer
32768, // size of return buffer
FileName // initialization file name
);
if ( Result == 32768 - 2 )
{
// The buffer is not large enough. Interestingly,
// even urlscan is not capable of handing a section this
// large so just assume the file is corrupt and ignore it.
Hr = S_OK;
goto exit;
}
if ( Add )
{
// Loop through the list copying it to the new buffer.
// Stop if the verb has already been added.
WCHAR *OriginalVerb = SectionData;
WCHAR *NewVerb = NewSectionData;
while( *OriginalVerb )
{
if ( wcscmp( OriginalVerb, Verb ) == 0 )
{
// verb already found, no more processing needed
Hr = S_OK;
goto exit;
}
SIZE_T VerbSize = wcslen( OriginalVerb ) + 1;
memcpy( NewVerb, OriginalVerb, sizeof( WCHAR ) * VerbSize );
OriginalVerb += VerbSize;
NewVerb += VerbSize;
}
// add the verb since it hasn't been added
SIZE_T VerbSize = wcslen( Verb ) + 1;
memcpy( NewVerb, Verb, sizeof( WCHAR ) * VerbSize );
NewVerb[ VerbSize ] = '\0'; // end the list
}
else
{
// Loop though the list copying all nonmatching verbs to the new buffer
// Keep track if list changes
bool ListChanged = false;
WCHAR *OriginalVerb = SectionData;
WCHAR *NewVerb = NewSectionData;
while( *OriginalVerb )
{
if ( wcscmp( OriginalVerb, Verb ) == 0 )
{
// verb to remove, skip it
OriginalVerb += wcslen( OriginalVerb ) + 1;
ListChanged = true;
}
else
{
// copy the verb
SIZE_T VerbSize = wcslen( OriginalVerb ) + 1;
memcpy( NewVerb, OriginalVerb, sizeof( WCHAR ) * VerbSize );
OriginalVerb += VerbSize;
NewVerb += VerbSize;
}
}
if ( !ListChanged )
{
Hr = S_OK;
goto exit;
}
*NewVerb = '\0'; // end the list
}
if ( !WritePrivateProfileSectionW(
Section, // section name
NewSectionData, // data
FileName // file name
) )
{
Hr = HRESULT_FROM_WIN32( GetLastError() );
goto exit;
}
Hr = S_OK;
exit:
delete[] SectionData;
delete[] NewSectionData;
return Hr;
}
HRESULT ModifyURLScanFiles(
bool Add )
{
// Loop though the list of filters and find valid copies of urlscan.ini
HRESULT Hr = S_OK;
IADsContainer *MbFiltersContainer = NULL;
IEnumVARIANT *EnumVariant = NULL;
IADs *Filter = NULL;
IUnknown *Unknown = NULL;
VARIANT Var;
VariantInit( &Var );
Hr = ADsGetObject( BSTR( L"IIS://LocalHost/W3SVC/Filters" ), __uuidof( IADsContainer), (void**)&MbFiltersContainer );
if ( FAILED( Hr ) )
goto exit;
Hr = MbFiltersContainer->get__NewEnum( &Unknown );
if ( FAILED( Hr ) )
goto exit;
Hr = Unknown->QueryInterface( __uuidof( *EnumVariant ), (void**)&EnumVariant );
if ( FAILED( Hr ) )
goto exit;
Unknown->Release();
Unknown = NULL;
while( 1 )
{
ULONG NumberFetched;
Hr = EnumVariant->Next( 1, &Var, &NumberFetched );
if ( FAILED( Hr ) )
goto exit;
if ( S_FALSE == Hr )
{
// All the filters were looped though.
Hr = S_OK;
goto exit;
}
Hr = VariantChangeType( &Var, &Var, 0, VT_UNKNOWN );
if ( FAILED( Hr ) )
goto exit;
Hr = Var.punkVal->QueryInterface( __uuidof( *Filter ), (void**)&Filter );
if ( FAILED( Hr ) )
goto exit;
VariantClear( &Var );
Hr = Filter->Get( (BSTR)L"FilterPath", &Var );
if ( FAILED( Hr ) )
goto exit;
Filter->Release();
Filter = NULL;
Hr = VariantChangeType( &Var, &Var, 0, VT_BSTR );
if ( FAILED( Hr ) )
goto exit;
// Test if this is UrlScan and bash the filepart
WCHAR * FilterPathString = (WCHAR*)Var.bstrVal;
SIZE_T FilterPathStringSize = wcslen( FilterPathString );
const WCHAR UrlScanDllName[] = L"urlscan.dll";
const WCHAR UrlScanIniName[] = L"urlscan.ini";
const SIZE_T UrlScanNameSize = sizeof( UrlScanDllName ) / sizeof( *UrlScanDllName );
if ( FilterPathStringSize < UrlScanNameSize )
continue;
WCHAR * FilterPathStringFilePart = FilterPathString + FilterPathStringSize - UrlScanNameSize;
if ( _wcsicmp( FilterPathStringFilePart, UrlScanDllName ) != 0 )
continue;
// this is an urlscan.dll filter, bash the filename to get the ini file name
wcscpy( FilterPathStringFilePart, UrlScanIniName );
WCHAR *IniFileName = FilterPathString;
UINT AllowVerbs =
GetPrivateProfileIntW(
L"options",
L"UseAllowVerbs",
-1,
IniFileName );
if ( AllowVerbs != 0 && AllowVerbs != 1 )
continue; // missing or broken ini file
if ( AllowVerbs )
Hr = ProcessVerbsInIniSection( L"AllowVerbs", L"BITS_POST", IniFileName, Add );
else
Hr = ProcessVerbsInIniSection( L"DenyVerbs", L"BITS_POST", IniFileName, !Add );
}
Hr = S_OK;
exit:
if ( MbFiltersContainer )
MbFiltersContainer->Release();
if ( EnumVariant )
EnumVariant->Release();
if ( Filter )
Filter->Release();
if ( Unknown )
Unknown->Release();
VariantClear( &Var );
return Hr;
}
#endif
STDAPI DllRegisterServer()
{
//
// Main entry point for setup
//
HRESULT Hr = InitializeSetup();
if ( FAILED( Hr ) )
return Hr;
Hr = RemoveFilterIfNeeded();
if ( FAILED( Hr ) )
return Hr;
Hr = StartupMSTask();
if ( FAILED( Hr ) )
return Hr;
Hr = InstallPropertySchema();
if ( FAILED( Hr ) )
return Hr;
Hr = InstallDefaultValues();
if ( FAILED( Hr ) )
return Hr;
Hr = ModifyLockdownList( true );
if ( FAILED( Hr ) )
return Hr;
Hr = ModifyLockdownListDisplay( true );
if ( FAILED( Hr ) )
return Hr;
Hr = ModifyInProcessList( true );
if ( FAILED( Hr ) )
return Hr;
#if 0
Hr = ModifyURLScanFiles( true );
if ( FAILED( Hr ) )
return Hr;
#endif
Hr = RestartIIS();
CleanupSetup();
return Hr;
}
STDAPI DllUnregisterServer()
{
//
// Main entry point for setup unregistration
//
HRESULT Hr = RemovePropertySchema();
if ( FAILED(Hr) )
return Hr;
Hr = ModifyLockdownList( false );
if ( FAILED( Hr ) )
goto failed;
Hr = ModifyLockdownListDisplay( false );
if ( FAILED( Hr ) )
goto failed;
Hr = ModifyInProcessList( false );
if ( FAILED( Hr ) )
return Hr;
Hr = RestartIIS();
return Hr;
failed:
return Hr;
}