Designing for UAC


UAC will not elevate an application’s privileges after it is running. UAC assigns privileges when the application starts, and will not change the privileges after that. If an application needs to run with elevated privileges, it must obtain those privileges when it starts.

To avoid giving your application more privileges than necessary, you should separate your code into the pieces that require elevated privileges and those that do not. The main program should run with normal user privileges. Later, it should execute other applications that run with elevated privileges when necessary.

For example, a program that saves data into its local database or into a SQL Server database doesn’t need administrator privileges. However, the Windows directory is protected, so a program that creates a summary file when it exits in that directory needs administrator privileges. You could separate this program into a piece that performs most of the work and another program that writes the summary information into the log file. Before closing, the first program would run the second to write into the file.

If possible, it’s better to rewrite an application slightly to avoid requiring special privileges. For example, consider that many applications are installed in the Program Files directory. That directory is protected, so an application requires special privileges to write into it. That means if the application saves information into a file located where its executable is, it will need extra privileges. You can work around this problem by making the program write to a file located in the current user’s directory hierarchy.

Other operations that require elevated privileges include writing into other protected directories, interacting directly with hardware, and modifying protected sections of the Registry such as HKEY_ LOCAL_MACHINE.

Breaking an application into privileged and non-privileged parts not only lets the main program run with the fewest privileges possible, but separating the application into high- and low-privileges sections will probably help you reduce the number of places that you need extra privileges. That should simplify the riskiest parts of your code and make them easier to debug. It will also improve the separation between the two pieces, making them even easier to debug.

Example programs ShellUAC and ExecuteMe (which are available for download on the book’s web site at www.vb-helper.com/vb_prog_ref.htm) demonstrate this handoff. Program ShellUAC uses the following code to run the ExecuteMe program, which is flagged for execution with elevated privileges. (How to flag an application in this way is described in the following sections.)

  Private Sub btnRun_Click(ByVal sender As System.Object, _  ByVal e As System.EventArgs) Handles btnRun.Click     Try         ' Start the process.         Dim pro As System.Diagnostics.Process         pro = System.Diagnostics.Process.Start( _             txtProgram.Text, txtArguments.Text)         ' Wait for the process to exit.         pro.WaitForExit()         ' Display the process's exit code.         MessageBox.Show("Exit code: " & pro.ExitCode)     Catch ex As System.ComponentModel.Win32Exception         ' This happens if the user fails to elevate to Administrator.         MessageBox.Show("Operation canceled", _             "Canceled", MessageBoxButtons.OK, _             MessageBoxIcon.Information)     End Try End Sub  

The code uses the System.Diagnostics.Process.Start function to execute the application. It passes the function the path to the program to execute, and the command-line parameters for the program that are entered in text boxes.

The code calls the returned object’s WaitForExit method, so it waits until the other program has finished. It then checks the process’s ExitCode property to see what value the ExecuteMe application returned.

The following code shows the ExecuteMe program’s Main subroutine:

  Function Main(ByVal cmdArgs() As String) As Integer     Dim frm As New frmChoices     ' Display the arguments.     For Each str As String In cmdArgs         frm.lstArguments.Items.Add(str)     Next str     ' Select the first item.     If frm.lstArguments.Items.Count > 0 Then         frm.lstArguments.SelectedIndex = 0     End If     ' Return the index of the selected item.     If frm.ShowDialog() = DialogResult.Cancel Then         Return -1     Else         Return frm.lstArguments.SelectedIndex     End If End Function  

The program starts by creating a frmChoices form and adding its command-line arguments to the form’s lstArguments list box. It selects the first item in the list and displays the form modally.

If the user clicks the form’s Cancel button, the program returns –1. If the user clicks OK, the program returns the index of the selected list item. The Process object in calling program ShellUAC receives the return value in its ExitCode parameter.

Tip 

Remember that the program that runs with elevated privileges can potentially do a lot of damage to the system. To make this program as safe as possible, you should try to restrict its capabilities as much as you can and still get the job done. If you make the program too general, a bug in the calling program or a malicious program written by a hacker might be able to use it to cause a lot of damage. For example, if the program’s command line arguments gave it the names of files to delete, a bug in the caller could delete important system files.

As part of the UAC user experience, any action that requires privilege elevation (and, therefore, a UAC dialog box) should be marked with the standard UAC shield. Figure 14-1 shows the ShellUAC application displaying a button with this shield. The button displays the UAC shield to warn the user that clicking it launches an application that requires privilege elevation.

image from book
Figure 14-1: Buttons that launch actions that require privilege elevation should display the UAC shield.

Unfortunately, there currently isn’t a really simple way to display the UAC shield in Visual Basic applications. However, you can use an API call to make a button display the shield. The ShellUAC program uses the AddShieldToButton subroutine shown in the following code to make a button display the shield:

  Imports System.Runtime.InteropServices Module UacStuff     Declare Auto Function SendMessage Lib "user32.dll" _         (ByVal hWnd As HandleRef, ByVal msg As Int32, _         ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Int32     ' Make the button display the UAC shield.     Public Sub AddShieldToButton(ByVal btn As Button)         Const BCM_SETSHIELD As Int32 = &H160C         btn.FlatStyle = Windows.Forms.FlatStyle.System         SendMessage(New HandleRef(btn, btn.Handle), _             BCM_SETSHIELD, IntPtr.Zero, CType(1, IntPtr))     End Sub End Module  

The module declares the SendMessage API function. Subroutine AddShieldToButton sets the button’s FlatStyle property to System, and then uses SendMessage to send the button the BCM_SHIELD message.




Visual Basic 2005 with  .NET 3.0 Programmer's Reference
Visual Basic 2005 with .NET 3.0 Programmer's Reference
ISBN: 470137053
EAN: N/A
Year: 2007
Pages: 417

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net