# HG changeset patch
# User StephaneLenclud
# Date 1360426689 -3600
# Node ID 60a1e2b6ed71b38fa97bc6e5e3528966a8d3612a
# Parent  4e41fb513d52dccc2ce06bf97bf2a4e4cca950cd
At last we can output stuff on our display.
The whole thing is still quite broken though.

diff -r 4e41fb513d52 -r 60a1e2b6ed71 GUI/MainForm.cs
--- a/GUI/MainForm.cs	Mon Feb 04 00:47:01 2013 +0100
+++ b/GUI/MainForm.cs	Sat Feb 09 17:18:09 2013 +0100
@@ -39,6 +39,7 @@
     private Color[] plotColorPalette;
     private SystemTray systemTray;
     private SoundGraphDisplay soundGraphDisplay;
+    private bool displayTick;
     private StartupManager startupManager = new StartupManager();
     private UpdateVisitor updateVisitor = new UpdateVisitor();
     private SensorGadget gadget;
@@ -285,18 +286,9 @@
 
       InitializePlotForm();
 
-      //
-      if (soundGraphDisplay.IsDllLoaded)
-      {
-          //Try init
-          //NativeWindow window;
-          soundGraphDisplay.Init(Handle);
 
-          //= Window.GetWindow(this);
-          //var wih = new WindowInteropHelper(window);
-          //IntPtr hWnd = wih.Handle;
-      }
-      
+      soundGraphDisplay.Init();
+
 
 
       startupMenuItem.Visible = startupManager.IsAvailable;
@@ -523,6 +515,20 @@
 
       if (wmiProvider != null)
         wmiProvider.Update();
+
+      if (soundGraphDisplay != null)
+      {
+          displayTick=!displayTick;
+          if (displayTick)
+          {
+              soundGraphDisplay.SetText("       ---", "");
+          }
+          else
+          {
+              soundGraphDisplay.SetText("       -+-", "");
+          }
+      }  
+
     }
 
     private void SaveConfiguration() {
@@ -738,41 +744,8 @@
       const int SC_MINIMIZE = 0xF020;
       const int SC_CLOSE = 0xF060;
 
-      if (m.Msg == SoundGraph.WM_DSP_PLUGIN_NOTIFY)
-      {
-        //Handling messages from our iMON Display
-          switch ((SoundGraph.DSPNotifyCode)m.WParam.ToInt32())
-          {
-              case SoundGraph.DSPNotifyCode.DSPNM_PLUGIN_SUCCEED:
-              case SoundGraph.DSPNotifyCode.DSPNM_IMON_RESTARTED:
-              case SoundGraph.DSPNotifyCode.DSPNM_HW_CONNECTED:
-                  {
-                      //Connection with our display is now open
-                      //Check if we have LCD or VFD
-                      //if ((lParam & DSPN_DSP_VFD) == DSPN_DSP_VFD) m_bVfdConnected = TRUE;
-                      //if ((lParam & DSPN_DSP_LCD) == DSPN_DSP_LCD) m_bLcdConnected = TRUE;
-                      soundGraphDisplay.DisplayPluginMessage(m.WParam.ToInt32(),false);
-                  }
-                  break;
-
-              case SoundGraph.DSPNotifyCode.DSPNM_PLUGIN_FAILED:
-              case SoundGraph.DSPNotifyCode.DSPNM_HW_DISCONNECTED:
-              case SoundGraph.DSPNotifyCode.DSPNM_IMON_CLOSED:
-                  {
-                      //Connection with our display is closed
-                      soundGraphDisplay.DisplayPluginMessage(m.LParam.ToInt32(), true);
-                  }
-                  break;
-
-              case SoundGraph.DSPNotifyCode.DSPNM_LCD_TEXT_SCROLL_DONE:
-                  {
-                      //Scroll finnished
-                  }
-                  break;
-          }
-
-      }
-      else if (minimizeToTray.Value &&
+ 
+      if (minimizeToTray.Value &&
         m.Msg == WM_SYSCOMMAND && m.WParam.ToInt64() == SC_MINIMIZE)
       {
           SysTrayHideShow();
diff -r 4e41fb513d52 -r 60a1e2b6ed71 GUI/SoundGraphDisplay.cs
--- a/GUI/SoundGraphDisplay.cs	Mon Feb 04 00:47:01 2013 +0100
+++ b/GUI/SoundGraphDisplay.cs	Sat Feb 09 17:18:09 2013 +0100
@@ -12,164 +12,18 @@
 using System.Collections.Generic;
 using System.Drawing;
 using System.Text;
+using System.Diagnostics;
 using System.Windows.Forms;
 using System.Windows;
 using OpenHardwareMonitor.Hardware;
 using OpenHardwareMonitor.Utilities;
 using System.Runtime.InteropServices;
+using UacHelpers;
 
 
 
-static class NativeMethods
-{
-    [System.Flags]
-    public enum LoadLibraryFlags : uint
-    {
-        DONT_RESOLVE_DLL_REFERENCES = 0x00000001,
-        LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010,
-        LOAD_LIBRARY_AS_DATAFILE = 0x00000002,
-        LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040,
-        LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020,
-        LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008
-    }
 
 
-    [DllImport("kernel32.dll", SetLastError = true)]
-    public static extern IntPtr LoadLibrary(string dllToLoad);
-
-    [DllImport("kernel32.dll")]
-    public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags);
-
-    [DllImport("kernel32.dll", SetLastError = true)]
-    public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
-
-    [DllImport("kernel32.dll", SetLastError = true)]
-    public static extern bool FreeLibrary(IntPtr hModule);
-}
-
-/**
-Definitions taken from public Sound Graph APIs.
- */
-static class SoundGraph
-{
-
-    const int WM_APP = 0x8000;
-    public const int WM_DSP_PLUGIN_NOTIFY = WM_APP + 1121;
-    /**DSPResult
-    @brief	These enumeration values represent the returned result for iMON Display API function calls.\n
-			    All iMON Display API function calls return one of this result values.\n
-			    For meaning of each result, refer the comment of each line below*/
-    public enum DSPResult : int
-    {
-	    DSP_SUCCEEDED = 0,				//// Function Call Succeeded Without Error
-	    DSP_E_FAIL,						//// Unspecified Failure
-	    DSP_E_OUTOFMEMORY,				//// Failed to Allocate Necessary Memory
-	    DSP_E_INVALIDARG,				//// One or More Arguments Are Not Valid
-	    DSP_E_NOT_INITED,				//// API is Not Initialized
-	    DSP_E_POINTER,					//// Pointer is Not Valid
-
-	    DSP_S_INITED = 0x1000,			//// API is Initialized
-	    DSP_S_NOT_INITED,				//// API is Not Initialized
-	    DSP_S_IN_PLUGIN_MODE,			//// API Can Control iMON Display (Display Plug-in Mode)
-	    DSP_S_NOT_IN_PLUGIN_MODE,		//// API Can't Control iMON Display
-    };
-
-
-    /**DSPNInitResult
-    @brief	These enumeration values represent the result status for requesting Display Plug-in Mode to iMON.\n
-			    iMON Display API notifies one of this result values to the caller application after requesting Display Plug-in Mode to iMON.\n
-			    For more information, refer the comment of each line below*/
-    public enum DSPNInitResult : int
-    {
-	    DSPN_SUCCEEDED = 0,				//// Display Plug-in Mode is Initialized Successfully
-	    DSPN_ERR_IN_USED = 0x0100,		//// Display Plug-in is Already Used by Other Application
-	    DSPN_ERR_HW_DISCONNECTED,		//// iMON HW is Not Connected
-	    DSPN_ERR_NOT_SUPPORTED_HW,		//// The Connected iMON HW doesn't Support Display Plug-in
-	    DSPN_ERR_PLUGIN_DISABLED,		//// Display Plug-in Mode Option is Disabled
-	    DSPN_ERR_IMON_NO_REPLY,			//// The Latest iMON is Not Installed or iMON Not Running
-	    DSPN_ERR_UNKNOWN = 0x0200,		//// Unknown Failure
-    };
-
-
-    /**DSPType
-    @brief	These enumeration values represent display type.\n
-			    Currently iMON Display API supports VFD and LCD products.*/
-    public enum DSPType : int
-    {
-	    DSPN_DSP_NONE	= 0,
-	    DSPN_DSP_VFD	= 0x01,			//// VFD products
-	    DSPN_DSP_LCD	= 0x02,			//// LCD products
-    };
-
-
-    /**DSPNotifyCode
-    @brief	These enumeration values represent the notification codes.\n
-			    iMON Display API will send or post message to the caller application.\n
-			    The caller application should assign the message and the winodw handle to receivce message with IMON_Display_Init fucntion.\n
-			    These enumeration values are used with WPARAM parameter of the message.\n 
-			    For more information, see the explanation of each notification code below*/
-    public enum DSPNotifyCode : int
-    {
-	    /**DSPNM_PLUGIN_SUCCEED
-	    @brief	When API succeeds to get the control for the display, API will post caller-specified message with DSPNM_PLUGIN_SUCCEED as WPARAM parameter.\n
-				    LPARAM represents DSPType. This value can be 0x01 (VFD), 0x02 (LCD) or 0x03 (VFD+LCD).*/
-	    DSPNM_PLUGIN_SUCCEED = 0,
-
-	    /**DSPNM_PLUGIN_FAILED
-	    @brief	When API fails to get the control for the display, API will post caller-specified message with DSPNM_PLUGIN_FAILED as WPARAM parameter.\n
-				    LPARAM represents error code with DSPNResult.*/
-	    DSPNM_PLUGIN_FAILED,
-
-	    /**DSPNM_IMON_RESTARTED
-	    @brief	When iMON starts, API will post caller-specified message with DSPNM_IMON_RESTARTED as WPARAM parameter.\n
-				    LPARAM represents DSPType. This value can be 0 (No Display), 0x01 (VFD), 0x02 (LCD) or 0x03 (VFD+LCD).*/
-	    DSPNM_IMON_RESTARTED,
-
-	    /**DSPNM_IMON_CLOSED
-	    @brief	When iMON closed, API will post caller-specified message with DSPNM_IMON_CLOSED as WPARAM parameter.\n
-				    LPARAM is not used.*/
-	    DSPNM_IMON_CLOSED,
-
-	    /**DSPNM_HW_CONNECTED
-	    @brief	When iMON HW newly connected, API will post caller-specified message with DSPNM_HW_CONNECTED as WPARAM parameter.\n
-				    LPARAM represents DSPType. This value can be 0 (No Display), 0x01 (VFD), 0x02 (LCD) or 0x03 (VFD+LCD).*/
-	    DSPNM_HW_CONNECTED,
-
-	    /**DSPNM_HW_DISCONNECTED
-	    @brief	When iMON HW disconnected, API will post caller-specified message with DSPNM_HW_DISCONNECTED as WPARAM parameter.\n
-				    LPARAM is DSPNResult value, DSPN_ERR_HW_DISCONNECTED.*/
-	    DSPNM_HW_DISCONNECTED,
-
-
-	    /**DSPNM_LCD_TEXT_SCROLL_DONE
-	    @brief	When iMON LCD finishes scrolling Text, API will post caller-specified message with DSPNM_LCD_TEXT_SCROLL_DONE as WPARAM parameter.\n
-				    The caller application may need to know when text scroll is finished, for sending next text.\n
-				    LPARAM is not used.*/
-	    DSPNM_LCD_TEXT_SCROLL_DONE = 0x1000,
-    };
-
-    /// Functions
-    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-    public delegate DSPResult IMON_Display_Uninit();
-
-    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-    public delegate DSPResult IMON_Display_Init(IntPtr hwndNoti, uint uMsgNotification);
-
-    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-    public delegate DSPResult IMON_Display_IsInited();
-
-    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-    public delegate DSPResult IMON_Display_IsPluginModeEnabled();
-
-    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-    public delegate DSPResult IMON_Display_SetVfdText(
-        [MarshalAs(UnmanagedType.LPWStr)] string lpsz1stLine,
-        [MarshalAs(UnmanagedType.LPWStr)] string lpsz2ndLine);
-
-    //IMONDSPAPI DSPResult IMON_Display_SetVfdText(LPCTSTR lpsz1stLine, LPCTSTR lpsz2ndLine);
-
-}
-
 
 
 namespace OpenHardwareMonitor.GUI
@@ -180,14 +34,8 @@
         private PersistentSettings settings;
         private UnitManager unitManager;
         private List<SensorFrontView> list = new List<SensorFrontView>();
-        //private bool mainIconEnabled = false;
-        //private NotifyIconAdv mainIcon;
-        IntPtr iSoundGraphDll;
-        SoundGraph.IMON_Display_Uninit iIMON_Display_Uninit;
-        SoundGraph.IMON_Display_Init iIMON_Display_Init;
-        SoundGraph.IMON_Display_IsInited iIMON_Display_IsInited;
-        SoundGraph.IMON_Display_IsPluginModeEnabled iIMON_Display_IsPluginModeEnabled;
-        SoundGraph.IMON_Display_SetVfdText iIMON_Display_SetVfdText;
+        private SoundGraph.Server iServer;
+
 
         public SoundGraphDisplay(IComputer computer, PersistentSettings settings,
           UnitManager unitManager)
@@ -198,38 +46,23 @@
             computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
             computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
 
+            //Start our client if needed
+            Process[] processes = Process.GetProcessesByName("SoundGraphAccess");
+            if (!(processes.Length > 0))
+            {
+
+                //Process client = UserAccountControl.CreateProcessAsStandardUser(@"D:\Dev\SoundGraphAccess\Debug\SoundGraphAccess.exe","");
+                    /*
+                Process client = new Process();
+                client.StartInfo.FileName = @"D:\Dev\SoundGraphAccess\Debug\SoundGraphAccess.exe";
+                client.StartInfo.WorkingDirectory = @"D:\Dev\SoundGraphAccess";
+                client.Start();*/
+            }
+
             //Try loading SoundGraph iMON Disaply DLL
-            iSoundGraphDll = NativeMethods.LoadLibraryEx(@"iMONDisplay.dll", IntPtr.Zero, NativeMethods.LoadLibraryFlags.LOAD_WITH_ALTERED_SEARCH_PATH);
-            int err=Marshal.GetLastWin32Error(); //If you 193  it means you need build for x86
-            if (err == 193)
-            {
-                Console.Write(@"iMON: Cannot load x86 DLL from x64 process.");
-            }
-            else if (err != 0)
-            {
-                Console.Write(@"iMON: Error: %i - Failed to load iMONDisplay.dll", err);
-            }
-            else
-            {
-                Console.Write(@"iMON: DLL loaded.");
-                //Gather our function pointers
-                //TODO: Check returned pointers for validity
-                IntPtr functionPointer = NativeMethods.GetProcAddress(iSoundGraphDll, "IMON_Display_Uninit");
-                iIMON_Display_Uninit = (SoundGraph.IMON_Display_Uninit)Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(SoundGraph.IMON_Display_Uninit));
-                
-                functionPointer = NativeMethods.GetProcAddress(iSoundGraphDll, "IMON_Display_Init");
-                iIMON_Display_Init = (SoundGraph.IMON_Display_Init)Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(SoundGraph.IMON_Display_Init));
-                
-                functionPointer = NativeMethods.GetProcAddress(iSoundGraphDll, "IMON_Display_IsInited");
-                iIMON_Display_IsInited = (SoundGraph.IMON_Display_IsInited)Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(SoundGraph.IMON_Display_IsInited));
-                
-                functionPointer = NativeMethods.GetProcAddress(iSoundGraphDll, "IMON_Display_IsPluginModeEnabled");
-                iIMON_Display_IsPluginModeEnabled = (SoundGraph.IMON_Display_IsPluginModeEnabled)Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(SoundGraph.IMON_Display_IsPluginModeEnabled));
-
-                functionPointer = NativeMethods.GetProcAddress(iSoundGraphDll, "IMON_Display_SetVfdText");
-                iIMON_Display_SetVfdText = (SoundGraph.IMON_Display_SetVfdText)Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(SoundGraph.IMON_Display_SetVfdText));
-
-            }
+            iServer = new SoundGraph.Server(@"\\.\pipe\sga-receiver", @"\\.\pipe\sga-sender");
+            iServer.Start();
+            //iServer.SendMessage("init:");
         }
 
         private void HardwareRemoved(IHardware hardware)
@@ -270,11 +103,7 @@
             foreach (SensorFrontView icon in list)
                 icon.Dispose();
 
-            //Unload our DLL
-            if (iSoundGraphDll != IntPtr.Zero)
-            {
-                bool result = NativeMethods.FreeLibrary(iSoundGraphDll);
-            }
+            iServer.Stop();
 
         }
 
@@ -349,19 +178,19 @@
              */
         }
 
-        public void Init(IntPtr aHWND)
+        public void Init()
         {
-            iIMON_Display_Init(aHWND, SoundGraph.WM_DSP_PLUGIN_NOTIFY);
+            iServer.SendMessage("init:");
         }
 
         public void Uninit()
         {
-            iIMON_Display_Uninit();
+            iServer.SendMessage("uninit:");
         }
 
         public void SetText(string aUpperLine, string aLowerLine)
         {
-
+            iServer.SendMessage("set-vfd-text:" + aUpperLine);
         }
 
         /*
@@ -378,47 +207,13 @@
             }
         }*/
 
-
+        /*
         public bool IsDllLoaded
         {
             get { return iSoundGraphDll!=IntPtr.Zero; }
         }
+         */
 
-        public void DisplayPluginMessage(int uErrCode, bool bError)
-        {
-	        if(bError)
-	        {
-                switch ((SoundGraph.DSPNInitResult)uErrCode)
-		        {
-                    case SoundGraph.DSPNInitResult.DSPN_ERR_IN_USED: 
-                        Console.Write("Display Plug-in is Already Used by Other Application.\n"); break;
-                    case SoundGraph.DSPNInitResult.DSPN_ERR_HW_DISCONNECTED: 
-                        Console.Write("iMON HW is Not Connected."); break;
-                    case SoundGraph.DSPNInitResult.DSPN_ERR_NOT_SUPPORTED_HW: 
-                        Console.Write("The Connected iMON HW doesn't Support Display Plug-in.\n"); break;
-                    case SoundGraph.DSPNInitResult.DSPN_ERR_PLUGIN_DISABLED: 
-                        Console.Write("Display Plug-in Mode Option is Disabled.\n"); break;
-                    case SoundGraph.DSPNInitResult.DSPN_ERR_IMON_NO_REPLY: 
-                        Console.Write("The Latest iMON is Not Installed or iMON Not Running.\n"); break;
-                    case SoundGraph.DSPNInitResult.DSPN_ERR_UNKNOWN: 
-                        Console.Write("Unknown Failure.\n"); break;
-		        }
-    	    }
-	        else
-            {
-                switch ((SoundGraph.DSPNotifyCode)uErrCode)
-		        {
-                    case SoundGraph.DSPNotifyCode.DSPNM_PLUGIN_SUCCEED: 
-                        Console.Write("Plug-in Mode Inited Successfully.\n"); break;
-                    case SoundGraph.DSPNotifyCode.DSPNM_IMON_RESTARTED: 
-                        Console.Write("iMON Started and Plug-in Mode Inited.\n"); break;
-                    case SoundGraph.DSPNotifyCode.DSPNM_HW_CONNECTED: 
-                        Console.Write("iMON HW Connected and Plug-in Mode Inited.\n"); break;
-		        }
-	        }
-	    
-            //GetDlgItem(IDC_STATIC_INFO)->SetWindowText((LPCTSTR)strErrMsg);
-        }
 
     }
 }
diff -r 4e41fb513d52 -r 60a1e2b6ed71 GUI/SoundGraphServer.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUI/SoundGraphServer.cs	Sat Feb 09 17:18:09 2013 +0100
@@ -0,0 +1,220 @@
+using System;
+using Microsoft.Win32.SafeHandles;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.IO;
+using System.Diagnostics;
+
+namespace SoundGraph
+{
+    public class Server
+    {
+        [DllImport("kernel32.dll", SetLastError = true)]
+        public static extern SafeFileHandle CreateNamedPipe(
+           String pipeName,
+           uint dwOpenMode,
+           uint dwPipeMode,
+           uint nMaxInstances,
+           uint nOutBufferSize,
+           uint nInBufferSize,
+           uint nDefaultTimeOut,
+           IntPtr lpSecurityAttributes);
+
+        [DllImport("kernel32.dll", SetLastError = true)]
+        public static extern int ConnectNamedPipe(
+           SafeFileHandle hNamedPipe,
+           IntPtr lpOverlapped);
+
+        [DllImport("kernel32.dll", SetLastError = true)]
+        public static extern int DisconnectNamedPipe(
+           SafeFileHandle hNamedPipe);
+
+        public const uint PIPE_ACCESS_DUPLEX = (0x00000003);
+        public const uint FILE_FLAG_OVERLAPPED = (0x40000000);
+        public const uint PIPE_ACCESS_OUTBOUND = (0x00000002);
+        public const uint PIPE_ACCESS_INBOUND = (0x00000001);
+        public const uint PIPE_TYPE_BYTE = (0x00000000);
+        public const uint PIPE_UNLIMITED_INSTANCES = 255;
+          
+        
+
+
+        public const int BUFFER_SIZE = 256;
+
+        //
+        public string iPipeNameOutbound;
+        Thread iThreadOutbound;
+        SafeFileHandle iPipeOutbound;
+        public FileStream iStreamOutbound;
+        //
+        public string iPipeNameInbound;
+        Thread iThreadInbound;
+        SafeFileHandle iPipeInbound;
+        public FileStream iStreamInbound;
+
+
+        public Server(string aPipeNameOutbound, string aPipeNameInbound)
+        {
+            iPipeNameOutbound = aPipeNameOutbound;
+            iPipeNameInbound = aPipeNameInbound;
+        }
+       
+        /**
+         * Start our services.
+         */
+        public void Start()
+        {
+            //Start outbound thread to send messages
+            this.iThreadOutbound = new Thread(new ThreadStart(ThreadOutbound));
+            this.iThreadOutbound.Start();
+            //Start inbound thread to receive messages
+            this.iThreadInbound = new Thread(new ThreadStart(ThreadInbound));
+            this.iThreadInbound.Start();
+        }
+
+        /**
+         * Outbound thread is sending messages to our client.
+         */
+        private void ThreadOutbound()
+        {
+            
+            //Create our outbound named pipe
+            iPipeOutbound = CreateNamedPipe(this.iPipeNameOutbound, PIPE_ACCESS_OUTBOUND /*| FILE_FLAG_OVERLAPPED*/, PIPE_TYPE_BYTE, PIPE_UNLIMITED_INSTANCES, BUFFER_SIZE, BUFFER_SIZE, 0, IntPtr.Zero);
+
+            //Could not create named pipe
+            if (iPipeOutbound.IsInvalid)
+            {
+                //TODO: error handling
+                return;
+            }
+
+            //Will complete once our client connects
+            int success = ConnectNamedPipe(iPipeOutbound, IntPtr.Zero);
+
+            //could not connect client
+            if (success == 0)
+            {
+                //TODO: error handling
+                return;
+            }
+
+            //Client now connected create our stream
+            iStreamOutbound = new FileStream(iPipeOutbound, FileAccess.Write, BUFFER_SIZE, false);
+ 
+        }
+
+        /**
+         * Inbound thread is receiving messages from our client
+         */
+        private void ThreadInbound()
+        {
+            //Client client = (Client)clientObj;
+            //clientse.stream = new FileStream(clientse.handle, FileAccess.ReadWrite, BUFFER_SIZE, true);
+
+            iPipeInbound = CreateNamedPipe(this.iPipeNameInbound, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE, PIPE_UNLIMITED_INSTANCES, BUFFER_SIZE, BUFFER_SIZE, 0, IntPtr.Zero);
+
+            //could not create named pipe
+            if (iPipeInbound.IsInvalid)
+                return;
+
+            //Will complete once a client connects
+            int success = ConnectNamedPipe(iPipeInbound, IntPtr.Zero);
+
+            //could not connect client
+            if (success == 0)
+                return;
+
+            //Client now connected create our inbound stream
+            iStreamInbound = new FileStream(iPipeInbound, FileAccess.Read, BUFFER_SIZE, false);
+
+
+            byte[] buffer = null;
+            ASCIIEncoding encoder = new ASCIIEncoding();
+
+            while (true)
+            {                
+                int bytesRead = 0;
+
+                try
+                {
+                    buffer = new byte[BUFFER_SIZE];
+                    bytesRead = iStreamInbound.Read(buffer, 0, BUFFER_SIZE);
+                }
+                catch
+                {
+                    //read error has occurred
+                    break;
+                }
+
+                //client has disconnected
+                if (bytesRead == 0)
+                    break;
+
+                //fire message received event
+                //if (this.MessageReceived != null)
+                //    this.MessageReceived(clientse, encoder.GetString(buffer, 0, bytesRead));
+
+                int ReadLength = 0;
+                for (int i = 0; i < BUFFER_SIZE; i++)
+                {
+                    //if (buffer[i].ToString("x2") != "cc")
+                    if (buffer[i] != 0)
+                    {
+                        ReadLength++;
+                    }
+                    else
+                        break;
+                }
+                if (ReadLength > 0)
+                {
+                    byte[] Rc = new byte[ReadLength];
+                    Buffer.BlockCopy(buffer, 0, Rc, 0, ReadLength);
+
+                    Console.WriteLine(encoder.GetString(Rc, 0, ReadLength));
+                    Trace.WriteLine("Received " + ReadLength + " Bytes: " + encoder.GetString(Rc, 0, ReadLength));
+                    buffer.Initialize();
+                }
+               
+            }
+
+            //clean up resources
+            iStreamInbound.Close();
+            iPipeInbound.Close();            
+        }
+
+        /**
+         * Send a message to our client.
+         */
+        public void SendMessage(string message)
+        {
+
+                ASCIIEncoding encoder = new ASCIIEncoding();
+                byte[] messageBuffer = encoder.GetBytes(message);
+
+                if (iStreamOutbound.CanWrite)
+                {
+                    iStreamOutbound.Write(messageBuffer, 0, messageBuffer.Length);
+                    iStreamOutbound.Flush();
+                }
+
+
+        }
+
+        /**
+         * 
+         */
+        public void Stop()
+        {
+            //clean up resources
+
+            DisconnectNamedPipe(this.iPipeOutbound);
+
+            //TODO: more cleanup
+            
+
+            this.iThreadOutbound.Abort();
+        }
+
+    }
+}
diff -r 4e41fb513d52 -r 60a1e2b6ed71 OpenHardwareMonitor.csproj
--- a/OpenHardwareMonitor.csproj	Mon Feb 04 00:47:01 2013 +0100
+++ b/OpenHardwareMonitor.csproj	Sat Feb 09 17:18:09 2013 +0100
@@ -9,7 +9,7 @@
     <OutputType>WinExe</OutputType>
     <NoStandardLibraries>false</NoStandardLibraries>
     <AssemblyName>OpenHardwareMonitor</AssemblyName>
-    <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
     <RootNamespace>OpenHardwareMonitor</RootNamespace>
     <ApplicationIcon>Resources\icon.ico</ApplicationIcon>
@@ -34,12 +34,13 @@
     <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
     <UseApplicationTrust>false</UseApplicationTrust>
     <BootstrapperEnabled>true</BootstrapperEnabled>
+    <TargetFrameworkProfile />
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
-    <OutputPath>Bin\Debug\</OutputPath>
+    <OutputPath>output\</OutputPath>
     <DefineConstants>TRACE;DEBUG</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
@@ -50,7 +51,7 @@
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>none</DebugType>
     <Optimize>true</Optimize>
-    <OutputPath>Bin\Release\</OutputPath>
+    <OutputPath>output\</OutputPath>
     <DefineConstants>TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
@@ -125,6 +126,7 @@
     <Compile Include="GUI\SensorNotifyIcon.cs" />
     <Compile Include="GUI\ShowDesktop.cs" />
     <Compile Include="GUI\SoundGraphDisplay.cs" />
+    <Compile Include="GUI\SoundGraphServer.cs" />
     <Compile Include="GUI\SplitContainerAdv.cs">
       <SubType>Component</SubType>
     </Compile>
@@ -226,6 +228,10 @@
       <Project>{B0397530-545A-471D-BB74-027AE456DF1A}</Project>
       <Name>OpenHardwareMonitorLib</Name>
     </ProjectReference>
+    <ProjectReference Include="UacHelpers.CppLibrary\UacHelpers.CppLibrary.vcxproj">
+      <Project>{d043a646-fe7a-4334-b23d-e327593c1ae2}</Project>
+      <Name>UacHelpers.UserAccountControl</Name>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
diff -r 4e41fb513d52 -r 60a1e2b6ed71 OpenHardwareMonitor.sln
--- a/OpenHardwareMonitor.sln	Mon Feb 04 00:47:01 2013 +0100
+++ b/OpenHardwareMonitor.sln	Sat Feb 09 17:18:09 2013 +0100
@@ -8,30 +8,77 @@
 		{B0397530-545A-471D-BB74-027AE456DF1A} = {B0397530-545A-471D-BB74-027AE456DF1A}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UacHelpers.UserAccountControl", "UacHelpers.CppLibrary\UacHelpers.CppLibrary.vcxproj", "{D043A646-FE7A-4334-B23D-E327593C1AE2}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
+		Debug|Mixed Platforms = Debug|Mixed Platforms
+		Debug|Win32 = Debug|Win32
+		Debug|x64 = Debug|x64
 		Debug|x86 = Debug|x86
 		Release|Any CPU = Release|Any CPU
+		Release|Mixed Platforms = Release|Mixed Platforms
+		Release|Win32 = Release|Win32
+		Release|x64 = Release|x64
 		Release|x86 = Release|x86
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 		{B0397530-545A-471D-BB74-027AE456DF1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{B0397530-545A-471D-BB74-027AE456DF1A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B0397530-545A-471D-BB74-027AE456DF1A}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+		{B0397530-545A-471D-BB74-027AE456DF1A}.Debug|Mixed Platforms.Build.0 = Debug|x86
+		{B0397530-545A-471D-BB74-027AE456DF1A}.Debug|Win32.ActiveCfg = Debug|x86
+		{B0397530-545A-471D-BB74-027AE456DF1A}.Debug|Win32.Build.0 = Debug|x86
+		{B0397530-545A-471D-BB74-027AE456DF1A}.Debug|x64.ActiveCfg = Debug|Any CPU
 		{B0397530-545A-471D-BB74-027AE456DF1A}.Debug|x86.ActiveCfg = Debug|x86
 		{B0397530-545A-471D-BB74-027AE456DF1A}.Debug|x86.Build.0 = Debug|x86
 		{B0397530-545A-471D-BB74-027AE456DF1A}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{B0397530-545A-471D-BB74-027AE456DF1A}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B0397530-545A-471D-BB74-027AE456DF1A}.Release|Mixed Platforms.ActiveCfg = Release|x86
+		{B0397530-545A-471D-BB74-027AE456DF1A}.Release|Mixed Platforms.Build.0 = Release|x86
+		{B0397530-545A-471D-BB74-027AE456DF1A}.Release|Win32.ActiveCfg = Release|x86
+		{B0397530-545A-471D-BB74-027AE456DF1A}.Release|Win32.Build.0 = Release|x86
+		{B0397530-545A-471D-BB74-027AE456DF1A}.Release|x64.ActiveCfg = Release|Any CPU
 		{B0397530-545A-471D-BB74-027AE456DF1A}.Release|x86.ActiveCfg = Release|x86
 		{B0397530-545A-471D-BB74-027AE456DF1A}.Release|x86.Build.0 = Release|x86
 		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Debug|Mixed Platforms.Build.0 = Debug|x86
+		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Debug|Win32.ActiveCfg = Debug|x86
+		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Debug|Win32.Build.0 = Debug|x86
+		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Debug|x64.ActiveCfg = Debug|Any CPU
 		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Debug|x86.ActiveCfg = Debug|x86
 		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Debug|x86.Build.0 = Debug|x86
 		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Release|Any CPU.Build.0 = Release|Any CPU
+		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Release|Mixed Platforms.ActiveCfg = Release|x86
+		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Release|Mixed Platforms.Build.0 = Release|x86
+		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Release|Win32.ActiveCfg = Release|x86
+		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Release|Win32.Build.0 = Release|x86
+		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Release|x64.ActiveCfg = Release|Any CPU
 		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Release|x86.ActiveCfg = Release|x86
 		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Release|x86.Build.0 = Release|x86
+		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Debug|Any CPU.ActiveCfg = Debug|x64
+		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Debug|Any CPU.Build.0 = Debug|x64
+		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Debug|Win32.ActiveCfg = Debug|Win32
+		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Debug|Win32.Build.0 = Debug|Win32
+		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Debug|x64.ActiveCfg = Debug|x64
+		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Debug|x64.Build.0 = Debug|x64
+		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Debug|x86.ActiveCfg = Debug|Win32
+		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Debug|x86.Build.0 = Debug|Win32
+		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Release|Any CPU.ActiveCfg = Release|Win32
+		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Release|Mixed Platforms.Build.0 = Release|Win32
+		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Release|Win32.ActiveCfg = Release|Win32
+		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Release|Win32.Build.0 = Release|Win32
+		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Release|x64.ActiveCfg = Release|x64
+		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Release|x64.Build.0 = Release|x64
+		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Release|x86.ActiveCfg = Release|Win32
+		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Release|x86.Build.0 = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff -r 4e41fb513d52 -r 60a1e2b6ed71 OpenHardwareMonitorLib.csproj
--- a/OpenHardwareMonitorLib.csproj	Mon Feb 04 00:47:01 2013 +0100
+++ b/OpenHardwareMonitorLib.csproj	Sat Feb 09 17:18:09 2013 +0100
@@ -10,7 +10,7 @@
     <AppDesignerFolder>Properties</AppDesignerFolder>
     <RootNamespace>OpenHardwareMonitor</RootNamespace>
     <AssemblyName>OpenHardwareMonitorLib</AssemblyName>
-    <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
     <FileUpgradeFlags>
     </FileUpgradeFlags>
@@ -31,12 +31,13 @@
     <IsWebBootstrapper>false</IsWebBootstrapper>
     <UseApplicationTrust>false</UseApplicationTrust>
     <BootstrapperEnabled>true</BootstrapperEnabled>
+    <TargetFrameworkProfile />
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
-    <OutputPath>Bin\Debug\</OutputPath>
+    <OutputPath>output\</OutputPath>
     <DefineConstants>TRACE;DEBUG</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
@@ -45,7 +46,7 @@
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>none</DebugType>
     <Optimize>true</Optimize>
-    <OutputPath>Bin\Release\</OutputPath>
+    <OutputPath>output\</OutputPath>
     <DefineConstants>TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
diff -r 4e41fb513d52 -r 60a1e2b6ed71 UacHelpers.CppLibrary/AssemblyInfo.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UacHelpers.CppLibrary/AssemblyInfo.cpp	Sat Feb 09 17:18:09 2013 +0100
@@ -0,0 +1,38 @@
+using namespace System;
+using namespace System::Reflection;
+using namespace System::Runtime::CompilerServices;
+using namespace System::Runtime::InteropServices;
+using namespace System::Security::Permissions;
+
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly:AssemblyTitleAttribute("UAC Helpers")];
+[assembly:AssemblyDescriptionAttribute("User Account Control C++/CLI Library")];
+[assembly:AssemblyConfigurationAttribute("")];
+[assembly:AssemblyCompanyAttribute("Sela Group")];
+[assembly:AssemblyProductAttribute("")];
+[assembly:AssemblyCopyrightAttribute("Copyright (c) Sasha Goldshtein 2008")];
+[assembly:AssemblyTrademarkAttribute("")];
+[assembly:AssemblyCultureAttribute("")];
+
+//
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the value or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly:AssemblyVersionAttribute("1.0.0.0")];
+
+[assembly:ComVisible(false)];
+
+[assembly:CLSCompliantAttribute(true)];
+
+[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
diff -r 4e41fb513d52 -r 60a1e2b6ed71 UacHelpers.CppLibrary/UacHelpers.CppLibrary.vcproj
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UacHelpers.CppLibrary/UacHelpers.CppLibrary.vcproj	Sat Feb 09 17:18:09 2013 +0100
@@ -0,0 +1,368 @@
+<?xml version="1.0" encoding="windows-1255"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="UacHelpers.UserAccountControl"
+	ProjectGUID="{D043A646-FE7A-4334-B23D-E327593C1AE2}"
+	RootNamespace="UacHelpersCppLibrary"
+	SccProjectName="SAK"
+	SccAuxPath="SAK"
+	SccLocalPath="SAK"
+	SccProvider="SAK"
+	Keyword="ManagedCProj"
+	TargetFrameworkVersion="131072"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			ManagedExtensions="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				GenerateXMLDocumentationFiles="true"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="$(NoInherit)"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				AssemblyDebug="1"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			ManagedExtensions="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				GenerateXMLDocumentationFiles="true"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="$(NoInherit)"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				AssemblyDebug="1"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			ManagedExtensions="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				PreprocessorDefinitions="WIN32;NDEBUG"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				GenerateXMLDocumentationFiles="true"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="$(NoInherit)"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			ManagedExtensions="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				PreprocessorDefinitions="WIN32;NDEBUG"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				GenerateXMLDocumentationFiles="true"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="$(NoInherit)"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+		<AssemblyReference
+			RelativePath="System.dll"
+			AssemblyName="System, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
+			MinFrameworkVersion="131072"
+		/>
+		<AssemblyReference
+			RelativePath="System.Data.dll"
+			AssemblyName="System.Data, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=x86"
+			MinFrameworkVersion="131072"
+		/>
+		<AssemblyReference
+			RelativePath="System.XML.dll"
+			AssemblyName="System.Xml, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
+			MinFrameworkVersion="131072"
+		/>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\AssemblyInfo.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\UserAccountControl.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\UserAccountControl.h"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff -r 4e41fb513d52 -r 60a1e2b6ed71 UacHelpers.CppLibrary/UacHelpers.CppLibrary.vcxproj
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UacHelpers.CppLibrary/UacHelpers.CppLibrary.vcxproj	Sat Feb 09 17:18:09 2013 +0100
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectName>UacHelpers.UserAccountControl</ProjectName>
+    <ProjectGuid>{D043A646-FE7A-4334-B23D-E327593C1AE2}</ProjectGuid>
+    <RootNamespace>UacHelpersCppLibrary</RootNamespace>
+    <SccProjectName>SAK</SccProjectName>
+    <SccAuxPath>SAK</SccAuxPath>
+    <SccLocalPath>SAK</SccLocalPath>
+    <SccProvider>SAK</SccProvider>
+    <Keyword>ManagedCProj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v110</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+    <CLRSupport>true</CLRSupport>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v110</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+    <CLRSupport>true</CLRSupport>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v110</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+    <CLRSupport>true</CLRSupport>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v110</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+    <CLRSupport>true</CLRSupport>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>11.0.51106.1</_ProjectFileVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <OutDir>..\output\</OutDir>
+    <IntDir>$(Configuration)\</IntDir>
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <OutDir>..\output\</OutDir>
+    <IntDir>$(Platform)\$(Configuration)\</IntDir>
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <OutDir>$(SolutionDir)$(Configuration)\</OutDir>
+    <IntDir>$(Configuration)\</IntDir>
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(Platform)\$(Configuration)\</IntDir>
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <PrecompiledHeader />
+      <GenerateXMLDocumentationFiles>true</GenerateXMLDocumentationFiles>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies />
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AssemblyDebug>true</AssemblyDebug>
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>
+      <DataExecutionPrevention />
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <PrecompiledHeader />
+      <GenerateXMLDocumentationFiles>true</GenerateXMLDocumentationFiles>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies />
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AssemblyDebug>true</AssemblyDebug>
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>
+      <DataExecutionPrevention />
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <PrecompiledHeader />
+      <GenerateXMLDocumentationFiles>true</GenerateXMLDocumentationFiles>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies />
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>
+      <DataExecutionPrevention />
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <PrecompiledHeader />
+      <GenerateXMLDocumentationFiles>true</GenerateXMLDocumentationFiles>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies />
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>
+      <DataExecutionPrevention />
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <Reference Include="System">
+      <CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
+      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+    </Reference>
+    <Reference Include="System.Data">
+      <CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
+      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+    </Reference>
+    <Reference Include="System.Xml">
+      <CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
+      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="AssemblyInfo.cpp" />
+    <ClCompile Include="UserAccountControl.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="UserAccountControl.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff -r 4e41fb513d52 -r 60a1e2b6ed71 UacHelpers.CppLibrary/UserAccountControl.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UacHelpers.CppLibrary/UserAccountControl.cpp	Sat Feb 09 17:18:09 2013 +0100
@@ -0,0 +1,226 @@
+#include "UserAccountControl.h"
+
+#include <windows.h>
+#pragma comment (lib, "kernel32.lib")
+#pragma comment (lib, "advapi32.lib")
+
+#include <vcclr.h>
+#include <msclr\marshal.h>
+#include <msclr\marshal_windows.h>
+
+using namespace msclr::interop;
+
+using namespace System::ComponentModel;
+using namespace Microsoft::Win32;
+
+namespace UacHelpers {
+
+	Process^ UserAccountControl::CreateProcessAsAdmin(System::String^ exePath, System::String^ arguments)
+    {
+        ProcessStartInfo^ psi = gcnew ProcessStartInfo(exePath, arguments);
+        psi->UseShellExecute = true;
+        psi->Verb = "runas";
+		return Process::Start(psi);
+    }
+
+	Process^ UserAccountControl::CreateProcessAsStandardUser(System::String^ exePath, System::String^ arguments)
+	{
+		marshal_context context;
+
+		//If the current process is not elevated, then there's no reason to go through the hassle --
+		//just use the standard System.Diagnostics.Process facilities.
+		if (!IsCurrentProcessElevated)
+		{
+			return Process::Start(exePath, arguments);
+		}
+
+		//The following implementation is roughly based on Aaron Margosis' post:
+		//http://blogs.msdn.com/aaron_margosis/archive/2009/06/06/faq-how-do-i-start-a-program-as-the-desktop-user-from-an-elevated-app.aspx
+
+		//Enable SeIncreaseQuotaPrivilege in this process.  (This requires administrative privileges.)
+		HANDLE hProcessToken = NULL;
+		if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hProcessToken))
+		{
+			throw gcnew Win32Exception(GetLastError());
+		}
+		else
+		{
+			TOKEN_PRIVILEGES tkp;
+			tkp.PrivilegeCount = 1;
+			LookupPrivilegeValueW(NULL, SE_INCREASE_QUOTA_NAME, &tkp.Privileges[0].Luid);
+			tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+			AdjustTokenPrivileges(hProcessToken, FALSE, &tkp, 0, NULL, NULL);
+			DWORD dwLastErr = GetLastError();
+			CloseHandle(hProcessToken);
+			if (ERROR_SUCCESS != dwLastErr)
+			{
+				throw gcnew Win32Exception(dwLastErr);
+			}
+		}
+
+		//Get window handle representing the desktop shell.  This might not work if there is no shell window, or when
+		//using a custom shell.  Also note that we're assuming that the shell is not running elevated.
+		HWND hShellWnd = GetShellWindow();
+		if (hShellWnd == NULL)
+		{
+			throw gcnew System::InvalidOperationException("Unable to locate shell window; you might be using a custom shell");
+		}
+
+		//Get the ID of the desktop shell process.
+		DWORD dwShellPID;
+		GetWindowThreadProcessId(hShellWnd, &dwShellPID);
+		if (dwShellPID == 0)
+		{
+			throw gcnew Win32Exception(GetLastError());
+		}
+
+		//Open the desktop shell process in order to get the process token.
+		HANDLE hShellProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwShellPID);
+		if (hShellProcess == NULL)
+		{
+			throw gcnew Win32Exception(GetLastError());
+		}
+
+		HANDLE hShellProcessToken = NULL;
+		HANDLE hPrimaryToken = NULL;
+		try
+		{
+			//Get the process token of the desktop shell.
+			if (!OpenProcessToken(hShellProcess, TOKEN_DUPLICATE, &hShellProcessToken))
+			{
+				throw gcnew Win32Exception(GetLastError());
+			}
+
+			//Duplicate the shell's process token to get a primary token.
+			const DWORD dwTokenRights = TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID;
+			if (!DuplicateTokenEx(hShellProcessToken, dwTokenRights, NULL, SecurityImpersonation, TokenPrimary, &hPrimaryToken))
+			{
+				throw gcnew Win32Exception(GetLastError());
+			}
+
+			//Start the target process with the new token.
+			STARTUPINFO si = {0}; si.cb = sizeof(si);
+			PROCESS_INFORMATION pi = {0};
+			if (!CreateProcessWithTokenW(hPrimaryToken, 0,
+				context.marshal_as<LPCWSTR>(exePath), context.marshal_as<LPWSTR>(exePath + " " + arguments),
+				0, NULL, NULL, &si, &pi))
+			{
+				throw gcnew Win32Exception(GetLastError());
+			}
+			CloseHandle(pi.hProcess);
+			CloseHandle(pi.hThread);
+
+			return Process::GetProcessById(pi.dwProcessId);
+		}
+		finally
+		{
+			if (hShellProcessToken != NULL)
+				CloseHandle(hShellProcessToken);
+
+			if (hPrimaryToken != NULL)
+				CloseHandle(hPrimaryToken);
+
+			if (hShellProcess != NULL)
+				CloseHandle(hShellProcess);
+		}
+	}
+
+	bool UserAccountControl::IsUserAdmin::get()
+	{
+		if (UserAccountControl::IsUacEnabled)
+			return GetProcessTokenElevationType() != TokenElevationTypeDefault;	//split token
+
+		//If UAC is off, we can't rely on the token; check for Admin group.
+		return WindowsPrincipal(WindowsIdentity::GetCurrent()).IsInRole("Administrators");
+	}
+
+	bool UserAccountControl::IsUacEnabled::get()
+	{
+		//Check the HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System\EnableLUA registry value.
+		RegistryKey^ key = Registry::LocalMachine->OpenSubKey(UacRegistryKey, false);
+		return key->GetValue(UacRegistryValue)->Equals(1);
+    }
+
+	void UserAccountControl::DisableUac()
+	{
+		SetUacRegistryValue(false);
+	}
+
+	void UserAccountControl::DisableUacAndRestartWindows()
+	{
+		DisableUac();
+		RestartWindows();
+	}
+
+	void UserAccountControl::EnableUac()
+	{
+		SetUacRegistryValue(true);
+	}
+
+	void UserAccountControl::EnableUacAndRestartWindows()
+	{
+		EnableUac();
+		RestartWindows();
+	}
+
+	bool UserAccountControl::IsCurrentProcessElevated::get()
+	{
+		return GetProcessTokenElevationType() == TokenElevationTypeFull;	//elevated
+	}
+
+	bool UserAccountControl::IsCurrentProcessVirtualized::get()
+	{
+		HANDLE hToken;
+        try
+        {
+            if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
+				throw gcnew Win32Exception(GetLastError());
+
+            DWORD virtualizationEnabled;
+			DWORD dwSize;
+			if (!GetTokenInformation(hToken, TokenVirtualizationEnabled, &virtualizationEnabled, sizeof(virtualizationEnabled), &dwSize))
+                throw gcnew Win32Exception(GetLastError());
+
+			return virtualizationEnabled != 0;
+        }
+        finally
+        {
+            CloseHandle(hToken);
+        }
+	}
+
+	int UserAccountControl::GetProcessTokenElevationType()
+	{
+		HANDLE hToken;
+        try
+        {
+            if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
+				throw gcnew Win32Exception(GetLastError());
+
+            TOKEN_ELEVATION_TYPE elevationType;
+			DWORD dwSize;
+            if (!GetTokenInformation(hToken, TokenElevationType, &elevationType, sizeof(elevationType), &dwSize))
+                throw gcnew Win32Exception(GetLastError());
+
+			return elevationType;
+        }
+        finally
+        {
+            CloseHandle(hToken);
+        }
+	}
+
+	void UserAccountControl::SetUacRegistryValue(bool enabled)
+	{
+		RegistryKey^ key = Registry::LocalMachine->OpenSubKey(UacRegistryKey, true);
+		key->SetValue(UacRegistryValue, enabled ? 1 : 0);
+	}
+
+	void UserAccountControl::RestartWindows()
+	{
+		InitiateSystemShutdownEx(NULL, NULL, 0/*Timeout*/,
+								 TRUE/*ForceAppsClosed*/, TRUE/*RebootAfterShutdown*/,
+								 SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_RECONFIG | SHTDN_REASON_FLAG_PLANNED);
+		//This shutdown flag corresponds to: "Operating System: Reconfiguration (Planned)".
+	}
+}
\ No newline at end of file
diff -r 4e41fb513d52 -r 60a1e2b6ed71 UacHelpers.CppLibrary/UserAccountControl.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UacHelpers.CppLibrary/UserAccountControl.h	Sat Feb 09 17:18:09 2013 +0100
@@ -0,0 +1,133 @@
+// UacHelpers.CppLibrary.h
+
+#pragma once
+
+using namespace System::Diagnostics;
+using namespace System::Security::Principal;
+
+namespace UacHelpers {
+
+	///<summary>
+	///Provides facilities for enabling and disabling User Account Control (UAC),
+	///determining elevation and virtualization status, and launching a process
+	///under elevated credentials.
+	///</summary>
+	///<remarks>
+	///Note that there's a delicate scenario where the registry key has already been
+	///changed, but the user has not logged off yet so the token hasn't been filtered.
+	///In that case, we will think that UAC is on but the user is not an admin (because
+	///the token is not a split token).
+	///</remarks>
+	public ref class UserAccountControl abstract sealed
+	{
+	public:
+		///<summary>
+		///Returns <b>true</b> if the current user has administrator privileges.
+		///</summary>
+		///<remarks>
+		///If UAC is on, then this property will return <b>true</b> even if the
+		///current process is not running elevated.  If UAC is off, then this
+		///property will return <b>true</b> if the user is part of the built-in
+		///<i>Administrators</i> group.
+		///</remarks>
+		static property bool IsUserAdmin
+        {
+            bool get();
+        }
+
+		///<summary>
+		///Returns <b>true</b> if User Account Control (UAC) is enabled on
+		///this machine.
+		///</summary>
+		///<remarks>
+		///This value is obtained by checking the LUA registry key.  It is possible
+		///that the user has not restarted the machine after enabling/disabling UAC.
+		///In that case, the value of the registry key does not reflect the true state
+		///of affairs.  It is possible to devise a custom solution that would provide
+		///a mechanism for tracking whether a restart occurred since UAC settings were
+		///changed (using the RunOnce mechanism, temporary files, or volatile registry keys).
+		///</remarks>
+		static property bool IsUacEnabled
+        {
+            bool get();
+        }
+
+		///<summary>
+		///Returns <b>true</b> if the current process is using UAC virtualization.
+		///</summary>
+		///<remarks>
+		///Under UAC virtualization, file system and registry accesses to specific
+		///locations performed by an application are redirected to provide backwards-
+		///compatibility.  64-bit applications or applications that have an associated
+		///manifest do not enjoy UAC virtualization because they are assumed to be
+		///compatible with Vista and UAC.
+		///</remarks>
+        static property bool IsCurrentProcessVirtualized
+        {
+            bool get();
+        }
+
+		///<summary>
+		///Returns <b>true</b> if the current process is elevated, i.e. if the process
+		///went through an elevation consent phase.
+		///</summary>
+		///<remarks>
+		///This property will return <b>false</b> if UAC is disabled and the process
+		///is running as admin.  It only determines whether the process went through
+		///the elevation procedure.
+		///</remarks>
+		static property bool IsCurrentProcessElevated
+        {
+            bool get();
+        }
+
+		///<summary>
+		///Disables User Account Control by changing the LUA registry key.
+		///The changes do not have effect until the system is restarted.
+		///</summary>
+		static void DisableUac();
+		
+		///<summary>
+		///Disables User Account Control and restarts the system.
+		///</summary>
+		static void DisableUacAndRestartWindows();
+
+		///<summary>
+		///Enables User Account Control by changing the LUA registry key.
+		///The changes do not have effect until the system is restarted.
+		///</summary>
+		static void EnableUac();
+
+		///<summary>
+		///Enables User Account Control and restarts the system.
+		///</summary>
+		static void EnableUacAndRestartWindows();
+
+		///<summary>
+		///Creates a process under the elevated token, regardless of UAC settings
+		///or the manifest associated with that process.
+		///</summary>
+		///<param name="exePath">The path to the executable file.</param>
+		///<param name="arguments">The command-line arguments to pass to the process.</param>
+		///<returns>A <see cref="Process"/> object representing the newly created process.</returns>
+		static Process^ CreateProcessAsAdmin(System::String^ exePath, System::String^ arguments);
+
+		///<summary>
+		///Creates a process under the standard user if the current process is elevated.  The identity
+		///of the standard user is determined by retrieving the user token of the currently running Explorer
+		//(shell) process.  If the current process is not elevated, the standard user is used.
+		///</summary>
+		///<param name="exePath">The path to the executable file.</param>
+		///<param name="arguments">The command-line arguments to pass to the process.</param>
+		///<returns>A <see cref="Process"/> object representing the newly created process.</returns>
+		static Process^ CreateProcessAsStandardUser(System::String^ exePath, System::String^ arguments);
+
+	private:
+		static int GetProcessTokenElevationType();
+		static void SetUacRegistryValue(bool enable);
+		static void RestartWindows();
+
+		static System::String^ UacRegistryKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
+		static System::String^ UacRegistryValue = "EnableLUA";
+	};
+}	// end namespace UacHelpers
\ No newline at end of file