Microsoft & .NETVisual C#Vista User Access Control and Visual C++

Vista User Access Control and Visual C++

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Windows Vista introduces a new security concept called User Access Control (UAC), where local administrators have two access tokens one representing the privileges of a normal user and the other holding the elevated privileges of the local administrator account. By default, an application will run using the lower-privileged token, and this can cause problems if the application attempts an operation that requires the privileges of the local administrator. Windows Vista has various built-in mechanisms that are designed to minimize unintended problems caused by UAC, but there are scenarios where the UAC-handling strategies of Vista may cause unexpected behavior. This article covers these scenarios, and how Visual C++ developers can deal with them.

Microsoft has been encouraging users to stop running as local administrators for a long time, and this push is reliant on applications that run effectively when not executed under the local administrator account. There are a number of operations that will not work when a user is not running as a local administrator writing to the Program Files directory and Windows directory, opening system-wide Registry keys with write permission, and using WMI to make changes in operating system setting such as power management settings and the system clock. UAC represents an increase in Microsoft’s vigor to end the practice of average users running as local administrators, and every time an application running under the privileges of a local administrator on Vista with UAC enabled attempts an operation that requires elevated privileges, a dialog is shown asking the end-user to authorize the operation, as shown in Figure 1.

Figure 1: Admin Approval Prompt

Although the Admin Approval Prompt is the most visible component of UAC, there is another feature that acts silently and has the potential to cause a significant degree of confusion among developers who write applications that require a full admin token to execute correctly. To understand this new feature, it is worth first briefly considering the motivation for its inclusion. Many applications write a log file to the directory they are installed to, which is typically in the %ProgramFiles% directory. This action, while it requires administrator privileges, is actually fairly benign, and throwing up an Admin Approval Prompt for every application that attempts to write to the %ProgramFiles% directory could create a storm of prompts, particularly as a user logs in and auto-run applications begin firing up and opening a log file. Changing the behavior of Windows to allow these %ProgramFiles% writes under a non-admin account would open up a huge hole in Windows security, as less privileged applications could inject malicious code in the binary of an application known to run with elevated privileges, so the course of action taken was to virtualize %ProgramFiles% and re-direct writes to a safe location. This has the dual benefits of avoiding an Admin Approval Prompt, and allowing legacy applications to run on Windows Vista under a non-admin account.

Virtualization is a short-term compatibility feature, and Microsoft has made it clear that developers should not rely on the feature for their applications to work correctly.

Consider the following simple C++ application:

int _tmain(int argc, _TCHAR* argv[])
{
   HANDLE hLogFile = CreateFile(_T("c:Program Fileslog.txt"),
   FILE_ALL_ACCESS,
   FILE_SHARE_WRITE,
   NULL,
   OPEN_ALWAYS,
   FILE_ATTRIBUTE_NORMAL,
   NULL
);

if (INVALID_HANDLE_VALUE == hLogFile)
   return ::GetLastError();

TCHAR* logText = _T("Text to logn");

DWORD lengthWritten;
WriteFile(hLogFile, logText, sizeof(TCHAR) * _tcslen(logText),
          &lengthWritten, NULL);

CloseHandle(hLogFile);

return 0;
}

The code has obvious problems. The path to %ProgramFiles% is hard-coded, and the application attempts to write a log file to this directory. When run as a local administrator on Windows XP, this code works fine, and the log file is created. On Windows Vista, the code appears to work fine, but no file is present in c:Program Files after the code finishes executing, as shown in Figure 2.

Figure 2: Windows Explorer View of Program Files

Notice the Compatibility Files button on the toolbar in Figure 2. When clicked, this will navigate Windows Explorer to the location where virtualized files are stored, as shown in Figure 3. Notice that the location of the virtualized files is in a per-user store, and is in a location that works with features such as Roaming User Profiles and Folder Redirections.

Figure 3: Location of UAC Virtualized Files

Virtualization is a great feature for allowing legacy applications to work under Vista without requiring explicit user permission, but can cause a problem for applications that actually require the ability to write to directories protected through virtualization. For example, an organization may have a utility application that can go through Program Files, find any .NET configuration file with a database connection string, and allow the user to change the connection string to a new value. A tool like this obviously needs to write to files in the real Program Files directory.

An application lets the operating system know that it needs to run with admin privileges by a setting in the application manifest file. The simplest form of the manifest file to let Vista know that the application should run using the Administrator’s token is:

<assembly>
   <trustInfo>
      <security>
         <requestedPrivileges>
            <requestedExecutionLevel level="requireAdministrator" />
         </requestedPrivileges>
      </security>
   </trustInfo>
</assembly>

Using Visual C++, the elements in this manifest file can be merged with the other manifest files settings like the SxS options by saving the elements to a file (called custom.manifest) in this case, and specifying that the custom contents are added to the generated manifest file as part of the build process, as shown in Figure 4.

Figure 4: Visual C++ Settings to Add Custom Manifest Elements

With this manifest file in place, the application will bring up a UAC prompt at start-up as shown in Figure 5 (the sterner orange prompt is reserved for applications that are not digitally signed, as opposed to the blue prompt in Figure 1), and if the application is given permission to run, virtualization is disabled for all Windows SDK calls made by the process.

Figure 5: UAC Prompt for an Unsigned Application

For most applications, particularly those that have been given a security audit and run using the principle of least privilege, Vista UAC should not provide any nasty surprises. For administrative applications that require higher-level privileges, a simple addition to the manifest file can be used to let Windows Vista know the privilege level that the application needs to execute effectively. Finally, Vista provides a degree of virtualization to protect system-wide resources while allowing legacy applications to work without needing to prompt the user for privilege escalation.

About the Author

Nick Wienholt is a Windows and .NET consultant based in Sydney, Australia. He has worked on a variety of IT projects over the last decade and continues to stay involved in the developer community. Nick is the co-founder and president of the Sydney Deep .NET User group, writes technical articles for Pinnacle Publishing and the Microsoft Developer Network, and is a participant in many .NET-related newsgroups. Nick’s most recent book is Maximizing .NET Performance.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories