views:

1404

answers:

2

Hi all,

I want to write a application that writes to all users on a local machine a specified key (eg: i want set the location for IE Favorites for all users to the same folder)

PS anybody used these functions? LoadUserProfile RegOpenCurrentUser CreateProcessAsUser

+1  A: 

We had the exact same issue the other day.

We discovered that you can just open the HKEY_USERS hive and write the changes to each user's SID.

And, If you want the settings to be present for any new users, you should also apply the settings to the HKEY_USERS/.DEFAULT key.

That is to say, just write your settings to...

HKEY_USERS\S-1-5-XX-XXXXXXXX-XXXXXXXXX-XXXXXXXX-XXXX\Software\...

For each of the SIDs present and:

HKEY_USERS\.DEFAULT\Software\...
John Gietzen
Only the SIDs of currently logged-in users will be there. If a user isn't logged in, then the OS doesn't load that user's registry hive, and so there's no subkey for that user.
Rob Kennedy
This is an incomplete solution for the reason that Rob outlined. My answer solves this issue.
Mick
I have +1'd your solution.
John Gietzen
+7  A: 

I've done this many times. The idea is to update the currently logged on user's HKCU (that's easy enough). Then you must enumerate every profile on the system and find their ntuser.dat file (that's easy enough too).

With the ntuser.dat file found, you load it into a temporary key in the HKLM hive (I usually use 'HKLM\TempHive'. Then edit away.

If there is more than 1 user logged on, their profile will be loaded under HKEY_USERS, by their SID. Simply update that location.

To modify the setting for any new users, simply modify the appropriate key under HKEY_USERS.DEFAULT, OR use the Delphi code below which will do this by loading the Default Users's HKCU registry hive (stored in ntuser.dat).

UPDATE: I found my Delphi code that demonstrates how to update the HKCU hives of users that are not logged onto the system.

This requires Russell Libby's 'Privilege' component, which is available here.

//NOTE:   sPathToUserHive is the full path to the users "ntuser.dat" file.
//
procedure LoadUserHive(sPathToUserHive: string);
var
  MyReg: TRegistry;
  UserPriv: TUserPrivileges;
begin
  UserPriv := TUserPrivileges.Create;    
  try
    with UserPriv do
    begin
      if HoldsPrivilege(SE_BACKUP_NAME) and HoldsPrivilege(SE_RESTORE_NAME) then
      begin
        PrivilegeByName(SE_BACKUP_NAME).Enabled := True;
        PrivilegeByName(SE_RESTORE_NAME).Enabled := True;

        MyReg := TRegistry.Create;    
        try
          MyReg.RootKey := HKEY_LOCAL_MACHINE;
          MyReg.UnLoadKey('TEMP_HIVE'); //unload hive to ensure one is not already loaded

          if MyReg.LoadKey('TEMP_HIVE', sPathToUserHive) then
          begin
            //ShowMessage( 'Loaded' );
            MyReg.OpenKey('TEMP_HIVE', False);

            if MyReg.OpenKey('TEMP_HIVE\Environment', True) then
            begin
              // --- Make changes *here* ---
              //
              MyReg.WriteString('KEY_TO_WRITE', 'VALUE_TO_WRITE');
              //
              //
            end;

            //Alright, close it up
            MyReg.CloseKey;
            MyReg.UnLoadKey('TEMP_HIVE');
            //let's unload the hive since we are done with it
          end
          else
          begin
            WriteLn('Error Loading: ' + sPathToUserHive);
          end;
        finally
          FreeAndNil(MyReg);
        end;

      end;
      WriteLn('Required privilege not held');
    end;
  finally
    FreeAndNil(UserPriv);
  end;
end;

I also wrote a VBScript a while ago that accomplishes this task. I used it for modifying some Internet Explorer settings, but you can customize it to your needs. It also demonstrates the general process:

Option Explicit

Dim fso
Dim WshShell
Dim objShell
Dim RegRoot
Dim strRegPathParent01
Dim strRegPathParent02

Set fso = CreateObject("Scripting.FileSystemObject")
Set WshShell = CreateObject("WScript.shell")


'==============================================
' Change variables here
'==============================================
'
'This is where our HKCU is temporarily loaded, and where we need to write to it
RegRoot = "HKLM\TEMPHIVE"
'
strRegPathParent01 = "Software\Microsoft\Windows\CurrentVersion\Internet Settings" 
strRegPathParent02 = "Software\Microsoft\Internet Explorer\Main"
'
'======================================================================



Call ChangeRegKeys()  'Sets registry keys per user

Sub ChangeRegKeys
 'Option Explicit
 On Error Resume Next

 Const USERPROFILE = 40
 Const APPDATA = 26

 Dim iResult
 Dim iResult1
 Dim iResult2
 Dim objShell
 Dim strUserProfile
 Dim objUserProfile
 Dim strAppDataFolder
 Dim strAppData
 Dim objDocsAndSettings
 Dim objUser
 Set objShell = CreateObject("Shell.Application")
 Dim sCurrentUser

 sCurrentUser = WshShell.ExpandEnvironmentStrings("%USERNAME%")

 strUserProfile = objShell.Namespace(USERPROFILE).self.path
 Set objUserProfile = fso.GetFolder(strUserProfile)
 Set objDocsAndSettings = fso.GetFolder(objUserProfile.ParentFolder)

 'Update settings for the user running the script
 '(0 = default, 1 = disable password cache)
 WshShell.RegWrite "HKCU\" & strRegPathParent01 & "\DisablePasswordCaching", "00000001", "REG_DWORD"
 WshShell.RegWrite "HKCU\" & strRegPathParent02 & "\FormSuggest PW Ask", "no", "REG_SZ"


 strAppDataFolder = objShell.Namespace(APPDATA).self.path
 strAppData = fso.GetFolder(strAppDataFolder).Name

 ' Enumerate subfolders of documents and settings folder
 For Each objUser In objDocsAndSettings.SubFolders 
  ' Check if application data folder exists in user subfolder
  If fso.FolderExists(objUser.Path & "\" & strAppData) Then 
   'WScript.Echo "AppData found for user " & objUser.Name
   If ((objUser.Name <> "All Users") and _
    (objUser.Name <> sCurrentUser) and _
    (objUser.Name <> "LocalService") and _ 
    (objUser.Name <> "NetworkService")) then
    'Load user's HKCU into temp area under HKLM
    iResult1 = WshShell.Run("reg.exe load " & RegRoot & " " & chr(34) & objDocsAndSettings & "\" & objUser.Name & "\NTUSER.DAT" & chr(34), 0, True)
    If iResult1 <> 0 Then
     WScript.Echo("***   An error occurred while loading HKCU: " & objUser.Name)
    Else
     WScript.Echo("HKCU loaded: " & objUser.Name)
    End If

    WshShell.RegWrite RegRoot & "\" & strRegPathParent01 & "\DisablePasswordCaching", "00000001", "REG_DWORD"
    WshShell.RegWrite RegRoot & "\" & strRegPathParent02 & "\FormSuggest PW Ask", "no", "REG_SZ"

    iResult2 = WshShell.Run("reg.exe unload " & RegRoot,0, True) 'Unload HKCU from HKLM
    If iResult2 <> 0 Then
     WScript.Echo("*** An error occurred while unloading HKCU: " & objUser.Name & vbcrlf)
    Else
     WScript.Echo("   unloaded: " & objUser.Name & vbcrlf)
    End If
   End If

  Else
   'WScript.Echo "No AppData found for user " & objUser.Name
  End If
 Next

End Sub
Mick
hi, this looks like what I want :) I'm testing right now, but i get an error[DCC Error] Privilege.pas(646): E2251 Ambiguous overloaded call to 'StrLen'
Remus Rigo
new error: project ... raised exception class EPrivilegdError with message "The privilege SeBackupPrivilege is not held by the user"(i am a member of administrators)
Remus Rigo
Here is a response from the author of the privilege component on this issue ========- The user account must......... (a) hold the SE_RESTORE_NAME and SE_BACKUP_NAME privileges ======== (b) Must have the privileges enabled. ================It does not matter if its administrator, power user, or plain user account. Admin does *HOLD* the privileges, but in most cases they are *NOT* enabled. Having (holding) the privilege is not the same as having the privilege enabled.========Regedit enables the reqd privileges, just like any other program has to before attempting the desired operation.
Mick
hi Mick, firts I want to thank you for this code, it works fine under XP, but when I run under Vista I get some errors, I will post later the exact message, is there something else I hould enable (other privileges?)
Remus Rigo
Please post the exact error message. In Vista (and 7), ensure that this code is running under an Administrative account.
Mick