At last we can output stuff on our display. MiniDisplay
authorStephaneLenclud
Mon, 02 Feb 2015 12:51:06 +0100
branchMiniDisplay
changeset 436e9aefd454d1e
parent 435 9ffcd8ed8537
child 437 38e7b78cf732
At last we can output stuff on our display.
The whole thing is still quite broken though.
Rebase: No start-up but that's ok.
GUI/MainForm.cs
GUI/SoundGraphDisplay.cs
GUI/SoundGraphServer.cs
OpenHardwareMonitor.csproj
OpenHardwareMonitor.sln
UacHelpers.CppLibrary/AssemblyInfo.cpp
UacHelpers.CppLibrary/UacHelpers.CppLibrary.vcxproj
UacHelpers.CppLibrary/UserAccountControl.cpp
UacHelpers.CppLibrary/UserAccountControl.h
     1.1 --- a/GUI/MainForm.cs	Mon Feb 04 00:47:01 2013 +0100
     1.2 +++ b/GUI/MainForm.cs	Mon Feb 02 12:51:06 2015 +0100
     1.3 @@ -39,6 +39,7 @@
     1.4      private Color[] plotColorPalette;
     1.5      private SystemTray systemTray;
     1.6      private SoundGraphDisplay soundGraphDisplay;
     1.7 +    private bool displayTick;
     1.8      private StartupManager startupManager = new StartupManager();
     1.9      private UpdateVisitor updateVisitor = new UpdateVisitor();
    1.10      private SensorGadget gadget;
    1.11 @@ -318,18 +319,9 @@
    1.12  
    1.13        InitializePlotForm();
    1.14  
    1.15 -      //
    1.16 -      if (soundGraphDisplay.IsDllLoaded)
    1.17 -      {
    1.18 -          //Try init
    1.19 -          //NativeWindow window;
    1.20 -          soundGraphDisplay.Init(Handle);
    1.21  
    1.22 -          //= Window.GetWindow(this);
    1.23 -          //var wih = new WindowInteropHelper(window);
    1.24 -          //IntPtr hWnd = wih.Handle;
    1.25 -      }
    1.26 -      
    1.27 +      soundGraphDisplay.Init();
    1.28 +
    1.29  
    1.30  
    1.31        startupMenuItem.Visible = startupManager.IsAvailable;
    1.32 @@ -555,6 +547,19 @@
    1.33        if (wmiProvider != null)
    1.34          wmiProvider.Update();
    1.35  
    1.36 +      if (soundGraphDisplay != null)
    1.37 +      {
    1.38 +          displayTick=!displayTick;
    1.39 +          if (displayTick)
    1.40 +          {
    1.41 +              soundGraphDisplay.SetText("       ---", "");
    1.42 +          }
    1.43 +          else
    1.44 +          {
    1.45 +              soundGraphDisplay.SetText("       -+-", "");
    1.46 +          }
    1.47 +      }  
    1.48 +
    1.49  
    1.50        if (logSensors != null && logSensors.Value && delayCount >= 4)
    1.51          logger.Log();
    1.52 @@ -777,41 +782,8 @@
    1.53        const int SC_MINIMIZE = 0xF020;
    1.54        const int SC_CLOSE = 0xF060;
    1.55  
    1.56 -      if (m.Msg == SoundGraph.WM_DSP_PLUGIN_NOTIFY)
    1.57 -      {
    1.58 -        //Handling messages from our iMON Display
    1.59 -          switch ((SoundGraph.DSPNotifyCode)m.WParam.ToInt32())
    1.60 -          {
    1.61 -              case SoundGraph.DSPNotifyCode.DSPNM_PLUGIN_SUCCEED:
    1.62 -              case SoundGraph.DSPNotifyCode.DSPNM_IMON_RESTARTED:
    1.63 -              case SoundGraph.DSPNotifyCode.DSPNM_HW_CONNECTED:
    1.64 -                  {
    1.65 -                      //Connection with our display is now open
    1.66 -                      //Check if we have LCD or VFD
    1.67 -                      //if ((lParam & DSPN_DSP_VFD) == DSPN_DSP_VFD) m_bVfdConnected = TRUE;
    1.68 -                      //if ((lParam & DSPN_DSP_LCD) == DSPN_DSP_LCD) m_bLcdConnected = TRUE;
    1.69 -                      soundGraphDisplay.DisplayPluginMessage(m.WParam.ToInt32(),false);
    1.70 -                  }
    1.71 -                  break;
    1.72 -
    1.73 -              case SoundGraph.DSPNotifyCode.DSPNM_PLUGIN_FAILED:
    1.74 -              case SoundGraph.DSPNotifyCode.DSPNM_HW_DISCONNECTED:
    1.75 -              case SoundGraph.DSPNotifyCode.DSPNM_IMON_CLOSED:
    1.76 -                  {
    1.77 -                      //Connection with our display is closed
    1.78 -                      soundGraphDisplay.DisplayPluginMessage(m.LParam.ToInt32(), true);
    1.79 -                  }
    1.80 -                  break;
    1.81 -
    1.82 -              case SoundGraph.DSPNotifyCode.DSPNM_LCD_TEXT_SCROLL_DONE:
    1.83 -                  {
    1.84 -                      //Scroll finnished
    1.85 -                  }
    1.86 -                  break;
    1.87 -          }
    1.88 -
    1.89 -      }
    1.90 -      else if (minimizeToTray.Value &&
    1.91 + 
    1.92 +      if (minimizeToTray.Value &&
    1.93          m.Msg == WM_SYSCOMMAND && m.WParam.ToInt64() == SC_MINIMIZE)
    1.94        {
    1.95            SysTrayHideShow();
     2.1 --- a/GUI/SoundGraphDisplay.cs	Mon Feb 04 00:47:01 2013 +0100
     2.2 +++ b/GUI/SoundGraphDisplay.cs	Mon Feb 02 12:51:06 2015 +0100
     2.3 @@ -12,164 +12,18 @@
     2.4  using System.Collections.Generic;
     2.5  using System.Drawing;
     2.6  using System.Text;
     2.7 +using System.Diagnostics;
     2.8  using System.Windows.Forms;
     2.9  using System.Windows;
    2.10  using OpenHardwareMonitor.Hardware;
    2.11  using OpenHardwareMonitor.Utilities;
    2.12  using System.Runtime.InteropServices;
    2.13 +using UacHelpers;
    2.14  
    2.15  
    2.16  
    2.17 -static class NativeMethods
    2.18 -{
    2.19 -    [System.Flags]
    2.20 -    public enum LoadLibraryFlags : uint
    2.21 -    {
    2.22 -        DONT_RESOLVE_DLL_REFERENCES = 0x00000001,
    2.23 -        LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010,
    2.24 -        LOAD_LIBRARY_AS_DATAFILE = 0x00000002,
    2.25 -        LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040,
    2.26 -        LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020,
    2.27 -        LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008
    2.28 -    }
    2.29  
    2.30  
    2.31 -    [DllImport("kernel32.dll", SetLastError = true)]
    2.32 -    public static extern IntPtr LoadLibrary(string dllToLoad);
    2.33 -
    2.34 -    [DllImport("kernel32.dll")]
    2.35 -    public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags);
    2.36 -
    2.37 -    [DllImport("kernel32.dll", SetLastError = true)]
    2.38 -    public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
    2.39 -
    2.40 -    [DllImport("kernel32.dll", SetLastError = true)]
    2.41 -    public static extern bool FreeLibrary(IntPtr hModule);
    2.42 -}
    2.43 -
    2.44 -/**
    2.45 -Definitions taken from public Sound Graph APIs.
    2.46 - */
    2.47 -static class SoundGraph
    2.48 -{
    2.49 -
    2.50 -    const int WM_APP = 0x8000;
    2.51 -    public const int WM_DSP_PLUGIN_NOTIFY = WM_APP + 1121;
    2.52 -    /**DSPResult
    2.53 -    @brief	These enumeration values represent the returned result for iMON Display API function calls.\n
    2.54 -			    All iMON Display API function calls return one of this result values.\n
    2.55 -			    For meaning of each result, refer the comment of each line below*/
    2.56 -    public enum DSPResult : int
    2.57 -    {
    2.58 -	    DSP_SUCCEEDED = 0,				//// Function Call Succeeded Without Error
    2.59 -	    DSP_E_FAIL,						//// Unspecified Failure
    2.60 -	    DSP_E_OUTOFMEMORY,				//// Failed to Allocate Necessary Memory
    2.61 -	    DSP_E_INVALIDARG,				//// One or More Arguments Are Not Valid
    2.62 -	    DSP_E_NOT_INITED,				//// API is Not Initialized
    2.63 -	    DSP_E_POINTER,					//// Pointer is Not Valid
    2.64 -
    2.65 -	    DSP_S_INITED = 0x1000,			//// API is Initialized
    2.66 -	    DSP_S_NOT_INITED,				//// API is Not Initialized
    2.67 -	    DSP_S_IN_PLUGIN_MODE,			//// API Can Control iMON Display (Display Plug-in Mode)
    2.68 -	    DSP_S_NOT_IN_PLUGIN_MODE,		//// API Can't Control iMON Display
    2.69 -    };
    2.70 -
    2.71 -
    2.72 -    /**DSPNInitResult
    2.73 -    @brief	These enumeration values represent the result status for requesting Display Plug-in Mode to iMON.\n
    2.74 -			    iMON Display API notifies one of this result values to the caller application after requesting Display Plug-in Mode to iMON.\n
    2.75 -			    For more information, refer the comment of each line below*/
    2.76 -    public enum DSPNInitResult : int
    2.77 -    {
    2.78 -	    DSPN_SUCCEEDED = 0,				//// Display Plug-in Mode is Initialized Successfully
    2.79 -	    DSPN_ERR_IN_USED = 0x0100,		//// Display Plug-in is Already Used by Other Application
    2.80 -	    DSPN_ERR_HW_DISCONNECTED,		//// iMON HW is Not Connected
    2.81 -	    DSPN_ERR_NOT_SUPPORTED_HW,		//// The Connected iMON HW doesn't Support Display Plug-in
    2.82 -	    DSPN_ERR_PLUGIN_DISABLED,		//// Display Plug-in Mode Option is Disabled
    2.83 -	    DSPN_ERR_IMON_NO_REPLY,			//// The Latest iMON is Not Installed or iMON Not Running
    2.84 -	    DSPN_ERR_UNKNOWN = 0x0200,		//// Unknown Failure
    2.85 -    };
    2.86 -
    2.87 -
    2.88 -    /**DSPType
    2.89 -    @brief	These enumeration values represent display type.\n
    2.90 -			    Currently iMON Display API supports VFD and LCD products.*/
    2.91 -    public enum DSPType : int
    2.92 -    {
    2.93 -	    DSPN_DSP_NONE	= 0,
    2.94 -	    DSPN_DSP_VFD	= 0x01,			//// VFD products
    2.95 -	    DSPN_DSP_LCD	= 0x02,			//// LCD products
    2.96 -    };
    2.97 -
    2.98 -
    2.99 -    /**DSPNotifyCode
   2.100 -    @brief	These enumeration values represent the notification codes.\n
   2.101 -			    iMON Display API will send or post message to the caller application.\n
   2.102 -			    The caller application should assign the message and the winodw handle to receivce message with IMON_Display_Init fucntion.\n
   2.103 -			    These enumeration values are used with WPARAM parameter of the message.\n 
   2.104 -			    For more information, see the explanation of each notification code below*/
   2.105 -    public enum DSPNotifyCode : int
   2.106 -    {
   2.107 -	    /**DSPNM_PLUGIN_SUCCEED
   2.108 -	    @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
   2.109 -				    LPARAM represents DSPType. This value can be 0x01 (VFD), 0x02 (LCD) or 0x03 (VFD+LCD).*/
   2.110 -	    DSPNM_PLUGIN_SUCCEED = 0,
   2.111 -
   2.112 -	    /**DSPNM_PLUGIN_FAILED
   2.113 -	    @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
   2.114 -				    LPARAM represents error code with DSPNResult.*/
   2.115 -	    DSPNM_PLUGIN_FAILED,
   2.116 -
   2.117 -	    /**DSPNM_IMON_RESTARTED
   2.118 -	    @brief	When iMON starts, API will post caller-specified message with DSPNM_IMON_RESTARTED as WPARAM parameter.\n
   2.119 -				    LPARAM represents DSPType. This value can be 0 (No Display), 0x01 (VFD), 0x02 (LCD) or 0x03 (VFD+LCD).*/
   2.120 -	    DSPNM_IMON_RESTARTED,
   2.121 -
   2.122 -	    /**DSPNM_IMON_CLOSED
   2.123 -	    @brief	When iMON closed, API will post caller-specified message with DSPNM_IMON_CLOSED as WPARAM parameter.\n
   2.124 -				    LPARAM is not used.*/
   2.125 -	    DSPNM_IMON_CLOSED,
   2.126 -
   2.127 -	    /**DSPNM_HW_CONNECTED
   2.128 -	    @brief	When iMON HW newly connected, API will post caller-specified message with DSPNM_HW_CONNECTED as WPARAM parameter.\n
   2.129 -				    LPARAM represents DSPType. This value can be 0 (No Display), 0x01 (VFD), 0x02 (LCD) or 0x03 (VFD+LCD).*/
   2.130 -	    DSPNM_HW_CONNECTED,
   2.131 -
   2.132 -	    /**DSPNM_HW_DISCONNECTED
   2.133 -	    @brief	When iMON HW disconnected, API will post caller-specified message with DSPNM_HW_DISCONNECTED as WPARAM parameter.\n
   2.134 -				    LPARAM is DSPNResult value, DSPN_ERR_HW_DISCONNECTED.*/
   2.135 -	    DSPNM_HW_DISCONNECTED,
   2.136 -
   2.137 -
   2.138 -	    /**DSPNM_LCD_TEXT_SCROLL_DONE
   2.139 -	    @brief	When iMON LCD finishes scrolling Text, API will post caller-specified message with DSPNM_LCD_TEXT_SCROLL_DONE as WPARAM parameter.\n
   2.140 -				    The caller application may need to know when text scroll is finished, for sending next text.\n
   2.141 -				    LPARAM is not used.*/
   2.142 -	    DSPNM_LCD_TEXT_SCROLL_DONE = 0x1000,
   2.143 -    };
   2.144 -
   2.145 -    /// Functions
   2.146 -    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
   2.147 -    public delegate DSPResult IMON_Display_Uninit();
   2.148 -
   2.149 -    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
   2.150 -    public delegate DSPResult IMON_Display_Init(IntPtr hwndNoti, uint uMsgNotification);
   2.151 -
   2.152 -    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
   2.153 -    public delegate DSPResult IMON_Display_IsInited();
   2.154 -
   2.155 -    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
   2.156 -    public delegate DSPResult IMON_Display_IsPluginModeEnabled();
   2.157 -
   2.158 -    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
   2.159 -    public delegate DSPResult IMON_Display_SetVfdText(
   2.160 -        [MarshalAs(UnmanagedType.LPWStr)] string lpsz1stLine,
   2.161 -        [MarshalAs(UnmanagedType.LPWStr)] string lpsz2ndLine);
   2.162 -
   2.163 -    //IMONDSPAPI DSPResult IMON_Display_SetVfdText(LPCTSTR lpsz1stLine, LPCTSTR lpsz2ndLine);
   2.164 -
   2.165 -}
   2.166 -
   2.167  
   2.168  
   2.169  namespace OpenHardwareMonitor.GUI
   2.170 @@ -180,14 +34,8 @@
   2.171          private PersistentSettings settings;
   2.172          private UnitManager unitManager;
   2.173          private List<SensorFrontView> list = new List<SensorFrontView>();
   2.174 -        //private bool mainIconEnabled = false;
   2.175 -        //private NotifyIconAdv mainIcon;
   2.176 -        IntPtr iSoundGraphDll;
   2.177 -        SoundGraph.IMON_Display_Uninit iIMON_Display_Uninit;
   2.178 -        SoundGraph.IMON_Display_Init iIMON_Display_Init;
   2.179 -        SoundGraph.IMON_Display_IsInited iIMON_Display_IsInited;
   2.180 -        SoundGraph.IMON_Display_IsPluginModeEnabled iIMON_Display_IsPluginModeEnabled;
   2.181 -        SoundGraph.IMON_Display_SetVfdText iIMON_Display_SetVfdText;
   2.182 +        private SoundGraph.Server iServer;
   2.183 +
   2.184  
   2.185          public SoundGraphDisplay(IComputer computer, PersistentSettings settings,
   2.186            UnitManager unitManager)
   2.187 @@ -198,38 +46,23 @@
   2.188              computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
   2.189              computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
   2.190  
   2.191 +            //Start our client if needed
   2.192 +            Process[] processes = Process.GetProcessesByName("SoundGraphAccess");
   2.193 +            if (!(processes.Length > 0))
   2.194 +            {
   2.195 +
   2.196 +                //Process client = UserAccountControl.CreateProcessAsStandardUser(@"D:\Dev\SoundGraphAccess\Debug\SoundGraphAccess.exe","");
   2.197 +                    /*
   2.198 +                Process client = new Process();
   2.199 +                client.StartInfo.FileName = @"D:\Dev\SoundGraphAccess\Debug\SoundGraphAccess.exe";
   2.200 +                client.StartInfo.WorkingDirectory = @"D:\Dev\SoundGraphAccess";
   2.201 +                client.Start();*/
   2.202 +            }
   2.203 +
   2.204              //Try loading SoundGraph iMON Disaply DLL
   2.205 -            iSoundGraphDll = NativeMethods.LoadLibraryEx(@"iMONDisplay.dll", IntPtr.Zero, NativeMethods.LoadLibraryFlags.LOAD_WITH_ALTERED_SEARCH_PATH);
   2.206 -            int err=Marshal.GetLastWin32Error(); //If you 193  it means you need build for x86
   2.207 -            if (err == 193)
   2.208 -            {
   2.209 -                Console.Write(@"iMON: Cannot load x86 DLL from x64 process.");
   2.210 -            }
   2.211 -            else if (err != 0)
   2.212 -            {
   2.213 -                Console.Write(@"iMON: Error: %i - Failed to load iMONDisplay.dll", err);
   2.214 -            }
   2.215 -            else
   2.216 -            {
   2.217 -                Console.Write(@"iMON: DLL loaded.");
   2.218 -                //Gather our function pointers
   2.219 -                //TODO: Check returned pointers for validity
   2.220 -                IntPtr functionPointer = NativeMethods.GetProcAddress(iSoundGraphDll, "IMON_Display_Uninit");
   2.221 -                iIMON_Display_Uninit = (SoundGraph.IMON_Display_Uninit)Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(SoundGraph.IMON_Display_Uninit));
   2.222 -                
   2.223 -                functionPointer = NativeMethods.GetProcAddress(iSoundGraphDll, "IMON_Display_Init");
   2.224 -                iIMON_Display_Init = (SoundGraph.IMON_Display_Init)Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(SoundGraph.IMON_Display_Init));
   2.225 -                
   2.226 -                functionPointer = NativeMethods.GetProcAddress(iSoundGraphDll, "IMON_Display_IsInited");
   2.227 -                iIMON_Display_IsInited = (SoundGraph.IMON_Display_IsInited)Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(SoundGraph.IMON_Display_IsInited));
   2.228 -                
   2.229 -                functionPointer = NativeMethods.GetProcAddress(iSoundGraphDll, "IMON_Display_IsPluginModeEnabled");
   2.230 -                iIMON_Display_IsPluginModeEnabled = (SoundGraph.IMON_Display_IsPluginModeEnabled)Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(SoundGraph.IMON_Display_IsPluginModeEnabled));
   2.231 -
   2.232 -                functionPointer = NativeMethods.GetProcAddress(iSoundGraphDll, "IMON_Display_SetVfdText");
   2.233 -                iIMON_Display_SetVfdText = (SoundGraph.IMON_Display_SetVfdText)Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(SoundGraph.IMON_Display_SetVfdText));
   2.234 -
   2.235 -            }
   2.236 +            iServer = new SoundGraph.Server(@"\\.\pipe\sga-receiver", @"\\.\pipe\sga-sender");
   2.237 +            iServer.Start();
   2.238 +            //iServer.SendMessage("init:");
   2.239          }
   2.240  
   2.241          private void HardwareRemoved(IHardware hardware)
   2.242 @@ -270,11 +103,7 @@
   2.243              foreach (SensorFrontView icon in list)
   2.244                  icon.Dispose();
   2.245  
   2.246 -            //Unload our DLL
   2.247 -            if (iSoundGraphDll != IntPtr.Zero)
   2.248 -            {
   2.249 -                bool result = NativeMethods.FreeLibrary(iSoundGraphDll);
   2.250 -            }
   2.251 +            iServer.Stop();
   2.252  
   2.253          }
   2.254  
   2.255 @@ -349,19 +178,19 @@
   2.256               */
   2.257          }
   2.258  
   2.259 -        public void Init(IntPtr aHWND)
   2.260 +        public void Init()
   2.261          {
   2.262 -            iIMON_Display_Init(aHWND, SoundGraph.WM_DSP_PLUGIN_NOTIFY);
   2.263 +            iServer.SendMessage("init:");
   2.264          }
   2.265  
   2.266          public void Uninit()
   2.267          {
   2.268 -            iIMON_Display_Uninit();
   2.269 +            iServer.SendMessage("uninit:");
   2.270          }
   2.271  
   2.272          public void SetText(string aUpperLine, string aLowerLine)
   2.273          {
   2.274 -
   2.275 +            iServer.SendMessage("set-vfd-text:" + aUpperLine);
   2.276          }
   2.277  
   2.278          /*
   2.279 @@ -378,47 +207,13 @@
   2.280              }
   2.281          }*/
   2.282  
   2.283 -
   2.284 +        /*
   2.285          public bool IsDllLoaded
   2.286          {
   2.287              get { return iSoundGraphDll!=IntPtr.Zero; }
   2.288          }
   2.289 +         */
   2.290  
   2.291 -        public void DisplayPluginMessage(int uErrCode, bool bError)
   2.292 -        {
   2.293 -	        if(bError)
   2.294 -	        {
   2.295 -                switch ((SoundGraph.DSPNInitResult)uErrCode)
   2.296 -		        {
   2.297 -                    case SoundGraph.DSPNInitResult.DSPN_ERR_IN_USED: 
   2.298 -                        Console.Write("Display Plug-in is Already Used by Other Application.\n"); break;
   2.299 -                    case SoundGraph.DSPNInitResult.DSPN_ERR_HW_DISCONNECTED: 
   2.300 -                        Console.Write("iMON HW is Not Connected."); break;
   2.301 -                    case SoundGraph.DSPNInitResult.DSPN_ERR_NOT_SUPPORTED_HW: 
   2.302 -                        Console.Write("The Connected iMON HW doesn't Support Display Plug-in.\n"); break;
   2.303 -                    case SoundGraph.DSPNInitResult.DSPN_ERR_PLUGIN_DISABLED: 
   2.304 -                        Console.Write("Display Plug-in Mode Option is Disabled.\n"); break;
   2.305 -                    case SoundGraph.DSPNInitResult.DSPN_ERR_IMON_NO_REPLY: 
   2.306 -                        Console.Write("The Latest iMON is Not Installed or iMON Not Running.\n"); break;
   2.307 -                    case SoundGraph.DSPNInitResult.DSPN_ERR_UNKNOWN: 
   2.308 -                        Console.Write("Unknown Failure.\n"); break;
   2.309 -		        }
   2.310 -    	    }
   2.311 -	        else
   2.312 -            {
   2.313 -                switch ((SoundGraph.DSPNotifyCode)uErrCode)
   2.314 -		        {
   2.315 -                    case SoundGraph.DSPNotifyCode.DSPNM_PLUGIN_SUCCEED: 
   2.316 -                        Console.Write("Plug-in Mode Inited Successfully.\n"); break;
   2.317 -                    case SoundGraph.DSPNotifyCode.DSPNM_IMON_RESTARTED: 
   2.318 -                        Console.Write("iMON Started and Plug-in Mode Inited.\n"); break;
   2.319 -                    case SoundGraph.DSPNotifyCode.DSPNM_HW_CONNECTED: 
   2.320 -                        Console.Write("iMON HW Connected and Plug-in Mode Inited.\n"); break;
   2.321 -		        }
   2.322 -	        }
   2.323 -	    
   2.324 -            //GetDlgItem(IDC_STATIC_INFO)->SetWindowText((LPCTSTR)strErrMsg);
   2.325 -        }
   2.326  
   2.327      }
   2.328  }
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/GUI/SoundGraphServer.cs	Mon Feb 02 12:51:06 2015 +0100
     3.3 @@ -0,0 +1,220 @@
     3.4 +using System;
     3.5 +using Microsoft.Win32.SafeHandles;
     3.6 +using System.Text;
     3.7 +using System.Runtime.InteropServices;
     3.8 +using System.Threading;
     3.9 +using System.IO;
    3.10 +using System.Diagnostics;
    3.11 +
    3.12 +namespace SoundGraph
    3.13 +{
    3.14 +    public class Server
    3.15 +    {
    3.16 +        [DllImport("kernel32.dll", SetLastError = true)]
    3.17 +        public static extern SafeFileHandle CreateNamedPipe(
    3.18 +           String pipeName,
    3.19 +           uint dwOpenMode,
    3.20 +           uint dwPipeMode,
    3.21 +           uint nMaxInstances,
    3.22 +           uint nOutBufferSize,
    3.23 +           uint nInBufferSize,
    3.24 +           uint nDefaultTimeOut,
    3.25 +           IntPtr lpSecurityAttributes);
    3.26 +
    3.27 +        [DllImport("kernel32.dll", SetLastError = true)]
    3.28 +        public static extern int ConnectNamedPipe(
    3.29 +           SafeFileHandle hNamedPipe,
    3.30 +           IntPtr lpOverlapped);
    3.31 +
    3.32 +        [DllImport("kernel32.dll", SetLastError = true)]
    3.33 +        public static extern int DisconnectNamedPipe(
    3.34 +           SafeFileHandle hNamedPipe);
    3.35 +
    3.36 +        public const uint PIPE_ACCESS_DUPLEX = (0x00000003);
    3.37 +        public const uint FILE_FLAG_OVERLAPPED = (0x40000000);
    3.38 +        public const uint PIPE_ACCESS_OUTBOUND = (0x00000002);
    3.39 +        public const uint PIPE_ACCESS_INBOUND = (0x00000001);
    3.40 +        public const uint PIPE_TYPE_BYTE = (0x00000000);
    3.41 +        public const uint PIPE_UNLIMITED_INSTANCES = 255;
    3.42 +          
    3.43 +        
    3.44 +
    3.45 +
    3.46 +        public const int BUFFER_SIZE = 256;
    3.47 +
    3.48 +        //
    3.49 +        public string iPipeNameOutbound;
    3.50 +        Thread iThreadOutbound;
    3.51 +        SafeFileHandle iPipeOutbound;
    3.52 +        public FileStream iStreamOutbound;
    3.53 +        //
    3.54 +        public string iPipeNameInbound;
    3.55 +        Thread iThreadInbound;
    3.56 +        SafeFileHandle iPipeInbound;
    3.57 +        public FileStream iStreamInbound;
    3.58 +
    3.59 +
    3.60 +        public Server(string aPipeNameOutbound, string aPipeNameInbound)
    3.61 +        {
    3.62 +            iPipeNameOutbound = aPipeNameOutbound;
    3.63 +            iPipeNameInbound = aPipeNameInbound;
    3.64 +        }
    3.65 +       
    3.66 +        /**
    3.67 +         * Start our services.
    3.68 +         */
    3.69 +        public void Start()
    3.70 +        {
    3.71 +            //Start outbound thread to send messages
    3.72 +            this.iThreadOutbound = new Thread(new ThreadStart(ThreadOutbound));
    3.73 +            this.iThreadOutbound.Start();
    3.74 +            //Start inbound thread to receive messages
    3.75 +            this.iThreadInbound = new Thread(new ThreadStart(ThreadInbound));
    3.76 +            this.iThreadInbound.Start();
    3.77 +        }
    3.78 +
    3.79 +        /**
    3.80 +         * Outbound thread is sending messages to our client.
    3.81 +         */
    3.82 +        private void ThreadOutbound()
    3.83 +        {
    3.84 +            
    3.85 +            //Create our outbound named pipe
    3.86 +            iPipeOutbound = CreateNamedPipe(this.iPipeNameOutbound, PIPE_ACCESS_OUTBOUND /*| FILE_FLAG_OVERLAPPED*/, PIPE_TYPE_BYTE, PIPE_UNLIMITED_INSTANCES, BUFFER_SIZE, BUFFER_SIZE, 0, IntPtr.Zero);
    3.87 +
    3.88 +            //Could not create named pipe
    3.89 +            if (iPipeOutbound.IsInvalid)
    3.90 +            {
    3.91 +                //TODO: error handling
    3.92 +                return;
    3.93 +            }
    3.94 +
    3.95 +            //Will complete once our client connects
    3.96 +            int success = ConnectNamedPipe(iPipeOutbound, IntPtr.Zero);
    3.97 +
    3.98 +            //could not connect client
    3.99 +            if (success == 0)
   3.100 +            {
   3.101 +                //TODO: error handling
   3.102 +                return;
   3.103 +            }
   3.104 +
   3.105 +            //Client now connected create our stream
   3.106 +            iStreamOutbound = new FileStream(iPipeOutbound, FileAccess.Write, BUFFER_SIZE, false);
   3.107 + 
   3.108 +        }
   3.109 +
   3.110 +        /**
   3.111 +         * Inbound thread is receiving messages from our client
   3.112 +         */
   3.113 +        private void ThreadInbound()
   3.114 +        {
   3.115 +            //Client client = (Client)clientObj;
   3.116 +            //clientse.stream = new FileStream(clientse.handle, FileAccess.ReadWrite, BUFFER_SIZE, true);
   3.117 +
   3.118 +            iPipeInbound = CreateNamedPipe(this.iPipeNameInbound, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE, PIPE_UNLIMITED_INSTANCES, BUFFER_SIZE, BUFFER_SIZE, 0, IntPtr.Zero);
   3.119 +
   3.120 +            //could not create named pipe
   3.121 +            if (iPipeInbound.IsInvalid)
   3.122 +                return;
   3.123 +
   3.124 +            //Will complete once a client connects
   3.125 +            int success = ConnectNamedPipe(iPipeInbound, IntPtr.Zero);
   3.126 +
   3.127 +            //could not connect client
   3.128 +            if (success == 0)
   3.129 +                return;
   3.130 +
   3.131 +            //Client now connected create our inbound stream
   3.132 +            iStreamInbound = new FileStream(iPipeInbound, FileAccess.Read, BUFFER_SIZE, false);
   3.133 +
   3.134 +
   3.135 +            byte[] buffer = null;
   3.136 +            ASCIIEncoding encoder = new ASCIIEncoding();
   3.137 +
   3.138 +            while (true)
   3.139 +            {                
   3.140 +                int bytesRead = 0;
   3.141 +
   3.142 +                try
   3.143 +                {
   3.144 +                    buffer = new byte[BUFFER_SIZE];
   3.145 +                    bytesRead = iStreamInbound.Read(buffer, 0, BUFFER_SIZE);
   3.146 +                }
   3.147 +                catch
   3.148 +                {
   3.149 +                    //read error has occurred
   3.150 +                    break;
   3.151 +                }
   3.152 +
   3.153 +                //client has disconnected
   3.154 +                if (bytesRead == 0)
   3.155 +                    break;
   3.156 +
   3.157 +                //fire message received event
   3.158 +                //if (this.MessageReceived != null)
   3.159 +                //    this.MessageReceived(clientse, encoder.GetString(buffer, 0, bytesRead));
   3.160 +
   3.161 +                int ReadLength = 0;
   3.162 +                for (int i = 0; i < BUFFER_SIZE; i++)
   3.163 +                {
   3.164 +                    //if (buffer[i].ToString("x2") != "cc")
   3.165 +                    if (buffer[i] != 0)
   3.166 +                    {
   3.167 +                        ReadLength++;
   3.168 +                    }
   3.169 +                    else
   3.170 +                        break;
   3.171 +                }
   3.172 +                if (ReadLength > 0)
   3.173 +                {
   3.174 +                    byte[] Rc = new byte[ReadLength];
   3.175 +                    Buffer.BlockCopy(buffer, 0, Rc, 0, ReadLength);
   3.176 +
   3.177 +                    Console.WriteLine(encoder.GetString(Rc, 0, ReadLength));
   3.178 +                    Trace.WriteLine("Received " + ReadLength + " Bytes: " + encoder.GetString(Rc, 0, ReadLength));
   3.179 +                    buffer.Initialize();
   3.180 +                }
   3.181 +               
   3.182 +            }
   3.183 +
   3.184 +            //clean up resources
   3.185 +            iStreamInbound.Close();
   3.186 +            iPipeInbound.Close();            
   3.187 +        }
   3.188 +
   3.189 +        /**
   3.190 +         * Send a message to our client.
   3.191 +         */
   3.192 +        public void SendMessage(string message)
   3.193 +        {
   3.194 +
   3.195 +                ASCIIEncoding encoder = new ASCIIEncoding();
   3.196 +                byte[] messageBuffer = encoder.GetBytes(message);
   3.197 +
   3.198 +                if (iStreamOutbound.CanWrite)
   3.199 +                {
   3.200 +                    iStreamOutbound.Write(messageBuffer, 0, messageBuffer.Length);
   3.201 +                    iStreamOutbound.Flush();
   3.202 +                }
   3.203 +
   3.204 +
   3.205 +        }
   3.206 +
   3.207 +        /**
   3.208 +         * 
   3.209 +         */
   3.210 +        public void Stop()
   3.211 +        {
   3.212 +            //clean up resources
   3.213 +
   3.214 +            DisconnectNamedPipe(this.iPipeOutbound);
   3.215 +
   3.216 +            //TODO: more cleanup
   3.217 +            
   3.218 +
   3.219 +            this.iThreadOutbound.Abort();
   3.220 +        }
   3.221 +
   3.222 +    }
   3.223 +}
     4.1 --- a/OpenHardwareMonitor.csproj	Mon Feb 04 00:47:01 2013 +0100
     4.2 +++ b/OpenHardwareMonitor.csproj	Mon Feb 02 12:51:06 2015 +0100
     4.3 @@ -113,6 +113,7 @@
     4.4      <Compile Include="GUI\SensorNotifyIcon.cs" />
     4.5      <Compile Include="GUI\ShowDesktop.cs" />
     4.6      <Compile Include="GUI\SoundGraphDisplay.cs" />
     4.7 +    <Compile Include="GUI\SoundGraphServer.cs" />
     4.8      <Compile Include="GUI\SplitContainerAdv.cs">
     4.9        <SubType>Component</SubType>
    4.10      </Compile>
    4.11 @@ -215,6 +216,10 @@
    4.12        <Project>{B0397530-545A-471D-BB74-027AE456DF1A}</Project>
    4.13        <Name>OpenHardwareMonitorLib</Name>
    4.14      </ProjectReference>
    4.15 +    <ProjectReference Include="UacHelpers.CppLibrary\UacHelpers.CppLibrary.vcxproj">
    4.16 +      <Project>{D043A646-FE7A-4334-B23D-E327593C1AE2}</Project>
    4.17 +      <Name>UacHelpers.UserAccountControl</Name>
    4.18 +    </ProjectReference>
    4.19    </ItemGroup>
    4.20    <ItemGroup>
    4.21      <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
     5.1 --- a/OpenHardwareMonitor.sln	Mon Feb 04 00:47:01 2013 +0100
     5.2 +++ b/OpenHardwareMonitor.sln	Mon Feb 02 12:51:06 2015 +0100
     5.3 @@ -8,20 +8,61 @@
     5.4  		{B0397530-545A-471D-BB74-027AE456DF1A} = {B0397530-545A-471D-BB74-027AE456DF1A}
     5.5  	EndProjectSection
     5.6  EndProject
     5.7 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UacHelpers.UserAccountControl", "UacHelpers.CppLibrary\UacHelpers.CppLibrary.vcxproj", "{D043A646-FE7A-4334-B23D-E327593C1AE2}"
     5.8 +EndProject
     5.9  Global
    5.10  	GlobalSection(SolutionConfigurationPlatforms) = preSolution
    5.11  		Debug|Any CPU = Debug|Any CPU
    5.12 +		Debug|Mixed Platforms = Debug|Mixed Platforms
    5.13 +		Debug|Win32 = Debug|Win32
    5.14 +		Debug|x64 = Debug|x64
    5.15  		Release|Any CPU = Release|Any CPU
    5.16 +		Release|Mixed Platforms = Release|Mixed Platforms
    5.17 +		Release|Win32 = Release|Win32
    5.18 +		Release|x64 = Release|x64
    5.19  	EndGlobalSection
    5.20  	GlobalSection(ProjectConfigurationPlatforms) = postSolution
    5.21  		{B0397530-545A-471D-BB74-027AE456DF1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
    5.22  		{B0397530-545A-471D-BB74-027AE456DF1A}.Debug|Any CPU.Build.0 = Debug|Any CPU
    5.23 +		{B0397530-545A-471D-BB74-027AE456DF1A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
    5.24 +		{B0397530-545A-471D-BB74-027AE456DF1A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
    5.25 +		{B0397530-545A-471D-BB74-027AE456DF1A}.Debug|Win32.ActiveCfg = Debug|Any CPU
    5.26 +		{B0397530-545A-471D-BB74-027AE456DF1A}.Debug|Win32.Build.0 = Debug|Any CPU
    5.27 +		{B0397530-545A-471D-BB74-027AE456DF1A}.Debug|x64.ActiveCfg = Debug|Any CPU
    5.28  		{B0397530-545A-471D-BB74-027AE456DF1A}.Release|Any CPU.ActiveCfg = Release|Any CPU
    5.29  		{B0397530-545A-471D-BB74-027AE456DF1A}.Release|Any CPU.Build.0 = Release|Any CPU
    5.30 +		{B0397530-545A-471D-BB74-027AE456DF1A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
    5.31 +		{B0397530-545A-471D-BB74-027AE456DF1A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
    5.32 +		{B0397530-545A-471D-BB74-027AE456DF1A}.Release|Win32.ActiveCfg = Release|Any CPU
    5.33 +		{B0397530-545A-471D-BB74-027AE456DF1A}.Release|x64.ActiveCfg = Release|Any CPU
    5.34  		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
    5.35  		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Debug|Any CPU.Build.0 = Debug|Any CPU
    5.36 +		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
    5.37 +		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
    5.38 +		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Debug|Win32.ActiveCfg = Debug|Any CPU
    5.39 +		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Debug|Win32.Build.0 = Debug|Any CPU
    5.40 +		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Debug|x64.ActiveCfg = Debug|Any CPU
    5.41  		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Release|Any CPU.ActiveCfg = Release|Any CPU
    5.42  		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Release|Any CPU.Build.0 = Release|Any CPU
    5.43 +		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
    5.44 +		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Release|Mixed Platforms.Build.0 = Release|Any CPU
    5.45 +		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Release|Win32.ActiveCfg = Release|Any CPU
    5.46 +		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Release|x64.ActiveCfg = Release|Any CPU
    5.47 +		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Debug|Any CPU.ActiveCfg = Debug|x64
    5.48 +		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Debug|Any CPU.Build.0 = Debug|x64
    5.49 +		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Debug|Mixed Platforms.ActiveCfg = Debug|x64
    5.50 +		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Debug|Mixed Platforms.Build.0 = Debug|x64
    5.51 +		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Debug|Win32.ActiveCfg = Debug|Win32
    5.52 +		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Debug|Win32.Build.0 = Debug|Win32
    5.53 +		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Debug|x64.ActiveCfg = Debug|x64
    5.54 +		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Debug|x64.Build.0 = Debug|x64
    5.55 +		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Release|Any CPU.ActiveCfg = Release|x64
    5.56 +		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Release|Mixed Platforms.ActiveCfg = Release|x64
    5.57 +		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Release|Mixed Platforms.Build.0 = Release|x64
    5.58 +		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Release|Win32.ActiveCfg = Release|Win32
    5.59 +		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Release|Win32.Build.0 = Release|Win32
    5.60 +		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Release|x64.ActiveCfg = Release|x64
    5.61 +		{D043A646-FE7A-4334-B23D-E327593C1AE2}.Release|x64.Build.0 = Release|x64
    5.62  	EndGlobalSection
    5.63  	GlobalSection(SolutionProperties) = preSolution
    5.64  		HideSolutionNode = FALSE
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/UacHelpers.CppLibrary/AssemblyInfo.cpp	Mon Feb 02 12:51:06 2015 +0100
     6.3 @@ -0,0 +1,38 @@
     6.4 +using namespace System;
     6.5 +using namespace System::Reflection;
     6.6 +using namespace System::Runtime::CompilerServices;
     6.7 +using namespace System::Runtime::InteropServices;
     6.8 +using namespace System::Security::Permissions;
     6.9 +
    6.10 +//
    6.11 +// General Information about an assembly is controlled through the following
    6.12 +// set of attributes. Change these attribute values to modify the information
    6.13 +// associated with an assembly.
    6.14 +//
    6.15 +[assembly:AssemblyTitleAttribute("UAC Helpers")];
    6.16 +[assembly:AssemblyDescriptionAttribute("User Account Control C++/CLI Library")];
    6.17 +[assembly:AssemblyConfigurationAttribute("")];
    6.18 +[assembly:AssemblyCompanyAttribute("Sela Group")];
    6.19 +[assembly:AssemblyProductAttribute("")];
    6.20 +[assembly:AssemblyCopyrightAttribute("Copyright (c) Sasha Goldshtein 2008")];
    6.21 +[assembly:AssemblyTrademarkAttribute("")];
    6.22 +[assembly:AssemblyCultureAttribute("")];
    6.23 +
    6.24 +//
    6.25 +// Version information for an assembly consists of the following four values:
    6.26 +//
    6.27 +//      Major Version
    6.28 +//      Minor Version
    6.29 +//      Build Number
    6.30 +//      Revision
    6.31 +//
    6.32 +// You can specify all the value or you can default the Revision and Build Numbers
    6.33 +// by using the '*' as shown below:
    6.34 +
    6.35 +[assembly:AssemblyVersionAttribute("1.0.0.0")];
    6.36 +
    6.37 +[assembly:ComVisible(false)];
    6.38 +
    6.39 +[assembly:CLSCompliantAttribute(true)];
    6.40 +
    6.41 +[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/UacHelpers.CppLibrary/UacHelpers.CppLibrary.vcxproj	Mon Feb 02 12:51:06 2015 +0100
     7.3 @@ -0,0 +1,216 @@
     7.4 +<?xml version="1.0" encoding="utf-8"?>
     7.5 +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
     7.6 +  <ItemGroup Label="ProjectConfigurations">
     7.7 +    <ProjectConfiguration Include="Debug|Win32">
     7.8 +      <Configuration>Debug</Configuration>
     7.9 +      <Platform>Win32</Platform>
    7.10 +    </ProjectConfiguration>
    7.11 +    <ProjectConfiguration Include="Debug|x64">
    7.12 +      <Configuration>Debug</Configuration>
    7.13 +      <Platform>x64</Platform>
    7.14 +    </ProjectConfiguration>
    7.15 +    <ProjectConfiguration Include="Release|Win32">
    7.16 +      <Configuration>Release</Configuration>
    7.17 +      <Platform>Win32</Platform>
    7.18 +    </ProjectConfiguration>
    7.19 +    <ProjectConfiguration Include="Release|x64">
    7.20 +      <Configuration>Release</Configuration>
    7.21 +      <Platform>x64</Platform>
    7.22 +    </ProjectConfiguration>
    7.23 +  </ItemGroup>
    7.24 +  <PropertyGroup Label="Globals">
    7.25 +    <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
    7.26 +    <ProjectName>UacHelpers.UserAccountControl</ProjectName>
    7.27 +    <ProjectGuid>{D043A646-FE7A-4334-B23D-E327593C1AE2}</ProjectGuid>
    7.28 +    <RootNamespace>UacHelpersCppLibrary</RootNamespace>
    7.29 +    <SccProjectName>
    7.30 +    </SccProjectName>
    7.31 +    <SccAuxPath>
    7.32 +    </SccAuxPath>
    7.33 +    <SccLocalPath>
    7.34 +    </SccLocalPath>
    7.35 +    <SccProvider>
    7.36 +    </SccProvider>
    7.37 +    <Keyword>ManagedCProj</Keyword>
    7.38 +  </PropertyGroup>
    7.39 +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
    7.40 +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    7.41 +    <ConfigurationType>DynamicLibrary</ConfigurationType>
    7.42 +    <CharacterSet>Unicode</CharacterSet>
    7.43 +    <CLRSupport>true</CLRSupport>
    7.44 +    <WholeProgramOptimization>true</WholeProgramOptimization>
    7.45 +  </PropertyGroup>
    7.46 +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    7.47 +    <ConfigurationType>DynamicLibrary</ConfigurationType>
    7.48 +    <CharacterSet>Unicode</CharacterSet>
    7.49 +    <CLRSupport>true</CLRSupport>
    7.50 +  </PropertyGroup>
    7.51 +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    7.52 +    <ConfigurationType>DynamicLibrary</ConfigurationType>
    7.53 +    <CharacterSet>Unicode</CharacterSet>
    7.54 +    <CLRSupport>true</CLRSupport>
    7.55 +    <WholeProgramOptimization>true</WholeProgramOptimization>
    7.56 +  </PropertyGroup>
    7.57 +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    7.58 +    <ConfigurationType>DynamicLibrary</ConfigurationType>
    7.59 +    <CharacterSet>Unicode</CharacterSet>
    7.60 +    <CLRSupport>true</CLRSupport>
    7.61 +  </PropertyGroup>
    7.62 +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
    7.63 +  <ImportGroup Label="ExtensionSettings">
    7.64 +  </ImportGroup>
    7.65 +  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
    7.66 +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
    7.67 +  </ImportGroup>
    7.68 +  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
    7.69 +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
    7.70 +  </ImportGroup>
    7.71 +  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
    7.72 +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
    7.73 +  </ImportGroup>
    7.74 +  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
    7.75 +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
    7.76 +  </ImportGroup>
    7.77 +  <PropertyGroup Label="UserMacros" />
    7.78 +  <PropertyGroup>
    7.79 +    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
    7.80 +    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
    7.81 +    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
    7.82 +    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
    7.83 +    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
    7.84 +    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>
    7.85 +    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
    7.86 +    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
    7.87 +    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
    7.88 +    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
    7.89 +    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
    7.90 +    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</IntDir>
    7.91 +    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
    7.92 +    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
    7.93 +    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
    7.94 +    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
    7.95 +    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    7.96 +    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
    7.97 +    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
    7.98 +    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
    7.99 +    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
   7.100 +    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
   7.101 +    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
   7.102 +    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
   7.103 +    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
   7.104 +  </PropertyGroup>
   7.105 +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
   7.106 +    <ClCompile>
   7.107 +      <Optimization>Disabled</Optimization>
   7.108 +      <PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   7.109 +      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
   7.110 +      <PrecompiledHeader>
   7.111 +      </PrecompiledHeader>
   7.112 +      <GenerateXMLDocumentationFiles>true</GenerateXMLDocumentationFiles>
   7.113 +      <WarningLevel>Level3</WarningLevel>
   7.114 +      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
   7.115 +    </ClCompile>
   7.116 +    <Link>
   7.117 +      <AdditionalDependencies>
   7.118 +      </AdditionalDependencies>
   7.119 +      <GenerateDebugInformation>true</GenerateDebugInformation>
   7.120 +      <AssemblyDebug>true</AssemblyDebug>
   7.121 +      <RandomizedBaseAddress>false</RandomizedBaseAddress>
   7.122 +      <DataExecutionPrevention>
   7.123 +      </DataExecutionPrevention>
   7.124 +      <TargetMachine>MachineX86</TargetMachine>
   7.125 +    </Link>
   7.126 +  </ItemDefinitionGroup>
   7.127 +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
   7.128 +    <Midl>
   7.129 +      <TargetEnvironment>X64</TargetEnvironment>
   7.130 +    </Midl>
   7.131 +    <ClCompile>
   7.132 +      <Optimization>Disabled</Optimization>
   7.133 +      <PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   7.134 +      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
   7.135 +      <PrecompiledHeader>
   7.136 +      </PrecompiledHeader>
   7.137 +      <GenerateXMLDocumentationFiles>true</GenerateXMLDocumentationFiles>
   7.138 +      <WarningLevel>Level3</WarningLevel>
   7.139 +      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
   7.140 +    </ClCompile>
   7.141 +    <Link>
   7.142 +      <AdditionalDependencies>
   7.143 +      </AdditionalDependencies>
   7.144 +      <GenerateDebugInformation>true</GenerateDebugInformation>
   7.145 +      <AssemblyDebug>true</AssemblyDebug>
   7.146 +      <RandomizedBaseAddress>false</RandomizedBaseAddress>
   7.147 +      <DataExecutionPrevention>
   7.148 +      </DataExecutionPrevention>
   7.149 +      <TargetMachine>MachineX64</TargetMachine>
   7.150 +    </Link>
   7.151 +  </ItemDefinitionGroup>
   7.152 +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
   7.153 +    <ClCompile>
   7.154 +      <PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   7.155 +      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
   7.156 +      <PrecompiledHeader>
   7.157 +      </PrecompiledHeader>
   7.158 +      <GenerateXMLDocumentationFiles>true</GenerateXMLDocumentationFiles>
   7.159 +      <WarningLevel>Level3</WarningLevel>
   7.160 +      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
   7.161 +    </ClCompile>
   7.162 +    <Link>
   7.163 +      <AdditionalDependencies>
   7.164 +      </AdditionalDependencies>
   7.165 +      <GenerateDebugInformation>true</GenerateDebugInformation>
   7.166 +      <RandomizedBaseAddress>false</RandomizedBaseAddress>
   7.167 +      <DataExecutionPrevention>
   7.168 +      </DataExecutionPrevention>
   7.169 +      <TargetMachine>MachineX86</TargetMachine>
   7.170 +    </Link>
   7.171 +  </ItemDefinitionGroup>
   7.172 +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
   7.173 +    <Midl>
   7.174 +      <TargetEnvironment>X64</TargetEnvironment>
   7.175 +    </Midl>
   7.176 +    <ClCompile>
   7.177 +      <PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   7.178 +      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
   7.179 +      <PrecompiledHeader>
   7.180 +      </PrecompiledHeader>
   7.181 +      <GenerateXMLDocumentationFiles>true</GenerateXMLDocumentationFiles>
   7.182 +      <WarningLevel>Level3</WarningLevel>
   7.183 +      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
   7.184 +    </ClCompile>
   7.185 +    <Link>
   7.186 +      <AdditionalDependencies>
   7.187 +      </AdditionalDependencies>
   7.188 +      <GenerateDebugInformation>true</GenerateDebugInformation>
   7.189 +      <RandomizedBaseAddress>false</RandomizedBaseAddress>
   7.190 +      <DataExecutionPrevention>
   7.191 +      </DataExecutionPrevention>
   7.192 +      <TargetMachine>MachineX64</TargetMachine>
   7.193 +    </Link>
   7.194 +  </ItemDefinitionGroup>
   7.195 +  <ItemGroup>
   7.196 +    <Reference Include="System">
   7.197 +      <CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
   7.198 +      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
   7.199 +    </Reference>
   7.200 +    <Reference Include="System.Data">
   7.201 +      <CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
   7.202 +      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
   7.203 +    </Reference>
   7.204 +    <Reference Include="System.Xml">
   7.205 +      <CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
   7.206 +      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
   7.207 +    </Reference>
   7.208 +  </ItemGroup>
   7.209 +  <ItemGroup>
   7.210 +    <ClCompile Include="AssemblyInfo.cpp" />
   7.211 +    <ClCompile Include="UserAccountControl.cpp" />
   7.212 +  </ItemGroup>
   7.213 +  <ItemGroup>
   7.214 +    <ClInclude Include="UserAccountControl.h" />
   7.215 +  </ItemGroup>
   7.216 +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   7.217 +  <ImportGroup Label="ExtensionTargets">
   7.218 +  </ImportGroup>
   7.219 +</Project>
   7.220 \ No newline at end of file
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/UacHelpers.CppLibrary/UserAccountControl.cpp	Mon Feb 02 12:51:06 2015 +0100
     8.3 @@ -0,0 +1,226 @@
     8.4 +#include "UserAccountControl.h"
     8.5 +
     8.6 +#include <windows.h>
     8.7 +#pragma comment (lib, "kernel32.lib")
     8.8 +#pragma comment (lib, "advapi32.lib")
     8.9 +
    8.10 +#include <vcclr.h>
    8.11 +#include <msclr\marshal.h>
    8.12 +#include <msclr\marshal_windows.h>
    8.13 +
    8.14 +using namespace msclr::interop;
    8.15 +
    8.16 +using namespace System::ComponentModel;
    8.17 +using namespace Microsoft::Win32;
    8.18 +
    8.19 +namespace UacHelpers {
    8.20 +
    8.21 +	Process^ UserAccountControl::CreateProcessAsAdmin(System::String^ exePath, System::String^ arguments)
    8.22 +    {
    8.23 +        ProcessStartInfo^ psi = gcnew ProcessStartInfo(exePath, arguments);
    8.24 +        psi->UseShellExecute = true;
    8.25 +        psi->Verb = "runas";
    8.26 +		return Process::Start(psi);
    8.27 +    }
    8.28 +
    8.29 +	Process^ UserAccountControl::CreateProcessAsStandardUser(System::String^ exePath, System::String^ arguments)
    8.30 +	{
    8.31 +		marshal_context context;
    8.32 +
    8.33 +		//If the current process is not elevated, then there's no reason to go through the hassle --
    8.34 +		//just use the standard System.Diagnostics.Process facilities.
    8.35 +		if (!IsCurrentProcessElevated)
    8.36 +		{
    8.37 +			return Process::Start(exePath, arguments);
    8.38 +		}
    8.39 +
    8.40 +		//The following implementation is roughly based on Aaron Margosis' post:
    8.41 +		//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
    8.42 +
    8.43 +		//Enable SeIncreaseQuotaPrivilege in this process.  (This requires administrative privileges.)
    8.44 +		HANDLE hProcessToken = NULL;
    8.45 +		if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hProcessToken))
    8.46 +		{
    8.47 +			throw gcnew Win32Exception(GetLastError());
    8.48 +		}
    8.49 +		else
    8.50 +		{
    8.51 +			TOKEN_PRIVILEGES tkp;
    8.52 +			tkp.PrivilegeCount = 1;
    8.53 +			LookupPrivilegeValueW(NULL, SE_INCREASE_QUOTA_NAME, &tkp.Privileges[0].Luid);
    8.54 +			tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    8.55 +			AdjustTokenPrivileges(hProcessToken, FALSE, &tkp, 0, NULL, NULL);
    8.56 +			DWORD dwLastErr = GetLastError();
    8.57 +			CloseHandle(hProcessToken);
    8.58 +			if (ERROR_SUCCESS != dwLastErr)
    8.59 +			{
    8.60 +				throw gcnew Win32Exception(dwLastErr);
    8.61 +			}
    8.62 +		}
    8.63 +
    8.64 +		//Get window handle representing the desktop shell.  This might not work if there is no shell window, or when
    8.65 +		//using a custom shell.  Also note that we're assuming that the shell is not running elevated.
    8.66 +		HWND hShellWnd = GetShellWindow();
    8.67 +		if (hShellWnd == NULL)
    8.68 +		{
    8.69 +			throw gcnew System::InvalidOperationException("Unable to locate shell window; you might be using a custom shell");
    8.70 +		}
    8.71 +
    8.72 +		//Get the ID of the desktop shell process.
    8.73 +		DWORD dwShellPID;
    8.74 +		GetWindowThreadProcessId(hShellWnd, &dwShellPID);
    8.75 +		if (dwShellPID == 0)
    8.76 +		{
    8.77 +			throw gcnew Win32Exception(GetLastError());
    8.78 +		}
    8.79 +
    8.80 +		//Open the desktop shell process in order to get the process token.
    8.81 +		HANDLE hShellProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwShellPID);
    8.82 +		if (hShellProcess == NULL)
    8.83 +		{
    8.84 +			throw gcnew Win32Exception(GetLastError());
    8.85 +		}
    8.86 +
    8.87 +		HANDLE hShellProcessToken = NULL;
    8.88 +		HANDLE hPrimaryToken = NULL;
    8.89 +		try
    8.90 +		{
    8.91 +			//Get the process token of the desktop shell.
    8.92 +			if (!OpenProcessToken(hShellProcess, TOKEN_DUPLICATE, &hShellProcessToken))
    8.93 +			{
    8.94 +				throw gcnew Win32Exception(GetLastError());
    8.95 +			}
    8.96 +
    8.97 +			//Duplicate the shell's process token to get a primary token.
    8.98 +			const DWORD dwTokenRights = TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID;
    8.99 +			if (!DuplicateTokenEx(hShellProcessToken, dwTokenRights, NULL, SecurityImpersonation, TokenPrimary, &hPrimaryToken))
   8.100 +			{
   8.101 +				throw gcnew Win32Exception(GetLastError());
   8.102 +			}
   8.103 +
   8.104 +			//Start the target process with the new token.
   8.105 +			STARTUPINFO si = {0}; si.cb = sizeof(si);
   8.106 +			PROCESS_INFORMATION pi = {0};
   8.107 +			if (!CreateProcessWithTokenW(hPrimaryToken, 0,
   8.108 +				context.marshal_as<LPCWSTR>(exePath), context.marshal_as<LPWSTR>(exePath + " " + arguments),
   8.109 +				0, NULL, NULL, &si, &pi))
   8.110 +			{
   8.111 +				throw gcnew Win32Exception(GetLastError());
   8.112 +			}
   8.113 +			CloseHandle(pi.hProcess);
   8.114 +			CloseHandle(pi.hThread);
   8.115 +
   8.116 +			return Process::GetProcessById(pi.dwProcessId);
   8.117 +		}
   8.118 +		finally
   8.119 +		{
   8.120 +			if (hShellProcessToken != NULL)
   8.121 +				CloseHandle(hShellProcessToken);
   8.122 +
   8.123 +			if (hPrimaryToken != NULL)
   8.124 +				CloseHandle(hPrimaryToken);
   8.125 +
   8.126 +			if (hShellProcess != NULL)
   8.127 +				CloseHandle(hShellProcess);
   8.128 +		}
   8.129 +	}
   8.130 +
   8.131 +	bool UserAccountControl::IsUserAdmin::get()
   8.132 +	{
   8.133 +		if (UserAccountControl::IsUacEnabled)
   8.134 +			return GetProcessTokenElevationType() != TokenElevationTypeDefault;	//split token
   8.135 +
   8.136 +		//If UAC is off, we can't rely on the token; check for Admin group.
   8.137 +		return WindowsPrincipal(WindowsIdentity::GetCurrent()).IsInRole("Administrators");
   8.138 +	}
   8.139 +
   8.140 +	bool UserAccountControl::IsUacEnabled::get()
   8.141 +	{
   8.142 +		//Check the HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System\EnableLUA registry value.
   8.143 +		RegistryKey^ key = Registry::LocalMachine->OpenSubKey(UacRegistryKey, false);
   8.144 +		return key->GetValue(UacRegistryValue)->Equals(1);
   8.145 +    }
   8.146 +
   8.147 +	void UserAccountControl::DisableUac()
   8.148 +	{
   8.149 +		SetUacRegistryValue(false);
   8.150 +	}
   8.151 +
   8.152 +	void UserAccountControl::DisableUacAndRestartWindows()
   8.153 +	{
   8.154 +		DisableUac();
   8.155 +		RestartWindows();
   8.156 +	}
   8.157 +
   8.158 +	void UserAccountControl::EnableUac()
   8.159 +	{
   8.160 +		SetUacRegistryValue(true);
   8.161 +	}
   8.162 +
   8.163 +	void UserAccountControl::EnableUacAndRestartWindows()
   8.164 +	{
   8.165 +		EnableUac();
   8.166 +		RestartWindows();
   8.167 +	}
   8.168 +
   8.169 +	bool UserAccountControl::IsCurrentProcessElevated::get()
   8.170 +	{
   8.171 +		return GetProcessTokenElevationType() == TokenElevationTypeFull;	//elevated
   8.172 +	}
   8.173 +
   8.174 +	bool UserAccountControl::IsCurrentProcessVirtualized::get()
   8.175 +	{
   8.176 +		HANDLE hToken;
   8.177 +        try
   8.178 +        {
   8.179 +            if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
   8.180 +				throw gcnew Win32Exception(GetLastError());
   8.181 +
   8.182 +            DWORD virtualizationEnabled;
   8.183 +			DWORD dwSize;
   8.184 +			if (!GetTokenInformation(hToken, TokenVirtualizationEnabled, &virtualizationEnabled, sizeof(virtualizationEnabled), &dwSize))
   8.185 +                throw gcnew Win32Exception(GetLastError());
   8.186 +
   8.187 +			return virtualizationEnabled != 0;
   8.188 +        }
   8.189 +        finally
   8.190 +        {
   8.191 +            CloseHandle(hToken);
   8.192 +        }
   8.193 +	}
   8.194 +
   8.195 +	int UserAccountControl::GetProcessTokenElevationType()
   8.196 +	{
   8.197 +		HANDLE hToken;
   8.198 +        try
   8.199 +        {
   8.200 +            if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
   8.201 +				throw gcnew Win32Exception(GetLastError());
   8.202 +
   8.203 +            TOKEN_ELEVATION_TYPE elevationType;
   8.204 +			DWORD dwSize;
   8.205 +            if (!GetTokenInformation(hToken, TokenElevationType, &elevationType, sizeof(elevationType), &dwSize))
   8.206 +                throw gcnew Win32Exception(GetLastError());
   8.207 +
   8.208 +			return elevationType;
   8.209 +        }
   8.210 +        finally
   8.211 +        {
   8.212 +            CloseHandle(hToken);
   8.213 +        }
   8.214 +	}
   8.215 +
   8.216 +	void UserAccountControl::SetUacRegistryValue(bool enabled)
   8.217 +	{
   8.218 +		RegistryKey^ key = Registry::LocalMachine->OpenSubKey(UacRegistryKey, true);
   8.219 +		key->SetValue(UacRegistryValue, enabled ? 1 : 0);
   8.220 +	}
   8.221 +
   8.222 +	void UserAccountControl::RestartWindows()
   8.223 +	{
   8.224 +		InitiateSystemShutdownEx(NULL, NULL, 0/*Timeout*/,
   8.225 +								 TRUE/*ForceAppsClosed*/, TRUE/*RebootAfterShutdown*/,
   8.226 +								 SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_RECONFIG | SHTDN_REASON_FLAG_PLANNED);
   8.227 +		//This shutdown flag corresponds to: "Operating System: Reconfiguration (Planned)".
   8.228 +	}
   8.229 +}
   8.230 \ No newline at end of file
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/UacHelpers.CppLibrary/UserAccountControl.h	Mon Feb 02 12:51:06 2015 +0100
     9.3 @@ -0,0 +1,133 @@
     9.4 +// UacHelpers.CppLibrary.h
     9.5 +
     9.6 +#pragma once
     9.7 +
     9.8 +using namespace System::Diagnostics;
     9.9 +using namespace System::Security::Principal;
    9.10 +
    9.11 +namespace UacHelpers {
    9.12 +
    9.13 +	///<summary>
    9.14 +	///Provides facilities for enabling and disabling User Account Control (UAC),
    9.15 +	///determining elevation and virtualization status, and launching a process
    9.16 +	///under elevated credentials.
    9.17 +	///</summary>
    9.18 +	///<remarks>
    9.19 +	///Note that there's a delicate scenario where the registry key has already been
    9.20 +	///changed, but the user has not logged off yet so the token hasn't been filtered.
    9.21 +	///In that case, we will think that UAC is on but the user is not an admin (because
    9.22 +	///the token is not a split token).
    9.23 +	///</remarks>
    9.24 +	public ref class UserAccountControl abstract sealed
    9.25 +	{
    9.26 +	public:
    9.27 +		///<summary>
    9.28 +		///Returns <b>true</b> if the current user has administrator privileges.
    9.29 +		///</summary>
    9.30 +		///<remarks>
    9.31 +		///If UAC is on, then this property will return <b>true</b> even if the
    9.32 +		///current process is not running elevated.  If UAC is off, then this
    9.33 +		///property will return <b>true</b> if the user is part of the built-in
    9.34 +		///<i>Administrators</i> group.
    9.35 +		///</remarks>
    9.36 +		static property bool IsUserAdmin
    9.37 +        {
    9.38 +            bool get();
    9.39 +        }
    9.40 +
    9.41 +		///<summary>
    9.42 +		///Returns <b>true</b> if User Account Control (UAC) is enabled on
    9.43 +		///this machine.
    9.44 +		///</summary>
    9.45 +		///<remarks>
    9.46 +		///This value is obtained by checking the LUA registry key.  It is possible
    9.47 +		///that the user has not restarted the machine after enabling/disabling UAC.
    9.48 +		///In that case, the value of the registry key does not reflect the true state
    9.49 +		///of affairs.  It is possible to devise a custom solution that would provide
    9.50 +		///a mechanism for tracking whether a restart occurred since UAC settings were
    9.51 +		///changed (using the RunOnce mechanism, temporary files, or volatile registry keys).
    9.52 +		///</remarks>
    9.53 +		static property bool IsUacEnabled
    9.54 +        {
    9.55 +            bool get();
    9.56 +        }
    9.57 +
    9.58 +		///<summary>
    9.59 +		///Returns <b>true</b> if the current process is using UAC virtualization.
    9.60 +		///</summary>
    9.61 +		///<remarks>
    9.62 +		///Under UAC virtualization, file system and registry accesses to specific
    9.63 +		///locations performed by an application are redirected to provide backwards-
    9.64 +		///compatibility.  64-bit applications or applications that have an associated
    9.65 +		///manifest do not enjoy UAC virtualization because they are assumed to be
    9.66 +		///compatible with Vista and UAC.
    9.67 +		///</remarks>
    9.68 +        static property bool IsCurrentProcessVirtualized
    9.69 +        {
    9.70 +            bool get();
    9.71 +        }
    9.72 +
    9.73 +		///<summary>
    9.74 +		///Returns <b>true</b> if the current process is elevated, i.e. if the process
    9.75 +		///went through an elevation consent phase.
    9.76 +		///</summary>
    9.77 +		///<remarks>
    9.78 +		///This property will return <b>false</b> if UAC is disabled and the process
    9.79 +		///is running as admin.  It only determines whether the process went through
    9.80 +		///the elevation procedure.
    9.81 +		///</remarks>
    9.82 +		static property bool IsCurrentProcessElevated
    9.83 +        {
    9.84 +            bool get();
    9.85 +        }
    9.86 +
    9.87 +		///<summary>
    9.88 +		///Disables User Account Control by changing the LUA registry key.
    9.89 +		///The changes do not have effect until the system is restarted.
    9.90 +		///</summary>
    9.91 +		static void DisableUac();
    9.92 +		
    9.93 +		///<summary>
    9.94 +		///Disables User Account Control and restarts the system.
    9.95 +		///</summary>
    9.96 +		static void DisableUacAndRestartWindows();
    9.97 +
    9.98 +		///<summary>
    9.99 +		///Enables User Account Control by changing the LUA registry key.
   9.100 +		///The changes do not have effect until the system is restarted.
   9.101 +		///</summary>
   9.102 +		static void EnableUac();
   9.103 +
   9.104 +		///<summary>
   9.105 +		///Enables User Account Control and restarts the system.
   9.106 +		///</summary>
   9.107 +		static void EnableUacAndRestartWindows();
   9.108 +
   9.109 +		///<summary>
   9.110 +		///Creates a process under the elevated token, regardless of UAC settings
   9.111 +		///or the manifest associated with that process.
   9.112 +		///</summary>
   9.113 +		///<param name="exePath">The path to the executable file.</param>
   9.114 +		///<param name="arguments">The command-line arguments to pass to the process.</param>
   9.115 +		///<returns>A <see cref="Process"/> object representing the newly created process.</returns>
   9.116 +		static Process^ CreateProcessAsAdmin(System::String^ exePath, System::String^ arguments);
   9.117 +
   9.118 +		///<summary>
   9.119 +		///Creates a process under the standard user if the current process is elevated.  The identity
   9.120 +		///of the standard user is determined by retrieving the user token of the currently running Explorer
   9.121 +		//(shell) process.  If the current process is not elevated, the standard user is used.
   9.122 +		///</summary>
   9.123 +		///<param name="exePath">The path to the executable file.</param>
   9.124 +		///<param name="arguments">The command-line arguments to pass to the process.</param>
   9.125 +		///<returns>A <see cref="Process"/> object representing the newly created process.</returns>
   9.126 +		static Process^ CreateProcessAsStandardUser(System::String^ exePath, System::String^ arguments);
   9.127 +
   9.128 +	private:
   9.129 +		static int GetProcessTokenElevationType();
   9.130 +		static void SetUacRegistryValue(bool enable);
   9.131 +		static void RestartWindows();
   9.132 +
   9.133 +		static System::String^ UacRegistryKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
   9.134 +		static System::String^ UacRegistryValue = "EnableLUA";
   9.135 +	};
   9.136 +}	// end namespace UacHelpers
   9.137 \ No newline at end of file