<2017 March>
SunMonTueWedThuFriSat
2627281234
567891011
12131415161718
19202122232425
2627282930311
2345678

On this page...

Mid-2008 and x64 is Still a Dead End
Unknown Device Installed & Ready to Use
Sony Ericsson Must be Kidding Me
MS Sample for Starting Elevated Processes (UAC)
Telnet in Vista
Windows Vista Application Development Requirements for User Account Control Compatibility
What is Vista Trying to Tell Me?
UAC Elevation in Managed Code: Guidance for Implementing COM Elevation
UAC Elevation in Managed Code: A .NET COM Component Elevated
UAC Elevation in Managed Code: "Talking" to an Elevated Process via WCF
PowerShell 1.0 for Windows Vista
UAC Elevation in Managed Code: Starting Elevated COM Components
UAC Elevation in Managed Code: Starting Elevated Processes
Visual Studio on Vista: Not so Fast!
Crashing Vista With WPF Applications
Security for Applications in Windows Vista Forum
TweakUAC
Shift Expectations
eXPired
Passing the News: Online Security Sessions from TechEd IT Forum Available
CLI Essentials: Robocopy Part of Vista
Vista Firewall
Windows Vista Feature Matrix
Virtualization
Stiffware
Windows Vista Security Guide
Gotta Be Kidding Me
MWconn News
EasyBCD
MWConn Available in English
Merlin - Yes, Magic IS Required
Assorted .NET Framework 3.0 Downloads
When You Thought They Couldn't Make UAC Any More Annoying...
Windows Media Player Cannot Play The File
Previous Versions
Vista On My Machine
Vista Is a Descendant Of NT Alright...
UAC Prompts & Security
Search

Links

Member of...


ASP Insiders

MVP Visual Developer ASP/ASP.NET

Enter CodeZone

Blog Categories

Microsoft

Blogroll

Deutsche Resourcen

Management

Sign In
 

#  Wednesday, 30 July 2008

I am currently working on a Compact Framework project, and started development on a different machine - where I successfully used the Cellular Emulator of the Windows Mobile SDK. Today, on the other machine (the laptop), it didn't start but present me with the following error message:

After some searching (on the G-word search engine), I came across this post:

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3538593&SiteID=1

Sure enough I am using Vista x64, heck, we are living in 2008 with multicore CPUs and 4GB+ of RAM!

And here is the Catch 22: when moving development to a Virtual PC image, you don't get USB ports which you need for connecting to a real device...

Categories: .NET | Smartphone and PocketPC | Vista | x64
Wednesday, 30 July 2008 16:55:11 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]

 



#  Thursday, 19 July 2007

This is the most ridiculous message I have received so far on Vista.

Categories: Vista
Thursday, 19 July 2007 11:33:56 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]

 



#  Thursday, 28 June 2007

"The Sony Ericsson Update Service for Windows Vista™ will be available for download on www.sonyericsson.com/updateservice in September." You ain't serious, right? This is more than annoying simply because I don't have a single computer with XP any more - not that SE software ever worked on XP either.

Categories: this | Vista
Thursday, 28 June 2007 10:34:29 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]

 



#  Monday, 04 June 2007

Microsoft released a UAC demo. It is just basic process elevation (read: save the time by not downloading it), which I described in more detail (with more reuseability) in UAC Elevation in Managed Code: Starting Elevated Processes.

Categories: .NET | Vista | UAC
Monday, 04 June 2007 10:34:52 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]

 



#  Thursday, 10 May 2007

Just tried to do the usual "telnet myserver port#" to see if a service is actually listening, but Vista came up with a search window. The command line told me that there is no such tool as telnet. Wtf? Solution: Vista Tip: Get Telnet Back

Categories: Vista
Thursday, 10 May 2007 10:46:01 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]

 



#  Wednesday, 21 February 2007

This is v2 of the Vista UAC development requirements document. From the TOC:

  • Why User Account Control?
  • How UAC Works
  • Will UAC Affect Your Application?
  • Designing Applications for Windows Vista
  • Deploying and Patching Applications for Standard Users
  • Troubleshooting Common Issues
  • References
Categories: Security | UAC | Vista
Wednesday, 21 February 2007 09:48:17 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]

 



#  Friday, 16 February 2007

Categories: this | Vista
Friday, 16 February 2007 19:51:04 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]

 

In my last blog entry UAC Elevation in Managed Code: A .NET COM Component Elevated I showed how to get up and running with an all-managed code solution for UAC and COM elevation. Today I want close out my series on UAC with some information on how to properly organize the project plus present a library you can reuse to get up and running quickly - without many of the manual and tedious steps from the previous proof of concept example.

Speaking of the previous sample: it is still the basis for this best practice, so the following directory layout will look familiar to you:

Before diving into code, I want to start out with the SampleSetup directory, which contains the executables. As you can guess, the starting point is Step1Register. It contains register.bat, which you have to execute:

Note that on machines without the .NET Framework SDK, there is no gacutil.exe. In that case, you have to drag & drop ManagedElevator.dll to c:\windows\assembly.

And in case you have been wondering from this screenshot, yes, the application now also plays nicely on Windows XP:

Of course, there is no consent UI popping up, nor is there a shield icon like there is on Windows Vista:

The magic for this cross-platform functionality is hidden in the UACHelper project - which brings us to the source section of this blog post:

All the necessary COM elevation magic is now moved to this neat little library - including the adapted UAC bits of VistaBridgeLibrary (no longer necessary). The names already give away the purpose of each class and where they are used:

  • COMRegistration Used by the elevated component to automatically register the necessary registry keys.
  • ShieldButton Used by the client to display a button with a shield icon (on Vista). For XP, no shield is rendered.
  • COMElevation Starts the requested component with admin privileges.
  • ElevatedProcess If you want to start a simple process elevated. Not used in this guidance.

The first customer of this library is the elevated component, so we start discussing this guy next:

At first glance, this is similar to the previous POC implementation. The main difference now is that I have broken down the functionality by feature area into namespaces:

  • The "main" namespace
  • The .Components namespace
  • The .Guids namespace
  • The .InterOp namespace

Let's look at these one by one.

The "main" namespace

Here, we have one class only:

class RegisterFunctions
{
  [ComRegisterFunction]
  public static void CustomRegister(Type t)
  {
    COMRegistration.RegisterForElevation(Assembly.GetExecutingAssembly().Location,
       SampleComponent.ClassToElevate,
       Global.AppId,
       100);

    // add additional "for elevation" components here by duplicating the above
  }

  [ComUnregisterFunction]
  public static void CustomUnregister(Type t)
  {
    COMRegistration.UnRegisterFromElevation(Assembly.GetExecutingAssembly().Location,
        Global.AppId);
  }
}

It is called when the assembly is regasm'ed, and it is here where you call into COMRegistration.RegisterForElevation to add all the necessary registry keys for elevation:

public static void RegisterForElevation(string assemblyLocation,
    string classToElevate,
    string appId,
    int localizedStringId)
{
 if (!UACHelperFunctions.IsUACEnabledOS()) return;

 // [HKEY_CLASSES_ROOT\CLSID\{71E050A7-AF7F-42dd-BE00-BF955DDD13D4}]
 // "AppID"="{75AB90B0-8B9C-45c9-AC55-C53A9D718E1A}"
 // "LocalizedString"="@E:\\Daten\\Firma\\Konferenzen und Talks\\..."
 RegistryKey classKey = Registry.ClassesRoot.OpenSubKey(@"CLSID\{" + classToElevate + "}", true);
 classKey.SetValue("AppId", "{" + appId + "}", RegistryValueKind.String);
 classKey.SetValue("LocalizedString", "@" + assemblyLocation + ",-" + localizedStringId.ToString(), RegistryValueKind.String);

 // [HKEY_CLASSES_ROOT\CLSID\{71E050A7-AF7F-42dd-BE00-BF955DDD13D4}\Elevation]
 // "Enabled"=dword:00000001
 RegistryKey elevationKey = classKey.CreateSubKey("Elevation");
 elevationKey.SetValue("Enabled", 1, RegistryValueKind.DWord);
 elevationKey.Close();

 classKey.Close();

 // [HKEY_CLASSES_ROOT\AppID\{75AB90B0-8B9C-45c9-AC55-C53A9D718E1A}]
 // @="ManagedElevator"
 // "DllSurrogate"=""
 RegistryKey hkcrappId = Registry.ClassesRoot.OpenSubKey("AppID", true);
 RegistryKey appIdKey = hkcrappId.CreateSubKey("{" + appId + "}");
 appIdKey.SetValue(null, Path.GetFileNameWithoutExtension(assemblyLocation));
 appIdKey.SetValue("DllSurrogate", "", RegistryValueKind.String);
 appIdKey.Close();

 // [HKEY_CLASSES_ROOT\AppID\ManagedElevator.dll]
 // "AppID"="{75AB90B0-8B9C-45c9-AC55-C53A9D718E1A}"
 RegistryKey asmKey = hkcrappId.CreateSubKey(Path.GetFileName(assemblyLocation));
 asmKey.SetValue("AppID", "{" + appId + "}", RegistryValueKind.String);
 asmKey.Close();

 hkcrappId.Close();
}

Please take note that when the component is registered on eg Windows XP, no registry entries are written. After all, they are not needed.

The .Components namespace

Not much of a change - it contains the administrative component(s).

The .Guids namespace

The guids have been moved to a separate namespace. The reason? That way you can reference the assembly in the client project and use the guids directly - no magic strings anywhere any more.

The .InterOp namespace

This is the most important change with regards to the POC project - defining the correct ComImport'ed interface is now the responsibility of the implementer of the elevated component. That way, anyone needing access to this component only needs to reference the assembly and they are good to go. It is a bad idea to have this interface part of the client codebase!

Speaking of the client... here is the button code for DemoForm.cs:

private void cmdLaunch_Click(object sender, EventArgs e)
{
 if (UACHelperFunctions.IsUACEnabledOS())
 {
   IHelloWorld ihw = COMElevation.Start<IHelloWorld>(
        SampleComponent.ClassToElevate, SampleComponent.IHelloWorld);
   ihw.SayHello();
   COMElevation.Release(ihw);
 }
 else
 {
   ManagedElevator.Components.ClassToElevate c = new ManagedElevator.Components.ClassToElevate();
   c.SayHello();
 }
}

What looks interesting at first is COMElevation.Start as well as Release:

public class COMElevation
{
 public static TIFace Start<TIFace>(string IID_Class, string IID_Interface)
 {
  return Start<TIFace>(new Guid(IID_Class), new Guid(IID_Interface));
 }

 public static TIFace Start<TIFace>(Guid IID_Class, Guid IID_Interface)
 {
  object o = UACManager.LaunchElevatedCOMObject(IID_Class, IID_Interface);
  return (TIFace)o;
 }

 public static void Release(object o)
 {
  Marshal.ReleaseComObject(o);
 }
}

Actually all it does is encapsulate the necessary calls to UACManager and Marshal. Why is there no if / else using IsUACEnabledOS here? Well, at first I thought I'd build such a switch, but then I thought again: why would I use COM InterOp if I don't have to? I already referenced the assembly for the component (for the guids and interop interface), so why not use managed all the way and save time? That's what I did in the cmdLaunch_Click event handler.

That's it for the code folks, now a little discussion at the end on why in the world would you even think about doing this in a cross-platform way, or why it is a stupid idea all along:

This approach is only sensible if your application runs as administrative user on XP, otherwise all the calls in the administrative component will fail. However, the cross-platform part is only there to make it a complete best practice, there is no "you must use it cross-platform" - if you build applications for Windows Vista with the eventual need to elevate a task, then UACHelper is definitely for you! (and forget about that it would even work on XP)

Oh, and I almost forgot - here is the complete download, source code included of course (my code is BSD licensed):

AutomaticRegistration.zip (91.92 KB)

Categories: Security | UAC | Use the source Luke | Vista
Friday, 16 February 2007 08:02:29 (W. Europe Standard Time, UTC+01:00)  #    Comments [1]

 



#  Monday, 05 February 2007

I admit it: UAC Elevation in Managed Code: "Talking" to an Elevated Process via WCF is a kludge. The reason why I dabbled with this approach at all is that I failed to implement COM elevation with managed code (not elevating a COM component, but the COM component itself). However, at long last, I succeeded in that respect too: I now present you the all-managed code solution to UAC elevation!

Once again I built myself a small demo frontend application:

As you can guess, the first button does plain vanilla COM InterOp without any UAC elevation. Thus its code is rather simple:

private void simpleCallButton_Click(object sender, EventArgs e)
{
  Type t = Type.GetTypeFromCLSID(new Guid("71E050A7-AF7F-42dd-BE00-BF955DDD13D4"));
  object o = Activator.CreateInstance(t);
  t.InvokeMember("SayHello", BindingFlags.InvokeMethod, null, o, null);
}

Why this reflection magic? Well, the COM component I am calling here is implemented in .NET - and both VS as well as tlbimp balk at reimporting the exported type library.

The COM component in question has been regasm'ed & gacutil'ed (ManagedElevator project in the download). Although the name implies that I am after elevation, it is pretty much a standard COM component written using C#:

public class TheGuids
{
  public const string IHelloWorld = "B8CD5C09-9ACD-49b0-BF6F-C7B0F29795F9";
  public const string ClassToElevate = "71E050A7-AF7F-42dd-BE00-BF955DDD13D4";
  public const string AppId = "75AB90B0-8B9C-45c9-AC55-C53A9D718E1A";
}

[Guid(TheGuids.IHelloWorld)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IHelloWorld
{
  [ComVisible(true)]
  void SayHello();
}

[Guid(TheGuids.ClassToElevate)]
[ClassInterface(ClassInterfaceType.None)]
public class ClassToElevate : IHelloWorld
{
 public ClassToElevate()
 {
 }

 [ComVisible(true)]
 public void SayHello()
 {
  MessageBox.Show("Hello World");
 }
}

So how do you go from "standard" "plain-vanilla" COM component to COM elevation? The part that stumped me for so long was the ClassInterface attribute - if you forget this guy, you'll end up with an InvalidCastException thrown by UACManager.LaunchElevatedCOMObject.

But that's not quite all to get up and running with COM elevation: in addition, you need to modify the default registration for this component - specifically, you need to configure the DllSurrogate. This is where the AppId GUID comes into play: it isn't used in code (kept there for documentation purposes only), but in registryadditions.reg. It binds the various registry keys. And speaking of this .reg file, please take note of the LocalizedString value: it contains the text for the UAC prompt (also check out UACPrompts.rc, resource.h, compilerc.bat as well as the properties of the ManagedElevator project where the compiled .res file is referenced).

Note Before importing the .reg file into the registry make sure to fix the file path contained in LocalizedString! And if you create your own elevated COM component DO NOT reuse any of my three GUIDs - use guidgen.exe to create your personal ones.

From there, UAC elevation is smooth sailing. The Reflection version of COM elevation looks very similar to non-elevated calls:

private void managedElevation_Click(object sender, EventArgs e)
{
  // CLSID
  Guid classId = new Guid("71E050A7-AF7F-42dd-BE00-BF955DDD13D4");

  // Interface ID
  Guid interfaceId = new Guid("B8CD5C09-9ACD-49b0-BF6F-C7B0F29795F9");

  object o = UACManager.LaunchElevatedCOMObject(classId, interfaceId);

  Type t = o.GetType();
  t.InvokeMember("SayHello", BindingFlags.InvokeMethod, null, o, null);

  Marshal.ReleaseComObject(o);
}

Of course this is not really a good solution (late binding). So instead I manually imported the IHelloWorld interface:

[
ComImport(),
Guid("B8CD5C09-9ACD-49b0-BF6F-C7B0F29795F9"),
InterfaceType(ComInterfaceType.InterfaceIsDual)
]
  interface IHelloWorld
  {
   [
   MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime),
   PreserveSig
   ]
    void SayHello();
  }

Which makes calls into the elevated COM object much easier and cleaner:

private void managedElevationInterface_Click(object sender, EventArgs e)
{
  Guid classId = new Guid("71E050A7-AF7F-42dd-BE00-BF955DDD13D4");
  Guid interfaceId = new Guid("B8CD5C09-9ACD-49b0-BF6F-C7B0F29795F9");

  object o = UACManager.LaunchElevatedCOMObject(classId, interfaceId);

  IHelloWorld ihw = (IHelloWorld)o;
  ihw.SayHello();

  Marshal.ReleaseComObject(o);
}

So why should you use the COM elevation solution instead of starting the process? Well, there are a couple of reasons:

  • You can package more than one component into a DLL and still have custom UAC prompts thanks to LocalizedString
  • Your users don't get "an unidentified program..." warnings. Thank you COM registration
  • If you ever need to talk more extensively with the elevated process then this approach can be adapted more easily

The source code

ConsumeMyElevatedCOM.zip (97.56 KB)

You will find a file aptly named notes.txt in the ManagedElevator project that describes all the necessary steps to get up and running.

I hope you find this sample useful and not have to spend as much time as I did. Cheers!

Categories: .NET | Security | UAC | Vista
Monday, 05 February 2007 22:41:46 (W. Europe Standard Time, UTC+01:00)  #    Comments [7]

 



#  Sunday, 04 February 2007

In the blog post UAC Elevation in Managed Code: Starting Elevated Processes I talked about how to start an elevated process. However, just starting a process might not cut the mustard, for example if you need to hand over data to the elevated process. You could achieve this by passing, let's say, some data as command line arguments to ProcessInfo before starting the elevated process. But that seriously limits communication.

So how can you perform communication with an elevated process? My first idea was to use .NET Remoting. Once I thought through the multi-instance scenario, I quickly realized that this meant the server had to be running in the non-elevated application, because only it could properly choose a port. And because I am not a fan of Remoting anyways, I decided to give WCF (Windows Communication Foundation, a pillar of .NET 3.0) a try.

It looked like smooth sailing at first, but then I realized that with WCF too I needed to implement the service inside the non-elevated application. This time, however, the reason was "How do I know when the elevated application has initialized before I can actually start communicating with it?". Back to the drawing board.

The final solution now looks like this: the non-elevated application starts a service. The operations contract specifies a callback, which, once the elevated application has signalled its readiness, can be used by the non-elevated application to "talk" with the elevated application. I didn't intend to go duplex, but hey, if there's no other way I am willing to take plunge. Speaking of tricks of the trade: I am using imperative binding to a named pipe. Reason? Well, WS bindings won't work (see here and here), and the TCP channel would pop up a firewall warning. That's why.

Let's look at the applications - first the non-elevated one:

This time I forfeited eye candy (the shield button). Same (missing eye candy) goes for the elevated application as it is a console application only:

Solution-wise, this simple two-application scenario is split into four projects:

So where do we start? With the easy part inside ElevationContract:

[ServiceContract(Namespace = "http://Christoph.Wille.Samples",
CallbackContract = typeof(IElevatedProcess))]
public interface IWaitForElevatedProcess
{
  [OperationContract(IsOneWay = false)]
  void ElevatedProcessStarted();
}

[ServiceContract(Namespace = "http://Christoph.Wille.Samples")]
public interface IElevatedProcess
{
  [OperationContract(IsOneWay = false)]
  void SayHello(string message);
}

The interface IWaitForElevatedProcess is implemented in StandardUserApp. It is the service endpoint that is initialized before the elevated process is started - and once the elevated application is up and running, it calls into ElevatedProcessStarted. And we are in business for using the IElevatedProcess callback that is implemented in the ElevatedProcess console application.

So how is the service endpoint intialized - let's take a look inside:

private const string theProcess = @"..\..\..\ElevatedProcess\bin\Debug\ElevatedProcess.exe";

private void tryitButton_Click(object sender, EventArgs e)
{
  string channelIdentifier = MiscHelpers.CreateRandomString(64);
  MyUACServiceHost.StartService(channelIdentifier);

  // starting it modal doesn't work (obviously - unless we have more threads, of course)
  ElevatedProcess.Start(theProcess, channelIdentifier);
}

Interesting tidbit #1 is CreateRandomString: it creates a random string to use for the address. Why? Well, if multiple instances of our application are running and trying to elevate a process, we are in trouble. Which brings me to StartService:

internal static void StartService(string pipeEndPoint)
{
  NetNamedPipeBinding binding = new NetNamedPipeBinding();
  binding.Name = "uacbinding";
  binding.Security.Mode = NetNamedPipeSecurityMode.Transport;

  Uri baseAddress = new Uri("net.pipe://localhost/uac/" + pipeEndPoint);

  myServiceHost = new ServiceHost(typeof(SampleService), baseAddress);
  myServiceHost.AddServiceEndpoint(typeof(IWaitForElevatedProcess), binding, baseAddress);
  myServiceHost.Open();
}

As I said before, I am doing it imperatively (no configuration in app.config necessary). That's all there is to getting the service up and running.

Now let's switch to the console application's Main method:

static void Main(string[] args)
{
  if (args.Length != 1)
  {
    Console.WriteLine("One argument expected - the channel identifier");
    return;
  }

  NetNamedPipeBinding binding = new NetNamedPipeBinding();
  binding.Name = "uacbinding";
  binding.Security.Mode = NetNamedPipeSecurityMode.Transport;

  String url = "net.pipe://localhost/uac/" + args[0];
  EndpointAddress address = new EndpointAddress(url);

  WaitForElevatedProcess client = new WaitForElevatedProcess(
      new InstanceContext(new SampleCallback()),
      binding,
      address);

  client.ElevatedProcessStarted();

  Console.WriteLine("The elevated process is now ready");
  Console.ReadLine();

  client.Close();
}

Similar to normal client WCF code, however, with the duplex twist hidden inside WaitForElevatedProcess:

public class WaitForElevatedProcess : DuplexClientBase<IWaitForElevatedProcess>, IWaitForElevatedProcess
{
  public WaitForElevatedProcess(System.ServiceModel.InstanceContext callbackInstance,
 
    System.ServiceModel.Channels.Binding binding,
    System.ServiceModel.EndpointAddress remoteAddress)
       : base(callbackInstance, binding, remoteAddress)
  {
  }

  public void ElevatedProcessStarted()
  {
    base.Channel.ElevatedProcessStarted();
  }
}

Once the channel is connected, this elevated process calls back into the service piece which lives in the non-elevated application, namely SampleService:

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant,
      InstanceContextMode = InstanceContextMode.PerSession)]
public class SampleService : IWaitForElevatedProcess
{
  public void ElevatedProcessStarted()
  {
    OperationContext.Current.GetCallbackChannel<IElevatedProcess>().SayHello("Chris");
  }
}

This method is the workhorse where I can talk to the elevated process - if only my callback interface had more as well as more serious methods ;-)

Speaking of talking, I owe you the code for the callee in the console application:

[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class SampleCallback : IElevatedProcess
{
  public void SayHello(string message)
  {
    Console.WriteLine("Hello world " + message);
  }
}

That's it - to recap: first, we initialize the WCF service. Then elevate a process. This process, once initialized, calls into our service and leaves a callback. And then we are in business talking to the elevated process (setting data, being notified when the elevated application quits and why, ...).

Sample warnings before you download: MyUACServiceHost definitely should be instance instead of static. And, more restricting - starting the elevated process modal won't allow communication unless you start the service on a separate thread. For simplicity reasons I didn't do this for the POC.

ElevateProcessTalkWCF.zip (27 KB)

Before concluding I wanted to add a few words: my ideal implementation for UAC would be COM elevation. That way, one can put more than one component into a single DLL, and still get a meaningful UAC prompt thanks to the LocalizedString registry key - which is per component, and not per executable (which is the case for this solution if you add multiple actions). If you need differing prompts for each administrative action, there is only one course of action you can take with processes: create multiple executables. Not very pretty, but I failed with writing an elevatable (not a word, I am sure) managed (C#) COM component.

Categories: .NET | 3.0 | Security | UAC | Vista | WCF
Sunday, 04 February 2007 22:23:45 (W. Europe Standard Time, UTC+01:00)  #    Comments [3]

 

Categories: Cool Download | Vista
Sunday, 04 February 2007 11:43:49 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]

 



#  Tuesday, 30 January 2007

The previous installment UAC Elevation in Managed Code: Starting Elevated Processes dealt with starting executables with the "real" administrative token. In this blog post, we deal with starting a COM component with elevated privileges. For in-depth background information, please consult Kenny Kerr's absolutely excellent post on Windows Vista for Developers – Part 4 – User Account Control.

To start with, we need a COM component. Instead of writing an ATL C++ COM component from scratch, I took the MyElevateCom sample from CoCreateInstanceAsAdmin or CreateElevatedComObject sample from the Vista Compatibility Team Blog. Note that for building it, check out my post Visual Studio on Vista: Not so Fast!

Assuming that you built and successfully registered the COM component (it is built to the instuctions from Kenny's post), you can go about and write the managed caller. First, we need a reference to the component:

Then comes the tricky part - actually instantiating the COM component. When you take a look at the C++ example, you see that quite some "moniker magic" is involved that cannot be replicated by simply newing up the component. So how to mimic this behavior in managed code? The Microsoft® Windows® Software Development Kit for Windows Vista™ and .NET Framework 3.0 Runtime Components comes to the rescue: inside, you find C:\Program Files\Microsoft SDKs\Windows\v6.0\Samples\CrossTechnologySamples.zip, which contains the VistaBridge sample.

From that, I took the VistaBridgeLibary, and modified the static UACManager.LaunchElevatedCOMObject method a bit:

[return: MarshalAs(UnmanagedType.Interface)]
public static object LaunchElevatedCOMObject(Guid Clsid, Guid InterfaceID)
{
  string CLSID = Clsid.ToString("B");
  string monikerName = "Elevation:Administrator!new:" + CLSID;

  NativeMethods.BIND_OPTS3 bo = new NativeMethods.BIND_OPTS3();
  bo.cbStruct = (uint)Marshal.SizeOf(bo);
  bo.hwnd = IntPtr.Zero;
  bo.dwClassContext = (int)NativeMethods.CLSCTX.CLSCTX_LOCAL_SERVER;

  object retVal = UnsafeNativeMethods.CoGetObject(monikerName, ref bo, InterfaceID);

  return (retVal);
}

Modifications: the method is now public instead of internal, and CLSCTX changed to local server (otherwise it wouldn't work).

Next, we need a UI:

This button is the CommandLinkWinForms control from VistaBridgeLibary, with the ShieldIcon property set to true.

Let's hook up the event code:

private void tryItButton_Click(object sender, EventArgs e)
{
 Guid IID_ITheElevated =
  new Guid(0x5EFC3EFB, 0xC7D3, 0x4D00, 0xB7, 0x2E, 0x2F, 0x86, 0x4A, 0x1E, 0xAD, 0x06);

 Guid CLSID_TheElevated =
  new Guid(0x253E7696, 0xA524, 0x4E49, 0x9E, 0x50, 0xBF, 0xCC, 0x29, 0x91, 0x31, 0x23);

 object o = UACManager.LaunchElevatedCOMObject(CLSID_TheElevated, IID_ITheElevated);

 ITheElevated iface = (ITheElevated)o;

 // Call the method on the interface just like in the C++ example
 iface.ShowMe();

 // Release the object
 Marshal.ReleaseComObject(o);
}

The interface ID as well as class ID guids come directly from the C++ project (it is always a good idea to "speak" more than one language), but you could obtain those from the type library or registry as well if you don't have the source code of the component handy.

Object creation is handled via LaunchElevatedCOMObject, and the resultant object is cast to the interface from the imported type library. Noteable (and important) is the last line: because the object wasn't created by the runtime, we have to take care of its destruction (the created interface doesn't have a Release() method, so we use Marshal.ReleaseComObject).

That's it - your managed code is now instantiating an elevated COM object that has full reign over the system.

ElevateCOMComponentSample.zip (117.07 KB)

Categories: .NET | Security | UAC | Use the source Luke | Vista
Tuesday, 30 January 2007 10:14:50 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]

 

When you are working with Windows Vista, you know that even the administrative users are stripped ("filtered") of their privileges for normal operations, and that when you have to perform tasks requiring administrative privileges, you are presented with an UAC elevation prompt. The idea of this blog post series is to provide you with working samples on how to work with elevation from inside managed applications (you might also want to read Windows Vista Application Development Requirements for User Account Control Compatibility).

I want to side-step the really easy part - providing a manifest to start the entire application elevated (a good idea if the application makes no sense at all unless it has administrative rights, like regedit.exe). You can find information on those topics in Adding a UAC Manifest to Managed Code and Vista: User Account Control.

Now back to the topic of this post: App A needs to start App B with administrative rights (because App B e.g. needs to write to HKLM or Program Files). Therefore, we somehow must run App B as an administrative user (or with the non-filtered token of the current user). So how do we go about it?

First, some eye candy. You definitely already saw those nice shield icons before:

Those shield icons are stock on Windows Vista and indicate to the user that the action that hides behind the button requires elevation. I didn't create a button control myself - instead, I reused one that is readily available on the Web: Add a UAC Shield to your Winforms buttons in C#.

All I had to do myself was to start the Process ("App B"):

private void startProcess_Click(object sender, EventArgs e)
{
  ProcessStartInfo psi = new ProcessStartInfo();
  psi.FileName = theProcess;
  psi.Verb = "runas";
  Process.Start(psi);
}

The ticket (so to speak) for the elevation prompt is setting the Verb to "runas" in the ProcessStartInfo instance - this will pop up the elevation prompt if necessary when Process.Start is called.

This simplistic approach has a problem though - once App B is started, users can switch back to App A, because it App B isn't "modal" for App A. To solve this problem, I incorporated the approach from Daniel Moth outlined in his post Launch elevated and modal too:

private void launchModal_Click(object sender, EventArgs e)
{
  ProcessStartInfo psi = new ProcessStartInfo();
  psi.FileName = theProcess;
  psi.Verb = "runas";

  psi.ErrorDialog = true;
  psi.ErrorDialogParentHandle = this.Handle;

  try
  {
    Process p = Process.Start(psi);
    p.WaitForExit();
  }
  catch (Exception ex)
  {
    MessageBox.Show(ex.ToString());
  }
}

And that's it - App B is now modal. Once App B quits, control is relinquished to App A (which still doesn't run with administrative rights).

ElevateProcessSample.zip (21.1 KB)

Categories: Security | UAC | Use the source Luke | Vista
Tuesday, 30 January 2007 08:14:31 (W. Europe Standard Time, UTC+01:00)  #    Comments [1]

 



#  Monday, 29 January 2007

If you want to do this (Register Output, C++)

and don't want to get this error message

then start Visual Studio with Run as Administrator. I have SP1 and no Vista supplements installed, so maybe there will be (or already is) an elevation prompt for registering output.

Categories: Vista | Visual Studio
Monday, 29 January 2007 17:46:24 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]

 

From the "What could possibly go wrong?" department: starting a WPF application (verified offenders are MsbuildG and VistaBridge from the Windows Vista SDK) crashes Vista. Or the graphics driver to be more precise. The result is nonetheless a perfectly reproducible BSOD on my IBM X31 laptop. The funny part? This ATI Mobility driver (6.14.10.6546) came from the Windows Vista Update Service and is MS HW Compat signed!

Categories: .NET | Tri 0 | Vista
Monday, 29 January 2007 10:20:11 (W. Europe Standard Time, UTC+01:00)  #    Comments [2]

 



#  Thursday, 25 January 2007

Got a developer question on how Windows Vista security affects your application? Then the MSDN Forum Security for Applications in Windows Vista is the right place to go.

Categories: Community | Security | Vista
Thursday, 25 January 2007 10:38:07 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]

 

I don't recommend turning off UAC (User Account Control) on Windows Vista, but there might be valid reasons to shut it off once in a while for testing purposes (like in a VM). That is where TweakUAC comes in handy:

Categories: Security | UAC | Vista
Thursday, 25 January 2007 10:32:21 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]

 



#  Wednesday, 24 January 2007

The Shift key can be very useful on Windows Vista. For example, type in the name of the application in the Search box and press Ctrl+Shift+Enter:

This will start the application as Administrator. Next is Windows Explorer, where Shift + right-clicking on a file will yield a different context menu:

The new feature is "Copy as Path" - allowing you to copy the full file path to the clipboard. I need that quite often, so this is a welcome addition indeed.

Speaking of Shift +  right-clicking: when you do that without a file selected on the right-hand pane in Explorer, you get another option, namely "Open Command Windows Here":

That is most useful!

Categories: Vista
Wednesday, 24 January 2007 10:23:10 (W. Europe Standard Time, UTC+01:00)  #    Comments [3]

 



#  Tuesday, 02 January 2007

Now I can claim my office to be XP-free too (via eXPired Poster Available!) - the last victim of migration was my IBM X31.

Categories: Vista
Tuesday, 02 January 2007 14:07:12 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]

 



#  Friday, 22 December 2006

Michael Howard has all the links in this blog entry Online Security Sessions from TechEd IT Forum Available. Topics include: malware cleaning, UAC internals, social engineering, Vista kernel changes, Vista firewall and IPSec enhancements. Which reminds me that the post-conference DVDs should tip up in my mailbox rsn.

Categories: .NET | Security | Training and Conferences | Vista
Friday, 22 December 2006 16:46:01 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]

 



#  Tuesday, 12 December 2006

The most useful utility for deployment (or name your task, like directory comparison) is most decidedly Robocopy, which previously shipped only as part of the OS resource kits. Now with Windows Vista, however, Robocopy comes in the box.

To get up and running quickly, I recommend that you get Robocopy GUI:

It makes getting started with Robocopy a tad easier.

Categories: Administration | Vista
Tuesday, 12 December 2006 21:01:27 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]

 

This is the firewall settings dialog - much the same as we know it from Windows XP already:

However, once you fire up the management console (mmc.exe), you can add snapins for advanced firewall configuration (ok, IPSec is one of my personal favorites and not necessary to configure the firewall per se...):

Once you have done this, you can now configure the firewall like, well, an administrator would expect - rule based:

Categories: Administration | Security | Vista
Tuesday, 12 December 2006 20:46:50 (W. Europe Standard Time, UTC+01:00)  #    Comments [1]

 



#  Wednesday, 29 November 2006

Because I simply cannot remember which feature is in which edition of Windows Vista, I searched the Web to come up with a couple of useful feature comparison matrixes to back up my memory:

Update And of course the Windows Vista Product Guide.

Categories: Vista
Wednesday, 29 November 2006 16:01:30 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]

 



#  Monday, 20 November 2006

I already talked about the virtualization features of Windows Vista in a previous blog post entitled UAC Redirection 4 Fun & Profit. Today, I want to tackle the file redirection that happens when UAC virtualizes your application and you try to write to a location it monitors - like the Program Files directory:

This command prompt was started with Run as Administrator (the window title hints at that). I was UAC-prompted, and then could go about my business. Not so if I would be running it unelevated:

It tells me that I don't have access. Right, not a big surprise, but why didn't virtualization kick in for cmd.exe? Because it is off by default for the command line. How can I turn it on? Well, easy. Go to Windows Task Manager

Add the Virtualization column

After a bit drag & drop magic I made it the second column and I can see which application is virtualized or not. And sure enough, cmd.exe isn't. Right-clicking allows you to change that:

You will be warned that this will possibly affect the running application, but go ahead. And then try again to write to the Program Files location:

This time I can write to Program Files - wait a second, really? No, it of course went to the virtual store for this user account:

As you can see, it lives next to files from a heck a lot of applications that wanted to write to somewhere (like system32) where they didn't have access to - but virtualization (on by default for applications except those opting out explicitly) took care of the disk operations and redirected them to the virtual store. Note that a well-written application (ie one that doesn't require administrative rights) wouldn't show up here...

Categories: Security | Vista
Monday, 20 November 2006 08:03:43 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]

 



#  Thursday, 16 November 2006

In today's pre-lunch session at IT Forum the speaker used a term I had never heard before: stiffware. And I have to agree - stiffware does pose a serious problem when you cannot 'call' (other means of 'communication' might be unreliable to say the least <g />) the guy who wrote that piece of software so you can properly configure or even install it.

Speaking of the session itself, Microsoft SoftGrid is a really cool technology. The client - which contains more than the SoftGrid client - called the Desktop Optimization Pack, is equally interesting.

Categories: Administration | this | Vista
Thursday, 16 November 2006 12:07:18 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]

 



#  Thursday, 09 November 2006

The Windows Vista Security Guide provides recommendations and tools to further harden Windows Vista. Well, go get it.

Categories: Security | Vista
Thursday, 09 November 2006 08:28:41 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]

 



#  Monday, 18 September 2006

That's not very funny when all you try to do is watch a Live Meeting on another Vista feature on your Vista box (last time, I was saved this problem by LM on Vista not being able to connect to the audio stream). And I thought the last time I saw a system swap itself to death was on Windows 3.0...

In other Vista news - try this: right-click on a .zip archive of your choice, select the Open With... option from the context menu. In the dialog that pops up expand Other and choose Internet Explorer. Fun ensues. 

Categories: Vista
Monday, 18 September 2006 19:29:44 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]

 

MWconn got a new homepage which is also available in English (here). What is MWconn anyways? Take a look at my short MWconn setup guide / introduction plus if you use a Merlin UMTS card on Windows Vista, my installation instructions for the U630.

Categories: Cool Download | Vista
Monday, 18 September 2006 11:00:26 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]

 



#  Tuesday, 22 August 2006

EasyBCD is a must-have tool for Windows Vista to manage the new bootloader:

Categories: Cool Download | Vista
Tuesday, 22 August 2006 20:22:46 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]

 



#  Tuesday, 18 July 2006

Aside from just reporting the fact, I decided to write a short guided tour to get you started - and tested it with the most recent version of Windows Vista 5472.

  1. Download from http://mwconn.tribal-sunrise.com/ - the site is still German-only, but simply click the link "Version 1.0".
  2. Copy to folder UMTS
  3. Right-click and Run as Administrator
  4. You are asked for your preferred language - click No for English
  5. MWConn asks to create connection-type specific program copies - choose Yes:
  6. MWConn needs a connection to dial - it can create one itself, so choose Yes:
  7. You will be presented a message box that informs you about connection creation success / failure. You are almost done, and your UMTS folder now looks like this:
  8. Run UMTSGPRS (as Administrator). If asked again for the language, choose No to retain English. It will exit with a note that you should edit MWConn.ini.
  9. Edit MWConn.ini - you only need to edit a few entries:

    08 COM=
    09 PIN=
    10 NET=
    11 APN=
  10. Once done, start UMTSGPRS again, and you will be logged into your network:

For details on configuring the settings in #9, see the Comments section of my previous blog post Merlin - Yes, Magic IS Required.

Categories: Vista
Tuesday, 18 July 2006 14:50:29 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]

 



#  Wednesday, 28 June 2006

My post Novatel Wireless Merlin U630 on Windows Vista generated quite some feedback like "How did you install the drivers?". So I decided to take the latest and greatest build 5456 and see if I would get it up and running there too. Here is the list of things you need to do:

Obviously, the first thing to do is to insert the card. You will be prompted for driver installation, and it will try to do just that. However, it will only succeed in installing a "Generic Multifunction PC-Card". The two ports (later identified as multifunction device) will fail because it cannot detect the drivers.

Now we have to rectify this problem. Let's go to Device Manager (via Control Panel / Hardware), and right-click on the "Generic Multifunction PC-Card".  Choose "Update Driver":

This will magically turn it into the Novatel Wireless UMTS Modem Parent. And this in turn will allow auto-detection of the two ports:

Please note that the secondary port will show up under COM ports, not Modems:

And here things get hairy - as I pointed out, I am using MWConn. The current 0.9 version (as a reminder: at this time, German-only) assumes that the secondary port is above the primary (ie COM4 for primary, COM5 for secondary). However, on one of my laptops (Samsung X20) - the screenshot above - it is exactly the other way around and MWConn cannot cope with that at the moment. The IBM X31 orders the ports nicely right - and as such, UMTS works like a charm!

By the way, use MWConn with administrative rights because it does create network connections:

I will report back on the inverted port problem, the author of MWConn promised to send me an updated version that can deal with this issue. So stay tuned!

Update I got the new version - and I am modifying this blog entry under Windows Vista 5456 using the Merlin U630 in UMTS mode, on the Samsung X20. Now both laptops work! Proof:

Categories: Vista
Wednesday, 28 June 2006 13:08:33 (W. Europe Daylight Time, UTC+02:00)  #    Comments [4]

 



#  Monday, 26 June 2006
Categories: .NET | Tri 0 | Vista | Visual Studio | Workflow Foundation
Monday, 26 June 2006 14:10:48 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]

 

The Beta 2 UAC experience was somewhat annoying, but the current interim's experience was able to actually top the user aggravation c'mere (my definition of UAC):

UAC prompts appear as minimized dialog boxes! Guys, get your act together.

Categories: Vista
Monday, 26 June 2006 12:12:41 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]

 



#  Sunday, 04 June 2006

I had seen this error message on another Vista box previously, but at that time it definitely was related to a wrongly installed HDA driver for the onboard sound. This time sound was working, and some videos did actually play, so I was peeved when I got this error message while trying to watch recorded Web casts:

Yesterday, my solution was to boot XP - but leaving Vista just for watching Web casts, well, that is ridiculous. So I set out for a search on what other media players are capable of viewing WMV files. In the end (the third one I tried) I settled for the free DivX Player which nicely views all the recordings Windows Media Player 11 balked at.

Other casualties to report: the Sony Ericsson tools PC Suite as well as Update Service crash and burn on installation (the first one with MDAC, the other one with an already well-hated Java Exception, this time however on x86 and a different index).

Categories: Vista
Sunday, 04 June 2006 11:21:50 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]

 



#  Friday, 02 June 2006

Now, UAC is painful at times like installation (but getting better according to Reducing Elevation Prompts in RC1), however, there are loads of cool features hidden behind all the glitz of Aero that are really cool. Like Previous Versions:

It uses the Volume Shadow Copy technology already in use on Windows Server 2003, and it "hides" itself as part of System Protection / automatic restore points:

This is definitely one of those features that "sell" a product.

Categories: Vista
Friday, 02 June 2006 21:15:42 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]

 



#  Thursday, 01 June 2006

I decided to take the plunge and try running Vista on a daily basis. Thus far the following casualties must be reported:

  • Matrox P650 PCIe. No drivers, thus no dual head. Sorry Matrox. In more than ten years this is now the first time that my machine has no Matrox graphics card inside.
  • PDFCreator. For some reason the setup msi dies during installation, as well as during the subsequent uninstallation. Too bad.
  • Daemon Tools. On the first try, it didn't work. Maybe I'll give it another shot.

Given my previous experiences on my two laptops, it really turns out that the graphics drivers (or lack of) are the #1 issue for getting productive with Vista.

Let's see how long it takes until I hit a snag that makes me return to XP. Copying Application Data stuff to Vista was already quite "interesting" because Firefox and Thunderbird store their settings in Roaming and not Local.

Categories: this | Vista
Thursday, 01 June 2006 20:28:57 (W. Europe Daylight Time, UTC+02:00)  #    Comments [2]

 



#  Wednesday, 31 May 2006

But Adobe thinks I am too stupid to choose my baseline OS on my own, and presents me with a rather limited choice:

Also note that IE 7+ doesn't render the page correctly (menu). Time to fix your Web page, Adobe.

Categories: Vista
Wednesday, 31 May 2006 15:56:20 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]

 

When you run an application that needs administrative rights (in this specific case via a manifest file), you are prompted with an UAC dialog to allow this operation:

This is the dialog you get for the "default" user, the one you create during setup that is a member of the Administrators group. Contrast that to the dialog a standard user is presented with:

uacpromptforadmin.PNG

Now, I am fine with prompting the user to enter administrative credentials. However, I am not fine with providing the user with the name of the administrative user(s) on that machine. In my opinion, this is giving away security-related information without need.

Update Of course you can always use net localgroup Administrators to get a list of the members of the Administrators group (Markus pinged me on that one). This feature has been available for ages, true. However, I am not convinced that the UAC convenience of providing the administrative accounts on a silver platter is really necessary.

Categories: Security | this | Vista
Wednesday, 31 May 2006 14:46:05 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]

 



© Copyright 2017 Christoph Wille

newtelligence dasBlog 2.3.9074.18820
Subscribe to this weblog's RSS feed with SharpReader, Radio Userland, NewsGator or any other aggregator listening on port 5335 by clicking this button.   RSS 2.0|Atom 1.0  Send mail to the author(s)

 
Don't contact us via this (fleischfalle@alphasierrapapa.com) email address.