(Chris Hack)
12/26/2002 3:34:00 AM
I have written a simple Automation Server (*.exe) which exposes a
single Automation Object. I have written a C# Web Service to call the
Automation Server and recieve a simple status message. When I set IIS
to NTLM Challenge Response and use the WindowsIdentity.Ipersonate() on
the user returned by IIS, the Automation Server starts up as a windows
application and my call to the Automation Object works fine. However,
if I obtain a new WindowsIdentity from calling the windows API
LogonUser, the Automation Server does not show up. It shows up in the
Task Manager but the main window is not there. I use the EXACT same
user that is being passed by IIS from NTML Challenge Response. Here
is my code, hopefully someone can help me out.
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using System.Security;
using System.Security.Principal;
using System.Runtime;
using System.Runtime.InteropServices;
namespace MyWebService
{
public class XService : System.Web.Services.WebService
{
//-------------------------------------------------------------
// Impersenating specific user
//-------------------------------------------------------------
// Constants
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
// Windows API declarations
[DllImport("advapi32.dll", CharSet=CharSet.Auto)]
public static extern int LogonUser(
String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken
);
[DllImport("advapi32.dll",
CharSet=System.Runtime.InteropServices.CharSet.Auto,
SetLastError=true)]
public extern static int DuplicateToken(
IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken
);
//-------------------------------------------------------------
// Private Members
private WindowsImpersonationContext m_impersonationContext;
// Constructor
public XService() {
InitializeComponent();
}
#region Component Designer generated code
//Required by the Web Services Designer
private IContainer components = null;
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent() {
}
protected override void Dispose( bool disposing ) {
if(disposing && components != null) {
components.Dispose();
}
base.Dispose(disposing);
}
#endregion
private bool ImpersonateUser(bool Custom) {
if (Custom) return ImpersonateCustomUser("chack", "mygroup",
"mypass");
else return ImpersonateWebUser();
}
//-------------------------------------------------------------
// Impersenating a specific user
//-------------------------------------------------------------
private bool ImpersonateCustomUser(string userName, string domain,
string password) {
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if(
LogonUser(
userName,
domain,
password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
ref token
) != 0
) {
if(DuplicateToken(token, 2, ref tokenDuplicate) != 0) {
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
m_impersonationContext = tempWindowsIdentity.Impersonate();
return (m_impersonationContext != null);
}
else return false;
}
else return false;
}
private bool ImpersonateWebUser() {
WindowsIdentity tempWindowsIdentity;
tempWindowsIdentity =
(System.Security.Principal.WindowsIdentity)User.Identity;
m_impersonationContext = tempWindowsIdentity.Impersonate();
return (m_impersonationContext != null);
}
private void UndoImpersonation() {
m_impersonationContext.Undo();
}
[WebMethod]
public string StatusMessage() {
AutoObjTest.MyAutoObjClass xs;
string sm;
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Calling ImpersonateWebUser Works correctly
// Calling ImpersonateCustomUser doesn't cause
// an error but the automation server gets hung
// and must be shut down with task manager
// (plus the main window never shows up)
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (ImpersonateUser(false)) {
xs = new AutoObjTest.MyAutoObjClass();
sm = xs.StatusMessage;
UndoImpersonation();
xs = null;
return sm;
}
else throw (new Exception("Unable to impersonate user."));
}
}
}