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.
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