Sign in to follow this  
Followers 0
seanhart

RegWriteAllUsers / RegDeleteAllUsers

25 posts in this topic

#1 ·  Posted (edited)

I needed to do this for work recently and thought I'd share it. Here is a UDF which allows you to write a user specific registry key to ever user profile on the system (whether logged on or off). Includes the "default user" registry, so changes apply to any new users that log on as well.

Examples:

; Give everyone a new IE home page (note you don't need HKCU)

RegWriteAllUsers("Software\Microsoft\Internet Explorer\Main", "Start Page", "REG_SZ", "http://www.google.com")

; Delete everyone's custom wallpaper (note it you can use HKCU if you want)

RegDeleteAllUsers("HKEY_CURRENT_USER\Control Panel\Desktop", "WallPaper")

Code uses RegLoadHive functions by Larry.

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.2.2.0
 Author:         Sean Hart

 Script Function:
    UDFs to write or delete registry keys from all user profiles on the system.
    
    Uses RegLoadHive functions provided by Larry

#ce ----------------------------------------------------------------------------


; === RegWriteAllUsers ===
; Writes "current user" registry data to every user profile on the system.
; Requires RegLoadHive and RegUnLoadHive functions.
;
; Inputs:   $key    - see RegWrite function for details (no HKU\HKCU\HKLM required)
;           $value  - see RegWrite function for details
;           $type   - see RegWrite function for details
;           $data   - see RegWrite function for details
;
; Returns:  nothing
Func RegWriteAllUsers($key, $value, $type, $data)
    Dim $i, $curkey, $ExpandEnvStrings, $profiledir, $curdir, $search
    
    ; init variables
    $i = 1
    $error = 0
    $ExpandEnvStrings = Opt("ExpandEnvStrings",1)
    $profiledir = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList", "ProfilesDirectory")
    
    ; change directory to profile directory
    $curdir = @WorkingDir
    FileChangeDir($profiledir)
    
    ; replace HKU / HKCU / HKLM in key if require
    Select
    Case StringLeft($key, 4) = "HKU\"
        $key = StringRight($key, StringLen($key) - 4)
    Case StringLeft($key, 5) = "HKCU\"
        $key = StringRight($key, StringLen($key) - 5)
    Case StringLeft($key, 5) = "HKLM\"
        $key = StringRight($key, StringLen($key) - 5)
    Case StringLeft($key, 11) = "HKEY_USERS\"
        $key = StringRight($key, StringLen($key) - 11)
    Case StringLeft($key, 18) = "HKEY_CURRENT_USER\"
        $key = StringRight($key, StringLen($key) - 18)
    Case StringLeft($key, 19) = "HKEY_LOCAL_MACHINE\"
        $key = StringRight($key, StringLen($key) - 19)
    EndSelect
    
    ; Go through all directories where ntuser.dat is accessible
    $search = FileFindFirstFile("*.*")
    $dir = FileFindNextFile($search)
    While @error = 0
        ; Process directories
        If StringInStr(FileGetAttrib($profiledir & "\" & $dir), "D") Then
            ; Check for ntuser.dat
            If FileExists($profiledir & "\" & $dir & "\ntuser.dat") Then
                ; Try and load hive
                If RegLoadHive("TempUser", $profiledir & "\" & $dir & "\ntuser.dat") Then
                    ; Apply new registry data
                    RegWrite("HKEY_USERS\TempUser\" & $key, $value, $type, $data)
                    
                    ; Unload hive
                    RegUnloadHive("TempUser")
                EndIf
            EndIf
        EndIf
        $dir = FileFindNextFile($search)
    WEnd
    
    ; Start by going through all currently logged on user keys (exclude system accounts and classes)
    $curkey = RegEnumKey("HKEY_USERS", $i)
    While @error = 0
        If (StringLen($curkey) > 8) And (Not StringInStr($curkey, "_Classes")) Then
            RegWrite("HKEY_USERS\" & $curkey & "\" & $key, $value, $type, $data)
        EndIf
        $i = $i + 1
        $curkey = RegEnumKey("HKEY_USERS", $i)
    WEnd
    
    ; Put settings back and change back to previous directory
    Opt("ExpandEnvStrings",$ExpandEnvStrings)
    FileChangeDir($curdir)
    
EndFunc
; === END RegWriteAllUsers ===


; === RegDeleteAllUsers ===
; Deletes "current user" registry data from every user profile on the system.
; Requires RegLoadHive and RegUnLoadHive functions.
;
; Inputs:   $key    - see RegDelete function for details (no HKU\HKCU\HKLM required)
;           $value  - (optional) see RegDelete function for details
;
; Returns:  nothing
Func RegDeleteAllUsers($key, $value = "ÿ")
    Dim $i, $curkey, $ExpandEnvStrings, $profiledir, $curdir, $search
    
    ; init variables
    $i = 1
    $error = 0
    $ExpandEnvStrings = Opt("ExpandEnvStrings",1)
    $profiledir = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList", "ProfilesDirectory")
    
    ; change directory to profile directory
    $curdir = @WorkingDir
    FileChangeDir($profiledir)
    
    ; replace HKU / HKCU / HKLM in key if require
    Select
    Case StringLeft($key, 4) = "HKU\"
        $key = StringRight($key, StringLen($key) - 4)
    Case StringLeft($key, 5) = "HKCU\"
        $key = StringRight($key, StringLen($key) - 5)
    Case StringLeft($key, 5) = "HKLM\"
        $key = StringRight($key, StringLen($key) - 5)
    Case StringLeft($key, 11) = "HKEY_USERS\"
        $key = StringRight($key, StringLen($key) - 11)
    Case StringLeft($key, 18) = "HKEY_CURRENT_USER\"
        $key = StringRight($key, StringLen($key) - 18)
    Case StringLeft($key, 19) = "HKEY_LOCAL_MACHINE\"
        $key = StringRight($key, StringLen($key) - 19)
    EndSelect

    ; Go through all directories where ntuser.dat is accessible
    $search = FileFindFirstFile("*.*")
    $dir = FileFindNextFile($search)
    While @error = 0
        ; Process directories
        If StringInStr(FileGetAttrib($profiledir & "\" & $dir), "D") Then
            ; Check for ntuser.dat
            If FileExists($profiledir & "\" & $dir & "\ntuser.dat") Then
                ; Try and load hive
                If RegLoadHive("TempUser", $profiledir & "\" & $dir & "\ntuser.dat") Then
                    ; Delete registry data
                    If $value = "ÿ" Then
                        RegDelete("HKEY_USERS\TempUser\" & $key)
                    Else
                        RegDelete("HKEY_USERS\TempUser\" & $key, $value)
                    EndIf
                    
                    ; Unload hive
                    RegUnloadHive("TempUser")
                EndIf
            EndIf
        EndIf
        $dir = FileFindNextFile($search)
    WEnd
    
    ; Start by going through all currently logged on user keys (exclude system accounts and classes)
    $curkey = RegEnumKey("HKEY_USERS", $i)
    While @error = 0
        If (StringLen($curkey) > 8) And (Not StringInStr($curkey, "_Classes")) Then
            ; Delete registry data
            If $value = "ÿ" Then
                RegDelete("HKEY_USERS\" & $curkey & "\" & $key)
            Else
                RegDelete("HKEY_USERS\" & $curkey & "\" & $key, $value)
            EndIf
        EndIf
        $i = $i + 1
        $curkey = RegEnumKey("HKEY_USERS", $i)
    WEnd
    
EndFunc
; === END RegDeleteAllUsers ===


; === RegLoadHive ===
; Loads a ntuser.dat file as a registry hive
; Requires SetPrivilege function.
;
; Inputs:   $hiveName       - name for the hive
;           $NTUSER_datFile - full path to ntuser.dat file to load
;           $RLH_key        - (optional) root for hive (defaults to HKU)
;
; Returns:  1 - Successful
;           0 - Error (sets @error)
Func RegLoadHive($hiveName, $NTUSER_datFile, $RLH_key = "HKU")
    If Not (@OSTYPE=="WIN32_NT") Then
        SetError(-1)
        Return 0
    EndIf
    Const $HKEY_LOCAL_MACHINE = 0x80000002
    Const $HKEY_USERS = 0x80000003
    Const $SE_RESTORE_NAME = "SeRestorePrivilege"
    Const $SE_BACKUP_NAME = "SeBackupPrivilege"
    Local $RLH_ret
    Local $aPriv[2]
    If $RLH_key = "HKLM" Then
        $RLH_key = $HKEY_LOCAL_MACHINE
    ElseIf $RLH_key = "HKU" Then
        $RLH_key = $HKEY_USERS
    Else
        SetError(-2)
        Return 0
    EndIf
    $aPriv[0] = $SE_RESTORE_NAME
    $aPriv[1] = $SE_BACKUP_NAME
    SetPrivilege($aPriv,1)
    $RLH_ret = DllCall("Advapi32.dll","int","RegLoadKey","int",$RLH_key,"str",$hiveName,"str",$NTUSER_datFile)
    SetError($RLH_ret[0])
    Return Not $RLH_ret[0]
EndFunc
; === END RegLoadHive ===


; === RegUnloadHive ===
; Unloads a registry hive
; Requires SetPrivilege function.
;
; Inputs:   $hiveName       - name for the hive
;           $RLH_key        - (optional) root for hive (defaults to HKU)
;
; Returns:  1 - Successful
;           0 - Error (sets @error)
Func RegUnloadHive($hiveName, $RUH_key = "HKU")
    If Not (@OSTYPE=="WIN32_NT") Then
        SetError(-1)
        Return 0
    EndIf
    Const $HKEY_LOCAL_MACHINE = 0x80000002
    Const $HKEY_USERS = 0x80000003
    Local $RUH_ret
    If $RUH_key = "HKLM" Then
        $RUH_key = $HKEY_LOCAL_MACHINE
    ElseIf $RUH_key = "HKU" Then
        $RUH_key = $HKEY_USERS
    Else
        SetError(-2)
        Return 0
    EndIf
    $RUH_ret = DllCall("Advapi32.dll","int","RegUnLoadKey","int",$RUH_key,"Str",$hiveName)
    Return Not $RUH_ret[0]
EndFunc
; === RegUnloadHive ===


; === SetPrivilege ===
; Special function for use with registry hive functions
Func SetPrivilege( $privilege, $bEnable )
    Const $TOKEN_ADJUST_PRIVILEGES = 0x0020
    Const $TOKEN_QUERY = 0x0008
    Const $SE_PRIVILEGE_ENABLED = 0x0002
    Local $hToken, $SP_auxret, $SP_ret, $hCurrProcess, $nTokens, $nTokenIndex, $priv
    $nTokens = 1
    $LUID = DLLStructCreate("dword;int")
    If IsArray($privilege) Then    $nTokens = UBound($privilege)
    $TOKEN_PRIVILEGES = DLLStructCreate("dword;dword[" & (3 * $nTokens) & "]")
    $NEWTOKEN_PRIVILEGES = DLLStructCreate("dword;dword[" & (3 * $nTokens) & "]")
    $hCurrProcess = DLLCall("kernel32.dll","hwnd","GetCurrentProcess")
    $SP_auxret = DLLCall("advapi32.dll","int","OpenProcessToken","hwnd",$hCurrProcess[0], _
                "int",BitOR($TOKEN_ADJUST_PRIVILEGES,$TOKEN_QUERY),"int_ptr",0)
    If $SP_auxret[0] Then
        $hToken = $SP_auxret[3]
        DLLStructSetData($TOKEN_PRIVILEGES,1,1)
        $nTokenIndex = 1
        While $nTokenIndex <= $nTokens
            If IsArray($privilege) Then
                $priv = $privilege[$nTokenIndex-1]
            Else
                $priv = $privilege
            EndIf
            $ret = DLLCall("advapi32.dll","int","LookupPrivilegeValue","str","","str",$priv, _
                        "ptr",DLLStructGetPtr($LUID))
            If $ret[0] Then
                If $bEnable Then
                    DLLStructSetData($TOKEN_PRIVILEGES,2,$SE_PRIVILEGE_ENABLED,(3 * $nTokenIndex))
                Else
                    DLLStructSetData($TOKEN_PRIVILEGES,2,0,(3 * $nTokenIndex))
                EndIf
                DLLStructSetData($TOKEN_PRIVILEGES,2,DllStructGetData($LUID,1),(3 * ($nTokenIndex-1)) + 1)
                DLLStructSetData($TOKEN_PRIVILEGES,2,DllStructGetData($LUID,2),(3 * ($nTokenIndex-1)) + 2)
                DLLStructSetData($LUID,1,0)
                DLLStructSetData($LUID,2,0)
            EndIf
            $nTokenIndex += 1
        WEnd
        $ret = DLLCall("advapi32.dll","int","AdjustTokenPrivileges","hwnd",$hToken,"int",0, _
            "ptr",DllStructGetPtr($TOKEN_PRIVILEGES),"int",DllStructGetSize($NEWTOKEN_PRIVILEGES), _
            "ptr",DllStructGetPtr($NEWTOKEN_PRIVILEGES),"int_ptr",0)
        $f = DLLCall("kernel32.dll","int","GetLastError")
    EndIf
    $NEWTOKEN_PRIVILEGES = 0
    $TOKEN_PRIVILEGES = 0
    $LUID = 0
    If $SP_auxret[0] = 0 Then Return 0
    $SP_auxret = DLLCall("kernel32.dll","int","CloseHandle","hwnd",$hToken)
    If Not $ret[0] And Not $SP_auxret[0] Then Return 0
    return $ret[0]
EndFunc
; === END SetPrivilege ===

RegAllUsers.au3

Edited by seanhart

Share this post


Link to post
Share on other sites



thats nice, keep up the good work!

Share this post


Link to post
Share on other sites

Can I ask what systems you have tested this on?

Such as WinXP, Win2k3 and if it is x86 or x64.

Thanks

Share this post


Link to post
Share on other sites

it's a Good Script . :)

Share this post


Link to post
Share on other sites

Can I ask what systems you have tested this on?

Such as WinXP, Win2k3 and if it is x86 or x64.

Thanks

I've tested on Win 2K, XP, and Vista (UAC turned off).

Can't speak for 2003 (though it should work) or 64bit.

Thanks to everyone else for the comments.

Share this post


Link to post
Share on other sites

First thing good job.

I written reg all script in vb, kix, Autoit. So am very familiar with the concept.

I see 2 problems.

1. Getting Profile Directory value is ok but then you have to enumerate the files which will take longer. It's best to go enumerate the profilelist for each S-1-5-21-XXXX is a user profile within each one you will see string "ProfileImagepath" that has a value exp.("%systemdrive%\Documents and Settings\JoeSmith") then all you need to add is \ntdat.dat". There is another reason why you want to do this. That would be in #2

2. Another issue is if the hive is already loaded it will fail. It is not uncommon for having two or more hives loaded at the same time it is only because when enduser logs off it doesn't unload for some reason. So how to resolve of it is easy you need to verify first if it's loaded. if you enumerate each profilelist it has a unique S-1-5-21-XXXXX then verify under the HKEY_USERS you will find the Unique Profile ID if its there then its loaded. Then you will just need to write the keys there. If you dont find it then use the value for "profileImagePath" while adding "\ntdat.at" then write to it.

If you do it this way it should run faster and wont skip any profiles.

Ignore S-1-5-18,S-1-5-19, and S-1-5-20 are for your local admin accounts exp(network,system accounts)

Share this post


Link to post
Share on other sites

First thing good job.

I written reg all script in vb, kix, Autoit. So am very familiar with the concept.

I see 2 problems.

1. Getting Profile Directory value is ok but then you have to enumerate the files which will take longer. It's best to go enumerate the profilelist for each S-1-5-21-XXXX is a user profile within each one you will see string "ProfileImagepath" that has a value exp.("%systemdrive%\Documents and Settings\JoeSmith") then all you need to add is \ntdat.dat". There is another reason why you want to do this. That would be in #2

2. Another issue is if the hive is already loaded it will fail. It is not uncommon for having two or more hives loaded at the same time it is only because when enduser logs off it doesn't unload for some reason. So how to resolve of it is easy you need to verify first if it's loaded. if you enumerate each profilelist it has a unique S-1-5-21-XXXXX then verify under the HKEY_USERS you will find the Unique Profile ID if its there then its loaded. Then you will just need to write the keys there. If you dont find it then use the value for "profileImagePath" while adding "\ntdat.at" then write to it.

If you do it this way it should run faster and wont skip any profiles.

Ignore S-1-5-18,S-1-5-19, and S-1-5-20 are for your local admin accounts exp(network,system accounts)

Thanks cryn for the feedback. I agree with you for point 1, it probably is faster to load files based on enumerating the profilelist in the registry. I've used that key in the past but didn't think about it for this use, good idea.

Your second point isn't quite right though. I've written the script to try every ntuser.dat file in the profile folder, and you are correct that any profiles in use will fail. However the second part of the code then enumerates all loaded profile keys under HKU which will catch the ones that failed earlier. So it's not quite as clean as it can be but it does work for all profiles. I have excluded local system accounts by ignoring SIDs with 8 or less characters.

I might re-write with some of your recommendations if I have time, thanks for them.

Sean

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

np i guess it's just coding preference then either way good job on the script.

Edited by cryn

Share this post


Link to post
Share on other sites

Anyone still have the original RegLoadHive? I cannot locate it using search.

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

Anyone still have the original RegLoadHive? I cannot locate it using search.

All functions from the original RegLoadHive by Larry are included in seanhart's 1st post above.

They are:

  • Func RegLoadHive

  • Func RegUnloadHive

  • Func SetPrivilege
Also, note that DllStructDelete has been removed from AutoIt3.

From the Help file:

To release allocated memory just reset the returned variable to 0

Sadly, the original post of Larry's code got deleted when he left the forum :)

Edited by ResNullius

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

I just want to say thank you for the script you wrote. I also added 2 additional functions to Copy and Delete files and made sure all the variables were defined as I always force variables to be declared out of habit.

AllUsers.au3

CODE

#include-once

#cs ----------------------------------------------------------------------------

AutoIt Version: 3.2.8.1

Author: Todd Murray

Credit: Based on code written by Sean Hart and Larry from the AutoIT Forums

http://www.autoitscript.com/forum/index.ph...egWriteAllUsers

Script Function:

UDFs to write or delete files and registry keys from all user profiles on the system.

Uses RegLoadHive functions provided by Larry

#ce ----------------------------------------------------------------------------

; === FileCopyAllUsers ===

; Writes files to every user profile on the system (Do not include path to profile)

; Requires RegLoadHive and RegUnLoadHive functions.

;

; Inputs: $source - see FileCopy function for details

; $dest - see FileCopy function for details.

; $flag - see FileCopy function for details.

; $attrib - Numberal value indicating what profiles to apply the change to.

; 1 - user

; 2 - default

; 4 - all users

; 8 - system

;

; Enter the numeric value for which profiles you want to affect. To handle

; multiple types add the value's together. 1-15 are appropriate input with

; 15 meaning all profiles.

;

; Returns: nothing

Func FileCopyAllUsers($source, $dest, $flag, $attrib)

Dim $error, $ExpandEnvStrings, $AllUsersProfile, $DefaultUserProfile, $ProfilesDirectory, $curdir, $search, $profile, $SystemDirectoryAttribute

; init variables

$error = 0

$ExpandEnvStrings = Opt("ExpandEnvStrings",1)

$AllUsersProfile = RegRead("HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList", "AllUsersProfile")

$DefaultUserProfile = RegRead("HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList", "DefaultUserProfile")

$ProfilesDirectory = RegRead("HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList", "ProfilesDirectory")

$source = @ScriptDir & "\" & $source

; change directory to profile directory

$curdir = @WorkingDir

FileChangeDir($ProfilesDirectory)

; Go through all directories

$search = FileFindFirstFile("*.*")

$profile = FileFindNextFile($search)

While @error = 0

; Checks to ensure the target is a directory

If StringRegExp(FileGetAttrib($profile), "D", 0) <> 0 Then

$SystemDirectoryAttribute = StringRegExp(FileGetAttrib($profile), "SHD", 0)

Switch $attrib

Case 1; User Profiles

If $profile <> $AllUsersProfile And $profile <> $DefaultUserProfile And $SystemDirectoryAttribute = False Then

FileCopy($source, $ProfilesDirectory & "\" & $profile & $dest, $flag)

EndIf

Case 2; Default User Profile

If $profile = $DefaultUserProfile Then

FileCopy($source, $ProfilesDirectory & "\" & $profile & $dest, $flag)

EndIf

Case 3; User Profiles + Default User Profile

If $profile <> $AllUsersProfile And $SystemDirectoryAttribute = False Then

FileCopy($source, $ProfilesDirectory & "\" & $profile & $dest, $flag)

EndIf

Case 4; All Users Profile

If $profile = $AllUsersProfile Then

FileCopy($source, $ProfilesDirectory & "\" & $profile & $dest, $flag)

EndIf

Case 5; User Profiles + All Users Profile

If $profile = $DefaultUserProfile And $SystemDirectoryAttribute = False Then

FileCopy($source, $ProfilesDirectory & "\" & $profile & $dest, $flag)

EndIf

Case 6; Default User Profile + All Users Profile

If $profile = $DefaultUserProfile Or $profile = $AllUsersProfile Then

FileCopy($source, $ProfilesDirectory & "\" & $profile & $dest, $flag)

EndIf

Case 7; User Profiles + Default User Profile + All Users Profile

If $SystemDirectoryAttribute = False Then

FileCopy($source, $ProfilesDirectory & "\" & $profile & $dest, $flag)

EndIf

Case 8; System Profiles

If $SystemDirectoryAttribute = True Then

FileCopy($source, $ProfilesDirectory & "\" & $profile & $dest, $flag)

EndIf

Case 9; User Profiles + System Profiles

If $profile <> $AllUsersProfile And $profile <> $DefaultUserProfile Then

FileCopy($source, $ProfilesDirectory & "\" & $profile & $dest, $flag)

EndIf

Case 10; Default User Profile + System Profiles

If $profile = $DefaultUserProfile Or $SystemDirectoryAttribute = True Then

FileCopy($source, $ProfilesDirectory & "\" & $profile & $dest, $flag)

EndIf

Case 11; User Profiles + Default User Profile + System Profiles

If $profile <> $AllUsersProfile Then

FileCopy($source, $ProfilesDirectory & "\" & $profile & $dest, $flag)

EndIf

Case 12; All Users Profile + System Profiles

If $profile = $AllUsersProfile Or $SystemDirectoryAttribute = True Then

FileCopy($source, $ProfilesDirectory & "\" & $profile & $dest, $flag)

EndIf

Case 13; User Profiles + All Users Profile + System Profiles

If $profile <> $DefaultUserProfile Then

FileCopy($source, $ProfilesDirectory & "\" & $profile & $dest, $flag)

EndIf

Case 14; Default User Profile + All Users Profile + System Profiles

If $profile = $AllUsersProfile Or $profile = $DefaultUserProfile Or $SystemDirectoryAttribute = True Then

FileCopy($source, $ProfilesDirectory & "\" & $profile & $dest, $flag)

EndIf

Case 15; User Profiles + Default User Profile + All Users Profile + System Profiles

FileCopy($source, $ProfilesDirectory & "\" & $profile & $dest, $flag)

EndSwitch

EndIf

$profile = FileFindNextFile($search)

WEnd

; Put settings back and change back to previous directory

Opt("ExpandEnvStrings",$ExpandEnvStrings)

FileChangeDir($curdir)

EndFunc

; === END FileCopyAllUsers ===

; === FileDeleteAllUsers ===

; Deletes file from every user profile on the system.

; Requires RegLoadHive and RegUnLoadHive functions.

;

; Inputs: $path - see FileDelete function for details (Do not include path to profile)

; $attrib - Numberal value indicating what profiles to apply the change to.

; 1 - user

; 2 - default

; 4 - all users

; 8 - system

;

; Enter the numeric value for which profiles you want to affect. To handle

; multiple types add the value's together. 1-15 are appropriate input with

; 15 meaning all profiles.

;

; Returns: nothing

Func FileDeleteAllUsers($path, $attrib)

Dim $error, $ExpandEnvStrings, $AllUsersProfile, $DefaultUserProfile, $ProfilesDirectory, $curdir, $search, $profile, $SystemDirectoryAttribute

; init variables

$error = 0

$ExpandEnvStrings = Opt("ExpandEnvStrings",1)

$AllUsersProfile = RegRead("HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList", "AllUsersProfile")

$DefaultUserProfile = RegRead("HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList", "DefaultUserProfile")

$ProfilesDirectory = RegRead("HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList", "ProfilesDirectory")

; change directory to profile directory

$curdir = @WorkingDir

FileChangeDir($ProfilesDirectory)

; Go through all directories

$search = FileFindFirstFile("*.*")

$profile = FileFindNextFile($search)

While @error = 0

; Checks to ensure the target is a directory

If StringRegExp(FileGetAttrib($profile), "D", 0) <> 0 Then

$SystemDirectoryAttribute = StringRegExp(FileGetAttrib($profile), "SHD", 0)

Switch $attrib

Case 1; User Profiles

If $profile <> $AllUsersProfile And $profile <> $DefaultUserProfile And $SystemDirectoryAttribute = False Then

FileDelete($ProfilesDirectory & "\" & $profile & $path)

EndIf

Case 2; Default User Profile

If $profile = $DefaultUserProfile Then

FileDelete($ProfilesDirectory & "\" & $profile & $path)

EndIf

Case 3; User Profiles + Default User Profile

If $profile <> $AllUsersProfile And $SystemDirectoryAttribute = False Then

FileDelete($ProfilesDirectory & "\" & $profile & $path)

EndIf

Case 4; All Users Profile

If $profile = $AllUsersProfile Then

FileDelete($ProfilesDirectory & "\" & $profile & $path)

EndIf

Case 5; User Profiles + All Users Profile

If $profile = $DefaultUserProfile And $SystemDirectoryAttribute = False Then

FileDelete($ProfilesDirectory & "\" & $profile & $path)

EndIf

Case 6; Default User Profile + All Users Profile

If $profile = $DefaultUserProfile Or $profile = $AllUsersProfile Then

FileDelete($ProfilesDirectory & "\" & $profile & $path)

EndIf

Case 7; User Profiles + Default User Profile + All Users Profile

If $SystemDirectoryAttribute = False Then

FileDelete($ProfilesDirectory & "\" & $profile & $path)

EndIf

Case 8; System Profiles

If $SystemDirectoryAttribute = True Then

FileDelete($ProfilesDirectory & "\" & $profile & $path)

EndIf

Case 9; User Profiles + System Profiles

If $profile <> $AllUsersProfile And $profile <> $DefaultUserProfile Then

FileDelete($ProfilesDirectory & "\" & $profile & $path)

EndIf

Case 10; Default User Profile + System Profiles

If $profile = $DefaultUserProfile Or $SystemDirectoryAttribute = True Then

FileDelete($ProfilesDirectory & "\" & $profile & $path)

EndIf

Case 11; User Profiles + Default User Profile + System Profiles

If $profile <> $AllUsersProfile Then

FileDelete($ProfilesDirectory & "\" & $profile & $path)

EndIf

Case 12; All Users Profile + System Profiles

If $profile = $AllUsersProfile Or $SystemDirectoryAttribute = True Then

FileDelete($ProfilesDirectory & "\" & $profile & $path)

EndIf

Case 13; User Profiles + All Users Profile + System Profiles

If $profile <> $DefaultUserProfile Then

FileDelete($ProfilesDirectory & "\" & $profile & $path)

EndIf

Case 14; Default User Profile + All Users Profile + System Profiles

If $profile = $AllUsersProfile Or $profile = $DefaultUserProfile Or $SystemDirectoryAttribute = True Then

FileDelete($ProfilesDirectory & "\" & $profile & $path)

EndIf

Case 15; User Profiles + Default User Profile + All Users Profile + System Profiles

FileDelete($ProfilesDirectory & "\" & $profile & $path)

EndSwitch

EndIf

$profile = FileFindNextFile($search)

WEnd

; Put settings back and change back to previous directory

Opt("ExpandEnvStrings",$ExpandEnvStrings)

FileChangeDir($curdir)

EndFunc

; === END FileDeleteAllUsers ===

; === RegWriteAllUsers ===

; Writes "current user" registry data to every user profile on the system.

; Requires RegLoadHive and RegUnLoadHive functions.

;

; Inputs: $key - see RegWrite function for details (no HKU\HKCU\HKLM required)

; $value - see RegWrite function for details

; $type - see RegWrite function for details

; $data - see RegWrite function for details

;

; Returns: nothing

Func RegWriteAllUsers($key, $value, $type, $data)

Dim $i, $error, $ExpandEnvStrings, $ProfilesDirectory, $curdir, $search, $profile, $curkey

; init variables

$i = 1

$error = 0

$ExpandEnvStrings = Opt("ExpandEnvStrings",1)

$ProfilesDirectory = RegRead("HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList", "ProfilesDirectory")

; change directory to profile directory

$curdir = @WorkingDir

FileChangeDir($ProfilesDirectory)

; replace HKU / HKCU / HKLM in key if require

Select

Case StringLeft($key, 4) = "HKU\"

$key = StringRight($key, StringLen($key) - 4)

Case StringLeft($key, 5) = "HKCU\"

$key = StringRight($key, StringLen($key) - 5)

Case StringLeft($key, 5) = "HKLM\"

$key = StringRight($key, StringLen($key) - 5)

Case StringLeft($key, 11) = "HKEY_USERS\"

$key = StringRight($key, StringLen($key) - 11)

Case StringLeft($key, 18) = "HKEY_CURRENT_USER\"

$key = StringRight($key, StringLen($key) - 18)

Case StringLeft($key, 19) = "HKEY_LOCAL_MACHINE\"

$key = StringRight($key, StringLen($key) - 19)

EndSelect

; Go through all directories where ntuser.dat is accessible

$search = FileFindFirstFile("*.*")

$profile = FileFindNextFile($search)

While @error = 0

; Process directories

If StringInStr(FileGetAttrib($ProfilesDirectory & "\" & $profile), "D") Then

; Check for ntuser.dat

If FileExists($ProfilesDirectory & "\" & $profile & "\ntuser.dat") Then

; Try and load hive

If RegLoadHive("TempUser", $ProfilesDirectory & "\" & $profile & "\ntuser.dat") Then

; Apply new registry data

RegWrite("HKEY_USERS\TempUser\" & $key, $value, $type, $data)

; Unload hive

RegUnloadHive("TempUser")

EndIf

EndIf

EndIf

$profile = FileFindNextFile($search)

WEnd

; Start by going through all currently logged on user keys (exclude system accounts and classes)

$curkey = RegEnumKey("HKEY_USERS", $i)

While @error = 0

If (StringLen($curkey) > 8) And (Not StringInStr($curkey, "_Classes")) Then

RegWrite("HKEY_USERS\" & $curkey & "\" & $key, $value, $type, $data)

EndIf

$i = $i + 1

$curkey = RegEnumKey("HKEY_USERS", $i)

WEnd

; Put settings back and change back to previous directory

Opt("ExpandEnvStrings",$ExpandEnvStrings)

FileChangeDir($curdir)

EndFunc

; === END RegWriteAllUsers ===

; === RegDeleteAllUsers ===

; Deletes "current user" registry data from every user profile on the system.

; Requires RegLoadHive and RegUnLoadHive functions.

;

; Inputs: $key - see RegDelete function for details (no HKU\HKCU\HKLM required)

; $value - (optional) see RegDelete function for details

;

; Returns: nothing

Func RegDeleteAllUsers($key, $value = "ÿ")

Dim $i, $error, $ExpandEnvStrings, $ProfilesDirectory, $curdir, $search, $profile, $curkey

; init variables

$i = 1

$error = 0

$ExpandEnvStrings = Opt("ExpandEnvStrings",1)

$ProfilesDirectory = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList", "ProfilesDirectory")

; change directory to profile directory

$curdir = @WorkingDir

FileChangeDir($ProfilesDirectory)

; replace HKU / HKCU / HKLM in key if require

Select

Case StringLeft($key, 4) = "HKU\"

$key = StringRight($key, StringLen($key) - 4)

Case StringLeft($key, 5) = "HKCU\"

$key = StringRight($key, StringLen($key) - 5)

Case StringLeft($key, 5) = "HKLM\"

$key = StringRight($key, StringLen($key) - 5)

Case StringLeft($key, 11) = "HKEY_USERS\"

$key = StringRight($key, StringLen($key) - 11)

Case StringLeft($key, 18) = "HKEY_CURRENT_USER\"

$key = StringRight($key, StringLen($key) - 18)

Case StringLeft($key, 19) = "HKEY_LOCAL_MACHINE\"

$key = StringRight($key, StringLen($key) - 19)

EndSelect

; Go through all directories where ntuser.dat is accessible

$search = FileFindFirstFile("*.*")

$profile = FileFindNextFile($search)

While @error = 0

; Process directories

If StringInStr(FileGetAttrib($ProfilesDirectory & "\" & $profile), "D") Then

; Check for ntuser.dat

If FileExists($ProfilesDirectory & "\" & $profile & "\ntuser.dat") Then

; Try and load hive

If RegLoadHive("TempUser", $ProfilesDirectory & "\" & $profile & "\ntuser.dat") Then

; Delete registry data

If $value = "ÿ" Then

RegDelete("HKEY_USERS\TempUser\" & $key)

Else

RegDelete("HKEY_USERS\TempUser\" & $key, $value)

EndIf

; Unload hive

RegUnloadHive("TempUser")

EndIf

EndIf

EndIf

$profile = FileFindNextFile($search)

WEnd

; Start by going through all currently logged on user keys (exclude system accounts and classes)

$curkey = RegEnumKey("HKEY_USERS", $i)

While @error = 0

If (StringLen($curkey) > 8) And (Not StringInStr($curkey, "_Classes")) Then

; Delete registry data

If $value = "ÿ" Then

RegDelete("HKEY_USERS\" & $curkey & "\" & $key)

Else

RegDelete("HKEY_USERS\" & $curkey & "\" & $key, $value)

EndIf

EndIf

$i = $i + 1

$curkey = RegEnumKey("HKEY_USERS", $i)

WEnd

EndFunc

; === END RegDeleteAllUsers ===

; === RegLoadHive ===

; Loads a ntuser.dat file as a registry hive

; Requires SetPrivilege function.

;

; Inputs: $hiveName - name for the hive

; $NTUSER_datFile - full path to ntuser.dat file to load

; $RLH_key - (optional) root for hive (defaults to HKU)

;

; Returns: 1 - Successful

; 0 - Error (sets @error)

Func RegLoadHive($hiveName, $NTUSER_datFile, $RLH_key = "HKU")

If Not (@OSTYPE=="WIN32_NT") Then

SetError(-1)

Return 0

EndIf

Const $HKEY_LOCAL_MACHINE = 0x80000002

Const $HKEY_USERS = 0x80000003

Const $SE_RESTORE_NAME = "SeRestorePrivilege"

Const $SE_BACKUP_NAME = "SeBackupPrivilege"

Local $RLH_ret

Local $aPriv[2]

If $RLH_key = "HKLM" Then

$RLH_key = $HKEY_LOCAL_MACHINE

ElseIf $RLH_key = "HKU" Then

$RLH_key = $HKEY_USERS

Else

SetError(-2)

Return 0

EndIf

$aPriv[0] = $SE_RESTORE_NAME

$aPriv[1] = $SE_BACKUP_NAME

SetPrivilege($aPriv,1)

$RLH_ret = DllCall("Advapi32.dll","int","RegLoadKey","int",$RLH_key,"str",$hiveName,"str",$NTUSER_datFile)

SetError($RLH_ret[0])

Return Not $RLH_ret[0]

EndFunc

; === END RegLoadHive ===

; === RegUnloadHive ===

; Unloads a registry hive

; Requires SetPrivilege function.

;

; Inputs: $hiveName - name for the hive

; $RLH_key - (optional) root for hive (defaults to HKU)

;

; Returns: 1 - Successful

; 0 - Error (sets @error)

Func RegUnloadHive($hiveName, $RUH_key = "HKU")

If Not (@OSTYPE=="WIN32_NT") Then

SetError(-1)

Return 0

EndIf

Const $HKEY_LOCAL_MACHINE = 0x80000002

Const $HKEY_USERS = 0x80000003

Local $RUH_ret

If $RUH_key = "HKLM" Then

$RUH_key = $HKEY_LOCAL_MACHINE

ElseIf $RUH_key = "HKU" Then

$RUH_key = $HKEY_USERS

Else

SetError(-2)

Return 0

EndIf

$RUH_ret = DllCall("Advapi32.dll","int","RegUnLoadKey","int",$RUH_key,"Str",$hiveName)

Return Not $RUH_ret[0]

EndFunc

; === RegUnloadHive ===

; === SetPrivilege ===

; Special function for use with registry hive functions

Func SetPrivilege( $privilege, $bEnable )

Const $TOKEN_ADJUST_PRIVILEGES = 0x0020

Const $TOKEN_QUERY = 0x0008

Const $SE_PRIVILEGE_ENABLED = 0x0002

Local $hToken, $LUID, $TOKEN_PRIVILEGES, $NEWTOKEN_PRIVILEGES, $SP_auxret, $SP_ret, $hCurrProcess, $nTokens, $nTokenIndex, $priv, $ret, $f

$nTokens = 1

$LUID = DLLStructCreate("dword;int")

If IsArray($privilege) Then $nTokens = UBound($privilege)

$TOKEN_PRIVILEGES = DLLStructCreate("dword;dword[" & (3 * $nTokens) & "]")

$NEWTOKEN_PRIVILEGES = DLLStructCreate("dword;dword[" & (3 * $nTokens) & "]")

$hCurrProcess = DLLCall("kernel32.dll","hwnd","GetCurrentProcess")

$SP_auxret = DLLCall("advapi32.dll","int","OpenProcessToken","hwnd",$hCurrProcess[0], _

"int",BitOR($TOKEN_ADJUST_PRIVILEGES,$TOKEN_QUERY),"int_ptr",0)

If $SP_auxret[0] Then

$hToken = $SP_auxret[3]

DLLStructSetData($TOKEN_PRIVILEGES,1,1)

$nTokenIndex = 1

While $nTokenIndex <= $nTokens

If IsArray($privilege) Then

$priv = $privilege[$nTokenIndex-1]

Else

$priv = $privilege

EndIf

$ret = DLLCall("advapi32.dll","int","LookupPrivilegeValue","str","","str",$priv, _

"ptr",DLLStructGetPtr($LUID))

If $ret[0] Then

If $bEnable Then

DLLStructSetData($TOKEN_PRIVILEGES,2,$SE_PRIVILEGE_ENABLED,(3 * $nTokenIndex))

Else

DLLStructSetData($TOKEN_PRIVILEGES,2,0,(3 * $nTokenIndex))

EndIf

DLLStructSetData($TOKEN_PRIVILEGES,2,DllStructGetData($LUID,1),(3 * ($nTokenIndex-1)) + 1)

DLLStructSetData($TOKEN_PRIVILEGES,2,DllStructGetData($LUID,2),(3 * ($nTokenIndex-1)) + 2)

DLLStructSetData($LUID,1,0)

DLLStructSetData($LUID,2,0)

EndIf

$nTokenIndex += 1

WEnd

$ret = DLLCall("advapi32.dll","int","AdjustTokenPrivileges","hwnd",$hToken,"int",0, _

"ptr",DllStructGetPtr($TOKEN_PRIVILEGES),"int",DllStructGetSize($NEWTOKEN_PRIVILEGES), _

"ptr",DllStructGetPtr($NEWTOKEN_PRIVILEGES),"int_ptr",0)

$f = DLLCall("kernel32.dll","int","GetLastError")

EndIf

$NEWTOKEN_PRIVILEGES = 0

$TOKEN_PRIVILEGES = 0

$LUID = 0

If $SP_auxret[0] = 0 Then Return 0

$SP_auxret = DLLCall("kernel32.dll","int","CloseHandle","hwnd",$hToken)

If Not $ret[0] And Not $SP_auxret[0] Then Return 0

return $ret[0]

EndFunc

; === END SetPrivilege ===

I'll also be posting code for disabling the Acrobat updater in versions 5.x, 6.x, 7.x, and 8.x utilizing this code.

Edited by ToddMurray

Share this post


Link to post
Share on other sites

Anyone have this working on v3.2.10.0 ?

Share this post


Link to post
Share on other sites

Anyone have this working on v3.2.10.0 ?

I just noticed it appears to be broken on v3.2.10.0, some of the constants appear to be in use already (e.g. $SE_RESTORE_NAME, $TOKEN_ADJUST_PRIVILEGES). Does anyone know if these have been added as internal constants now?

I'll take a look around and see what I can find. In the mean time just renaming the constants should do the trick.

Share this post


Link to post
Share on other sites

#16 ·  Posted (edited)

Hi seanhart.

I wrote identical functions for this. I consider some of your implementations better than mine. And some of mine better than yours. Here it is what I have until now:

#include-once
#include <Array.au3>
#include <File.au3>

; #INDEX# =======================================================================================================================================
; Title .........: HKCUReg
; AutoIt Version : 3.2.10++
; Language ......: English
; Description ...: Perform registry operations on 'HKCU' for all user accounts on the local computer
; ===============================================================================================================================================

; #CURRENT# =====================================================================================================================================
;_RegWrite
;_RegDelete
;_RegImport
; ===============================================================================================================================================

; #INTERNAL_USE_ONLY#============================================================================================================================
;_ProfileDirList
; ===============================================================================================================================================

Global Const $TempHive = "HKEY_USERS\NTUSER"

; #FUNCTION# ====================================================================================================================================
; Name...........: _RegWrite
; Description ...: Creates a key or value in the registry.
; Syntax.........: _RegWrite($UserLevel, $KeyName [,$ValueName, $Type, $Value])
; Parameters ....: $UserLevel - 0 for current user. 1 for all users.
;                  $KeyName - see RegWrite function for details (no HKCU\ required)
;                  $ValueName - [optional] see RegWrite function for details
;                  $Type - [optional] see RegWrite function for details
;                  $Value - [optional] see RegWrite function for details
; Requirement(s).: Registry Console Tool
; Return values .: @error is set to 1, if $UserLevel is set to 1 and the current user doesn't have full administrator privileges.
; Author ........: engine
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; _RegWrite(1, "Software\7-Zip", "Path", "REG_SZ", @ProgramFilesDir & "\7-Zip")
; ===============================================================================================================================================

Func _RegWrite($UserLevel, $KeyName, $ValueName = "", $Type = "", $Value = "")
    RegWrite("HKCU\" & $KeyName, $ValueName, $Type, $Value)
    Switch $UserLevel
    Case 0
        Return
    Case 1
        If Not IsAdmin() Then Return SetError(1)
    EndSwitch
    
    Local $UserProfileDir = _ProfileDirList()
    
    For $iPath In $UserProfileDir
        If FileExists($iPath & "\NTUSER.DAT") Then
            RunWait("reg load " & $TempHive & " NTUSER.DAT", $iPath, @SW_HIDE)
            RegWrite($TempHive & "\" & $KeyName, $ValueName, $Type, $Value)
            RunWait("reg unload " & $TempHive, "", @SW_HIDE)
        EndIf
    Next
    Return
EndFunc ;==> _RegWrite

; #FUNCTION# ====================================================================================================================================
; Name...........: _RegDelete
; Description ...: Deletes a key or value from the registry.
; Syntax.........: _RegDelete($UserLevel, $KeyName [,$ValueName])
; Parameters ....: $UserLevel - 0 for current user. 1 for all users.
;                  $KeyName - see RegDelete function for details (no HKCU\ required)
;                  $ValueName - [optional] see RegDelete function for details
; Requirement(s).: Registry Console Tool
; Return values .: @error is set to 1, if $UserLevel is set to 1 and the current user doesn't have full administrator privileges.
; Author ........: engine
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; _RegDelete(1, "Software\7-Zip", "Path")
; ===============================================================================================================================================

Func _RegDelete($UserLevel, $KeyName, $ValueName = "")
    RegDelete("HKCU\" & $KeyName, $ValueName)
    Switch $UserLevel
    Case 0
        Return
    Case 1
        If Not IsAdmin() Then Return SetError(1)
    EndSwitch
    
    Local $UserProfileDir = _ProfileDirList()
    
    For $iPath In $UserProfileDir
        If FileExists($iPath & "\NTUSER.DAT") Then
            RunWait("reg load " & $TempHive & " NTUSER.DAT", $iPath, @SW_HIDE)
            RegDelete($TempHive & "\" & $KeyName, $ValueName)
            RunWait("reg unload " & $TempHive, "", @SW_HIDE)
        EndIf
    Next
    Return
EndFunc ;==> _RegDelete

; #FUNCTION# ====================================================================================================================================
; Name...........: _RegImport
; Description ...: Imports a previously exported reg file to the registry.
; Syntax.........: _RegImport($UserLevel, $RegFile)
; Parameters ....: $UserLevel - 0 for current user. 1 for all users.
;                  $RegFile - Path and filename of the file to be imported. File extension (.reg)
; Requirement(s).: Registry Console Tool, #include <Array.au3>, #include <File.au3>
; Return values .: @error is set to 1, if $UserLevel is set to 1 and the current user doesn't have full administrator privileges.
; Author ........: engine
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; _RegImport(1, "ffdshow.reg")
; ===============================================================================================================================================

Func _RegImport($UserLevel, $RegFile)
    RunWait("reg import " & $RegFile, "", @SW_HIDE)
    Switch $UserLevel
    Case 0
        Return
    Case 1
        If Not IsAdmin() Then Return SetError(1)
    EndSwitch
    
    Local $rfArray
    Local $TempRegFile = _TempFile(@UserProfileDir, "~", ".reg")
    Local $UserProfileDir = _ProfileDirList()
    
    _FileReadToArray($RegFile, $rfArray)
    For $j = 1 To $rfArray[0]
        $rfArray[$j] = StringReplace($rfArray[$j], "HKEY_CURRENT_USER", $TempHive)
    Next
    _ArrayDelete($rfArray, 0)
    _FileWriteFromArray($TempRegFile, $rfArray)
    For $iPath In $UserProfileDir
        If FileExists($iPath & "\NTUSER.DAT") Then
            RunWait("reg load " & $TempHive & " NTUSER.DAT", $iPath, @SW_HIDE)
            RunWait('reg import "' & $TempRegFile & '"', "", @SW_HIDE)
            RunWait("reg unload " & $TempHive, "", @SW_HIDE)
        EndIf
    Next
    FileDelete($TempRegFile)
    Return
EndFunc ;==> _RegImport

; #INTERNAL_USE_ONLY#============================================================================================================================
; Name...........: _ProfileDirList
; Description ...: Determine each user's Profile folder.
; Syntax.........: _ProfileDirList($Computer)
; Parameters ....: $Computer - The network name of the computer (optional). The local computer is default.
; Requirement(s).: WMI capable operating system, #include <Array.au3>
; Return values .: Returns an array containing the path to each user's Profile folder, except the current one.
; Author ........: engine
; Modified.......:
; Remarks .......: For internal use only
; Related .......:
; Link ..........;
; Example .......;
; ===============================================================================================================================================

Func _ProfileDirList($Computer = "localhost")
    Local $avArray[1]
    Local Const $ProfileListKey = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
    
    $avArray[0] = RegRead($ProfileListKey, "ProfilesDirectory") & "\" & RegRead($ProfileListKey, "DefaultUserProfile")
    $Account = ObjGet("winmgmts:\\" & $Computer & "\root\CIMV2")
    $aItems = $Account.ExecQuery("Select * from Win32_UserAccount")
    For $ObjAccount In $aItems
        If $ObjAccount.Status = "OK" Then
            _ArrayAdd($avArray, RegRead($ProfileListKey & "\" & $ObjAccount.SID, "ProfileImagePath"))
        EndIf
    Next
    For $j = 0 To UBound($avArray) - 1
        Local $iEnv = StringRegExp($avArray[$j], "\x25\S{1,128}\x25", 1)
        If Not @error Then
            $avArray[$j] = StringReplace($avArray[$j], $iEnv[0], EnvGet(StringReplace($iEnv[0], "%", "")))
        EndIf
    Next
    _ArrayDelete($avArray, _ArraySearch($avArray, @UserProfileDir))
    Return $avArray
EndFunc ;==> _ProfileDirList

I tested this on Windows XP.

I will see if I can use RegLoadHive and RegUnloadHive functions from your script.

Kind regards.

Edited by engine

My contributions:Local account UDF Registry UDFs DriverSigning UDF Windows Services UDF [url="http://www.autoitscript.com/forum/index.php?showtopic=81880"][/url]

Share this post


Link to post
Share on other sites

#17 ·  Posted (edited)

The function "SetPrivilege" isn't working in latest AutoIt version 3.2.12.0 I tried renaming the constants and variables like seanhart suggested, but without success. So I had to keep using registry console tool. I can't understand that function enough to even try to fix it. I rewrote my functions to address cryn's concerns. And added an option to edit a specific account, besides the current user or all users.

#include-once
#include <Array.au3>
#include <File.au3>

; #INDEX# =======================================================================================================================================
; Title .........: HKCUReg
; AutoIt Version : 3.2.10++
; Language ......: English
; Description ...: Perform registry operations on 'HKCU\' for all user accounts on the local computer
; ===============================================================================================================================================

; #CURRENT# =====================================================================================================================================
;_RegWrite
;_RegDelete
;_RegImport
; ===============================================================================================================================================

; #INTERNAL_USE_ONLY#============================================================================================================================
;GetProfile
; ===============================================================================================================================================

; #FUNCTION# ====================================================================================================================================
; Name...........: _RegWrite
; Description ...: Creates a key or value in the registry
; Syntax.........: _RegWrite($user, $key [,$value, $type, $data, $name])
; Parameters ....: $user - 0 for current user
;                          1 for all users or to specify an account name
;                  $key - see RegWrite function for details (no 'HKCU\' required)
;                  $value - [optional] see RegWrite function for details
;                  $type - [optional] see RegWrite function for details
;                  $data - [optional] see RegWrite function for details
;                  $name - [optional] account name, defaults to all users
; Requirement(s).: Registry Console Tool
; Return values .: When $user = 0 return values are the same as RegWrite function
;                  Success - 1
;                  Failure - 0, sets @error to:
;                  |-4 - Registry Console Tool not found on system dir
;                  |-3 - The $user parameter value is wrong
;                  |4 - The operation failed for one or more of the profiles
; Author ........: engine
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; _RegWrite(1, "Software\7-Zip", "Path", "REG_SZ", @ProgramFilesDir & "\7-Zip")
;                  _RegWrite(1, "Software\7-Zip", "Path", "REG_SZ", @ProgramFilesDir & "\7-Zip", "Guest")
; ===============================================================================================================================================

Func _RegWrite($user, $key, $value = "", $type = "", $data = "", $name = "")
    Switch $user
    Case 0
        Return RegWrite("HKCU\" & $key, $value, $type, $data)
    Case 1
        If Not FileExists(@SystemDir & "\reg.exe") Then Return SetError(-4, 0, 0)
    Case Else
        Return SetError(-3, 0, 0)
    EndSwitch
    Local $Profile = GetProfile($name)
    Local $resArray[1]
    For $j = 1 To $Profile[0][0]
        Local $LoadFailed = 1
        If FileExists($Profile[$j][0] & "\NTUSER.DAT") And $Profile[$j][2] = 0 Then
            $LoadFailed = RunWait("reg load " & $Profile[$j][1] & " NTUSER.DAT", $Profile[$j][0], @SW_HIDE)
        EndIf
        Local $Result = RegWrite($Profile[$j][1] & "\" & $key, $value, $type, $data)
        If Not $LoadFailed Then RunWait("reg unload " & $Profile[$j][1], "", @SW_HIDE)
        _ArrayAdd($resArray, $Result)
    Next
    Switch _ArrayMin($resArray, 1, 1)
    Case 0
        Return SetError(4, 0, 0)
    Case 1
        Return 1
    EndSwitch
EndFunc ;==> _RegWrite

; #FUNCTION# ====================================================================================================================================
; Name...........: _RegDelete
; Description ...: Deletes a key or value from the registry
; Syntax.........: _RegDelete($user, $key [,$value, $name])
; Parameters ....: $user - 0 for current user
;                          1 for all users or to specify an account name
;                  $key - see RegDelete function for details (no 'HKCU\' required)
;                  $value - [optional] see RegDelete function for details
;                  $name - [optional] account name, defaults to all users
; Requirement(s).: Registry Console Tool
; Return values .: When $user = 0 return values are the same as RegDelete function
;                  Success - 1
;                  Failure - 0, sets @error to:
;                  |-4 - Registry Console Tool not found on system dir
;                  |-3 - The $user parameter value is wrong
;                  |4 - The operation failed for one or more of the profiles
; Author ........: engine
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; _RegDelete(1, "Software\7-Zip", "Path")
;                  _RegDelete(1, "Software\7-Zip", "Path", "Guest")
; ===============================================================================================================================================

Func _RegDelete($user, $key, $value = "", $name = "")
    Switch $user
    Case 0
        Return RegDelete("HKCU\" & $key, $value)
    Case 1
        If Not FileExists(@SystemDir & "\reg.exe") Then Return SetError(-4, 0, 0)
    Case Else
        Return SetError(-3, 0, 0)
    EndSwitch
    Local $Profile = GetProfile($name)
    Local $resArray[1]
    For $j = 1 To $Profile[0][0]
        Local $LoadFailed = 1
        If FileExists($Profile[$j][0] & "\NTUSER.DAT") And $Profile[$j][2] = 0 Then
            $LoadFailed = RunWait("reg load " & $Profile[$j][1] & " NTUSER.DAT", $Profile[$j][0], @SW_HIDE)
        EndIf
        Local $Result = RegDelete($Profile[$j][1] & "\" & $key, $value)
        If Not $LoadFailed Then RunWait("reg unload " & $Profile[$j][1], "", @SW_HIDE)
        _ArrayAdd($resArray, $Result)
    Next
    Switch _ArrayMin($resArray, 1, 1)
    Case 0
        Return SetError(4, 0, 0)
    Case 1
        Return 1
    EndSwitch
EndFunc ;==> _RegDelete

; #FUNCTION# ====================================================================================================================================
; Name...........: _RegImport
; Description ...: Imports a previously exported reg file to the registry
; Syntax.........: _RegImport($user, $reg [, $name])
; Parameters ....: $user - 0 for current user
;                          1 for all users or to specify an account name
;                  $reg - Path and filename of the file to be imported, file extension (.reg)
;                  $name - [optional] account name, defaults to all users
; Requirement(s).: Registry Console Tool
; Return values .: Success - 1
;                  Failure - 0, sets @error to:
;                  |-4 - Registry Console Tool not found on system dir
;                  |-3 - The $user parameter value is wrong
;                  |4 - The operation failed for one or more of the profiles
; Author ........: engine
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; _RegImport(1, "ffdshow.reg")
;                  _RegImport(1, "ffdshow.reg", "Guest")
; ===============================================================================================================================================

Func _RegImport($user, $reg, $name = "")
    If Not FileExists(@SystemDir & "\reg.exe") Then Return SetError(-4, 0, 0)
    Select
    Case $user = 0
        $eCode = RunWait("reg import " & $reg, "", @SW_HIDE)
        Return SetError(4 * $eCode, 0, 1 - $eCode)
    Case $user <> 1
        Return SetError(-3, 0, 0)
    EndSelect
    Local $Profile = GetProfile($name)
    Local $resArray[1]
    For $j = 1 To $Profile[0][0]
        Local $LoadFailed = 1
        If FileExists($Profile[$j][0] & "\NTUSER.DAT") And $Profile[$j][2] = 0 Then
            $LoadFailed = RunWait("reg load " & $Profile[$j][1] & " NTUSER.DAT", $Profile[$j][0], @SW_HIDE)
        EndIf
        Local $regArray
        _FileReadToArray($reg, $regArray)
        For $k = 1 To $regArray[0]
            $regArray[$k] = StringReplace($regArray[$k], "HKEY_CURRENT_USER", $Profile[$j][1])
        Next
        _ArrayDelete($regArray, 0)
        Local $TempReg = _TempFile(@UserProfileDir, "~", ".reg")
        _FileWriteFromArray($TempReg, $regArray)
        Local $Result = RunWait('reg import "' & $TempReg & '"', "", @SW_HIDE)
        FileDelete($TempReg)
        If Not $LoadFailed Then RunWait("reg unload " & $Profile[$j][1], "", @SW_HIDE)
        _ArrayAdd($resArray, $Result)
    Next
    Switch _ArrayMax($resArray, 1, 1)
    Case 1
        Return SetError(4, 0, 0)
    Case 0
        Return 1
    EndSwitch
EndFunc ;==> _RegImport

; #INTERNAL_USE_ONLY#============================================================================================================================
; Name...........: GetProfile
; Description ...: Determine each user's Profile folder, the user's SID and if the profile is loaded to the registry
; Syntax.........: GetProfile($aName)
; Parameters ....: $aName - account name, defaults to all users
; Requirement(s).: WMI capable operating system
; Return values .: An array containing the path to each user's profile folder, the user's SID
;                  The array returned is two-dimensional and is made up as follows:
;                  $array[0][0] = Number of profiles
;                  $array[1][0] = Path to 1st user profile
;                  $array[1][1] = 1st user SID
;                  $array[1][2] = 1 if 1st user profile is loaded to the registry, 0 if not
;                  $array[2][0] = Path to 2nd user profile
;                  $array[2][1] = 2nd user SID
;                  $array[2][2] = 1 if 2nd user profile is loaded to the registry, 0 if not
;                  ...
;                  $array[n][0] = Path to nth user profile
;                  $array[n][1] = nth user SID
;                  $array[n][2] = 1 if nth user profile is loaded to the registry, 0 if not
; Author ........: engine
; Modified.......:
; Remarks .......: For internal use only
; Related .......:
; Link ..........;
; Example .......; GetProfile("Default User") to get Default User's profile data
; ===============================================================================================================================================

Func GetProfile($aName = "")
    Local $avArray[1][3]
    Local Const $ProfileListKey = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
    Local Const $DefaultUser = RegRead($ProfileListKey, "DefaultUserProfile")
    Local Const $Root = "HKEY_USERS\"
    Local $Account = ObjGet("winmgmts:\\localhost\root\CIMV2")
    If $aName = "" Or $aName = $DefaultUser Then
        Local $aItems = $Account.ExecQuery("Select * from Win32_UserAccount")
    Else
        Local $aItems = $Account.ExecQuery('Select * from Win32_UserAccount where name like "' & $aName & '"')
    EndIf
    For $ObjAccount In $aItems
        Local $iPath = RegRead($ProfileListKey & "\" & $ObjAccount.SID, "ProfileImagePath")
        If Not @error Then
            Local $iUBound = UBound($avArray)
            ReDim $avArray[$iUBound + 1][3]
            $avArray[$iUBound][0] = $iPath
            $avArray[$iUBound][1] = $Root & $ObjAccount.SID
            RegEnumKey("HKU\" & $ObjAccount.SID, 1)
            If @error Then
                $avArray[$iUBound][2] = 0
            Else
                $avArray[$iUBound][2] = 1
            EndIf
        EndIf
    Next
    If $aName = "" Or $aName = $DefaultUser Then
        $iUBound = UBound($avArray)
        Local $sum = 0
        For $j = 1 To $iUBound - 1
            $sum = $avArray[$j][2] + $sum
        Next
        ReDim $avArray[$iUBound + 1][3]
        $avArray[$iUBound][0] = RegRead($ProfileListKey, "ProfilesDirectory") & "\" & $DefaultUser
        If $sum = 0 Then
            $avArray[$iUBound][1] = "HKEY_CURRENT_USER"
            $avArray[$iUBound][2] = 1
        Else
            $avArray[$iUBound][1] = $Root & "DefaultUserProfile"
            $avArray[$iUBound][2] = 0
        EndIf
        If $aName = $DefaultUser Then
            Local $duArray[2][3] = [["", "", ""], [$avArray[$iUBound][0], $avArray[$iUBound][1], $avArray[$iUBound][2]]]
            $avArray = $duArray
        EndIf
    EndIf
    $avArray[0][0] = UBound($avArray) - 1
    For $j = 1 To $avArray[0][0]
        Local $iEnv = StringRegExp($avArray[$j][0], "\x25\S{1,128}\x25", 1)
        If Not @error Then $avArray[$j][0] = StringReplace($avArray[$j][0], $iEnv[0], EnvGet(StringReplace($iEnv[0], "%", "")))
    Next
    Return $avArray
EndFunc ;==> GetProfile
Edited by engine

My contributions:Local account UDF Registry UDFs DriverSigning UDF Windows Services UDF [url="http://www.autoitscript.com/forum/index.php?showtopic=81880"][/url]

Share this post


Link to post
Share on other sites

The function "SetPrivilege" isn't working in latest AutoIt version 3.2.12.0 I tried renaming the constants and variables like seanhart suggested, but without success. So I had to keep using registry console tool. I can't understand that function enough to even try to fix it.

Hi engine,

I have also had issues with the SetPrivilege function on 3.2.12.0. In the end the following post helped me track down and resolve the problem : http://www.autoitscript.com/forum/index.ph...penprocesstoken

=> Change the following two lines in SetPrivilege():

$SP_auxret = DLLCall("advapi32.dll","int","OpenProcessToken","hwnd",$hCurrProcess[0], "int",BitOR($TOKEN_ADJUST_PRIVILEGES,$TOKEN_QUERY),"int_ptr",0)

...

$ret = DLLCall("advapi32.dll","int","AdjustTokenPrivileges","hwnd",$hToken,"int",0,   _
                "ptr",DllStructGetPtr($TOKEN_PRIVILEGES),"int",DllStructGetSize($NEWTOKEN_PRIVILEGES),   _
                "ptr",DllStructGetPtr($NEWTOKEN_PRIVILEGES),"int_ptr",0)

to read:

$SP_auxret = DLLCall("advapi32.dll","int","OpenProcessToken","hwnd",$hCurrProcess[0], "int",BitOR($TOKEN_ADJUST_PRIVILEGES,$TOKEN_QUERY),"int*",0)

...

$ret = DLLCall("advapi32.dll","int","AdjustTokenPrivileges","hwnd",$hToken,"int",0,   _
                "ptr",DllStructGetPtr($TOKEN_PRIVILEGES),"int",DllStructGetSize($NEWTOKEN_PRIVILEGES),   _
                "ptr",DllStructGetPtr($NEWTOKEN_PRIVILEGES),"int*",0)

This allows the RegHiveLoad / Unload functions to work correctly on 3.2.12.0 :)

thecharliec

Share this post


Link to post
Share on other sites

I originally attempted to do something like this to modify registry entries for all users, I found the loading and unloading of hives to be too slow and cumbersome. I ended up using ActiveSetup instead, this allowed me to write one registry key to modify all users (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Active Setup\Installed Components). A different approach to look at to accomplish a similar task.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0