(This article was originally published at the TweakUAC site.)
Version 2.1 (Updated 2008-Feb-24)
While porting our applications to Windows Vista, we had to overcome quite a few challenges related to the new security features of Vista (such as the User Account Control). We decided to make public several functions we’ve developed, to make it easier for other developers to solve such problems, too.
The functions we’ve developed are written in C++ (using Microsoft Visual Studio 2005), and packaged in the file VistaTools.cxx. Please note:
THIS CODE AND INFORMATION IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
TERMS OF USE: You are free to use this file in any way you like, for both the commercial and non-commercial purposes, royalty-free, AS LONG AS you agree with the warranty disclaimer above, EXCEPT that you may not remove or modify the warranty statement and the copyright notice the file contains.
The file VistaTools.cxx contains the following functions:
BOOL IsVista();
Use IsVista() to determine whether the current process is running under Windows Vista (or a later version of Windows, whatever it will be).
Return Values:
If the function succeeds, and the current version of Windows is Vista or later, the return value is TRUE.
If the function fails, or if the current version of Windows is older than Vista (that is, if it is Windows XP, Windows 2000, Windows Server 2003, Windows 98, etc.) the return value is FALSE.
BOOL IsWow64();
Use IsWow64() to determine whether the current 32-bit process is running under 64-bit Windows (Vista or XP).
Return Values:
If the function succeeds, and the current version of Windows is x64, the return value is TRUE.
If the function fails, or if the current version of Windows is 32-bit, the return value is FALSE.
NOTE: While this function is not Vista specific (it works under XP as well), we include it here to be able to prevent execution of the 32-bit code under 64-bit Windows, when required.
HRESULT
GetElevationType( __out TOKEN_ELEVATION_TYPE * ptet );
Use GetElevationType() to determine the elevation type of the current process.
Parameters:
ptet – [out] Pointer to a variable that receives the elevation type of the current process.
The possible values are:
TokenElevationTypeDefault – User is not using a “split” token. This value indicates that either UAC is disabled, or the process is started by a standard user (not a member of the Administrators group).
The following two values can be returned only if both the UAC is enabled and the user is a member of the Administrator’s group (that is, the user has a “split” token):
TokenElevationTypeFull – the process is running elevated.
TokenElevationTypeLimited – the process is not running elevated.
Return Values:
If the function succeeds, the return value is S_OK. If the function fails, the return value is E_FAIL. To get extended error information, call GetLastError().
HRESULT
IsElevated( __out_opt BOOL * pbElevated = NULL );
Use IsElevated() to determine whether the current process is elevated or not.
Parameters:
pbElevated – [out] [optional] Pointer to a BOOL variable that, if non-NULL, receives the result.
The possible values are:
TRUE – the current process is elevated. This value indicates that either UAC is enabled, and the process was elevated by the administrator, or that UAC is disabled and the process was started by a user who is a member of the Administrators group.
FALSE – the current process is not elevated (limited). This value indicates that either UAC is enabled, and the process was started normally, without the elevation, or that UAC is disabled and the process was started by a standard user.
Return Values
If the function succeeds, and the current process is elevated, the return value is S_OK. If the function succeeds, and the current process is not elevated, the return value is S_FALSE. If the function fails, the return value is E_FAIL. To get extended error information, call GetLastError().
BOOL
RunElevated(
__in HWND hwnd,
__in LPCTSTR pszPath,
__in_opt LPCTSTR pszParameters = NULL,
__in_opt LPCTSTR pszDirectory = NULL );
Use RunElevated() to start an elevated process. This function calls ShellExecEx() with the verb “runas” to start the elevated process.
Parameters:
hwnd – [in] Window handle to any message boxes that the system might produce while executing this function.
pszPath -[in] Address of a null-terminated string that specifies the name of the executable file that should be used to start the process.
pszParameters – [in] [optional] Address of a null-terminated string that contains the command-line parameters for the process. If NULL, no parameters are passed to the process.
pszDirectory – [in] [optional] Address of a null-terminated string that specifies the name of the working directory. If NULL, the current directory is used as the working directory.
Return Values
If the function succeeds, the return value is TRUE. If the function fails, the return value is FALSE. To get extended error information, call GetLastError().
NOTE: This function will start a process elevated no matter which attribute (asInvoker, highestAvailable, or requireAdministrator) is specified in its manifest, and even if there is no such attribute at all.
BOOL
RunNonElevated(
__in HWND hwnd,
__in LPCTSTR pszPath,
__in_opt LPCTSTR pszParameters = NULL,
__in_opt LPCTSTR pszDirectory = NULL );
Use RunNonElevated() to start a non-elevated process. If the current process is not elevated, it calls ShellExecuteEx() to start the new process. If the current process is elevated, it injects itself into the (non-elevated) shell process, and starts a non-elevated process from there.
Parameters:
hwnd – [in] Window handle to any message boxes that the system might produce while executing this function.
pszPath – [in] Address of a null-terminated string that specifies the executable file that should be used to start the process.
pszParameters – [in] [optional] Address of a null-terminated string that contains the command-line parameters for the process. If NULL, no parameters are passed to the process.
pszDirectory – [in] [optional] Address of a null-terminated string that specifies the name of the working directory. If NULL, the current directory is used as the working directory.
Return Values
If the function succeeds, the return value is TRUE. If the function fails, the return value is FALSE. To get extended error information, call GetLastError().
NOTE: For this function to work, the application must be marked with the asInvoker or highestAvailable attributes in its manifest. If the executable to be started is marked as requireAdministrator, it will be started elevated!
How to use the file VistaTools.cxx
Make sure you have the latest Windows SDK (see msdn.microsoft.com for more information) or this file may not compile!
This file contains the Win32 stuff only, it can be used with or without other frameworks, such as MFC, ATL, etc.
This is a “combo” file that contains both the declarations (usually placed in the .h files) as well as the definitions (usually placed in the .cpp files) of the functions. To get the declarations only, include it as you would any .h file. To get both the declarations and definitions, define IMPLEMENT_VISTA_TOOLS before including the file. (The latter should be done once and only once per project).
For example, to use this file in a MFC project, create a file MyVistaTools.cpp that contains the following:
#include “StdAfx.h”
#define IMPLEMENT_VISTA_TOOLS
#include “VistaTools.cxx”
This would make MyVistaTools.cpp the implementation file of the VistaTools function for your project. Don’t forget to add MyVistaTools.cpp to your project! You can add VistaTools.cxx to your project, as well, but it should be excluded from the build, because its contents is compiled when it is included in MyVistaTools.cpp file with IMPLEMENT_VISTA_TOOLS defined, as shown above.
In other files of your project, where you need to use the functions declared in VistaTools.cxx, include it without defining IMPLEMENT_VISTA_TOOLS, just as you would include a .h file:
#include “VistaTools.cxx”
To use the function RunNonElevated(), this file must be compiled into a DLL. In such a case, define DLL_EXPORTS when compiling the DLL, and do not define DLL_EXPORTS when compiling the projects linking to the DLL.
If you don’t need to use RunNonElevated(), then this file may be a part of an EXE project. In such a case, define DONTWANT_RunNonElevated and NO_DLL_IMPORTS to make this file compile properly.
For an example of using VistaTools.cxx in a real project, see VistaElevator 2.0.
How do I download the file VistaTools.cxx?
Simply right-click on the link below and choose the Save target as command (or similar) to save it to your hard drive:
Download VistaTools.cxx
If you use this file in your own project, an acknowledgment will be appreciated, although it’s not required.
Enjoy!
Did you know? Our USB Encryption Software can protect any USB flash drive or any other external drive with a password and strong encryption. Try it free for 30 days! Read more…
February 17th, 2007 at 10:10 pm
I believe that this is because there is an NTFS fork on the directory that says that anything in that directory shouldn’t be trusted. This is similar to XP in how it knows that a file was downloaded recently by IE.
February 19th, 2007 at 6:06 pm
Hi Andrei,
Have a quick question about TweakUAC. Can I suppress UAC messages only for a single application using TWeak? Or does it suppress all UAC messages, system wide?
Thanks.
Regards,
Soumitra
Hi Soumitra,
> Can I suppress UAC messages only for a single application using TWeak?
No, it’s impossible.
> Or does it suppress all UAC messages, system wide?
Yes, that’s how it works.
Andrei.
February 20th, 2007 at 11:22 am
Hi Myria,
> I believe that this is because there is an NTFS fork on the directory that says that anything in that directory shouldn’t be trusted. This is similar to XP in how it knows that a file was downloaded recently by IE.
It may very well be so, but it does not make it any less of a bug. If a file contains a valid digital signature, Windows should not misrepresent it as coming from an unidentified publisher.
Andrei.
February 26th, 2007 at 1:09 pm
How did you take a screenshot of the UAC? I can’t get Print Screen to copy it to the clipboard, and the snipping tool isn’t working either.
February 26th, 2007 at 9:55 pm
Hi Chris,
> How did you take a screenshot of the UAC? I can’t get Print Screen to copy it to the clipboard, and the snipping tool isn’t working either.
Those tools don’t work because UAC displays its messages on the secure desktop, to which the “normal” user tools have no access. To solve this problem, I’ve changed the local security policy to make the UAC prompts to appear on the user’s desktop. After that, I used the regular Print Screen key to capture the screenshots.
Hope this helps,
Andrei.
March 4th, 2007 at 2:58 am
Hi Andrei,
I sell software to a *very* non-technical customer base. My setup procedure includes installation of an .ocx file into the \windows\system32 folder and registration of it using regsvr32. In order to copy anything into the \windows\system32 folder under Vista I have to turn off UAC. I would like to be able to do this automatically, programmatically, so I don’t have to make my users mess with UAC. I’d like to be able to turn off UAC for a second or two programmatically, then turn it back on. Will your software enable me to do that?
Thanks
March 4th, 2007 at 11:42 am
Hi Matthew,
> I’d like to be able to turn off UAC for a second or two programmatically, then turn it back on.
Unfortunately it’s impossible: if you enable or disable the UAC, Windows must be restarted before the change would have take effect.
To solve your problem:
> In order to copy anything into the \windows\system32 folder under Vista I have to turn off UAC.
It looks like your setup process is executing non-elevated, that’s why it cannot do that. You may want to try to start it elevated and see if it would have solved the problem without turning off the UAC.
HTH
Andrei.
March 25th, 2007 at 10:24 am
don’t use TweakUAC because this program makes your Vista unsafe!
March 29th, 2007 at 10:30 pm
> How are you supposed to make the decision whether to trust a certain program or not if UAC does not provide you with the correct information? (Nevermind, it’s a rhetorical question).
The answer is you are not. A guest should not be allowed to make any decision about installing software. If you log on as a valid user, the prompt works just fine. If you log on as a guest, you shouldn’t be installing software, so any dire warning is fine.
Yes, this might be unintended behavior (or perhaps it is not), but its impact is null.
March 31st, 2007 at 4:47 pm
Hi Herbys, you wrote:
> The answer is you are not. A guest should not be allowed to make any decision about installing software.
Sorry, but you are missing the point: the UAC displays this information for the _administrator_ to use and to make a decision, not for the guest user. The administrator is supposed to review the information and enter his or her password to approve the action. Take a look at the screenshot and see for yourself.
> If you log on as a guest, you shouldn’t be installing software
Why shouldn’t I? What if I want to install a program for use by the guests only? For example, I use only one web browser (IE), but I never know what browser a guest may want to use. So, being a good host I want to install also Firefox and Opera, but I don’t want them to clutter my desktop, etc., I want them to be used by the guests only. To achieve that, I would log in to the guest account and install the additional browsers from there.
> so any dire warning is fine.
Wrong.
> Yes, this might be unintended behavior (or perhaps it is not), but its impact is null.
May be, may be not. In any case, it does not make it any less of a bug!
April 10th, 2007 at 9:28 pm
Is there any plan to adapt your program into a Control Panel Applet? I think that would be very clever.
April 11th, 2007 at 9:07 am
Hi Timothy, you wrote:
> Is there any plan to adapt your program into a Control Panel Applet?
No, we don’t have such plans at this time, sorry.
June 18th, 2007 at 9:19 pm
Anyone know why Vista won’t let me rename any new folder?
The permissions are all checked for me as administrator, still I get an error message, “folder does not exist”. I can put things in folder and move it, but can’t rename it?
January 29th, 2008 at 9:46 am
To be honest, I have always thought that digitally signing was merely a way of generating more revenue. It doesn’t offer you any more security and windows will always moan at you regardless of an application having a signature or not.
Even if your application has the “all powerful” and completely unnecessary Windows Logo certification, it still offers nothing to you as a user other than the reassurance that the person/s developing the software has allot of spare cash.
February 24th, 2008 at 10:34 am
Bob Said:
> To be honest, I have always thought that digitally signing was merely a way of generating more revenue.
I have to agree. I’ve heard the argument of how it’s all designed to protect users from malicious software, and that’s all well and good as far as that goes — but since Vista, and most mobile OSes, don’t offer a way for users to say “okay, I understand the risk, I accept full responsibility, please go ahead and run this unsigned application without restrictions, and never bother me again when I try to run this application”… That makes it pretty clear it’s just a racket initiated by VeriSign and the like, and happily endorsed by Microsoft.
May 17th, 2008 at 9:03 am
This is not a bug.
The first screen shot shows that Windows doesn’t trust the identity contained in the certificate. In other words, “I can read this, but I don’t know if I should trust the person who wrote it.”
The second screen shot just shows that the certificate is well-formed, that Windows can understand the information contained within it. It says nothing about what Windows will do with that information.
Who did you did you pay to sign the certificate for you? If they’re not someone with a well-established reputation, then I don’t WANT my computer to automatically trust them.
It’s just like how web browsers automatically trust SSL certificates signed by Thawte or Verisign, but will ask you before accepting a certificate from Andy’s Shady Overnight Certificate Company. As always, it’s a balancing act between usability and security.
May 17th, 2008 at 10:04 am
Andrew, you wrote:
> This is not a bug.
OK, there is a fine line between a bug and a feature, let’s assume for a moment that it’s a feature rather than a bug. If so, what benefit is this feature supposed to provide? As the second screen shows, the file is digitally signed, and Vista can detect that. Yet, it shows the publisher as “unidentified” on the first screen. Note also (as I mentioned in the post), that if you move the file to one a few specific folders (such as C:/Program files), Vista would magically begin to recognize the publisher. Move the file to some other folder, and it’s unidentified again.
If you can explain why they designed it that way, I would agree with you. Until then, it’s a bug. Guilty until proven innocent!
> Who did you pay to sign the certificate for you?
That particular file was signed with a Verisign certificate, but the same problem occurs with _any_ file, signed with _any_ certificate. Try it yourself and you will see.
June 1st, 2008 at 12:53 pm
I think that it occurs because of IE7 protected mode – see http://victor-youngun.blogspot.com/2008/03/internet-explorer-7-protected-mode-vs.html, it’s a guide to run firefox in protected mode, and this explains very good how the protected mode works… the prompt is because the “Download” Folder is a protected folder (level “low”) and I think it only displays at the guest, because Windows forces UAC to display certificate in normal user mode in “low” level folders, but NOT for the MUCH MORE RESTRICTED “guest” account. This would be my explanaition.
It doesn’t mean that I like it how Microsoft handels this but this would eventually explain WHY the warning appears sometimes and sometimes not.
June 1st, 2008 at 12:55 pm
sorry, in my last post there is a comma in the link, the correct link is:
http://victor-youngun.blogspot.com/2008/03/internet-explorer-7-protected-mode-vs.html
June 3rd, 2008 at 7:16 pm
Farthen: thank you for the information and explanation!