ATI Radeon Causes a UAC Prompt at User Logon

By , June 29, 2010 11:36 am

Recently, I encountered a strange issue after adding ATI Catalyst 10.4 Display Drivers to an offline Windows 7 image using the DISM.EXE /Add-Driver command. On systems that had an ATI Radeon video card, a UAC prompt would pop up the first time a user logged on and got to the desktop:

Since our users don’t have administrative rights they couldn’t complete this this operation, and the UAC prompt would continue to occur at every logon.  If I entered administrator credentials or logged in as an administrator, the UAC prompt went away for all users. But if I uninstalled the display adapter via Device Manager and scanned for hardware changes, the prompt came back. I proceeded to troubleshoot, but without much success:

  • Everything in Setupapi.offline.log indicated that the driver was successfully added to the offline image.
  • The issue affected any system that had an ATI Radeon HD display adapter, regardless of the model.
  • I had used previous versions of ATI Catalyst display drivers, including 9.12, without any problems. As it turns out, the UAC prompt began to appear beginning with Catalyst 10.1 and continued through the current version (10.6).
  • According to Device Manager, the display adapter was already installed and working properly. If I entered administrator credentials at the UAC prompt, no additional or new devices appeared in Device Manager.

Maybe the UAC prompt doesn’t seem like a big deal, but when you have 5000+ computers that displaying this annoying prompt at every logon, going around to each one and entering administrator credentials isn’t an option. I opened a support case with our system vendor, but after a month without much progress, I started digging deeper on my own.

One thing that I had overlooked originally was setupapi.dev.log, which tracks hardware device installs. I opened this log on a system that exhibited the UAC prompt behavior and began sifting through the entries. I found the install section for the ATI Radeon device. At first, it looked liked everything was fine. The driver installed successfully and the section closed with [Exit status: SUCCESS]. I then began to read through every line to see if there were any other clues. Finally, I found something:

 dvi:      {DIF_NEWDEVICEWIZARD_FINISHINSTALL} 13:58:19.543
 dvi:           CoInstaller 1: Enter 13:58:19.543
 dvi:           CoInstaller 1: Exit
 dvi:           Class installer: Enter 13:58:19.543
 dvi:           Class installer: Exit
 dvi:           Default installer: Enter 13:58:19.606
 dvi:           Default installer: Exit
 dvi:      {DIF_NEWDEVICEWIZARD_FINISHINSTALL - exit(0xe000020e)} 13:58:19.606
 ndv:      Device has a Finish Install Action that needs to be run.

The last line is what caught my attention. I searched through the rest of the log for the entry Device has a Finish Install Action that needs to be run. Sure enough, the ATI display adapter was the only device that had this status. I began looking for more information about DIF_NEWDEVICEWIZARD_FINISHINSTALL. This eventually led me to the Windows DDK documentation, where I learned about Finish-Install Actions:

After core device installation is complete for a device, Windows checks whether the CONFIGFLAG_FINISHINSTALL_ACTION flag or the CONFIGFLAG_FINISHINSTALL_UI flag is set for the device. If either of these flags is set for a device, Windows queues a finish-install process that performs the finish-install actions specific to the device. The process executes in the user’s context.

The finish-install process runs only in the context of a user with administrator credentials at one of the following times:

  • The next time that a user who has administrator credentials logs on while the device is attached.
  • When the device is reattached.
  • When the user selects Scan for hardware changes in Device Manager.

If a user is logged on without administrative privileges, Windows prompts the user for consent and credentials to run the finish-install actions in an administrator context.

Arrrrrgh! It seems that this behavior is by design!? I’m not sure why I haven’t come across another driver that exhibits this behavior, or why ATI decided to implement this behavior beginning in Catalyst 10.1.

The Finish-Install Action

Next, I decided to use Process Monitor to figure out what the Finish-Install action was doing. With Process Monitor running, I entered administrative credentials into the UAC prompt and let the install complete. I then began filtering out irrelevant Process Monitor entries to find out what what was happening during the Finish-Install action. As far as I could tell, it was setting the registry value INFName under HKLM\SOFTWARE\ATI Technologies\Co-installer to the name of the INF that was used to install the driver. That’s it.

Goodbye, Finish-Install Action

Since this seems to have little, if any, impact on the functionality of the display driver, I began searching for a way to skip or disable the Finish-Install actions. I searched through the Windows DDK documentation and came up with nothing. I also had Google searches coming out the wazoo.

Finally, I used Process Monitor again to see if I had missed anything during the first try. It turns out I did: The registry value ConfigFlags under HKLM\System\CurrentControlSet\Enum\PCI\VEN_1002&DEV_9540&SUBSYS_00021028&REV_00\4&10ef49db&0&0008 was being set to 0x0.  I went back and looked found that, after the display adapter is installed and before the UAC prompt, ConfigFlags is set to 0x00020000. As it turns out, this is the enumerated value for CONFIGFLAG_FINISHINSTALL_ACTION. I tried to modify the ConfigFlags value, but it turned out that only the SYSTEM account had permissions to do that. So I grabbed PSExec and ran this command:

PSEXEC -s REG ADD HKLM\System\CurrentControlSet\Enum\PCI\VEN_1002&DEV_9540&SUBSYS_00021028&REV_00\4&10ef49db&0&0008 /v "ConfigFlags" /t REG_DWORD /d 0 /f

Finally, the UAC prompt went away.

Note: If decide to try the command above, be aware that the registry path referenced will probably differ from yours. The names of the registry keys vary depending on what ATI video card you are using. VEN_1002&DEV_9540&SUBSYS_00021028&REV_00\4&10ef49db&0&0008 refers to the Radeon HD 4550 video card on the machine that I was using to troubleshoot. One way to solve this is by writing a VBScript that searches for ATI display adapters under HKLM\System\CurrentControlSet\Enum\PCI and verifies that ConfigFlags is set to 0x0.

30 Responses to “ATI Radeon Causes a UAC Prompt at User Logon”

  1. Nathan Sutton says:

    Thanks Boyd,

    As you know I have been looking into this for a while. Thanks for your persistence and professional approach to getting to the bottom of this bugger of a problem.

    Cheers,

    Nathan

  2. Ian Fraser says:

    Thanks VERY MUCH. You have solved a major issue for me, I have had this with three drivers so far. Microsoft’s LifeCam, an Audio driver for the Lenovo T420s laptop, and another keyboard filter driver. The webcam went through Microsoft PSS and they couldn’t solve it – so many thanks. Great detective work.

    • Boyd says:

      Glad I could help. I contacted ATI support this issue. They denied that this was a problem, but told me they would pass it along to developers. I never heard back.

  3. Jamie says:

    THANKS SO MUCH!! Was pulling my hair out at this, I even went down th epath of assuming the drivers were not digitally signed as we were trying to deploy to win7 x64! Amazes me how this is the only article on the net explaining this issue, Im sure others will no doubt hit this issue as and when more companies make the move to Win7…

    • Boyd says:

      Glad I could help. I hope that driver developers, especially those for vendors such as ATI, will realize that Finish-Install actions don’t work in non-administrator user environment.

  4. Hany says:

    Thanks alot for this post but how can i do it inside the image ? ia alreadt gave everyone full permision to that registry but still it is prompting

  5. Michael says:

    Some folks pointed me to this link:

    http://msdn.microsoft.com/en-us/library/ff545004(VS.85).aspx

    ” if the co-installer incorrectly sets the DI_FLAGSEX_FINISHINSTALL_ACTION flag, the user gets an undesired User Account Control (UAC) prompt for permission to proceed even though the finish-install action has no action to perform.”

  6. Eric says:

    How did you implement this into your image setup. We have this issue but cannot figure out how you changed this value on a 7 machine in Audit mode. We tried doing your PSEXEC cmd with our PCI vendor values but PSExec fails doing the Red ADD and gives errors on the “&” symbols. Did you add this into a Task Sequence as a script when did your deployment?

    • Boyd says:

      Hey Eric,

      Actually, we use systems management software (BigFix AKA Tivoli Endpoint Manager) to detect machines with this issue and apply the registry fix. The “action script” is specific to BigFix, but you could make a VBScript that would do the same thing, and put in a task sequence as well.

      Regarding the ampersand (&), the most likely reason you received an error is that it needs to be escaped with a caret (^).
      Here’s a simple example you can try at the dos prompt:

      REM Output: This is a test (and error)
      echo This is a test & testing 123
      REM Output: This is a test & testing 123
      echo This is a test ^& testing 123
  7. Eric says:

    Sorry typo, REG ADD*

  8. Jamie says:

    Just for info in case anyone else is trying to script this – Ive tried to run through the registry with a powershell script, however this fails when it gets to the Properties folder within every subkey under ENUM\PCI\VENXXX, since permissions are setup in such a way as to disable reads. I even tried psexecing out to the SYSTEM account – no joy.

    Best way Ive found, although Ive yet to code this, is to use the C:\windows\setupact.log – in here under the rows beginning with dispci.dll is the actual key name used for the driver – read this into Powershell, do some jiggery-pokery with strings and bingo – you have your registry location with which you can set the configflags to 0.

    HTH

  9. Jamie says:

    Quick update on my previous post – Ive created this Powershell script to accomplish setting this key automatically, just need to ensure this script runs as SYSTEM at first boot:

    Get-Content C:\windows\setupact.log | Select-String “PCI” -casesensitive | foreach {
    $PCILoc = $_.tostring().indexof(“\”)
    $PCILen = $_.tostring().length
    $PCILoc = $PCILen – $PCILoc
    $DispReg = $_.tostring().substring($_.tostring().length – $PCILoc, $PCILoc)
    $FullKey = “HKLM:\SYSTEM\CurrentControlSet\Enum\PCI” + $DispReg
    if ((Test-Path $FullKey) -eq “True”)
    {Set-ItemProperty $FullKey -name ConfigFlags -value 0}
    }

    It will read the contents of setupact.log, which will contain the key path to your display driver. It will filter the lines into lines with “PCI” in them (you can try substituting this with “dispci.dll: DisplayClassInstaller” in case you are worried about other PCI devices getting config flags set to 0), then form the full key based on this and if it exists, set the configflags value to 0.

    Hope that helps

  10. Richard says:

    Brilliant post. Also works for the Bluetooth 3.0 drivers on a Lenovo T420! This is my version using VBS. I’m about to test it from a SCCM task sequence…

    The Description of the ATI device appears to be unique under “HKLM\System\CurrentControlSet\Enum\”, so I’ve made the assumption that I can search on it. I have added the strcomp(left section as the Description field adds a couple of spaces to the end of the name! It also assumes that psexec.exe is in the same directory – will add some logic to make sure later on…

    The code;

    On Error Resume Next

    StringToLookFor=”ATI Mobility Radeon HD 3400 Series”

    strComputer = “.”
    Set objWMIService = GetObject(“winmgmts:” _
    & “{impersonationLevel=impersonate}!\\” & strComputer & “\root\cimv2″)

    Set objShell = CreateObject(“Wscript.Shell”)

    Set colItems = objWMIService.ExecQuery(“Select Description,DeviceID from Win32_PnPSignedDriver”)

    For Each objItem in colItems
    If StrComp(Left(objItem.Description,Len(StringToLookFor)),StringToLookFor,1)=0 Then

    Wscript.Echo “Description: ” & objItem.Description
    Wscript.Echo “Device ID: ” & objItem.DeviceID
    DeviceID=objItem.DeviceID
    End If
    Next

    MainKey=”HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\”

    FullString=MainKey & DeviceID
    CommandLine=”PSEXEC.exe -s REG ADD ” & FullString & ” /v “”ConfigFlags”” /t REG_DWORD /d 0 /f”

    returnCode=ObjShell.Run(CommandLine)
    WScript.Echo “RC:” & returnCode

  11. JS2010 says:

    I just went through the same thing with 2 other ATI or AMD Radeon video drivers (both bootcamp):

    http://social.technet.microsoft.com/Forums/en/w7itproinstall/thread/3c90cad7-3729-49b6-8d16-a89fc7830702

  12. Asgar says:

    Thanks Boyd,
    This is very useful information and it helped me a lot. But I have another problem when I try update the following registry

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\PCI\VEN_1002&DEV_9712&SUBSYS_1455103C&REV_00\4&c60e52a&0&2808]
    “ConfigFlags”=dword:00000000.
    I am getting Following error “Cannot edit ConfigFlags: Error writing the value’s new contents”. Even tried updating using Powershell then I am getting Access denied error.

    Any help would be much appreciated.

    • Boyd says:

      Hey Asgar, it’s a permissions issue. By default, that registry value can only be edited by NT Authority\SYSTEM. You could change the permissions, but it’s probably easier to just use PSEXEC.EXE -S to execute the command as SYSTEM, which is what I actually did in the post above.

      Thanks,

      Matt

  13. BarryB says:

    Hi Boyd,

    let me echo the thanks of the others above, esp. for such a concise breakdown of the cause and the solution. I just started looking at this and you have saved me a lot of time and effort thanks again,

    Barry

  14. Alex Ridge says:

    Your explanation is fantastic and exactly what I needed to prompt Dell to hopefully resolve this issue on their Optiplex 780 drivers.

    • Boyd says:

      Alex, I’d be interested in hearing what the outcome is with your Dell case. As far as I can tell, this is an issue because of ATI’s drivers, but perhaps Dell can persuade them to resolve it.

  15. Ryan Breneman says:

    Thanks so much for your excellent post! I work in a school district and we just order 200+ lenovo x130e laptops and I had 3 drivers that were giving me the same problems that you described. Thank you so much for your fix, I wasn’t sure what to do until I found this!

    Ryan

  16. Richard Braitsch says:

    I am having the same issue and very glad for your detailed explanation of the underlying cause. I just want to add that the same issue can apply to other enum categories. I am struggling with a Logitech webcam which is enumerated under USB.

    • Boyd says:

      You’re absolutely correct, we had the same issues with Logitech webcams. Pretty much any driver that insists on performing a Finish-Install Action. I think that part of the blame lies with Microsoft for allowing developers to do this. It makes life a real PITA for us sysadmins who follow the least privilege model.

  17. Nick says:

    Good call… very similar to COnexant audio driver issue on http://forums.techarena.in/windows-software/1426799.htm

  18. Paul says:

    I wrote this vbs fix. In your task sequence, restart after driver install then add a task to run this script. Basically it reads the sub enum keys, excludes anything with root in the name and resets any configflags that are not 0. Out puts a log file to c:\windows\logs

    ‘ =======================================================================================

    ‘ _______________________________________________________________________________________
    ‘ Declare Variables
    ‘ _______________________________________________________________________________________
    ‘ Option Explicit
    Dim objNetwork, objShell, objFSO
    Dim strTemp, strWinDir, strUsername, strSystemdrive, strUserprofile, strComputername
    Dim strProgramfiles, strAllusersprofile, strAppData, strLogText

    ‘On Error Resume Next

    Set objNetwork = CreateObject(“WScript.Network”)
    Set objShell = CreateObject(“wscript.shell”)
    Set objFSO = CreateObject(“Scripting.FileSystemObject”)

    ‘ _______________________________________________________________________________________
    ‘ Assign value to Global variables. Un-comment to use
    ‘ _______________________________________________________________________________________
    ‘strTemp = objShell.ExpandEnvironmentStrings(“%temp%”)
    strWindir = objShell.ExpandEnvironmentStrings(“%windir%”)
    ‘strUsername = objShell.ExpandEnvironmentStrings(“%username%”)
    ‘strSystemdrive = objShell.ExpandEnvironmentStrings(“%systemdrive%”)
    ‘strUserprofile = objShell.ExpandEnvironmentStrings(“%userprofile%”)
    ‘strComputername = objShell.ExpandEnvironmentStrings(“%computername%”)
    ‘strProgramfiles = objShell.ExpandEnvironmentStrings(“%programfiles%”)
    ‘strAllusersprofile = objShell.ExpandEnvironmentStrings(“%allusersprofile%”)
    ‘strAppData = objShell.ExpandEnvironmentStrings(“%appdata%”)
    ‘ _______________________________________________________________________________________
    ‘ Constants Eg:Const wbemFlagForwardOnly = &h20
    ‘ _______________________________________________________________________________________
    ‘Const HKEY_CLASSES_ROOT = &H80000000
    Const HKEY_CURRENT_USER = &H80000001
    Const HKEY_LOCAL_MACHINE = &H80000002
    ‘Const HKEY_USERS = &H80000003
    ‘Const HKEY_CURRENT_CONFIG = &H80000005

    Const ForWriting = 2
    Const ForAppending = 8
    Const ForReading = 1
    ‘ _______________________________________________________________________________________
    ‘ Setup Logging
    ‘ _______________________________________________________________________________________

    ‘ Makes sure the folder exists if not creates it.
    If Not objFSO.FolderExists(strWindir & “\Logs”) Then
    Set objFolder = objFSO.CreateFolder(strWindir & “\Logs”)
    End If
    ‘Set up a log file in the C:\Windows\Logs directory to track issues
    Set objLogFile = objFSO.OpenTextFile(strWindir & “\Logs” & “\” & “UACConfigFlagsCheckv001.log”, ForWriting, True)

    ‘ _______________________________________________________________________________________
    ‘ Script Body start
    ‘ _______________________________________________________________________________________

    WriteLog(“Script Start”)

    ‘ #############################################################################
    ‘ Get the model number
    ‘ #############################################################################

    strComputer = “.”

    ‘wscript.echo strComputer
    Set objWMIService = GetObject(“winmgmts:\\” & strComputer & “\root\cimv2″)
    Set colItems = objWMIService.ExecQuery(“Select * from Win32_ComputerSystem”,,48)
    For Each objItem in colItems
    ‘WScript.Echo “Model: ” & objItem.Model
    modelnumber = objItem.Model
    Next

    ‘ #############################################################################
    ‘ Check if the model number is Not to be updated add you models to exclude this script here
    ‘ #############################################################################

    ‘wscript.echo modelnumber

    if lcase(modelnumber) = lcase(“changeme”) or lcase(modelnumber) = lcase(“changeme2″) then
    WriteLog “Script quitting this model is not to be updated:” & modelnumber
    Wscript.quit
    else
    WriteLog “This model can be updated:” & modelnumber
    end if
    ‘ #############################################################################

    Dim oReg
    Set oReg=GetObject(“winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv”)

    Call FindRegKey(oReg, HKEY_LOCAL_MACHINE, “SYSTEM\CurrentControlSet\Enum”)

    Sub FindRegKey(oReg, Key, sSubkey)
    ‘ Deletes registry key and subkeys (permissions to delete keys must exist)
    ‘ Key: Tree that contains the sSubKey path
    ‘ (HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_USERS or HKEY_CURRENT_CONFIG)
    ‘ sSubkey: Subkey to be deleted (Case-sensitive string)
    ‘ (Example: “SOFTWARE\System Admin Scripting Guide”)
    Dim aSubkeys, subkey
    oReg.EnumKey Key, sSubkey, aSubkeys
    If Not IsNull(aSubKeys) Then
    For Each subkey In aSubkeys
    Call FindRegKey(oReg, Key, sSubKey & “\” & subkey)
    Next
    End If
    ‘ Error trapping in case we can’t delete (no permissions)
    On Error Resume Next
    WriteLog “Check:” & sSubKey
    strKeyCheck = “HKEY_LOCAL_MACHINE\” & sSubKey & “\ConfigFlags”
    strRegEntry = objShell.RegRead(strKeyCheck)
    If strRegEntry “” Then
    WriteLog “Found value:” & strKeyCheck & “\” & strRegEntry
    If strRegEntry “0” Then
    If Instr (Lcase(strKeyCheck), “root”) > 0 Then
    Else
    WriteLog “Warning Key Needs Updating:” & strKeyCheck & “\” & strRegEntry
    objShell.RegWrite strKeyCheck, “0”, “REG_DWORD”
    WriteLog “Key Updated:” & strKeyCheck & ” Value Added:0″
    End IF
    End IF
    Else
    ‘WriteLog “No Found value:” & strKeyCheck & “\” & strRegEntry
    End If
    On Error GoTo 0
    strKeyCheck = “”
    strRegEntry = “”
    strCheckValue = “”
    End Sub

    ‘Clean up the objects and close the script (uncomment objects used)
    Set objNetwork = Nothing
    Set objFSO = Nothing
    Set objShell = Nothing
    WriteLog(“Script Finish”)
    ‘Wscript.echo “Finished”
    objLogFile.Close()
    WScript.Quit
    ‘ _______________________________________________________________________________________
    ‘ Script Body Finish
    ‘ _______________________________________________________________________________________

    ‘ =======================================================================================
    ‘ Functions
    ‘ =======================================================================================
    ‘ _______________________________________________________________________________________
    ‘ Write to Log File
    ‘ _______________________________________________________________________________________
    Sub WriteLog(strLogText)
    objLogFile.WriteLine Now & ” :: ” & strLogText
    End Sub

    • Boyd says:

      Paul, thanks very much for writing this script and sharing it with others. WordPress comments don’t handle code very well… you might want to put it in pastebin and share the link, or if you have a blog you could post it there and share the link as well. Again, thanks for sharing!

  19. Adam J says:

    Anybody have any luck adding this as a task in an OSD Task Sequence in SCCM? I’ve tried the command:

    “%location%\PSEXEC.exe” /accepteula -s REG ADD “HKLM\System\CurrentControlSet\Enum\PCI\VEN_1002&DEV_9591&SUBSYS_30E7103C&REV_00\4&2a217053&0&0008″ /v “ConfigFlags” /t REG_DWORD /d 0 /f

    It keeps erroring out for me.

  20. SRH says:

    I wrote this script and run it in an OSD task sequence in SCCM:

    Param(
    [string] $EnumSubKey = $(throw “-EnumSubKey param required”),
    [string] $SearchText = $(throw “-SearchText param required”)
    )
    # Start logging.
    $logfile = “$env:windir\Logs\KillDriverUAC.log”
    Start-Transcript $logfile -Append
    Write-Host “Starting script.”

    try {
    [array] $colDevList = Get-ChildItem -Path “Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\$EnumSubKey”
    $colDevList | foreach-object {
    [array] $colDevKey = get-childitem -path “Registry::$_”
    $colDevKey | foreach-object {
    $intConfigFlags = (Get-ItemProperty -Path “Registry::$_” -Name “ConfigFlags” -ErrorAction SilentlyContinue).ConfigFlags
    If ( ($intConfigFlags -ne $null) -and ($intConfigFlags -ne 0) ) {
    Write-Host “Configflags found on $_. ConfigFlags setting is: $intConfigFlags”
    $strDeviceDesc = ((Get-ItemProperty -Path “Registry::$_” -Name “DeviceDesc” -ErrorAction SilentlyContinue).DeviceDesc).ToUpper()
    Write-Host $strDeviceDesc
    $SearchText = $SearchText.ToUpper()
    if ($strDeviceDesc.contains($SearchText)) {
    Write-Host “SearchText: $SearchText found in DeviceDesc key: $strDeviceDesc”
    Set-ItemProperty -Path “Registry::$_” -Name “ConfigFlags” -Value 0 | Out-Null
    Write-Host “ConfigFlags has been set to 0.”
    }
    }
    }
    }
    } catch {
    Write-Host “Error enumerating registry keys looking for:. error msg: ” + $_
    }

    # End logging
    Write-Host ” ”
    Write-Host “Script done.”
    Stop-Transcript

    the script is run with the parameters -enumsubkey and -searchtext. Searchtext is the string to look for in the ‘DeviceDesc’ registry key, so for instance:
    -enumsubkey “USB” -searchtext “ThinkPad Bluetooth 3.0″
    will fix the Lenovo Bluetooth driver.

  21. John says:

    Hi Boyd,
    Recently I faced same problem as yours, but a little difference is the UAC pop up every time when these systems boot, it’s trouble me, may i have some support from you? Thanks in advance!

Leave a Reply

Panorama Theme by Themocracy