Adding FrontView menu with persistent options for time display and packed mode.
Adding support for editorconfig and rebracer.
1 #include "UserAccountControl.h"
4 #pragma comment (lib, "kernel32.lib")
5 #pragma comment (lib, "advapi32.lib")
8 #include <msclr\marshal.h>
9 #include <msclr\marshal_windows.h>
11 using namespace msclr::interop;
13 using namespace System::ComponentModel;
14 using namespace Microsoft::Win32;
16 namespace UacHelpers {
18 Process^ UserAccountControl::CreateProcessAsAdmin(System::String^ exePath, System::String^ arguments)
20 ProcessStartInfo^ psi = gcnew ProcessStartInfo(exePath, arguments);
21 psi->UseShellExecute = true;
23 return Process::Start(psi);
26 Process^ UserAccountControl::CreateProcessAsStandardUser(System::String^ exePath, System::String^ arguments)
28 marshal_context context;
30 //If the current process is not elevated, then there's no reason to go through the hassle --
31 //just use the standard System.Diagnostics.Process facilities.
32 if (!IsCurrentProcessElevated)
34 return Process::Start(exePath, arguments);
37 //The following implementation is roughly based on Aaron Margosis' post:
38 //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
40 //Enable SeIncreaseQuotaPrivilege in this process. (This requires administrative privileges.)
41 HANDLE hProcessToken = NULL;
42 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hProcessToken))
44 throw gcnew Win32Exception(GetLastError());
49 tkp.PrivilegeCount = 1;
50 LookupPrivilegeValueW(NULL, SE_INCREASE_QUOTA_NAME, &tkp.Privileges[0].Luid);
51 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
52 AdjustTokenPrivileges(hProcessToken, FALSE, &tkp, 0, NULL, NULL);
53 DWORD dwLastErr = GetLastError();
54 CloseHandle(hProcessToken);
55 if (ERROR_SUCCESS != dwLastErr)
57 throw gcnew Win32Exception(dwLastErr);
61 //Get window handle representing the desktop shell. This might not work if there is no shell window, or when
62 //using a custom shell. Also note that we're assuming that the shell is not running elevated.
63 HWND hShellWnd = GetShellWindow();
64 if (hShellWnd == NULL)
66 throw gcnew System::InvalidOperationException("Unable to locate shell window; you might be using a custom shell");
69 //Get the ID of the desktop shell process.
71 GetWindowThreadProcessId(hShellWnd, &dwShellPID);
74 throw gcnew Win32Exception(GetLastError());
77 //Open the desktop shell process in order to get the process token.
78 HANDLE hShellProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwShellPID);
79 if (hShellProcess == NULL)
81 throw gcnew Win32Exception(GetLastError());
84 HANDLE hShellProcessToken = NULL;
85 HANDLE hPrimaryToken = NULL;
88 //Get the process token of the desktop shell.
89 if (!OpenProcessToken(hShellProcess, TOKEN_DUPLICATE, &hShellProcessToken))
91 throw gcnew Win32Exception(GetLastError());
94 //Duplicate the shell's process token to get a primary token.
95 const DWORD dwTokenRights = TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID;
96 if (!DuplicateTokenEx(hShellProcessToken, dwTokenRights, NULL, SecurityImpersonation, TokenPrimary, &hPrimaryToken))
98 throw gcnew Win32Exception(GetLastError());
101 //Start the target process with the new token.
102 STARTUPINFO si = {0}; si.cb = sizeof(si);
103 PROCESS_INFORMATION pi = {0};
104 if (!CreateProcessWithTokenW(hPrimaryToken, 0,
105 context.marshal_as<LPCWSTR>(exePath), context.marshal_as<LPWSTR>(exePath + " " + arguments),
106 0, NULL, NULL, &si, &pi))
108 throw gcnew Win32Exception(GetLastError());
110 CloseHandle(pi.hProcess);
111 CloseHandle(pi.hThread);
113 return Process::GetProcessById(pi.dwProcessId);
117 if (hShellProcessToken != NULL)
118 CloseHandle(hShellProcessToken);
120 if (hPrimaryToken != NULL)
121 CloseHandle(hPrimaryToken);
123 if (hShellProcess != NULL)
124 CloseHandle(hShellProcess);
128 bool UserAccountControl::IsUserAdmin::get()
130 if (UserAccountControl::IsUacEnabled)
131 return GetProcessTokenElevationType() != TokenElevationTypeDefault; //split token
133 //If UAC is off, we can't rely on the token; check for Admin group.
134 return WindowsPrincipal(WindowsIdentity::GetCurrent()).IsInRole("Administrators");
137 bool UserAccountControl::IsUacEnabled::get()
139 //Check the HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System\EnableLUA registry value.
140 RegistryKey^ key = Registry::LocalMachine->OpenSubKey(UacRegistryKey, false);
141 return key->GetValue(UacRegistryValue)->Equals(1);
144 void UserAccountControl::DisableUac()
146 SetUacRegistryValue(false);
149 void UserAccountControl::DisableUacAndRestartWindows()
155 void UserAccountControl::EnableUac()
157 SetUacRegistryValue(true);
160 void UserAccountControl::EnableUacAndRestartWindows()
166 bool UserAccountControl::IsCurrentProcessElevated::get()
168 return GetProcessTokenElevationType() == TokenElevationTypeFull; //elevated
171 bool UserAccountControl::IsCurrentProcessVirtualized::get()
176 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
177 throw gcnew Win32Exception(GetLastError());
179 DWORD virtualizationEnabled;
181 if (!GetTokenInformation(hToken, TokenVirtualizationEnabled, &virtualizationEnabled, sizeof(virtualizationEnabled), &dwSize))
182 throw gcnew Win32Exception(GetLastError());
184 return virtualizationEnabled != 0;
192 int UserAccountControl::GetProcessTokenElevationType()
197 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
198 throw gcnew Win32Exception(GetLastError());
200 TOKEN_ELEVATION_TYPE elevationType;
202 if (!GetTokenInformation(hToken, TokenElevationType, &elevationType, sizeof(elevationType), &dwSize))
203 throw gcnew Win32Exception(GetLastError());
205 return elevationType;
213 void UserAccountControl::SetUacRegistryValue(bool enabled)
215 RegistryKey^ key = Registry::LocalMachine->OpenSubKey(UacRegistryKey, true);
216 key->SetValue(UacRegistryValue, enabled ? 1 : 0);
219 void UserAccountControl::RestartWindows()
221 InitiateSystemShutdownEx(NULL, NULL, 0/*Timeout*/,
222 TRUE/*ForceAppsClosed*/, TRUE/*RebootAfterShutdown*/,
223 SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_RECONFIG | SHTDN_REASON_FLAG_PLANNED);
224 //This shutdown flag corresponds to: "Operating System: Reconfiguration (Planned)".