{"id":110336,"date":"2024-10-03T07:00:00","date_gmt":"2024-10-03T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=110336"},"modified":"2024-10-03T08:42:55","modified_gmt":"2024-10-03T15:42:55","slug":"20241003-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20241003-00\/?p=110336","title":{"rendered":"How can I detect whether the user is running as an elevated administrator (as opposed to a natural administrator)?"},"content":{"rendered":"<p>When a user with administrator privileges signs in, the User Account Control (UAC) feature signs in the administrator with a so-called &#8220;split token&#8221;, in which the user operates in Clark Kent mode: Although they have latent administrator privileges, the administrative powers in the token are disabled. To exercise those administrative powers, the user must elevate their token.<\/p>\n<p>A customer wanted to discourage users from running their program elevated, but they also didn&#8217;t want to scold users who were running with UAC disabled (such as on Windows Server), since those users had no opportunity to de-elevate.<\/p>\n<p>The way to inspect whether your token is split, and if so whether you have the non-administrator (&#8220;limited&#8221;) version or the administrator (&#8220;full&#8221;) version is to ask for the token&#8217;s elevation type.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>\u00a0<\/th>\n<th>Standard user<\/th>\n<th>Administrative user<\/th>\n<\/tr>\n<tr>\n<th>UAC disabled<\/th>\n<td>TokenElevationTypeDefault<\/td>\n<td>TokenElevationTypeDefault<\/td>\n<\/tr>\n<tr>\n<th>UAC enabled, not elevated<\/th>\n<td>TokenElevationTypeDefault<\/td>\n<td>TokenElevationTypeLimited<\/td>\n<\/tr>\n<tr>\n<th>UAC enabled, elevated<\/th>\n<td>N\/A<\/td>\n<td>TokenElevationTypeFull<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Non-administrative users cannot split their token (there being no administrator privileges to split out), and administrative users cannot split their tokens if UAC is disabled.<\/p>\n<p>If you are looking for &#8220;users who manually elevated&#8221;, then you can consult the table above and see that a token elevation type of <code>Full<\/code> exactly identifies the &#8220;Administrative user, UAC enabled, elevated&#8221; box.<\/p>\n<pre>bool IsManuallyElevatedViaUAC()\r\n{\r\n    TOKEN_ELEVATION_TYPE type;\r\n    DWORD actual;\r\n    if (!GetTokenInformation(\r\n            GetCurrentProcessToken(),\r\n            TokenElevationType,\r\n            &amp;type,\r\n            sizeof(type),\r\n            &amp;actual)) {\r\n        \/\/ insert your favorite error handling here\r\n        throw_error(GetLastError());\r\n    }\r\n    return type == TokenElevationTypeFull;\r\n}\r\n<\/pre>\n<p>We learned about <code>Get\u00adCurrent\u00adProcess\u00adToken()<\/code> <a title=\"Additional helpful pseudo-handles: The process token, the thread token, and the effective token\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20210105-00\/?p=104667\"> a little while ago<\/a>. This is a convenient pseudo-handle that refers to the current process. We ask for the current process&#8217;s token&#8217;s elevation type, and if that is <code>Full<\/code>, then we are in that box in the bottom right corner.<\/p>\n<p>The helpers in the <code>token_helpers.h<\/code> header in the Windows Implementation Library (wil) turn this into a one-line function.<\/p>\n<pre>bool IsManuallyElevatedViaUAC()\r\n{\r\n    return wil::get_token_information&lt;TOKEN_ELEVATION_TYPE&gt;(\r\n            GetCurrentProcessToken()) == TokenElevationTypeFull;\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>You can ask for the elevation type.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-110336","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>You can ask for the elevation type.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/110336","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=110336"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/110336\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=110336"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=110336"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=110336"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}