Michiel van Otegem, IT Composer

Tuesday, January 31, 2006

Microsoft Expression CTPs

Even een weekje met vakantie en je mist alweer vanalles.

Microsoft heeft vorig jaar een aantal grafische paketten aangekondigd genaamd Expression. Van twee van de drie is nu een CTP beschikbaar:
- Grafisch design: Microsoft Expression Graphic Designer
- UI design voor Vista: Microsoft Expression Interactive Designer

We wachten met smart op de Web/ASP.NET versie.

Wednesday, January 11, 2006

WindowsImpersonationContext: kan dat niet makkelijker?

Soms kom je dingen tegen dat je denkt... hadden ze dat nou niet ff makkelijker kunnen maken in het framework? Vandaag had ik er weer zo een, namelijk met de WindowsImpersonationContext. An sich is de context heel handig, gewapend met een zogenaamde token handle van een gebruikersaccount kun je de betreffende gebruiker impersoniseren. Dat is bijvoorbeeld nodig als toegang tot een netwerk share wilt delegeren, terwijl de rest van je applicatie gewoon werkt op basis van de ingelogde gebruiker. Dit komt met name in web scenario's nog wel eens voor.

Het probleem is dat je om de token handle te krijgen op basis van een gebruikersnaam en wachtwoord je een Win32 call moet maken. Met andere woorden je moet unmanaged code aanroepen (help!). Het is niet echt heel moelijk, maar je moet weten welke referenties naar DLLs je moet maken, een IntPtr gebruiken, enzovoorts. Allemaal niet waar wij als ontwikkelaars op zitten te wachten. En dat terwijl het niet eens zo ingewikkeld is om de ontwikkelaar daarvan af te schermen door een simpele wrapper class. Voordeel daarvan zou ook meteen weer zijn dat er niet met /unsafe gecompileerd hoeft te worden, wat voor de meeste mensen toch wel eng is. Met zo'n wrapper class zou de gemiddelde ontwikkelaar het volgende maar hoeven te doen:

Console.WriteLine("Huidige gebruiker: " + WindowsIdentity.GetCurrent().Name);
WrapperImpersonationContext context = new WrapperImpersonationContext(domain, username, password);
context.Enter();

// Voer code uit in context van ander gebruikersaccount
Console.WriteLine("Huidige gebruiker: " + WindowsIdentity.GetCurrent().Name);
context.Leave();
Console.WriteLine("Huidige gebruiker: " + WindowsIdentity.GetCurrent().Name);


Nu vraag je je natuurlijk af hoe die wrapper class er dan uit zou moeten zien. Wel... als volgt:

public class WrapperImpersonationContext
{
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain,

String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

[DllImport("kernel32.dll", CharSet
=System.Runtime.InteropServices.CharSet.Auto)]
private unsafe static extern int FormatMessage(int dwFlags, ref IntPtr lpSource,
int dwMessageId, int dwLanguageId, ref String lpBuffer, int nSize,
IntPtr* Arguments);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);

private const int LOGON32_PROVIDER_DEFAULT = 0;
private const int LOGON32_LOGON_INTERACTIVE = 2;

private string m_Domain;
private string m_Password;
private string m_Username;
private IntPtr m_Token;

private WindowsImpersonationContext m_Context = null;

[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public void Enter()
{
if(this.IsInContext) return;
m_Token = new IntPtr(0);
try
{
m_Token = IntPtr.Zero;
bool logonSuccessfull = LogonUser(
m_Username,
m_Domain,
m_Password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
ref m_Token);
if (logonSuccessfull == false)
{
int error = Marshal.GetLastWin32Error();
throw new Win32Exception(error);
}
WindowsIdentity identity = new WindowsIdentity(m_Token);
m_Context = identity.Impersonate();
}
catch (Exception exception)
{
// Catch exceptions here
}
}

public void Leave()
{
if (this.IsInContext == false) return;
m_Context.Undo();

if (m_Token != IntPtr.Zero) CloseHandle(m_Token);
m_Context = null;
}
}

Tuesday, January 10, 2006

Voor de serieuze Star Wars gek

http://www.thinkgeek.com/geektoys/warfare/69de/
Vooralsnog ben ik nog niet gevallen voor de "Dark Side", maar cool zijn ze wel.