ATI Radeon Causes a UAC Prompt at User Logon
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 0×0. I went back and looked found that, after the display adapter is installed and before the UAC prompt, ConfigFlags is set to 0×00020000. 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 0×0.

![[del.icio.us]](http://iboyd.net/wp-content/plugins/bookmarkify/delicious.png)
![[Digg]](http://iboyd.net/wp-content/plugins/bookmarkify/digg.png)
![[Facebook]](http://iboyd.net/wp-content/plugins/bookmarkify/facebook.png)
![[StumbleUpon]](http://iboyd.net/wp-content/plugins/bookmarkify/stumbleupon.png)
![[Twitter]](http://iboyd.net/wp-content/plugins/bookmarkify/twitter.png)
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
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.
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.
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…
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.
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
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.”
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?
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:
Ah Thanks for the info – I will give this a shot.
Sorry typo, REG ADD*
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
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
I know this is a late reply, but thanks for sharing!
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
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
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.
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
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
Your explanation is fantastic and exactly what I needed to prompt Dell to hopefully resolve this issue on their Optiplex 780 drivers.
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.
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
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.
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.
Good call… very similar to COnexant audio driver issue on http://forums.techarena.in/windows-software/1426799.htm
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
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!
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.
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.
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!