PageRenderTime 22ms CodeModel.GetById 12ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/Visual Studio 2008/VBUACSelfElevation/ReadMe.txt

#
Plain Text | 401 lines | 332 code | 69 blank | 0 comment | 0 complexity | 8a2d1e13be70a21f7a5e9200f5fc3ced MD5 | raw file
  1=============================================================================
  2          APPLICATION : VBUACSelfElevation Project Overview
  3=============================================================================
  4
  5/////////////////////////////////////////////////////////////////////////////
  6Summary: 
  7
  8User Account Control (UAC) is a new security component in Windows Vista and 
  9newer operating systems. With UAC fully enabled, interactive administrators 
 10normally run with least user privileges. This example demonstrates how to 
 11check the privilege level of the current process, and how to self-elevate 
 12the process by giving explicit consent with the Consent UI. 
 13
 14
 15/////////////////////////////////////////////////////////////////////////////
 16Prerequisite:
 17
 18You must run this sample on Windows Vista or newer operating systems.
 19
 20
 21/////////////////////////////////////////////////////////////////////////////
 22Demo:
 23
 24The following steps walk through a demonstration of the UAC sample.
 25
 26Step1. After you successfully build the sample project in Visual Studio 2008, 
 27you will get an application: VBUACSelfElevation.exe. 
 28
 29Step2. Run the application as a protected administrator on a Windows Vista or 
 30Windows 7 system with UAC fully enabled. The application should display the 
 31following content on the main dialog.
 32
 33  IsUserInAdminGroup:     True
 34  IsRunAsAdmin:           False
 35  IsProcessElevated:      False
 36  Integrity Level:        Medium
 37
 38There is a UAC shield icon on the Self-elevate button.
 39
 40Step3. Click on the Self-elevate button. You will see a Consent UI.
 41
 42  User Account Control
 43  ---------------------------------- 
 44  Do you want to allow the following program from an unknown publisher to 
 45  make changes to this computer?
 46
 47Step4. Click Yes to approve the elevation. The original application will then 
 48be started and display the following content on the main dialog.
 49
 50  IsUserInAdminGroup:     True
 51  IsRunAsAdmin:           True
 52  IsProcessElevated:      True
 53  Integrity Level:        High
 54
 55The Self-elevate button on the dialog does not have the UAC shield icon this 
 56time. That is, the application is running as elevated administrator. The 
 57elevation succeeds. If you click on the Self-elevate button again, the 
 58application will tell you that it is running as administrator.
 59
 60Step5. Close the application. 
 61
 62
 63/////////////////////////////////////////////////////////////////////////////
 64Creation:
 65
 66Step1. Create a new Visual Basic Windows Forms project named 
 67VBUACSelfElevation.
 68
 69Step2. Add controls to the main form
 70
 71  Type: Button
 72  ID: btnElevate
 73  Caption: "Self-elevate"
 74  
 75  Type: Label
 76  ID: lbInAdminGroup
 77  Use: Display whether the primary access token of the process belongs to 
 78  user account that is a member of the local Administrators group, even if it 
 79  currently is not elevated.
 80  
 81  Type: Label
 82  ID: lbIsRunAsAdmin
 83  Use: Display whether the application is run as administrator. 
 84  
 85  Type: Label
 86  ID: lbIsElevated
 87  Use: Display whether the process is elevated or not. Token elevation is 
 88  only available on Windows Vista and newer operating systems. The label 
 89  shows N/A on systems prior to Windows Vista.
 90 
 91  Type: Label
 92  ID: lbIntegrityLevel
 93  Use: Display the integrity level of the current process. Integrity level is 
 94  only available on Windows Vista and newer operating systems. The label 
 95  shows N/A on systems prior to Windows Vista.
 96
 97Step3. Check and display the current process's "run as administrator" status, 
 98elevation information and integrity level when the application initializes 
 99the main dialog.
100
101Create the following four helper functions:
102
103    ''' <summary>
104    ''' The function checks whether the primary access token of the process belongs 
105    ''' to user account that is a member of the local Administrators group, even if 
106    ''' it currently is not elevated.
107    ''' </summary>
108    ''' <returns>
109    ''' Returns True if the primary access token of the process belongs to user 
110    ''' account that is a member of the local Administrators group. Returns False 
111    ''' if the token does not.
112    ''' </returns>
113    ''' <exception cref="System.ComponentModel.Win32Exception">
114    ''' When any native Windows API call fails, the function throws a Win32Exception 
115    ''' with the last error code.
116    ''' </exception>
117    Friend Function IsUserInAdminGroup() As Boolean
118
119    ''' <summary>
120    ''' The function checks whether the current process is run as administrator.
121    ''' In other words, it dictates whether the primary access token of the 
122    ''' process belongs to user account that is a member of the local 
123    ''' Administrators group and it is elevated.
124    ''' </summary>
125    ''' <returns>
126    ''' Returns True if the primary access token of the process belongs to user 
127    ''' account that is a member of the local Administrators group and it is 
128    ''' elevated. Returns False if the token does not.
129    ''' </returns>
130    Friend Function IsRunAsAdmin() As Boolean
131
132    ''' <summary>
133    ''' The function gets the elevation information of the current process. It 
134    ''' dictates whether the process is elevated or not. Token elevation is only 
135    ''' available on Windows Vista and newer operating systems, thus 
136    ''' IsProcessElevated throws a C++ exception if it is called on systems prior 
137    ''' to Windows Vista. It is not appropriate to use this function to determine 
138    ''' whether a process is run as administartor.
139    ''' </summary>
140    ''' <returns>
141    ''' Returns True if the process is elevated. Returns False if it is not.
142    ''' </returns>
143    ''' <exception cref="System.ComponentModel.Win32Exception">
144    ''' When any native Windows API call fails, the function throws a Win32Exception
145    ''' with the last error code.
146    ''' </exception>
147    ''' <remarks>
148    ''' TOKEN_INFORMATION_CLASS provides TokenElevationType to check the elevation 
149    ''' type (TokenElevationTypeDefault / TokenElevationTypeLimited / 
150    ''' TokenElevationTypeFull) of the process. It is different from TokenElevation 
151    ''' in that, when UAC is turned off, elevation type always returns 
152    ''' TokenElevationTypeDefault even though the process is elevated (Integrity 
153    ''' Level == High). In other words, it is not safe to say if the process is 
154    ''' elevated based on elevation type. Instead, we should use TokenElevation.
155    ''' </remarks>
156    Friend Function IsProcessElevated() As Boolean
157
158    ''' <summary>
159    ''' The function gets the integrity level of the current process. Integrity 
160    ''' level is only available on Windows Vista and newer operating systems, thus 
161    ''' GetProcessIntegrityLevel throws a C++ exception if it is called on systems 
162    ''' prior to Windows Vista.
163    ''' </summary>
164    ''' <returns>
165    ''' Returns the integrity level of the current process. It is usually one of 
166    ''' these values:
167    ''' 
168    '''    SECURITY_MANDATORY_UNTRUSTED_RID - means untrusted level. It is used by 
169    '''    processes started by the Anonymous group. Blocks most write access.
170    '''    (SID: S-1-16-0x0)
171    '''    
172    '''    SECURITY_MANDATORY_LOW_RID - means low integrity level. It is used by 
173    '''    Protected Mode Internet Explorer. Blocks write acess to most objects 
174    '''    (such as files and registry keys) on the system. (SID: S-1-16-0x1000)
175    ''' 
176    '''    SECURITY_MANDATORY_MEDIUM_RID - means medium integrity level. It is used 
177    '''    by normal applications being launched while UAC is enabled. 
178    '''    (SID: S-1-16-0x2000)
179    '''    
180    '''    SECURITY_MANDATORY_HIGH_RID - means high integrity level. It is used by 
181    '''    administrative applications launched through elevation when UAC is 
182    '''    enabled, or normal applications if UAC is disabled and the user is an 
183    '''    administrator. (SID: S-1-16-0x3000)
184    '''    
185    '''    SECURITY_MANDATORY_SYSTEM_RID - means system integrity level. It is used 
186    '''    by services and other system-level applications (such as Wininit, 
187    '''    Winlogon, Smss, etc.)  (SID: S-1-16-0x4000)
188    ''' 
189    ''' </returns>
190    ''' <exception cref="System.ComponentModel.Win32Exception">
191    ''' When any native Windows API call fails, the function throws a Win32Exception 
192    ''' with the last error code.
193    ''' </exception>
194    Friend Function GetProcessIntegrityLevel() As Integer
195
196Some of the methods need to P/Invoke some native Windows APIs. The P/Invoke 
197signatures are defined in NativeMethod.vb.
198
199In the Load event of the main form, check and display the "run as 
200administrator" status, the elevation information, and the integrity level of 
201the current process.
202
203    ' Get and display whether the primary access token of the process belongs 
204    ' to user account that is a member of the local Administrators group even 
205    ' if it currently is not elevated (IsUserInAdminGroup).
206    Try
207        Dim fInAdminGroup As Boolean = Me.IsUserInAdminGroup
208        Me.lbInAdminGroup.Text = fInAdminGroup.ToString
209    Catch ex As Exception
210        Me.lbInAdminGroup.Text = "N/A"
211        MessageBox.Show(ex.Message, "An error occurred in IsUserInAdminGroup", _
212                        MessageBoxButtons.OK, MessageBoxIcon.Error)
213    End Try
214
215    ' Get and display whether the process is run as administrator or not 
216    ' (IsRunAsAdmin).
217    Try
218        Dim fIsRunAsAdmin As Boolean = Me.IsRunAsAdmin
219        Me.lbIsRunAsAdmin.Text = fIsRunAsAdmin.ToString
220    Catch ex As Exception
221        Me.lbIsRunAsAdmin.Text = "N/A"
222        MessageBox.Show(ex.Message, "An error occurred in IsRunAsAdmin", _
223                        MessageBoxButtons.OK, MessageBoxIcon.Error)
224    End Try
225    
226    ' Get and display the process elevation information (IsProcessElevated) 
227    ' and integrity level (GetProcessIntegrityLevel). The information is not 
228    ' available on operating systems prior to Windows Vista.
229    If (Environment.OSVersion.Version.Major >= 6) Then
230        ' Running Windows Vista or later (major version >= 6). 
231
232        Try
233            ' Get and display the process elevation information.
234            Dim fIsElevated As Boolean = Me.IsProcessElevated
235            Me.lbIsElevated.Text = fIsElevated.ToString
236
237            ' Update the Self-elevate button to show the UAC shield icon on 
238            ' the UI if the process is not elevated.
239            Me.btnElevate.FlatStyle = FlatStyle.System
240            NativeMethod.SendMessage(Me.btnElevate.Handle, NativeMethod.BCM_SETSHIELD, _
241                                     0, IIf(fIsElevated, IntPtr.Zero, New IntPtr(1)))
242        Catch ex As Exception
243            Me.lbIsElevated.Text = "N/A"
244            MessageBox.Show(ex.Message, "An error occurred in IsProcessElevated", _
245                            MessageBoxButtons.OK, MessageBoxIcon.Error)
246        End Try
247
248        Try
249            ' Get and display the process integrity level.
250            Dim IL As Integer = Me.GetProcessIntegrityLevel
251            Select Case IL
252                Case NativeMethod.SECURITY_MANDATORY_UNTRUSTED_RID
253                    Me.lbIntegrityLevel.Text = "Untrusted"
254                Case NativeMethod.SECURITY_MANDATORY_LOW_RID
255                    Me.lbIntegrityLevel.Text = "Low"
256                Case NativeMethod.SECURITY_MANDATORY_MEDIUM_RID
257                    Me.lbIntegrityLevel.Text = "Medium"
258                Case NativeMethod.SECURITY_MANDATORY_HIGH_RID
259                    Me.lbIntegrityLevel.Text = "High"
260                Case NativeMethod.SECURITY_MANDATORY_SYSTEM_RID
261                    Me.lbIntegrityLevel.Text = "System"
262                Case Else
263                    Me.lbIntegrityLevel.Text = "Unknown"
264            End Select
265        Catch ex As Exception
266            Me.lbIntegrityLevel.Text = "N/A"
267            MessageBox.Show(ex.Message, "An error occurred in GetProcessIntegrityLevel!", _
268                            MessageBoxButtons.OK, MessageBoxIcon.Hand)
269        End Try
270
271    Else
272        Me.lbIsElevated.Text = "N/A"
273        Me.lbIntegrityLevel.Text = "N/A"
274    End If
275
276Step4. Handle the click event of the Self-elevate button. When user clicks 
277the button, elevate the process by restarting itself with 
278ProcessStartInfo.UseShellExecute = true and ProcessStartInfo.Verb = "runas" 
279if the process is not run as administrator
280
281    Private Sub btnElevate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
282    Handles btnElevate.Click
283        ' Elevate the process if it is not run as administrator.
284        If (Not Me.IsRunAsAdmin) Then
285            ' Launch itself as administrator
286            Dim proc As New ProcessStartInfo
287            proc.UseShellExecute = True
288            proc.WorkingDirectory = Environment.CurrentDirectory
289            proc.FileName = Application.ExecutablePath
290            proc.Verb = "runas"
291
292            Try
293                Process.Start(proc)
294            Catch
295                ' The user refused the elevation.
296                ' Do nothing and return directly ...
297                Return
298            End Try
299
300            Application.Exit()  ' Quit itself
301        Else
302            MessageBox.Show("The process is running as administrator", "UAC")
303        End If
304    End Sub
305
306Step5. Automatically elevate the process when it's started up.
307
308If your application always requires administrative privileges, such as during 
309an installation step, the operating system can automatically prompt the user 
310for privileges elevation each time your application is invoked. 
311
312If a specific kind of resource (RT_MANIFEST) is found embedded within the 
313application executable, the system looks for the <trustInfo> section and 
314parses its contents. Here is an example of this section in the manifest file:
315
316    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
317       <security>
318          <requestedPrivileges>
319             <requestedExecutionLevel
320                level="requireAdministrator"
321             />
322          </requestedPrivileges>
323       </security>
324    </trustInfo>
325
326Three different values are possible for the level attribute
327
328  a) requireAdministrator 
329  The application must be started with Administrator privileges; it won't run 
330  otherwise.
331
332  b) highestAvailable 
333  The application is started with the highest possible privileges.
334  If the user is logged on with an Administrator account, an elevation prompt 
335  appears. If the user is a Standard User, the application is started 
336  (without any elevation prompt) with these standard privileges.
337
338  c) asInvoker 
339  The application is started with the same privileges as the calling 
340  application.
341
342To configure the elevation level in this Visual Basic Windows Forms project, 
343open the project's properties, turn to the Application tab, and click the 
344"View UAC Settings" button. This creates an app.manifest file and configures 
345the project to embed the manifest. You can find the "app.manifest" file in 
346the "My Project" folder of the VB.NET project. The file has the following 
347content by default.
348
349    <?xml version="1.0" encoding="utf-8"?>
350    <asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" 
351    xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" 
352    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
353      <assemblyIdentity version="1.0.0.0" name="MyApplication.app" />
354      <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
355        <security>
356          <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
357            <!-- UAC Manifest Options
358                If you want to change the Windows User Account Control level replace the 
359                requestedExecutionLevel node with one of the following.
360
361            <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
362            <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
363            <requestedExecutionLevel  level="highestAvailable" uiAccess="false" />
364
365                If you want to utilize File and Registry Virtualization for backward 
366                compatibility then delete the requestedExecutionLevel node.
367            -->
368            <requestedExecutionLevel level="asInvoker" uiAccess="false" />
369          </requestedPrivileges>
370          <applicationRequestMinimum>
371            <PermissionSet class="System.Security.PermissionSet" version="1" 
372            Unrestricted="true" ID="Custom" SameSite="site" />
373            <defaultAssemblyRequest permissionSetReference="Custom" />
374          </applicationRequestMinimum>
375        </security>
376      </trustInfo>
377    </asmv1:assembly>
378
379Here we are focusing on the line:
380
381    <requestedExecutionLevel level="asInvoker" uiAccess="false" />
382
383You can change it to be 
384
385    <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
386
387to require the application always be started with Administrator privileges.
388
389
390/////////////////////////////////////////////////////////////////////////////
391References:
392
393MSDN: User Account Control
394http://msdn.microsoft.com/en-us/library/aa511445.aspx
395
396MSDN: Windows Vista Application Development Requirements for User Account 
397Control Compatibility
398http://msdn.microsoft.com/en-us/library/bb530410.aspx
399
400
401/////////////////////////////////////////////////////////////////////////////