e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
612 lines
30 KiB
C#
612 lines
30 KiB
C#
//------------------------------------------------------------------------------
|
|
// <copyright file="RemoteWebConfigurationHost.cs" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
//------------------------------------------------------------------------------
|
|
|
|
namespace System.Web.Configuration {
|
|
using System.Collections;
|
|
using System.Configuration;
|
|
using System.Configuration.Internal;
|
|
using System.Web;
|
|
using System.Web.Util;
|
|
using System.Security;
|
|
using System.IO;
|
|
using System.Web.Hosting;
|
|
using System.Runtime.InteropServices;
|
|
using System.Reflection;
|
|
using System.Collections.Specialized;
|
|
using System.Xml;
|
|
using System.Security.Principal;
|
|
using System.Threading;
|
|
using System.Globalization;
|
|
using System.Security.Permissions;
|
|
|
|
[SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
|
|
internal sealed class RemoteWebConfigurationHost : DelegatingConfigHost
|
|
{
|
|
private const string KEY_MACHINE = "MACHINE";
|
|
|
|
private static object s_version = new object();
|
|
|
|
private string _Server;
|
|
private string _Username;
|
|
private string _Domain;
|
|
private string _Password;
|
|
private WindowsIdentity _Identity;
|
|
|
|
private Hashtable _PathMap; // configPath -> configFile
|
|
private string _ConfigPath;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
internal RemoteWebConfigurationHost() {}
|
|
|
|
public override void Init(IInternalConfigRoot configRoot, params object[] hostInitParams) {
|
|
throw ExceptionUtil.UnexpectedError("RemoteWebConfigurationHost::Init");
|
|
}
|
|
|
|
public override void InitForConfiguration(ref string locationSubPath, out string configPath, out string locationConfigPath,
|
|
IInternalConfigRoot root, params object[] hostInitConfigurationParams) {
|
|
|
|
|
|
WebLevel webLevel = (WebLevel) hostInitConfigurationParams[0];
|
|
// ConfigurationFileMap fileMap = (ConfigurationFileMap) hostInitConfigurationParams[1];
|
|
string path = (string) hostInitConfigurationParams[2];
|
|
string site = (string) hostInitConfigurationParams[3];
|
|
|
|
if (locationSubPath == null) {
|
|
locationSubPath = (string) hostInitConfigurationParams[4];
|
|
}
|
|
|
|
string server = (string) hostInitConfigurationParams[5];
|
|
string userName = (string) hostInitConfigurationParams[6];
|
|
string password = (string) hostInitConfigurationParams[7];
|
|
IntPtr tokenHandle = (IntPtr) hostInitConfigurationParams[8];
|
|
|
|
configPath = null;
|
|
locationConfigPath = null;
|
|
|
|
_Server = server;
|
|
_Username = GetUserNameFromFullName(userName);
|
|
_Domain = GetDomainFromFullName(userName);
|
|
_Password = password;
|
|
_Identity = (tokenHandle == IntPtr.Zero) ? null : new WindowsIdentity(tokenHandle); //CreateWindowsIdentity(username, domain, password, tokenHandle);
|
|
|
|
_PathMap = new Hashtable(StringComparer.OrdinalIgnoreCase);
|
|
|
|
#if !FEATURE_PAL // FEATURE_PAL does not have WindowsImpersonationContext, COM objects
|
|
//
|
|
// Send the path arguments to the server for parsing,
|
|
// and retreive the normalized paths and path mapping
|
|
// from config paths to file paths.
|
|
//
|
|
string filePaths;
|
|
try {
|
|
WindowsImpersonationContext wiContext = (_Identity != null) ? _Identity.Impersonate() : null;
|
|
try {
|
|
IRemoteWebConfigurationHostServer remoteSrv = RemoteWebConfigurationHost.CreateRemoteObject(server, _Username, _Domain, password); //(IRemoteWebConfigurationHostServer) Activator.CreateInstance(type);
|
|
try {
|
|
filePaths = remoteSrv.GetFilePaths((int) webLevel, path, site, locationSubPath);
|
|
} finally {
|
|
// Release COM objects
|
|
while (Marshal.ReleaseComObject(remoteSrv) > 0) {
|
|
}
|
|
}
|
|
} finally {
|
|
if (wiContext != null)
|
|
wiContext.Undo();
|
|
}
|
|
}
|
|
catch {
|
|
// Wrap finally clause with a try to avoid exception clauses being run
|
|
// while the thread is impersonated.
|
|
throw;
|
|
}
|
|
|
|
if (filePaths == null) {
|
|
throw ExceptionUtil.UnexpectedError("RemoteWebConfigurationHost::InitForConfiguration");
|
|
}
|
|
|
|
//
|
|
// Format of filePaths:
|
|
// appPath < appSiteName < appSiteID < configPath < locationConfigPath [< configPath < fileName]+
|
|
//
|
|
string[] parts = filePaths.Split(RemoteWebConfigurationHostServer.FilePathsSeparatorParams);
|
|
|
|
if (parts.Length < 7 || (parts.Length - 5) % 2 != 0) {
|
|
throw ExceptionUtil.UnexpectedError("RemoteWebConfigurationHost::InitForConfiguration");
|
|
}
|
|
|
|
// convert empty strings to nulls
|
|
for (int i = 0; i < parts.Length; i++) {
|
|
if (parts[i].Length == 0) {
|
|
parts[i] = null;
|
|
}
|
|
}
|
|
|
|
// get config paths
|
|
string appPath = parts[0];
|
|
string appSiteName = parts[1];
|
|
string appSiteID = parts[2];
|
|
configPath = parts[3];
|
|
locationConfigPath = parts[4];
|
|
_ConfigPath = configPath;
|
|
|
|
// Create a WebConfigurationFileMap to be used when we later initialize our delegating WebConfigurationHost
|
|
WebConfigurationFileMap configFileMap = new WebConfigurationFileMap();
|
|
VirtualPath appPathVirtualPath = VirtualPath.CreateAbsoluteAllowNull(appPath);
|
|
|
|
configFileMap.Site = appSiteID;
|
|
|
|
// populate the configpath->physical path mapping
|
|
for (int i = 5; i < parts.Length; i += 2) {
|
|
string configPathTemp = parts[i];
|
|
string physicalFilePath = parts[i+1];
|
|
|
|
_PathMap.Add(configPathTemp, physicalFilePath);
|
|
|
|
// Update the WebConfigurationFileMap
|
|
if (WebConfigurationHost.IsMachineConfigPath(configPathTemp)) {
|
|
configFileMap.MachineConfigFilename = physicalFilePath;
|
|
}
|
|
else {
|
|
string vPathString;
|
|
bool isRootApp;
|
|
|
|
if (WebConfigurationHost.IsRootWebConfigPath(configPathTemp)) {
|
|
vPathString = null;
|
|
isRootApp = false;
|
|
}
|
|
else {
|
|
VirtualPath vPath;
|
|
string dummy;
|
|
|
|
WebConfigurationHost.GetSiteIDAndVPathFromConfigPath(configPathTemp, out dummy, out vPath);
|
|
vPathString = VirtualPath.GetVirtualPathString(vPath);
|
|
isRootApp = (vPath == appPathVirtualPath);
|
|
}
|
|
|
|
configFileMap.VirtualDirectories.Add(vPathString,
|
|
new VirtualDirectoryMapping(Path.GetDirectoryName(physicalFilePath), isRootApp));
|
|
}
|
|
}
|
|
|
|
#else // !FEATURE_PAL: set dummy config path
|
|
string appPath = null;
|
|
_ConfigPath = configPath;
|
|
#endif // !FEATURE_PAL
|
|
|
|
// Delegate to a WebConfigurationHost for unhandled methods.
|
|
WebConfigurationHost webConfigurationHost = new WebConfigurationHost();
|
|
webConfigurationHost.Init(root, true, new UserMapPath(configFileMap, /*pathsAreLocal*/ false), null, appPath, appSiteName, appSiteID);
|
|
Host = webConfigurationHost;
|
|
}
|
|
|
|
// config path support
|
|
public override bool IsConfigRecordRequired(string configPath) {
|
|
// a record is required for every part of the config path
|
|
return configPath.Length <= _ConfigPath.Length;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
public override string GetStreamName(string configPath)
|
|
{
|
|
return (string) _PathMap[configPath];
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
public override object GetStreamVersion(string streamName) {
|
|
#if FEATURE_PAL // FEATURE_PAL: singelton version
|
|
return s_version;
|
|
#else
|
|
// for now, assume it is the same
|
|
// return s_version;
|
|
bool exists;
|
|
long size, createDate, lastWriteDate;
|
|
WindowsImpersonationContext wiContext = null;
|
|
|
|
try {
|
|
if (_Identity != null) {
|
|
wiContext = _Identity.Impersonate();
|
|
}
|
|
|
|
try {
|
|
//////////////////////////////////////////////////////////////////
|
|
// Step 3: Get the type and create the object on the remote server
|
|
IRemoteWebConfigurationHostServer remoteSrv = CreateRemoteObject(_Server, _Username, _Domain, _Password);
|
|
try {
|
|
//////////////////////////////////////////////////////////////////
|
|
// Step 4: Call the API
|
|
remoteSrv.GetFileDetails(streamName, out exists, out size, out createDate, out lastWriteDate);
|
|
}
|
|
finally {
|
|
while (Marshal.ReleaseComObject(remoteSrv) > 0) { } // release the COM object
|
|
}
|
|
}
|
|
finally {
|
|
if (wiContext != null) {
|
|
wiContext.Undo(); // revert impersonation
|
|
}
|
|
}
|
|
}
|
|
catch {
|
|
// Wrap finally clause with a try to avoid exception clauses being run
|
|
// while the thread is impersonated.
|
|
throw;
|
|
}
|
|
|
|
return new FileDetails(exists, size, DateTime.FromFileTimeUtc(createDate), DateTime.FromFileTimeUtc(lastWriteDate));
|
|
#endif // FEATURE_PAL
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
public override Stream OpenStreamForRead(string streamName) {
|
|
RemoteWebConfigurationHostStream rcs = new RemoteWebConfigurationHostStream(false, _Server, streamName, null, _Username, _Domain, _Password, _Identity);
|
|
if (rcs == null || rcs.Length < 1)
|
|
return null;
|
|
return rcs;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
public override Stream OpenStreamForWrite(string streamName, string templateStreamName, ref object writeContext) {
|
|
RemoteWebConfigurationHostStream rcs = new RemoteWebConfigurationHostStream(true, _Server, streamName, templateStreamName, _Username, _Domain, _Password, _Identity);
|
|
writeContext = rcs;
|
|
return rcs;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
public override void DeleteStream(string StreamName)
|
|
{
|
|
//
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
public override void WriteCompleted(string streamName, bool success, object writeContext)
|
|
{
|
|
if (success) {
|
|
RemoteWebConfigurationHostStream rcs = (RemoteWebConfigurationHostStream)writeContext;
|
|
rcs.FlushForWriteCompleted();
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
public override bool IsFile(string StreamName)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
public override bool PrefetchAll(string configPath, string StreamName)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
public override bool PrefetchSection(string sectionGroupName, string sectionName)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
public override void GetRestrictedPermissions(IInternalConfigRecord configRecord, out PermissionSet permissionSet, out bool isHostReady) {
|
|
WebConfigurationHost.StaticGetRestrictedPermissions(configRecord, out permissionSet, out isHostReady);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
public override bool IsRemote {
|
|
get { return true; }
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
// Encrypt/decrypt support
|
|
public override string DecryptSection(string encryptedXmlString, ProtectedConfigurationProvider protectionProvider, ProtectedConfigurationSection protectedConfigSection) {
|
|
return CallEncryptOrDecrypt(false, encryptedXmlString, protectionProvider, protectedConfigSection);
|
|
}
|
|
public override string EncryptSection(string clearTextXmlString, ProtectedConfigurationProvider protectionProvider, ProtectedConfigurationSection protectedConfigSection) {
|
|
return CallEncryptOrDecrypt(true, clearTextXmlString, protectionProvider, protectedConfigSection);
|
|
}
|
|
|
|
private string CallEncryptOrDecrypt(bool doEncrypt, string xmlString, ProtectedConfigurationProvider protectionProvider, ProtectedConfigurationSection protectedConfigSection)
|
|
{
|
|
#if !FEATURE_PAL // FEATURE_PAL has no COM objects => no encryption
|
|
// ROTORTODO: COM Objects are not implemented.
|
|
// CORIOLISTODO: COM Objects are not implemented.
|
|
ProviderSettings ps;
|
|
NameValueCollection nvc;
|
|
string [] paramKeys;
|
|
string [] paramValues;
|
|
string returnString = null;
|
|
string typeName;
|
|
WindowsImpersonationContext wiContext = null;
|
|
|
|
////////////////////////////////////////////////////////////
|
|
// Step 1: Create list of parameters for the protection provider
|
|
typeName = protectionProvider.GetType().AssemblyQualifiedName;
|
|
ps = protectedConfigSection.Providers[protectionProvider.Name];
|
|
if (ps == null)
|
|
throw ExceptionUtil.ParameterInvalid("protectionProvider");
|
|
|
|
nvc = ps.Parameters;
|
|
if (nvc == null)
|
|
nvc = new NameValueCollection();
|
|
|
|
paramKeys = nvc.AllKeys;
|
|
paramValues = new string[paramKeys.Length];
|
|
for(int iter = 0; iter<paramKeys.Length; iter++)
|
|
paramValues[iter] = nvc[paramKeys[iter]];
|
|
|
|
////////////////////////////////////////////////////////////
|
|
// Step 2: Set the impersonation if required
|
|
if (_Identity != null)
|
|
wiContext = _Identity.Impersonate();
|
|
|
|
try {
|
|
try {
|
|
//////////////////////////////////////////////////////////////////
|
|
// Step 3: Get the type and create the object on the remote server
|
|
IRemoteWebConfigurationHostServer remoteSrv = CreateRemoteObject(_Server, _Username, _Domain, _Password);
|
|
try {
|
|
//////////////////////////////////////////////////////////////////
|
|
// Step 4: Call the API
|
|
returnString = remoteSrv.DoEncryptOrDecrypt(doEncrypt, xmlString, protectionProvider.Name, typeName, paramKeys, paramValues);
|
|
} finally {
|
|
while (Marshal.ReleaseComObject(remoteSrv) > 0) { } // release the COM object
|
|
}
|
|
} finally {
|
|
if (wiContext != null)
|
|
wiContext.Undo(); // revert impersonation
|
|
}
|
|
}
|
|
catch {
|
|
}
|
|
|
|
return returnString;
|
|
#else // !FEATURE_PAL
|
|
throw new NotImplementedException("ROTORTODO");
|
|
#endif // !FEATURE_PAL
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////////////
|
|
private static string GetUserNameFromFullName(string fullUserName) {
|
|
if (string.IsNullOrEmpty(fullUserName))
|
|
return null;
|
|
if (fullUserName.Contains("@")) {
|
|
return fullUserName;
|
|
}
|
|
string[] splitted = fullUserName.Split(new char[] { '\\' });
|
|
if (splitted.Length == 1)
|
|
return fullUserName;
|
|
else
|
|
return splitted[1];
|
|
}
|
|
private static string GetDomainFromFullName(string fullUserName) {
|
|
if (string.IsNullOrEmpty(fullUserName))
|
|
return null;
|
|
if (fullUserName.Contains("@"))
|
|
return null;
|
|
string[] splitted = fullUserName.Split(new char[] { '\\' });
|
|
if (splitted.Length == 1)
|
|
return ".";
|
|
return splitted[0];
|
|
}
|
|
|
|
// impersonation support: create an identity from credentials
|
|
#if OLD_WAY
|
|
private static WindowsIdentity CreateWindowsIdentity(string userName, string password, IntPtr tokenHandle) {
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
// Step 0: Most common case: check if no credentials are supplied
|
|
if (string.IsNullOrEmpty(userName) && tokenHandle == IntPtr.Zero && string.IsNullOrEmpty(password))
|
|
return null;
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
// Step 1: Make sure that either username & password OR token is supplied
|
|
if ((string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password)) || (!string.IsNullOrEmpty(userName) && string.IsNullOrEmpty(password)))
|
|
throw ExceptionUtil.ParameterNullOrEmpty("password");
|
|
|
|
if (!string.IsNullOrEmpty(userName) && tokenHandle != IntPtr.Zero)
|
|
throw ExceptionUtil.ParameterInvalid("tokenHandle");
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
// Step 2: Create token if not supplied
|
|
if (!string.IsNullOrEmpty(userName))
|
|
tokenHandle = CreateUserToken(userName, password);
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
// Step 3: Create a windows identity from the token
|
|
WindowsIdentity wi = new WindowsIdentity(tokenHandle);
|
|
|
|
if (!string.IsNullOrEmpty(userName) && tokenHandle != IntPtr.Zero) // Close the handle if we created it.
|
|
UnsafeNativeMethods.CloseHandle(tokenHandle);
|
|
return wi;
|
|
}
|
|
|
|
private static IntPtr CreateUserToken(string fullUserName, string password) {
|
|
string userName, domain;
|
|
if (fullUserName.Contains("@")) {
|
|
userName = fullUserName;
|
|
domain = null;
|
|
} else {
|
|
string[] splitted = fullUserName.Split(new char[] { '\\' });
|
|
if (splitted.Length == 1) {
|
|
userName = fullUserName;
|
|
domain = ".";
|
|
} else {
|
|
userName = splitted[1];
|
|
domain = splitted[0];
|
|
}
|
|
}
|
|
//This parameter causes LogonUser to create a primary token.
|
|
const int LOGON32_PROVIDER_DEFAULT = 0;
|
|
const int LOGON32_LOGON_INTERACTIVE = 2;
|
|
const int LOGON32_LOGON_NETWORK = 3;
|
|
const int LOGON32_LOGON_BATCH = 4;
|
|
const int LOGON32_LOGON_SERVICE = 5;
|
|
const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8;
|
|
|
|
int[] Logon32Values = new int[] { LOGON32_LOGON_INTERACTIVE, LOGON32_LOGON_BATCH, LOGON32_LOGON_SERVICE, LOGON32_LOGON_NETWORK_CLEARTEXT, LOGON32_LOGON_NETWORK};
|
|
|
|
IntPtr tokenHandle = IntPtr.Zero;
|
|
int lastError = 0;
|
|
if (UnsafeNativeMethods.LogonUser(userName, domain, password, Logon32Values[0], LOGON32_PROVIDER_DEFAULT, ref tokenHandle) != 0)
|
|
return tokenHandle;
|
|
lastError = Marshal.GetHRForLastWin32Error();
|
|
for (int iter = 1; iter < Logon32Values.Length; iter++)
|
|
if (UnsafeNativeMethods.LogonUser(userName, domain, password, Logon32Values[iter], LOGON32_PROVIDER_DEFAULT, ref tokenHandle) != 0)
|
|
return tokenHandle;
|
|
Marshal.ThrowExceptionForHR(lastError);
|
|
return IntPtr.Zero;
|
|
}
|
|
#endif
|
|
internal static IRemoteWebConfigurationHostServer CreateRemoteObject(string server, string username, string domain, string password) {
|
|
|
|
#if !FEATURE_PAL // FEATURE_PAL has no COM objects
|
|
try {
|
|
if (string.IsNullOrEmpty(username))
|
|
return CreateRemoteObjectUsingGetTypeFromCLSID(server);
|
|
if (IntPtr.Size == 8)
|
|
return CreateRemoteObjectOn64BitPlatform(server, username, domain, password);
|
|
return CreateRemoteObjectOn32BitPlatform(server, username, domain, password);
|
|
} catch (COMException ex) {
|
|
if ((uint)ex.ErrorCode == 0x80040154)
|
|
throw new Exception(SR.GetString(SR.Make_sure_remote_server_is_enabled_for_config_access));
|
|
throw;
|
|
}
|
|
}
|
|
private static IRemoteWebConfigurationHostServer CreateRemoteObjectUsingGetTypeFromCLSID(string server) {
|
|
Type type = Type.GetTypeFromCLSID(typeof(RemoteWebConfigurationHostServer).GUID, server, true);
|
|
return (IRemoteWebConfigurationHostServer)Activator.CreateInstance(type);
|
|
}
|
|
|
|
private static IRemoteWebConfigurationHostServer CreateRemoteObjectOn32BitPlatform(string server, string username, string domain, string password)
|
|
{
|
|
MULTI_QI [] amqi = new MULTI_QI[1];
|
|
IntPtr guidbuf = IntPtr.Zero;
|
|
COAUTHINFO ca = null;
|
|
IntPtr captr = IntPtr.Zero;
|
|
COSERVERINFO cs = null;
|
|
Guid clsid = typeof(RemoteWebConfigurationHostServer).GUID;
|
|
int hr = 0;
|
|
COAUTHIDENTITY ci = null;
|
|
IntPtr ciptr = IntPtr.Zero;
|
|
|
|
try {
|
|
guidbuf = Marshal.AllocCoTaskMem(16);
|
|
Marshal.StructureToPtr(typeof(IRemoteWebConfigurationHostServer).GUID, guidbuf, false);
|
|
amqi[0] = new MULTI_QI(guidbuf);
|
|
|
|
ci = new COAUTHIDENTITY(username, domain, password);
|
|
ciptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(ci));
|
|
Marshal.StructureToPtr(ci, ciptr, false);
|
|
|
|
ca = new COAUTHINFO(RpcAuthent.WinNT, RpcAuthor.None, null, /*RpcLevel.Connect*/ RpcLevel.Default, RpcImpers.Impersonate, ciptr);
|
|
captr = Marshal.AllocCoTaskMem(Marshal.SizeOf(ca));
|
|
Marshal.StructureToPtr(ca, captr, false);
|
|
|
|
cs = new COSERVERINFO(server, captr);
|
|
hr = UnsafeNativeMethods.CoCreateInstanceEx(ref clsid, IntPtr.Zero, (int)ClsCtx.RemoteServer, cs, 1, amqi);
|
|
if ((uint)hr == 0x80040154)
|
|
throw new Exception(SR.GetString(SR.Make_sure_remote_server_is_enabled_for_config_access));
|
|
if (hr < 0)
|
|
Marshal.ThrowExceptionForHR(hr);
|
|
if (amqi[0].hr < 0)
|
|
Marshal.ThrowExceptionForHR(amqi[0].hr);
|
|
hr = UnsafeNativeMethods.CoSetProxyBlanket(amqi[0].pItf, RpcAuthent.WinNT, RpcAuthor.None, null, /*RpcLevel.Connect*/ RpcLevel.Default, RpcImpers.Impersonate, ciptr, 0);
|
|
if (hr < 0)
|
|
Marshal.ThrowExceptionForHR(hr);
|
|
return (IRemoteWebConfigurationHostServer)Marshal.GetObjectForIUnknown(amqi[0].pItf);
|
|
} finally {
|
|
if (amqi[0].pItf != IntPtr.Zero)
|
|
{
|
|
Marshal.Release(amqi[0].pItf);
|
|
amqi[0].pItf = IntPtr.Zero;
|
|
}
|
|
amqi[0].piid = IntPtr.Zero;
|
|
if (captr != IntPtr.Zero) {
|
|
Marshal.DestroyStructure(captr, typeof(COAUTHINFO));
|
|
Marshal.FreeCoTaskMem(captr);
|
|
}
|
|
if (ciptr != IntPtr.Zero) {
|
|
Marshal.DestroyStructure(ciptr, typeof(COAUTHIDENTITY));
|
|
Marshal.FreeCoTaskMem(ciptr);
|
|
}
|
|
if (guidbuf != IntPtr.Zero)
|
|
Marshal.FreeCoTaskMem(guidbuf);
|
|
}
|
|
#else // !FEATURE_PAL
|
|
throw new NotSupportedException();
|
|
#endif // !FEATURE_PAL
|
|
}
|
|
|
|
private static IRemoteWebConfigurationHostServer CreateRemoteObjectOn64BitPlatform(string server, string username, string domain, string password)
|
|
{
|
|
MULTI_QI_X64[] amqi = new MULTI_QI_X64[1];
|
|
IntPtr guidbuf = IntPtr.Zero;
|
|
COAUTHINFO_X64 ca = null;
|
|
IntPtr captr = IntPtr.Zero;
|
|
COSERVERINFO_X64 cs = null;
|
|
Guid clsid = typeof(RemoteWebConfigurationHostServer).GUID;
|
|
int hr = 0;
|
|
COAUTHIDENTITY_X64 ci = null;
|
|
IntPtr ciptr = IntPtr.Zero;
|
|
|
|
try {
|
|
guidbuf = Marshal.AllocCoTaskMem(16);
|
|
Marshal.StructureToPtr(typeof(IRemoteWebConfigurationHostServer).GUID, guidbuf, false);
|
|
amqi[0] = new MULTI_QI_X64(guidbuf);
|
|
|
|
ci = new COAUTHIDENTITY_X64(username, domain, password);
|
|
ciptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(ci));
|
|
Marshal.StructureToPtr(ci, ciptr, false);
|
|
|
|
ca = new COAUTHINFO_X64(RpcAuthent.WinNT, RpcAuthor.None, null, /*RpcLevel.Connect*/ RpcLevel.Default, RpcImpers.Impersonate, ciptr);
|
|
captr = Marshal.AllocCoTaskMem(Marshal.SizeOf(ca));
|
|
Marshal.StructureToPtr(ca, captr, false);
|
|
|
|
cs = new COSERVERINFO_X64(server, captr);
|
|
hr = UnsafeNativeMethods.CoCreateInstanceEx(ref clsid, IntPtr.Zero, (int)ClsCtx.RemoteServer, cs, 1, amqi);
|
|
if ((uint)hr == 0x80040154)
|
|
throw new Exception(SR.GetString(SR.Make_sure_remote_server_is_enabled_for_config_access));
|
|
if (hr < 0)
|
|
Marshal.ThrowExceptionForHR(hr);
|
|
if (amqi[0].hr < 0)
|
|
Marshal.ThrowExceptionForHR(amqi[0].hr);
|
|
hr = UnsafeNativeMethods.CoSetProxyBlanket(amqi[0].pItf, RpcAuthent.WinNT, RpcAuthor.None, null, /*RpcLevel.Connect*/ RpcLevel.Default, RpcImpers.Impersonate, ciptr, 0);
|
|
if (hr < 0)
|
|
Marshal.ThrowExceptionForHR(hr);
|
|
return (IRemoteWebConfigurationHostServer)Marshal.GetObjectForIUnknown(amqi[0].pItf);
|
|
} finally {
|
|
if (amqi[0].pItf != IntPtr.Zero) {
|
|
Marshal.Release(amqi[0].pItf);
|
|
amqi[0].pItf = IntPtr.Zero;
|
|
}
|
|
amqi[0].piid = IntPtr.Zero;
|
|
if (captr != IntPtr.Zero) {
|
|
Marshal.DestroyStructure(captr, typeof(COAUTHINFO_X64));
|
|
Marshal.FreeCoTaskMem(captr);
|
|
}
|
|
if (ciptr != IntPtr.Zero) {
|
|
Marshal.DestroyStructure(ciptr, typeof(COAUTHIDENTITY_X64));
|
|
Marshal.FreeCoTaskMem(ciptr);
|
|
}
|
|
if (guidbuf != IntPtr.Zero)
|
|
Marshal.FreeCoTaskMem(guidbuf);
|
|
}
|
|
}
|
|
}
|
|
}
|