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.
2448 lines
65 KiB
2448 lines
65 KiB
//---------------------------------------------------------------------
|
|
// Copyright (C)1998 Microsoft Corporation, All Rights Reserved.
|
|
//
|
|
// registry.cpp
|
|
//
|
|
//---------------------------------------------------------------------
|
|
|
|
#define UNICODE
|
|
#define INITGUID
|
|
|
|
#include <sysinc.h>
|
|
#include <malloc.h>
|
|
#include <winsock2.h>
|
|
#include <olectl.h> // for: SELFREG_E_CLASS
|
|
#include <iadmw.h> // COM Interface header
|
|
#include <iiscnfg.h> // MD_ & IIS_MD_ #defines
|
|
#include <httpfilt.h>
|
|
#include <httpext.h>
|
|
#include <ecblist.h>
|
|
#include <registry.h>
|
|
#include <filter.h>
|
|
#include <iwamreg.h>
|
|
#include <align.h>
|
|
#include <util.hxx>
|
|
#include <osfpcket.hxx>
|
|
#include <iads.h>
|
|
#include <adshlp.h>
|
|
#include <resource.h>
|
|
#include <iiisext.h>
|
|
#include <iisext_i.c>
|
|
|
|
// uncomment to debug setup problems
|
|
|
|
/*
|
|
#ifndef DBG_REG
|
|
#define DBG_REG 1
|
|
#endif // DBG_REG
|
|
|
|
#define DBG_ERROR 1
|
|
|
|
*/
|
|
|
|
// this defines control whether we will compile for the IIS security
|
|
// console or for the lockdown list.
|
|
#define IIS_SEC_CONSOLE 1
|
|
//#define IIS_LOCKDOWN_LIST
|
|
|
|
//----------------------------------------------------------------
|
|
// Globals:
|
|
//----------------------------------------------------------------
|
|
|
|
const rpcconn_tunnel_settings EchoRTS =
|
|
{
|
|
{
|
|
OSF_RPC_V20_VERS,
|
|
OSF_RPC_V20_VERS_MINOR,
|
|
rpc_rts,
|
|
PFC_FIRST_FRAG | PFC_LAST_FRAG,
|
|
{
|
|
NDR_LOCAL_CHAR_DREP | NDR_LOCAL_INT_DREP,
|
|
NDR_LOCAL_FP_DREP,
|
|
0,
|
|
0
|
|
},
|
|
FIELD_OFFSET(rpcconn_tunnel_settings, Cmd) + ConstPadN(FIELD_OFFSET(rpcconn_tunnel_settings, Cmd), 4),
|
|
0,
|
|
0
|
|
},
|
|
RTS_FLAG_ECHO,
|
|
0
|
|
};
|
|
|
|
const BYTE *GetEchoRTS (
|
|
OUT ULONG *EchoRTSSize
|
|
)
|
|
{
|
|
*EchoRTSSize = FIELD_OFFSET(rpcconn_tunnel_settings, Cmd)
|
|
+ ConstPadN(FIELD_OFFSET(rpcconn_tunnel_settings, Cmd), 4);
|
|
|
|
return (const BYTE *)&EchoRTS;
|
|
}
|
|
|
|
HMODULE g_hInst = NULL;
|
|
|
|
//----------------------------------------------------------------
|
|
// AnsiToUnicode()
|
|
//
|
|
// Convert an ANSI string to a UNICODE string.
|
|
//----------------------------------------------------------------
|
|
DWORD AnsiToUnicode( IN UCHAR *pszString,
|
|
IN ULONG ulStringLen,
|
|
OUT WCHAR *pwsString )
|
|
{
|
|
if (!pszString)
|
|
{
|
|
if (!pwsString)
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
pwsString[0] = 0;
|
|
return NO_ERROR;
|
|
}
|
|
}
|
|
|
|
if (!MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED,
|
|
(char*)pszString, 1+ulStringLen,
|
|
pwsString, 1+ulStringLen ))
|
|
{
|
|
return ERROR_NO_UNICODE_TRANSLATION;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// RegSetKeyAndValueIfDontExist()
|
|
//
|
|
// Private helper function for SetupRegistry() that checks if a key exists,
|
|
// and if not, creates a key, sets a value, then closes the key. If key
|
|
// exists, it is not touched.
|
|
//
|
|
// Parameters:
|
|
// pwsKey WCHAR* The name of the key
|
|
// pwsSubkey WCHAR* The name of a subkey
|
|
// pwsValueName WCHAR* The value name.
|
|
// pwsValue WCHAR* The data value to store
|
|
// dwType The type for the new registry value.
|
|
// dwDataSize The size for non-REG_SZ registry entry types.
|
|
//
|
|
// Return:
|
|
// BOOL TRUE if successful, FALSE otherwise.
|
|
//---------------------------------------------------------------------
|
|
BOOL RegSetKeyAndValueIfDontExist( const WCHAR *pwsKey,
|
|
const WCHAR *pwsSubKey,
|
|
const WCHAR *pwsValueName,
|
|
const WCHAR *pwsValue,
|
|
const DWORD dwType = REG_SZ,
|
|
DWORD dwDataSize = 0 )
|
|
{
|
|
HKEY hKey;
|
|
DWORD dwSize = 0;
|
|
WCHAR *pwsCompleteKey;
|
|
DWORD dwTypeFound;
|
|
long Error;
|
|
|
|
if (pwsKey)
|
|
dwSize = wcslen(pwsKey);
|
|
|
|
if (pwsSubKey)
|
|
dwSize += wcslen(pwsSubKey);
|
|
|
|
dwSize = (1+1+dwSize)*sizeof(WCHAR); // Extra +1 for the backslash...
|
|
|
|
pwsCompleteKey = (WCHAR*)_alloca(dwSize);
|
|
|
|
wcscpy(pwsCompleteKey,pwsKey);
|
|
|
|
if (NULL!=pwsSubKey)
|
|
{
|
|
wcscat(pwsCompleteKey, TEXT("\\"));
|
|
wcscat(pwsCompleteKey, pwsSubKey);
|
|
}
|
|
|
|
if ((Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
pwsCompleteKey,
|
|
0,
|
|
KEY_WRITE | KEY_QUERY_VALUE,
|
|
&hKey) ) == ERROR_SUCCESS )
|
|
{
|
|
if (( Error = RegQueryValueEx(
|
|
hKey,
|
|
pwsValueName,
|
|
0,
|
|
&dwTypeFound,
|
|
NULL,
|
|
NULL
|
|
) ) == ERROR_SUCCESS )
|
|
{
|
|
RegCloseKey(hKey);
|
|
return TRUE;
|
|
}
|
|
|
|
// the key exists, but the value does not. Fall through to
|
|
// create it
|
|
}
|
|
else
|
|
{
|
|
if (ERROR_SUCCESS != RegCreateKeyEx( HKEY_LOCAL_MACHINE,
|
|
pwsCompleteKey,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_WRITE, NULL, &hKey, NULL))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (pwsValue)
|
|
{
|
|
if ((dwType == REG_SZ)||(dwType == REG_EXPAND_SZ))
|
|
dwDataSize = (1+wcslen(pwsValue))*sizeof(WCHAR);
|
|
|
|
RegSetValueEx( hKey,
|
|
pwsValueName, 0, dwType, (BYTE *)pwsValue, dwDataSize );
|
|
}
|
|
else
|
|
{
|
|
RegSetValueEx( hKey,
|
|
pwsValueName, 0, dwType, (BYTE *)pwsValue, 0 );
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
return TRUE;
|
|
}
|
|
|
|
const WCHAR * const EVENT_LOG_SOURCE_NAME = L"RPC Proxy";
|
|
const WCHAR * const EVENT_LOG_KEY_NAME = L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\RPC Proxy";
|
|
const ULONG EVENT_LOG_CATEGORY_COUNT = 1;
|
|
|
|
HRESULT
|
|
RegisterEventLog()
|
|
{
|
|
|
|
HKEY EventLogKey = NULL;
|
|
DWORD Disposition;
|
|
|
|
LONG Result =
|
|
RegCreateKeyEx(
|
|
HKEY_LOCAL_MACHINE, // handle to open key
|
|
EVENT_LOG_KEY_NAME, // subkey name
|
|
0, // reserved
|
|
NULL, // class string
|
|
0, // special options
|
|
KEY_ALL_ACCESS, // desired security access
|
|
NULL, // inheritance
|
|
&EventLogKey, // key handle
|
|
&Disposition // disposition value buffer
|
|
);
|
|
|
|
if ( Result )
|
|
{
|
|
#if DBG
|
|
DbgPrint("RPCProxy: Can't create Eventlog key: %X\n", GetLastError());
|
|
#endif // DBG
|
|
return HRESULT_FROM_WIN32( Result );
|
|
}
|
|
|
|
DWORD Value = EVENT_LOG_CATEGORY_COUNT;
|
|
|
|
Result =
|
|
RegSetValueEx(
|
|
EventLogKey, // handle to key
|
|
L"CategoryCount", // value name
|
|
0, // reserved
|
|
REG_DWORD, // value type
|
|
(BYTE*)&Value, // value data
|
|
sizeof(Value) // size of value data
|
|
);
|
|
|
|
if ( Result )
|
|
{
|
|
#if DBG
|
|
DbgPrint("RPCProxy: Can't set CategoryCount value: %X\n", GetLastError());
|
|
#endif // DBG
|
|
goto error;
|
|
}
|
|
|
|
const WCHAR MessageFileName[] = L"%SystemRoot%\\system32\\rpcproxy\\rpcproxy.dll";
|
|
const DWORD MessageFileNameSize = sizeof( MessageFileName );
|
|
|
|
Result =
|
|
RegSetValueEx(
|
|
EventLogKey, // handle to key
|
|
L"CategoryMessageFile", // value name
|
|
0, // reserved
|
|
REG_EXPAND_SZ, // value type
|
|
(const BYTE*)MessageFileName, // value data
|
|
MessageFileNameSize // size of value data
|
|
);
|
|
|
|
if ( Result )
|
|
{
|
|
#if DBG
|
|
DbgPrint("RPCProxy: Can't set CategoryMessageFile value: %X\n", GetLastError());
|
|
#endif // DBG
|
|
goto error;
|
|
}
|
|
|
|
Result =
|
|
RegSetValueEx(
|
|
EventLogKey, // handle to key
|
|
L"EventMessageFile", // value name
|
|
0, // reserved
|
|
REG_EXPAND_SZ, // value type
|
|
(const BYTE*)MessageFileName, // value data
|
|
MessageFileNameSize // size of value data
|
|
);
|
|
|
|
if ( Result )
|
|
{
|
|
#if DBG
|
|
DbgPrint("RPCProxy: Can't set EventMessageFile value: %X\n", GetLastError());
|
|
#endif // DBG
|
|
goto error;
|
|
}
|
|
|
|
Value = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
|
|
Result =
|
|
RegSetValueEx(
|
|
EventLogKey, // handle to key
|
|
L"TypesSupported", // value name
|
|
0, // reserved
|
|
REG_DWORD, // value type
|
|
(BYTE*)&Value, // value data
|
|
sizeof(Value) // size of value data
|
|
);
|
|
|
|
if ( Result )
|
|
{
|
|
#if DBG
|
|
DbgPrint("RPCProxy: Can't set TypesSupported value: %X\n", GetLastError());
|
|
#endif // DBG
|
|
goto error;
|
|
}
|
|
|
|
RegCloseKey( EventLogKey );
|
|
EventLogKey = NULL;
|
|
return S_OK;
|
|
|
|
error:
|
|
|
|
if ( EventLogKey )
|
|
{
|
|
RegCloseKey( EventLogKey );
|
|
EventLogKey = NULL;
|
|
}
|
|
|
|
if ( REG_CREATED_NEW_KEY == Disposition )
|
|
{
|
|
RegDeleteKey(
|
|
HKEY_LOCAL_MACHINE,
|
|
EVENT_LOG_KEY_NAME );
|
|
}
|
|
|
|
return HRESULT_FROM_WIN32( Result );
|
|
|
|
}
|
|
|
|
HRESULT
|
|
UnRegisterEventLog()
|
|
{
|
|
|
|
RegDeleteKey(
|
|
HKEY_LOCAL_MACHINE,
|
|
EVENT_LOG_KEY_NAME );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
RPCProxyGetStartupInfo(
|
|
LPSTARTUPINFOA lpStartupInfo )
|
|
{
|
|
|
|
__try
|
|
{
|
|
GetStartupInfoA( lpStartupInfo );
|
|
}
|
|
__except( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
BOOL
|
|
RegisterOutOfProc(void)
|
|
{
|
|
|
|
//
|
|
// Runs a child process
|
|
//
|
|
|
|
STARTUPINFOA StartupInfo;
|
|
|
|
HRESULT Hr = RPCProxyGetStartupInfo( &StartupInfo );
|
|
|
|
if ( FAILED( Hr ) )
|
|
{
|
|
SetLastError( Hr );
|
|
return FALSE;
|
|
}
|
|
|
|
PROCESS_INFORMATION ProcessInfo;
|
|
CHAR sApplicationPath[MAX_PATH];
|
|
CHAR *pApplicationName = NULL;
|
|
CHAR sCmdLine[MAX_PATH];
|
|
DWORD dwLen = MAX_PATH;
|
|
DWORD dwCount;
|
|
|
|
dwCount = SearchPathA(NULL, // Search Path, NULL is PATH
|
|
"regsvr32.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 FALSE;
|
|
}
|
|
|
|
if (dwCount > dwLen)
|
|
{
|
|
SetLastError( ERROR_BUFFER_OVERFLOW );
|
|
return FALSE;
|
|
}
|
|
|
|
strcpy(sCmdLine, "regsvr32 /s rpcproxy.dll");
|
|
|
|
BOOL RetVal = CreateProcessA(
|
|
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 FALSE;
|
|
|
|
WaitForSingleObject( ProcessInfo.hProcess, INFINITE );
|
|
|
|
DWORD Status;
|
|
GetExitCodeProcess( ProcessInfo.hProcess, &Status );
|
|
|
|
CloseHandle( ProcessInfo.hProcess );
|
|
CloseHandle( ProcessInfo.hThread );
|
|
|
|
if ( ERROR_SUCCESS == Status )
|
|
return TRUE;
|
|
|
|
SetLastError( Status );
|
|
return FALSE;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// SetupRegistry()
|
|
//
|
|
// Add RPC proxy specific registry entries to contol its operation.
|
|
//
|
|
// \HKEY_LOCAL_MACHINE
|
|
// \Software
|
|
// \Microsoft
|
|
// \Rpc
|
|
// \RpcProxy
|
|
// \Enabled:REG_DWORD:0x00000001
|
|
// \ValidPorts:REG_SZ:<hostname>:1-5000
|
|
//
|
|
//---------------------------------------------------------------------
|
|
HRESULT SetupRegistry()
|
|
{
|
|
DWORD dwEnabled = 0x01;
|
|
DWORD dwSize;
|
|
DWORD dwStatus;
|
|
WCHAR *pwsValidPorts = 0;
|
|
char szHostName[MAX_TCPIP_HOST_NAME];
|
|
HRESULT hr;
|
|
|
|
// Note that gethostname() is an ANSI (non-unicode) function:
|
|
if (SOCKET_ERROR == gethostname(szHostName,sizeof(szHostName)))
|
|
{
|
|
dwStatus = WSAGetLastError();
|
|
return SELFREG_E_CLASS;
|
|
}
|
|
|
|
dwSize = 1 + _mbstrlen(szHostName);
|
|
pwsValidPorts = (WCHAR*)MemAllocate( sizeof(WCHAR)
|
|
* (dwSize + wcslen(REG_PORT_RANGE)) );
|
|
if (!pwsValidPorts)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
dwStatus = AnsiToUnicode((unsigned char*)szHostName,dwSize,pwsValidPorts);
|
|
if (dwStatus != NO_ERROR)
|
|
{
|
|
MemFree(pwsValidPorts);
|
|
return SELFREG_E_CLASS;
|
|
}
|
|
|
|
wcscat(pwsValidPorts,REG_PORT_RANGE);
|
|
|
|
if ( !RegSetKeyAndValueIfDontExist( REG_RPC_PATH,
|
|
REG_RPCPROXY,
|
|
REG_ENABLED,
|
|
(unsigned short *)&dwEnabled,
|
|
REG_DWORD,
|
|
sizeof(DWORD))
|
|
|
|
|| !RegSetKeyAndValueIfDontExist( REG_RPC_PATH,
|
|
REG_RPCPROXY,
|
|
REG_VALID_PORTS,
|
|
pwsValidPorts,
|
|
REG_SZ) )
|
|
{
|
|
MemFree(pwsValidPorts);
|
|
return SELFREG_E_CLASS;
|
|
}
|
|
|
|
MemFree(pwsValidPorts);
|
|
|
|
hr = RegisterEventLog ();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// CleanupRegistry()
|
|
//
|
|
// Delete the RpcProxy specific registry entries.
|
|
//---------------------------------------------------------------------
|
|
HRESULT CleanupRegistry()
|
|
{
|
|
HRESULT hr;
|
|
LONG lStatus;
|
|
DWORD dwLength = sizeof(WCHAR) + sizeof(REG_RPC_PATH)
|
|
+ sizeof(REG_RPCPROXY);
|
|
WCHAR *pwsSubKey;
|
|
|
|
pwsSubKey = (WCHAR*)_alloca(sizeof(WCHAR)*dwLength);
|
|
|
|
wcscpy(pwsSubKey,REG_RPC_PATH);
|
|
wcscat(pwsSubKey,TEXT("\\"));
|
|
wcscat(pwsSubKey,REG_RPCPROXY);
|
|
|
|
lStatus = RegDeleteKey( HKEY_LOCAL_MACHINE,
|
|
pwsSubKey );
|
|
|
|
(void) UnRegisterEventLog ();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// GetMetaBaseString()
|
|
//
|
|
// Retrieve a string value from the metabase.
|
|
//---------------------------------------------------------------------
|
|
HRESULT GetMetaBaseString( IN IMSAdminBase *pIMeta,
|
|
IN METADATA_HANDLE hMetaBase,
|
|
IN WCHAR *pwsKeyPath,
|
|
IN DWORD dwIdent,
|
|
OUT WCHAR *pwsBuffer,
|
|
IN OUT DWORD *pdwBufferSize )
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwSize;
|
|
METADATA_RECORD *pmbRecord;
|
|
|
|
dwSize = sizeof(METADATA_RECORD);
|
|
|
|
pmbRecord = (METADATA_RECORD*)MemAllocate(dwSize);
|
|
if (!pmbRecord)
|
|
{
|
|
return ERROR_OUTOFMEMORY;
|
|
}
|
|
|
|
memset(pmbRecord,0,dwSize);
|
|
|
|
pmbRecord->dwMDIdentifier = dwIdent;
|
|
pmbRecord->dwMDAttributes = 0; // METADATA_INHERIT;
|
|
pmbRecord->dwMDUserType = IIS_MD_UT_SERVER;
|
|
pmbRecord->dwMDDataType = STRING_METADATA;
|
|
pmbRecord->dwMDDataLen = *pdwBufferSize;
|
|
pmbRecord->pbMDData = (BYTE*)pwsBuffer;
|
|
|
|
hr = pIMeta->GetData( hMetaBase,
|
|
pwsKeyPath,
|
|
pmbRecord,
|
|
&dwSize );
|
|
#ifdef DBG_REG
|
|
if (FAILED(hr))
|
|
{
|
|
DbgPrint("pIMeta->GetData(): Failed: 0x%x\n",hr);
|
|
}
|
|
#endif
|
|
|
|
MemFree(pmbRecord);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// SetMetaBaseString()
|
|
//
|
|
// Store a string value into the metabase.
|
|
//---------------------------------------------------------------------
|
|
HRESULT SetMetaBaseString( IMSAdminBase *pIMeta,
|
|
METADATA_HANDLE hMetaBase,
|
|
WCHAR *pwsKeyPath,
|
|
DWORD dwIdent,
|
|
WCHAR *pwsBuffer,
|
|
DWORD dwAttributes,
|
|
DWORD dwUserType )
|
|
{
|
|
HRESULT hr;
|
|
METADATA_RECORD MbRecord;
|
|
|
|
memset(&MbRecord,0,sizeof(MbRecord));
|
|
|
|
MbRecord.dwMDIdentifier = dwIdent;
|
|
MbRecord.dwMDAttributes = dwAttributes;
|
|
MbRecord.dwMDUserType = dwUserType;
|
|
MbRecord.dwMDDataType = STRING_METADATA;
|
|
MbRecord.dwMDDataLen = sizeof(WCHAR) * (1 + wcslen(pwsBuffer));
|
|
MbRecord.pbMDData = (BYTE*)pwsBuffer;
|
|
|
|
hr = pIMeta->SetData( hMetaBase,
|
|
pwsKeyPath,
|
|
&MbRecord );
|
|
|
|
return hr;
|
|
}
|
|
|
|
#if IIS_LOCKDOWN_LIST
|
|
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;
|
|
}
|
|
|
|
#endif // #if #if IIS_LOCKDOWN_LIST
|
|
|
|
#if IIS_SEC_CONSOLE
|
|
|
|
HRESULT
|
|
EnableRpcProxyExtension (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enables the rpc proxy extension in the list of IIS ISAPI extensions.
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
Standard HRESULT
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr;
|
|
WCHAR* wszRootWeb6 = L"IIS://LOCALHOST/W3SVC";
|
|
IISWebService * pWeb = NULL;
|
|
VARIANT var1,var2;
|
|
BSTR ExtensionPath = NULL;
|
|
BSTR ExtensionGroup = NULL;
|
|
BSTR ExtensionDescription = NULL;
|
|
WCHAR FilterPath[ MAX_PATH + 1 ];
|
|
WCHAR ExtensionNameBuffer[ MAX_PATH ];
|
|
DWORD dwRet;
|
|
|
|
hr = ADsGetObject(wszRootWeb6, IID_IISWebService, (void**)&pWeb);
|
|
|
|
if (SUCCEEDED(hr) && NULL != pWeb)
|
|
{
|
|
VariantInit(&var1);
|
|
VariantInit(&var2);
|
|
|
|
var1.vt = VT_BOOL;
|
|
var1.boolVal = VARIANT_TRUE;
|
|
|
|
var2.vt = VT_BOOL;
|
|
var2.boolVal = VARIANT_TRUE;
|
|
|
|
dwRet = GetModuleFileNameW(
|
|
g_hInst,
|
|
FilterPath,
|
|
MAX_PATH );
|
|
|
|
if ( (dwRet > 0) && (dwRet != MAX_PATH))
|
|
{
|
|
FilterPath[MAX_PATH] = '\0';
|
|
ASSERT(GetLastError() == NO_ERROR);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(GetLastError() != NO_ERROR);
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
if (! LoadStringW(g_hInst, // handle to resource module
|
|
IDS_EXTENSION_NAME, // resource identifier
|
|
ExtensionNameBuffer, // resource buffer
|
|
MAX_PATH ) ) // size of buffer
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
ExtensionPath = SysAllocString(FilterPath);
|
|
if (ExtensionPath == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
ExtensionGroup = SysAllocString(L"RPCProxy");
|
|
if (ExtensionGroup == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
ExtensionDescription = SysAllocString(ExtensionNameBuffer);
|
|
if (ExtensionDescription == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
// During an upgrade the extension will already exist, so the API will fail.
|
|
hr = pWeb->AddExtensionFile(ExtensionPath, var1, ExtensionGroup, var2, ExtensionDescription);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pWeb->AddDependency(ExtensionPath, ExtensionGroup);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (HRESULT_CODE(hr) == ERROR_DUP_NAME)
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
#ifdef DBG_ERROR
|
|
DbgPrint("pWeb->AddExtensionFile failed: %X\r\n", hr);
|
|
#endif
|
|
// fall through with hr
|
|
}
|
|
}
|
|
|
|
VariantClear(&var1);
|
|
VariantClear(&var2);
|
|
pWeb->Release();
|
|
}
|
|
else
|
|
{
|
|
#ifdef DBG_ERROR
|
|
DbgPrint("FAIL:no object: %X\r\n", hr);
|
|
#endif
|
|
// fall through with hr
|
|
}
|
|
|
|
CleanupAndExit:
|
|
if (ExtensionPath != NULL)
|
|
SysFreeString(ExtensionPath);
|
|
|
|
if (ExtensionGroup != NULL)
|
|
SysFreeString(ExtensionGroup);
|
|
|
|
if (ExtensionDescription != NULL)
|
|
SysFreeString(ExtensionDescription);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
DisableRpcProxyExtension (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Disables the rpc proxy extension in the list of IIS ISAPI extensions.
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
Standard HRESULT
|
|
|
|
--*/
|
|
{
|
|
BSTR ExtensionPath = NULL;
|
|
HRESULT hr;
|
|
WCHAR* wszRootWeb6 = L"IIS://LOCALHOST/W3SVC";
|
|
IISWebService * pWeb = NULL;
|
|
DWORD dwRet;
|
|
WCHAR FilterPath[ MAX_PATH + 1 ];
|
|
|
|
hr = ADsGetObject(wszRootWeb6, IID_IISWebService, (void**)&pWeb);
|
|
|
|
if (SUCCEEDED(hr) && NULL != pWeb)
|
|
{
|
|
dwRet = GetModuleFileNameW(
|
|
g_hInst,
|
|
FilterPath,
|
|
MAX_PATH );
|
|
|
|
if ( (dwRet > 0) && (dwRet != MAX_PATH))
|
|
{
|
|
FilterPath[MAX_PATH] = '\0';
|
|
ASSERT(GetLastError() == NO_ERROR);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(GetLastError() != NO_ERROR);
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
ExtensionPath = SysAllocString(FilterPath);
|
|
if (ExtensionPath == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
// Call DeleteExtensionFileRecord for each of the DLLs you are removing
|
|
// from the system. This removes entries from WSERL.
|
|
hr = pWeb->DeleteExtensionFileRecord(ExtensionPath);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Call RemoveApplication (pYourAppName) - this removes your entry from
|
|
// ApplicationDependencies
|
|
hr = pWeb->RemoveApplication(ExtensionPath);
|
|
// fall through with the hr
|
|
}
|
|
else
|
|
{
|
|
#ifdef DBG_ERROR
|
|
DbgPrint("pWeb->DeleteExtensionFileRecord failed: %X\r\n", hr);
|
|
#endif
|
|
// fall through with the hr
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// fall through with the hr
|
|
}
|
|
|
|
CleanupAndExit:
|
|
if (ExtensionPath != NULL)
|
|
SysFreeString(ExtensionPath);
|
|
|
|
return hr;
|
|
}
|
|
|
|
#endif // #if IIS_SEC_CONSOLE
|
|
|
|
#if IIS_LOCKDOWN_LIST
|
|
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( BSTR( L"IsapiRestrictionList" ), &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( BSTR( L"IsapiRestrictionList" ), 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*)_alloca( sizeof(VARIANT) * ElementsToRemove );
|
|
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 ) )
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("RpcProxy: ADsGetObject(): Failed: 0x%x (%d)\n",
|
|
Hr, Hr );
|
|
#endif
|
|
return Hr;
|
|
}
|
|
|
|
Hr = Service->Get( BSTR( L"RestrictionListCustomDesc" ), &var );
|
|
if ( FAILED(Hr) )
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("RpcProxy: Service->Get(): Failed: 0x%x (%d)\n",
|
|
Hr, Hr );
|
|
#endif
|
|
// 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 ) )
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("RpcProxy: AddToLockdownListDisplay/RemoveFromLockdownListDisplay(): Failed: 0x%x (%d)\n",
|
|
Hr, Hr );
|
|
#endif
|
|
goto cleanup;
|
|
}
|
|
|
|
Hr = Service->Put( BSTR( L"RestrictionListCustomDesc" ), var );
|
|
if ( FAILED( Hr ) )
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("RpcProxy: Service->Put(): Failed: 0x%x (%d)\n",
|
|
Hr, Hr );
|
|
#endif
|
|
goto cleanup;
|
|
}
|
|
|
|
Hr = Service->SetInfo();
|
|
if ( FAILED( Hr ) )
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("RpcProxy: Service->SetInfo(): Failed: 0x%x (%d)\n",
|
|
Hr, Hr );
|
|
#endif
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
VariantClear( &var );
|
|
if ( Service )
|
|
Service->Release();
|
|
|
|
return Hr;
|
|
}
|
|
|
|
#endif // #if IIS_LOCKDOWN_LIST
|
|
|
|
//---------------------------------------------------------------------
|
|
// GetMetaBaseDword()
|
|
//
|
|
// Get a DWORD value from the metabase.
|
|
//---------------------------------------------------------------------
|
|
HRESULT GetMetaBaseDword( IMSAdminBase *pIMeta,
|
|
METADATA_HANDLE hMetaBase,
|
|
WCHAR *pwsKeyPath,
|
|
DWORD dwIdent,
|
|
DWORD *pdwValue )
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwSize;
|
|
METADATA_RECORD MbRecord;
|
|
|
|
memset(&MbRecord,0,sizeof(MbRecord));
|
|
*pdwValue = 0;
|
|
|
|
MbRecord.dwMDIdentifier = dwIdent;
|
|
MbRecord.dwMDAttributes = 0;
|
|
MbRecord.dwMDUserType = IIS_MD_UT_SERVER;
|
|
MbRecord.dwMDDataType = DWORD_METADATA;
|
|
MbRecord.dwMDDataLen = sizeof(DWORD);
|
|
MbRecord.pbMDData = (unsigned char *)pdwValue;
|
|
|
|
hr = pIMeta->GetData( hMetaBase,
|
|
pwsKeyPath,
|
|
&MbRecord,
|
|
&dwSize );
|
|
|
|
return hr;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// SetMetaBaseDword()
|
|
//
|
|
// Store a DWORD value into the metabase.
|
|
//---------------------------------------------------------------------
|
|
HRESULT SetMetaBaseDword( IMSAdminBase *pIMeta,
|
|
METADATA_HANDLE hMetaBase,
|
|
WCHAR *pwsKeyPath,
|
|
DWORD dwIdent,
|
|
DWORD dwValue,
|
|
DWORD dwAttributes,
|
|
DWORD dwUserType )
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwSize;
|
|
METADATA_RECORD MbRecord;
|
|
|
|
memset(&MbRecord,0,sizeof(MbRecord));
|
|
|
|
MbRecord.dwMDIdentifier = dwIdent;
|
|
MbRecord.dwMDAttributes = dwAttributes;
|
|
MbRecord.dwMDUserType = dwUserType;
|
|
MbRecord.dwMDDataType = DWORD_METADATA;
|
|
MbRecord.dwMDDataLen = sizeof(DWORD);
|
|
MbRecord.pbMDData = (unsigned char *)&dwValue;
|
|
|
|
hr = pIMeta->SetData( hMetaBase,
|
|
pwsKeyPath,
|
|
&MbRecord );
|
|
|
|
return hr;
|
|
}
|
|
|
|
RPC_STATUS
|
|
GetIISConnectionTimeout (
|
|
OUT ULONG *ConnectionTimeout
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Retrieve the connection timeout for IIS:
|
|
W3Svc/1/ROOT/Rpc/ConnectionTimeout
|
|
|
|
Arguments:
|
|
|
|
ConnectionTimeout - the connection timeout in seconds. Undefined
|
|
on failure
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK or RPC_S_* for error
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = 0;
|
|
DWORD dwValue = 0;
|
|
DWORD dwSize = 0;
|
|
IMSAdminBase *pIMeta = NULL;
|
|
BOOL CoInitSucceeded = FALSE;
|
|
|
|
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
|
if (FAILED(hr))
|
|
{
|
|
#ifdef DBG_ERROR
|
|
DbgPrint("GetIISConnectionTimeout: CoInitializeEx failed: Error: %X\n", hr);
|
|
#endif
|
|
goto MapErrorAndExit;
|
|
}
|
|
CoInitSucceeded = TRUE;
|
|
|
|
hr = CoCreateInstance( CLSID_MSAdminBase,
|
|
NULL,
|
|
CLSCTX_ALL,
|
|
IID_IMSAdminBase,
|
|
(void **)&pIMeta );
|
|
if (FAILED(hr))
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("CoCreateInstance(): Failed: 0x%x\n",hr);
|
|
#endif
|
|
goto MapErrorAndExit;
|
|
}
|
|
|
|
//
|
|
// Get: /W3Svc/1/ROOT/rpc/ConnectionTimeout
|
|
//
|
|
hr = GetMetaBaseDword( pIMeta,
|
|
METADATA_MASTER_ROOT_HANDLE,
|
|
TEXT("/lm/w3svc/1/ROOT/Rpc"),
|
|
MD_CONNECTION_TIMEOUT,
|
|
ConnectionTimeout);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("GetMetaBaseDword: Failed: 0x%x\n",hr);
|
|
#endif
|
|
// couldn't read at the site level - try the root
|
|
|
|
//
|
|
// Get: /W3Svc/ConnectionTimeout
|
|
//
|
|
hr = GetMetaBaseDword( pIMeta,
|
|
METADATA_MASTER_ROOT_HANDLE,
|
|
TEXT("/lm/w3svc"),
|
|
MD_CONNECTION_TIMEOUT,
|
|
ConnectionTimeout);
|
|
if (FAILED(hr))
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("GetMetaBaseDword: Failed: 0x%x\n",hr);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
MapErrorAndExit:
|
|
if (pIMeta != NULL)
|
|
pIMeta->Release();
|
|
|
|
if (CoInitSucceeded)
|
|
CoUninitialize();
|
|
|
|
if (FAILED(hr))
|
|
return RPC_S_OUT_OF_MEMORY;
|
|
else
|
|
return RPC_S_OK;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// SetupMetaBase()
|
|
//
|
|
// Setup entries in the metabase for both the filter and ISAPI parts
|
|
// of the RPC proxy. Note that these entries used to be in the registry.
|
|
//
|
|
// W3Svc/Filters/FilterLoadOrder "...,RpcProxy"
|
|
// W3Svc/Filters/RpcProxy/FilterImagePath "%SystemRoot%\System32\RpcProxy"
|
|
// W3Svc/Filters/RpcProxy/KeyType "IIsFilter"
|
|
// W3Svc/Filters/RpcProxy/FilterDescription "Microsoft RPC Proxy Filter, v1.0"
|
|
//
|
|
// W3Svc/1/ROOT/Rpc/KeyType "IIsWebVirtualDir"
|
|
// W3Svc/1/ROOT/Rpc/VrPath "%SystemRoot%\System32\RpcProxy"
|
|
// W3Svc/1/ROOT/Rpc/AccessPerm 0x205
|
|
// W3Svc/1/ROOT/Rpc/Win32Error 0x0
|
|
// W3Svc/1/ROOT/Rpc/DirectoryBrowsing 0x4000001E
|
|
// W3Svc/1/ROOT/Rpc/AppIsolated 0x0
|
|
// W3Svc/1/ROOT/Rpc/AppRoot "/LM/W3SVC/1/Root/rpc"
|
|
// W3Svc/1/ROOT/Rpc/AppWamClsid "{BF285648-0C5C-11D2-A476-0000F8080B50}"
|
|
// W3Svc/1/ROOT/Rpc/AppFriendlyName "rpc"
|
|
//
|
|
//---------------------------------------------------------------------
|
|
HRESULT SetupMetaBase()
|
|
{
|
|
HRESULT hr = 0;
|
|
DWORD dwValue = 0;
|
|
DWORD dwSize = 0;
|
|
DWORD dwBufferSize = sizeof(WCHAR) * ORIGINAL_BUFFER_SIZE;
|
|
WCHAR *pwsBuffer = (WCHAR*)MemAllocate(dwBufferSize);
|
|
WCHAR *pwsSystemRoot = _wgetenv(SYSTEM_ROOT);
|
|
WCHAR wsPath[METADATA_MAX_NAME_LEN];
|
|
|
|
IMSAdminBase *pIMeta;
|
|
METADATA_HANDLE hMetaBase;
|
|
|
|
//
|
|
// Name of this DLL (and where it is):
|
|
//
|
|
// WCHAR wszModule[256];
|
|
//
|
|
// if (!GetModuleFileName( g_hInst, wszModule,
|
|
// sizeof(wszModule)/sizeof(WCHAR)))
|
|
// {
|
|
// return SELFREG_E_CLASS;
|
|
// }
|
|
|
|
if (!pwsBuffer)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = CoCreateInstance( CLSID_MSAdminBase,
|
|
NULL,
|
|
CLSCTX_ALL,
|
|
IID_IMSAdminBase,
|
|
(void **)&pIMeta );
|
|
if (FAILED(hr))
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("CoCreateInstance(): Failed: 0x%x\n",hr);
|
|
#endif
|
|
MemFree(pwsBuffer);
|
|
return hr;
|
|
}
|
|
|
|
// Get a handle to the Web service:
|
|
hr = pIMeta->OpenKey( METADATA_MASTER_ROOT_HANDLE,
|
|
LOCAL_MACHINE_W3SVC,
|
|
(METADATA_PERMISSION_READ|METADATA_PERMISSION_WRITE),
|
|
20,
|
|
&hMetaBase );
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("pIMeta->OpenKey(): Failed: 0x%x\n",hr);
|
|
#endif
|
|
MemFree(pwsBuffer);
|
|
pIMeta->Release();
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// IIS Filter: FilterLoadOrder
|
|
//
|
|
dwSize = dwBufferSize;
|
|
hr = GetMetaBaseString( pIMeta,
|
|
hMetaBase,
|
|
MD_KEY_FILTERS, // See iiscnfg.h
|
|
MD_FILTER_LOAD_ORDER, // See iiscnfg.h
|
|
pwsBuffer,
|
|
&dwSize );
|
|
if (FAILED(hr) && (hr != MD_ERROR_DATA_NOT_FOUND))
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("GetMetaBaseString(): Failed: 0x%x\n",hr);
|
|
#endif
|
|
MemFree(pwsBuffer);
|
|
pIMeta->Release();
|
|
return hr;
|
|
}
|
|
|
|
if (hr == MD_ERROR_DATA_NOT_FOUND)
|
|
pwsBuffer[0] = '\0';
|
|
|
|
// Check whether too much of the buffer has been used up.
|
|
pwsBuffer[ORIGINAL_BUFFER_SIZE-1] = '\0';
|
|
if (wcslen(pwsBuffer) > MAX_USED_BUFFER_SIZE)
|
|
{
|
|
ASSERT(0);
|
|
MemFree(pwsBuffer);
|
|
pIMeta->Release();
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
if (!wcsstr(pwsBuffer,RPCPROXY))
|
|
{
|
|
// RpcProxy is not in FilterLoadOrder, so add it (if there were
|
|
// previous elements).
|
|
if (hr != MD_ERROR_DATA_NOT_FOUND)
|
|
{
|
|
wcscat(pwsBuffer,TEXT(","));
|
|
}
|
|
|
|
wcscat(pwsBuffer,RPCPROXY);
|
|
hr = SetMetaBaseString( pIMeta,
|
|
hMetaBase,
|
|
MD_KEY_FILTERS,
|
|
MD_FILTER_LOAD_ORDER,
|
|
pwsBuffer,
|
|
0,
|
|
IIS_MD_UT_SERVER );
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
MemFree(pwsBuffer);
|
|
pIMeta->Release();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// IIS Filter: RpcProxy/FilterImagePath
|
|
//
|
|
hr = pIMeta->AddKey( hMetaBase, MD_KEY_FILTERS_RPCPROXY );
|
|
if ( (FAILED(hr)) && (hr != 0x800700b7))
|
|
{
|
|
MemFree(pwsBuffer);
|
|
pIMeta->Release();
|
|
return hr;
|
|
}
|
|
|
|
|
|
wcscpy(pwsBuffer,pwsSystemRoot);
|
|
wcscat(pwsBuffer,RPCPROXY_PATH);
|
|
wcscat(pwsBuffer,TEXT("\\"));
|
|
wcscat(pwsBuffer,RPCPROXY_DLL);
|
|
hr = SetMetaBaseString( pIMeta,
|
|
hMetaBase,
|
|
MD_KEY_FILTERS_RPCPROXY,
|
|
MD_FILTER_IMAGE_PATH,
|
|
pwsBuffer,
|
|
0,
|
|
IIS_MD_UT_SERVER );
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
MemFree(pwsBuffer);
|
|
pIMeta->Release();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// IIS Filter: Filters/RpcProxy/KeyType
|
|
//
|
|
|
|
wcscpy(pwsBuffer,IISFILTER);
|
|
hr = SetMetaBaseString( pIMeta,
|
|
hMetaBase,
|
|
MD_KEY_FILTERS_RPCPROXY,
|
|
MD_KEY_TYPE,
|
|
pwsBuffer,
|
|
0,
|
|
IIS_MD_UT_SERVER );
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
MemFree(pwsBuffer);
|
|
pIMeta->Release();
|
|
return hr;
|
|
}
|
|
|
|
|
|
wcscpy(pwsBuffer, FILTER_DESCRIPTION_W);
|
|
hr = SetMetaBaseString( pIMeta,
|
|
hMetaBase,
|
|
MD_KEY_FILTERS_RPCPROXY,
|
|
MD_FILTER_DESCRIPTION,
|
|
pwsBuffer,
|
|
0,
|
|
IIS_MD_UT_SERVER );
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
MemFree(pwsBuffer);
|
|
pIMeta->Release();
|
|
return hr;
|
|
}
|
|
|
|
// We do not write the events we subscribe for to the metabase. We have
|
|
// already advertised our presence and in IIS 5 mode IIS will load us,
|
|
// ask for the events, and write them for us in the metabase
|
|
|
|
//
|
|
// Set: /W3Svc/1/ROOT/rpc/AccessPerm
|
|
//
|
|
dwValue = ACCESS_PERM_FLAGS;
|
|
hr = SetMetaBaseDword( pIMeta,
|
|
hMetaBase,
|
|
MD_KEY_ROOT_RPC,
|
|
MD_ACCESS_PERM,
|
|
dwValue,
|
|
METADATA_INHERIT,
|
|
IIS_MD_UT_FILE );
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
MemFree(pwsBuffer);
|
|
pIMeta->Release();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Disable entity body preload for this ISAPI
|
|
//
|
|
|
|
dwValue = 0;
|
|
|
|
hr = SetMetaBaseDword( pIMeta,
|
|
hMetaBase,
|
|
MD_KEY_ROOT_RPC,
|
|
MD_UPLOAD_READAHEAD_SIZE,
|
|
dwValue,
|
|
METADATA_INHERIT,
|
|
IIS_MD_UT_FILE );
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
MemFree(pwsBuffer);
|
|
pIMeta->Release();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Set: /W3Svc/1/ROOT/rpc/Win32Error
|
|
//
|
|
dwValue = 0;
|
|
hr = SetMetaBaseDword( pIMeta,
|
|
hMetaBase,
|
|
MD_KEY_ROOT_RPC,
|
|
MD_WIN32_ERROR,
|
|
dwValue,
|
|
METADATA_INHERIT,
|
|
IIS_MD_UT_SERVER );
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
MemFree(pwsBuffer);
|
|
pIMeta->Release();
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// Set: /W3Svc/1/ROOT/rpc/DirectroyBrowsing
|
|
//
|
|
dwValue = DIRECTORY_BROWSING_FLAGS;
|
|
hr = SetMetaBaseDword( pIMeta,
|
|
hMetaBase,
|
|
MD_KEY_ROOT_RPC,
|
|
MD_DIRECTORY_BROWSING,
|
|
dwValue,
|
|
METADATA_INHERIT,
|
|
IIS_MD_UT_FILE );
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
pIMeta->Release();
|
|
CoUninitialize();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Set: /W3Svc/1/ROOT/rpc/KeyType
|
|
//
|
|
wcscpy(pwsBuffer,IIS_WEB_VIRTUAL_DIR);
|
|
hr = SetMetaBaseString( pIMeta,
|
|
hMetaBase,
|
|
MD_KEY_ROOT_RPC,
|
|
MD_KEY_TYPE,
|
|
pwsBuffer,
|
|
0,
|
|
IIS_MD_UT_SERVER );
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
MemFree(pwsBuffer);
|
|
pIMeta->Release();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Set: /W3Svc/1/ROOT/rpc/VrPath
|
|
//
|
|
wcscpy(pwsBuffer,pwsSystemRoot);
|
|
wcscat(pwsBuffer,RPCPROXY_PATH);
|
|
hr = SetMetaBaseString( pIMeta,
|
|
hMetaBase,
|
|
MD_KEY_ROOT_RPC,
|
|
MD_VR_PATH,
|
|
pwsBuffer,
|
|
METADATA_INHERIT,
|
|
IIS_MD_UT_FILE );
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
MemFree(pwsBuffer);
|
|
pIMeta->Release();
|
|
return hr;
|
|
}
|
|
|
|
#if FALSE
|
|
|
|
//
|
|
// Set: /W3Svc/1/ROOT/rpc/AppIsolated
|
|
//
|
|
dwValue = 0;
|
|
hr = SetMetaBaseDword( pIMeta,
|
|
hMetaBase,
|
|
MD_KEY_ROOT_RPC,
|
|
MD_APP_ISOLATED,
|
|
dwValue,
|
|
METADATA_INHERIT,
|
|
IIS_MD_UT_WAM );
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
MemFree(pwsBuffer);
|
|
pIMeta->Release();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Set: /W3Svc/1/ROOT/rpc/AppRoot
|
|
//
|
|
wcscpy(pwsBuffer,APP_ROOT_PATH);
|
|
hr = SetMetaBaseString( pIMeta,
|
|
hMetaBase,
|
|
MD_KEY_ROOT_RPC,
|
|
MD_APP_ROOT,
|
|
pwsBuffer,
|
|
METADATA_INHERIT,
|
|
IIS_MD_UT_FILE );
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
MemFree(pwsBuffer);
|
|
pIMeta->Release();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Set: /W3Svc/1/ROOT/rpc/AppWamClsid
|
|
//
|
|
wcscpy(pwsBuffer,APP_WAM_CLSID);
|
|
hr = SetMetaBaseString( pIMeta,
|
|
hMetaBase,
|
|
MD_KEY_ROOT_RPC,
|
|
MD_APP_WAM_CLSID,
|
|
pwsBuffer,
|
|
METADATA_INHERIT,
|
|
IIS_MD_UT_WAM );
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
MemFree(pwsBuffer);
|
|
pIMeta->Release();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Set: /W3Svc/1/ROOT/rpc/AppFriendlyName
|
|
//
|
|
wcscpy(pwsBuffer,APP_FRIENDLY_NAME);
|
|
hr = SetMetaBaseString( pIMeta,
|
|
hMetaBase,
|
|
MD_KEY_ROOT_RPC,
|
|
MD_APP_FRIENDLY_NAME,
|
|
pwsBuffer,
|
|
METADATA_INHERIT,
|
|
IIS_MD_UT_WAM );
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
MemFree(pwsBuffer);
|
|
pIMeta->Release();
|
|
return hr;
|
|
}
|
|
|
|
#endif
|
|
|
|
//
|
|
// Release the handle and buffer:
|
|
//
|
|
MemFree(pwsBuffer);
|
|
|
|
pIMeta->CloseKey(hMetaBase);
|
|
|
|
pIMeta->Release();
|
|
|
|
CoUninitialize();
|
|
|
|
return 0;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// CleanupMetaBase()
|
|
//
|
|
//---------------------------------------------------------------------
|
|
HRESULT CleanupMetaBase()
|
|
{
|
|
HRESULT hr = 0;
|
|
DWORD dwSize = 0;
|
|
WCHAR *pwsRpcProxy;
|
|
WCHAR *pws;
|
|
DWORD dwBufferSize = sizeof(WCHAR) * ORIGINAL_BUFFER_SIZE;
|
|
WCHAR *pwsBuffer = (WCHAR*)MemAllocate(dwBufferSize);
|
|
|
|
// CComPtr <IMSAdminBase> pIMeta;
|
|
IMSAdminBase *pIMeta;
|
|
METADATA_HANDLE hMetaBase;
|
|
|
|
if (!pwsBuffer)
|
|
{
|
|
return ERROR_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = CoCreateInstance( CLSID_MSAdminBase,
|
|
NULL,
|
|
CLSCTX_ALL,
|
|
IID_IMSAdminBase,
|
|
(void **)&pIMeta );
|
|
if (FAILED(hr))
|
|
{
|
|
MemFree(pwsBuffer);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Get a handle to the Web service:
|
|
//
|
|
hr = pIMeta->OpenKey( METADATA_MASTER_ROOT_HANDLE,
|
|
TEXT("/LM/W3SVC"),
|
|
(METADATA_PERMISSION_READ|METADATA_PERMISSION_WRITE),
|
|
20,
|
|
&hMetaBase );
|
|
if (FAILED(hr))
|
|
{
|
|
MemFree(pwsBuffer);
|
|
pIMeta->Release();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Remove the RpcProxy reference from the FilterLoadOrder value:
|
|
//
|
|
dwSize = dwBufferSize;
|
|
hr = GetMetaBaseString( pIMeta,
|
|
hMetaBase,
|
|
MD_KEY_FILTERS,
|
|
MD_FILTER_LOAD_ORDER,
|
|
pwsBuffer,
|
|
&dwSize );
|
|
if (!FAILED(hr))
|
|
{
|
|
// Check whether too much of the buffer has been used up.
|
|
pwsBuffer[ORIGINAL_BUFFER_SIZE-1] = '\0';
|
|
if (wcslen(pwsBuffer) > MAX_USED_BUFFER_SIZE)
|
|
{
|
|
ASSERT(0);
|
|
MemFree(pwsBuffer);
|
|
pIMeta->Release();
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
if (pwsRpcProxy=wcsstr(pwsBuffer,RPCPROXY))
|
|
{
|
|
// "RpcProxy" is in FilterLoadOrder, so remove it:
|
|
|
|
// Check to see if RpcProxy is at the start of the list:
|
|
if (pwsRpcProxy != pwsBuffer)
|
|
{
|
|
pwsRpcProxy--; // Want to remove the comma before...
|
|
dwSize = sizeof(RPCPROXY);
|
|
}
|
|
else
|
|
{
|
|
dwSize = sizeof(RPCPROXY) - 1;
|
|
}
|
|
|
|
pws = pwsRpcProxy + dwSize;
|
|
memcpy(pwsRpcProxy,pws,sizeof(WCHAR)*(1+wcslen(pws)));
|
|
hr = SetMetaBaseString( pIMeta,
|
|
hMetaBase,
|
|
MD_KEY_FILTERS,
|
|
MD_FILTER_LOAD_ORDER,
|
|
pwsBuffer,
|
|
0,
|
|
IIS_MD_UT_SERVER );
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Delete: /W3Svc/Filters/RpcProxy
|
|
//
|
|
hr = pIMeta->DeleteKey( hMetaBase,
|
|
MD_KEY_FILTERS_RPCPROXY );
|
|
|
|
//
|
|
// Delete: /W3Svc/1/ROOT/Rpc
|
|
//
|
|
hr = pIMeta->DeleteKey( hMetaBase,
|
|
MD_KEY_FILTERS_RPCPROXY );
|
|
|
|
//
|
|
// Release the handle and buffer:
|
|
//
|
|
MemFree(pwsBuffer);
|
|
|
|
pIMeta->CloseKey(hMetaBase);
|
|
|
|
pIMeta->Release();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
const WCHAR InetInfoName[] = L"inetinfo.exe";
|
|
const ULONG InetInfoNameLength = sizeof(InetInfoName) / sizeof(WCHAR) - 1; // in characters without terminating NULL
|
|
|
|
BOOL
|
|
UpdateIsIISInCompatibilityMode (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reads the compatibility mode state. It used to read it from the metabase,
|
|
but after repeated problems in compatibility mode, WadeH suggested a simpler approach -
|
|
check whether we run in inetinfo. If yet, we're in compatibility mode.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
non-zero if the variable is correctly updated. 0 otherwise
|
|
|
|
--*/
|
|
{
|
|
WCHAR ExtensionPath[ MAX_PATH + 1 ];
|
|
ULONG ModuleFileNameLength; // in characters without terminating NULL
|
|
|
|
DWORD dwRet = GetModuleFileNameW(
|
|
GetModuleHandle(NULL),
|
|
ExtensionPath,
|
|
MAX_PATH );
|
|
|
|
if ( (dwRet > 0) && (dwRet != MAX_PATH))
|
|
{
|
|
ExtensionPath[MAX_PATH] = '\0';
|
|
ASSERT(GetLastError() == NO_ERROR);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(GetLastError() != NO_ERROR);
|
|
return FALSE;
|
|
}
|
|
|
|
ModuleFileNameLength = wcslen(ExtensionPath);
|
|
if (ModuleFileNameLength < InetInfoNameLength)
|
|
{
|
|
fIsIISInCompatibilityMode = FALSE;
|
|
}
|
|
|
|
if (_wcsicmp(ExtensionPath + ModuleFileNameLength - InetInfoNameLength, InetInfoName) == 0)
|
|
{
|
|
fIsIISInCompatibilityMode = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fIsIISInCompatibilityMode = FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// DllRegisterServer()
|
|
//
|
|
// Setup the Registry and MetaBase for the RPC proxy.
|
|
//---------------------------------------------------------------------
|
|
|
|
const char ChildProcessVar[] = "__RPCPROXY_CHILD_PROCESS";
|
|
const char ChildProcessVarValue[] = "__FROM_SETUP";
|
|
|
|
|
|
HRESULT DllRegisterServer()
|
|
{
|
|
HRESULT hr;
|
|
WORD wVersion = MAKEWORD(1,1);
|
|
WSADATA wsaData;
|
|
char EnvironmentVarBuffer[MAX_PATH];
|
|
DWORD Temp;
|
|
BOOL Result;
|
|
DWORD LastError;
|
|
|
|
#ifdef DBG_REG
|
|
DbgPrint("RpcProxy: DllRegisterServer(): Start\n");
|
|
#endif
|
|
|
|
// check if we are have already been called from the RPCProxy DllRegister routine
|
|
Temp = GetEnvironmentVariableA(ChildProcessVar, EnvironmentVarBuffer, MAX_PATH);
|
|
|
|
#ifdef DBG_REG
|
|
DbgPrint("RpcProxy: Result of looking for environment variable - %d\n", Temp);
|
|
#endif
|
|
|
|
// GetEnvironmentVariable does not count the terminating NULL.
|
|
if (Temp < sizeof(ChildProcessVarValue) - 1)
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("RpcProxy: Not a child process - spawning one\n");
|
|
#endif
|
|
|
|
// we didn't find the variable. Add it and spawn ourselves to register out of proc
|
|
Result = SetEnvironmentVariableA (ChildProcessVar, ChildProcessVarValue);
|
|
if (Result == FALSE)
|
|
return E_OUTOFMEMORY;
|
|
|
|
Result = RegisterOutOfProc();
|
|
if (Result == FALSE)
|
|
{
|
|
// capture the last error before we call SetEnvironmentVariable
|
|
LastError = GetLastError();
|
|
}
|
|
|
|
// before processing the result, remove the environment variable. If this fails, there
|
|
// isn't much we can do. Fortunately, failure to delete is completely benign
|
|
(void) SetEnvironmentVariableA (ChildProcessVar, NULL);
|
|
|
|
if (Result == FALSE)
|
|
{
|
|
return HRESULT_FROM_WIN32(LastError);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
if (WSAStartup(wVersion,&wsaData))
|
|
{
|
|
return SELFREG_E_CLASS;
|
|
}
|
|
|
|
hr = CoInitializeEx(0,COINIT_MULTITHREADED);
|
|
if (FAILED(hr))
|
|
{
|
|
hr = CoInitializeEx(0,COINIT_APARTMENTTHREADED);
|
|
if (FAILED(hr))
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("RpcProxy: CoInitialize(): Failed: 0x%x\n", hr );
|
|
#endif
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
hr = SetupRegistry();
|
|
if (FAILED(hr))
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("RpcProxy: SetupRegistry(): Failed: 0x%x (%d)\n",
|
|
hr, hr );
|
|
#endif
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
hr = SetupMetaBase();
|
|
if (FAILED(hr))
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("RpcProxy: SetupMetaBase(): Failed: 0x%x (%d)\n",
|
|
hr, hr );
|
|
#endif
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
#if IIS_LOCKDOWN_LIST
|
|
hr = ModifyLockdownList( true );
|
|
#endif // #if IIS_LOCKDOWN_LIST
|
|
|
|
#if IIS_SEC_CONSOLE
|
|
hr = EnableRpcProxyExtension();
|
|
#endif // #if IIS_SEC_CONSOLE
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("RpcProxy: ModifyLockdownList(): Failed: 0x%x (%d)\n",
|
|
hr, hr );
|
|
#endif
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
#if IIS_LOCKDOWN_LIST
|
|
hr = ModifyLockdownListDisplay( true );
|
|
#ifdef DBG_REG
|
|
if ( FAILED( hr ) )
|
|
{
|
|
DbgPrint("RpcProxy: ModifyLockdownListDisplay(): Failed: 0x%x (%d)\n",
|
|
hr, hr );
|
|
}
|
|
#endif
|
|
#endif // #if IIS_LOCKDOWN_LIST
|
|
|
|
CleanupAndExit:
|
|
CoUninitialize();
|
|
|
|
#ifdef DBG_REG
|
|
DbgPrint("RpcProxy: DllRegisterServer(): End: hr: 0x%x\n",hr);
|
|
#endif
|
|
|
|
return hr;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// DllUnregisterServer()
|
|
//
|
|
// Uninstall Registry and MetaBase values used by the RPC proxy.
|
|
//
|
|
// Modified to mostly return S_Ok, even if a problem occurs. This is
|
|
// done so that the uninstall will complete even if there is a problem
|
|
// in the un-register.
|
|
//---------------------------------------------------------------------
|
|
HRESULT DllUnregisterServer()
|
|
{
|
|
HRESULT hr;
|
|
WORD wVersion = MAKEWORD(1,1);
|
|
WSADATA wsaData;
|
|
|
|
#ifdef DBG_REG
|
|
DbgPrint("RpcProxy: DllUnregisterServer(): Start\n");
|
|
#endif
|
|
|
|
if (WSAStartup(wVersion,&wsaData))
|
|
{
|
|
return SELFREG_E_CLASS;
|
|
}
|
|
|
|
hr = CoInitializeEx(0,COINIT_MULTITHREADED);
|
|
if (FAILED(hr))
|
|
{
|
|
hr = CoInitializeEx(0,COINIT_APARTMENTTHREADED);
|
|
if (FAILED(hr))
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("RpcProxy: CoInitializeEx() Failed: 0x%x\n",hr);
|
|
#endif
|
|
return S_OK;
|
|
}
|
|
}
|
|
#if IIS_SEC_CONSOLE
|
|
hr = DisableRpcProxyExtension();
|
|
#endif // #if IIS_SEC_CONSOLE
|
|
|
|
#if IIS_LOCKDOWN_LIST
|
|
hr = ModifyLockdownList( false );
|
|
#endif // #if IIS_LOCKDOWN_LIST
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("RpcProxy: ModifyLockdownList() Failed: 0x%x (%d)\n",hr,hr);
|
|
#endif
|
|
return S_OK;
|
|
}
|
|
|
|
#if IIS_LOCKDOWN_LIST
|
|
hr = ModifyLockdownListDisplay( false );
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("RpcProxy: ModifyLockdownListDisplay() Failed: 0x%x (%d)\n",hr,hr);
|
|
#endif
|
|
return S_OK;
|
|
}
|
|
#endif // #if IIS_LOCKDOWN_LIST
|
|
|
|
hr = CleanupRegistry();
|
|
if (FAILED(hr))
|
|
{
|
|
#ifdef DBG_REG
|
|
DbgPrint("RpcProxy: CleanupRegistry() Failed: 0x%x (%d)\n",hr,hr);
|
|
#endif
|
|
return S_OK;
|
|
}
|
|
|
|
hr = CleanupMetaBase();
|
|
|
|
#ifdef DBG_REG
|
|
if (FAILED(hr))
|
|
{
|
|
DbgPrint("RpcProxy: CleanupMetaBase() Failed: 0x%x (%d)\n",hr,hr);
|
|
}
|
|
#endif
|
|
|
|
CoUninitialize();
|
|
|
|
#ifdef DBG_REG
|
|
DbgPrint("RpcProxy: DllUnregisterServer(): Start\n");
|
|
#endif
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// DllMain()
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BOOL WINAPI DllMain( HINSTANCE hInst,
|
|
ULONG ulReason,
|
|
LPVOID pvReserved )
|
|
{
|
|
BOOL fInitialized = TRUE;
|
|
|
|
switch (ulReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
if (!DisableThreadLibraryCalls(hInst))
|
|
{
|
|
fInitialized = FALSE;
|
|
}
|
|
else
|
|
{
|
|
g_hInst = hInst;
|
|
}
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
FreeServerInfo(&g_pServerInfo);
|
|
break;
|
|
|
|
case DLL_THREAD_ATTACH:
|
|
// Not used. Disabled.
|
|
break;
|
|
|
|
case DLL_THREAD_DETACH:
|
|
// Not used. Disabled.
|
|
break;
|
|
}
|
|
|
|
return fInitialized;
|
|
}
|