Anteaus Posted December 15, 2009 Share Posted December 15, 2009 (edited) Update of May 10 2010: Version 0.3 now uploaded, several enhancements.This utility allows for easy reassociation of a userprofile with its account, after any of the several kinds of mishap which can break that association. Whilst the process can be done manually, it involved some fairly complex registry-hacking and permissions-changing. This GUI tool makes it easy enough for most beginners - although it should also save network admins some time and effort when joining or extracting computers from a domain. Because of the diversity of profile-configs and the fundamental differences between XP and 7, getting this utility to work in all circumstances has proved something of a challenge. I imagine there are still a few cases which it can't cope with, although the new version should cover a lot more situations. Relies heavily on Helge Klein's SetACL utility, which must be in the same folder. A built version is available here. This contains all dependencies. To use, just expand the zip to any convenient place, and run reprofiler.exeexpandcollapse popup#RequireAdmin #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_icon=reprofiler.ico #AutoIt3Wrapper_UseUpx=n #AutoIt3Wrapper_UseAnsi=n #AutoIt3Wrapper_Res_Description=Profile-association Repair Tool #AutoIt3Wrapper_Res_Fileversion=0.3.0.0 #AutoIt3Wrapper_Res_LegalCopyright=IWR Consultancy, GPL v3 #AutoIt3Wrapper_Run_AU3Check=n #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** ; ReProfiler ; Released by IWR Consultancy, under the GPL licence, v3. #cs Changelog: v0.2->0.3 Now using 3.3.6.1 compiler and libraries, eliminates intermittent WMI bug causing "Error in line -1" message. Or, at least I hope it does! Temporary registry SID assigned when account's hive is already in use, overcomes inability to set registry permissions in some circumstances. Improved logic for handling changes to the active useraccount. Using ICACLS to set filesystem permissions on Vista/7, as this handles the cyclic junctions better. Permissions are now set recursively on all supported OS's. v0.1->0.2 Now compiled with Autoit 3.3.0.0 New method of profile assignment, works in more situations. Several obscure problems with setting of registry-permissions fixed. Erase Data now works for Windows 7. Assignment of active user's profile now possible. (In most cases it is no longer necessary to logon as another user to change your own assignment) Added detection of an attempt to delete the active profile. Properties panel is more informative. #ce opt ("TrayAutoPause",0) opt ("TrayIconHide",1) ; #include "directives.au3" #include <GUIConstants.au3> global $appVersion = "0.3 alpha" global $doswindow=@SW_MINIMIZE if FileExists(@scriptdir & "\setacl.exe")=0 then local $msg=msgbox(52,"Missing Dependency","This utility requires setacl.exe to be present in its own folder. Without this, some functionality may not work correctly. You can download SetACL from http://setacl.sourceforge.net. Do you wish to continue without it?") if $msg<>6 then exit endif if $appVersion<1 then msgbox(48,"Development version " & $appVersion," Please be aware that this is a pre-production release. Whilst this version has been tested quite extensively, it has not yet been deployed in the field or used in real IT-support scenarios. Therefore, please use with caution and always back-up your data.") endif $logfile=@TempDir & "\ProfileReassignment.log" if FileExists($logfile) then FileDelete($logfile) $showSysItems=0 $showBy = "User Account" $lvProfiles=-1 $lvUsers=-1 $prMode="user" $SystemFolders="|Default User|All Users|NetworkService|LocalService|__sbs_netsetup__|" $SystemUsers="|Default User|All Users|SBS Backup User|HelpAssistant|Administrator Tmpl|Power User Tmpl|guest|" global $allowDelete="YES" getprofiles() getusers() global $dirtyData=1 ; We got the data already, but we need to paint-in the GUI on first run. ; 0 no action, 1 repaint GUI only, 2 reload data and repaint GUI. $ProfGUI=GUICreate("Profiles in: " & $profileroot,550,550, 100,200,-1) $img1=GUICtrlCreateIcon(@ScriptFullPath,-1,34,12) $Label1 = GUICtrlCreateLabel("ReProfiler", 94, 14, 249, 40) GUICtrlSetFont(-1, 24, 800, 2, "Arial") $Label2 = GUICtrlCreateLabel("Profile Link Repair Tool", 340, 18, 120, 17) $Label4 = GUICtrlCreateLabel("By IWR Consultancy", 380, 38, 102, 17) $inpSysItems=GUICtrlCreateCheckbox("Show System Items",300,235) if $showSysItems then GuiCtrlSetState($inpSysItems,1) $btnProperties=GuiCtrlCreateButton("Properties", 30, 450, 110, 30) $btnExit=GuiCtrlCreateButton("Exit", 30, 500, 110, 30) $btnAssign=GuiCtrlCreateButton("Assign", 180, 450, 110, 30) $btnDetach=GuiCtrlCreateButton("Detach", 180, 500, 110, 30) $btnDelete=GuiCtrlCreateButton("Erase Data", 320, 500, 110, 30) $btnRefresh=GuiCtrlCreateButton("Refresh Views", 320, 450, 110, 30) $lblUserList = GuiCtrlCreateLabel("User Accounts:", 10, 50, 105, 20) $lblProfileList = GuiCtrlCreateLabel("Profile Folders:", 10, 250, 105, 20) do ; Main UI loop if $dirtyData > 1 then ; reload data getprofiles() getusers() endif if $dirtyData > 0 then ; refill GUI values dim $lvCtrl[1000] $lvCtrl[0]=0 if $lvProfiles<>-1 then GUICtrlDelete($lvProfiles) endif $lvProfiles = GUICtrlCreateListView (" Data Folder | Assigned User(s) ",10,270,530,150);,$LVS_SORTDESCENDING) dim $plv[$profdirs[0]+1] for $ct=1 to $profdirs[0] $lvVarlist=$profdirs[$ct] if $showSysItems=0 and stringinstr($systemFolders,"|" & filename($profdirs[$ct]) & "|") then continueloop if $showSysItems=0 and stringinstr(filename($profdirs[$ct]),"SUPPORT_",1) then continueloop $thisPIP=$profdirs[$ct] $thisUsers="" $profileSID="{orphaned}" for $userct=1 to $users[0][0] if $users[$userct][2]=$thisPIP then if $thisUsers <> "" then $thisUsers=$thisUsers & "," $thisUsers=$thisUsers & $users[$userct][0] & "\" & $users[$userct][1] $profileSID=$users[$userct][3] endif next ; $userct if $thisUsers <>"" then $lvVarlist= $lvVarlist & "|" & $thisUsers endif $plv[$ct]=GUICtrlCreateListViewItem($lvVarlist,$lvProfiles) $lvCtrl[$plv[$ct]]=$ct $plv[0]=$ct next ; $ct GUICtrlSendMsg($lvProfiles, 0x1000 + 30, 0, 280) GUICtrlSendMsg($lvProfiles, 0x1000 + 30, 1, 230) if $lvUsers<>-1 then GUICtrlDelete($lvUsers) endif $lvUsers = GUICtrlCreateListView (" Host | User |**| Assigned Folder | SID ",10,70,530,150) dim $ulv[$users[0][0]+1] for $ct=1 to $users[0][0] if $showSysItems=0 and stringinstr($systemUsers,"|" & $users[$ct][1] & "|") then continueloop if $showSysItems=0 and stringinstr($users[$ct][1],"SUPPORT_",1) then continueloop if $users[$ct][0]=@computername then $lvVarlist="Local" else $lvVarlist="Domain" endif $uFlags=" " $lvVarlist= $lvVarlist & "|" & $users[$ct][1] if $users[$ct][5]>0 then $uFlags=StringReplace($uFlags,1, "A") if $users[$ct][6]>0 then $uFlags=StringReplace($uFlags,2, "X") $lvVarlist= $lvVarlist & "|" & $uFlags $lvVarlist= $lvVarlist & "|" & $users[$ct][2] $lvVarlist= $lvVarlist & "|" & $users[$ct][3] $ulv[$ct]=GUICtrlCreateListViewItem($lvVarlist,$lvUsers) $lvCtrl[$ulv[$ct]]=$ct $ulv[0]=$ct next GUICtrlSendMsg($lvUsers, 0x1000 + 30, 0, 100) GUICtrlSendMsg($lvUsers, 0x1000 + 30, 1, 160) GUICtrlSendMsg($lvUsers, 0x1000 + 30, 2, 25) GUICtrlSendMsg($lvUsers, 0x1000 + 30, 3, 220) GUISetState() $dirtyData=0 endif ; End of data reload/paint sections $msg = GUIGetMsg() Select Case $msg = $btnRefresh $dirtyData = 2 Case $msg = $btnAssign $dirtyData = 2 prAssign() Case $msg = $btnDetach prDetach() Case $msg = $btnDelete prDelete() Case $msg = $btnProperties prProperties($prMode) Case $msg= $inpSysItems if GUICtrlRead($inpSysItems)= 1 then $showSysItems=1 else $showSysItems=0 endif $dirtyData=1 Case $msg=$GUI_EVENT_CLOSE or $msg=$btnExit exitloop EndSelect until 0 GUIDelete($ProfGUI) exit func prAssign() local $thisUser=$lvCtrl[GUICtrlRead($lvUsers)] local $thisProfile=$lvCtrl[GUICtrlRead($lvProfiles)] local $thisPath=$profdirs[$thisProfile] if $thisUser=0 or $thisProfile=0 then msgbox(48,"Input Error"," Please select a User and Profile from the respective lists before clicking Assign.") return -1 endif select case ($profdirs[$thisProfile]=@userprofiledir) $info="You are assigning a user to a profile which is currently in-use. Once completed you should RESTART the computer before attempting to test the result. Note that logging-off the current user is not sufficient, as this does not always fully unload the associated profile. Also be aware that if two users are assigned to the same profile, both accounts must never log-on simltaneously." & @lf & @lf & " - Do you wish to proceed?" local $msg=msgbox(52,"Please Note:", $info) $info="" if $msg <>6 then return 2 case @username=$users[$thisUser][1] $info="You are attempting to change the profile-assignment for the logged-on user. This may give rise to problems with the current user-session. It is suggested that you log-off and perform the reassignment under a separate account. If you elect to proceed with this change now, you should restart the computer immediately on completion." & @lf & @lf & " - Do you wish to proceed?" local $msg=msgbox(52,"Please Note:", $info) $info="" if $msg <>6 then return 2 case else local $info="Do you wish to assign the User Account named:" & @crlf & $users[$thisUser][1] & @crlf & "As a trustee of the data stored in the profile folder:" & @crlf & $profdirs[$thisProfile] local $msg=msgbox(36,"Please Confirm your Choice:", $info) $info="" if $msg <>6 then return 2 endselect ; Initialise new user if running Vista/7, as uninitialised users cannot have a profile assigned on these platforms: do $thisDomain=$users[$thisUser][0] $thisName=$users[$thisUser][1] $thisSID=$users[$thisUser][3] $thisPIP=$users[$thisUser][2] if stringinstr("WIN_2003|WIN_XP|WIN_2000", @OSVersion) then exitloop if $thisPIP <> "" then exitloop $thisPwd=inputbox("User requires initialising","This user has not previously logged-on to this computer, or has been Detached from the profile since last logon. Please enter the user's password so that the account can be initialised") if @error>0 then exitloop $runstr=@comspec & " /c" $rtn=RunAs($thisName,$thisDomain,$thisPwd,1,$runstr,@ScriptDir,$doswindow) sleep(1000) getprofiles() $piploc = "HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList\" & $thisSID $users[$thisUser][2] = RegRead($piploc,"ProfileImagePath") until 0 $thisDomain=$users[$thisUser][0] $thisName=$users[$thisUser][1] $thisSID=$users[$thisUser][3] $thisPIP=$users[$thisUser][2] ; $users[$thisUser][2] = RegRead($piploc,"ProfileImagePath") $profsz=regread("HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList","ProfilesDirectory") $thisAPath=$thisPath if stringinstr($thisPath,"\")=0 then $thisPath = $profsz & "\" & $thisPath ; (I see no reason to use an env string to determine location, as profiles are not relocatable anyway.) $thisPath=stringreplace($thisPath,envget("SystemDrive"),"%SystemDrive%",1) $piploc = "HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList\" & $thisSID $thisPIP=$thisPath ; Check for an existing key with a temp PIP and warn user to log out before proceeding: $tempPIP=RegRead($piploc,"ProfileImagePath") if stringinstr($tempPIP,"temp") then $msg=msgbox(52,"Problem - Account in use", "This account is active with a temporary profile. If possible you should log this user off before trying to resssign the profile. Proceed anyway? ") if $msg <>6 then return 0 endif ; Ideally should add check for any logon, not just temp. ** ; Check for existence of Vista/7 '.bak' registry key: $thisPIPBak=RegRead($piploc & ".bak","ProfileImagePath") if @error=0 then ; Probably best just to remove and re-create: RegDelete($piploc & ".bak") endif ; Check for an existing key with missing PIP entry and remove it if present: ; $existingKey=RegRead($piploc) ; if @error=0 then ; $existingPIP=RegRead($piploc","ProfileImagePath") ; if @error then ; RegDelete($piploc) ; endif ; endif ; What follows is an undocumented hack which causes profile to be loaded if present, recreated from default if not: RegDelete($piploc,"ProfileLoadTimeHigh") RegDelete($piploc,"ProfileLoadTimeLow") RegDelete($piploc,"RefCount") RegDelete($piploc,"Sid") RegWrite($piploc,"Flags","REG_DWORD",0xFFFFFFFF) RegWrite($piploc,"ProfileImagePath","REG_EXPAND_SZ",$thisPIP) if @error=0 then $result= "Change ProfileImagePath for this user... OK" & @CRLF else $result= "Change ProfileImagePath for this user... FAIL" & @CRLF endif $thisHive=$thisAPath & "\NTUSER.DAT" $thisClassHive=$thisAPath & "\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat" if $thisAPath<>@UserProfileDir then $thisHKU=$thisSID $rlh=True $rlh1=RegLoadHive($thisHKU, $thisHive) $rlh2=RegLoadHive($thisHKU & "_Classes", $thisClassHive) if not $rlh1 then $thisHKU="Reprofiler_HKU" $rlh1=RegLoadHive($thisHKU, $thisHive) $rlh2=RegLoadHive($thisHKU & "_Classes", $thisClassHive) endif $regUserSection='HKEY_USERS\' & $thisHKU ; msgbox(0,$thisAPAth & "apath>activeprofile" & @UserProfileDir,$thisHKU & "sid>hive" & $thisHive,10) if not $rlh1 then msgbox(0,"User-Registry Load Failure","The attempt to load the registry-section for this user failed. This may be due to the useraccount already being active under a separate thread. This may result in permissions problems for the user, or problems saving settings under that account. It is suggested that you restart the computer and repeat the profile-assignment, ensuring that the useraccount is NOT active.",60 ) endif Else $regUserSection='HKEY_CURRENT_USER' $rlh=False $rlh1=False $rlh2=False ; msgbox(0,"No Hive Load - " & $thisAPath & " - " & @UserProfileDir,$rlh1 & " " & $rlh2) ;+msg EndIf FileDelete($logfile) if stringinstr("WIN_2003|WIN_XP|WIN_2000", @OSVersion) then $result = $result & "Change ownership of profile contents.. " $runstr = 'cmd /c setacl -ot file -on "' & $thisPIP & '\*" -ownr "n:' & $thisSID & ';s:y" -actn setowner -rec cont_obj -log ' & $logfile $rtn1 = RunWait($Runstr,@scriptdir,$doswindow) if $rtn1=0 then $rtn1="OK" else $rtn1="Warning: " & $rtn1 endif else ; Because of Vista/7's cyclic symlinks, we use ICACLS here: $result = $result & "Add user ACL to profile contents with ICACLS.. " ; $runstr = 'cmd /c setacl -ot file -on "' & $thisPIP & '" -ownr "n:' & $thisSID & ';s:y" -actn setowner -log ' & $logfile $runstr = 'cmd /c icacls ' & $thisPIP & ' /grant *' & $thisSID & ':F /T /C >>icacls.' & $logfile $rtn1 = RunWait($Runstr,@scriptdir,$doswindow) if $rtn1=1 then $rtn1="OK" else $rtn1="Warning: " & $rtn1 endif endif $result = $result & $rtn1 & @CRLF $runstr = 'cmd /c setacl -ot file -on "' & $thisPIP & '" -ace "n:' & $thisSID & ';s:y;p:full" -actn ace -log ' & $logfile $result = $result & "Add user as trustee of profile root... " $rtn2 = RunWait($Runstr,@scriptdir,$doswindow) if $rtn2=0 then $rtn2="OK" $result = $result & $rtn2 & @CRLF $runstr = 'cmd /c setacl -ot reg -on "' & $regUserSection & '" -ace "n:' & $thisSID & ';s:y;p:full" -actn ace -log ' & $logfile $result = $result & "Add user as trustee of registry hive... " $rtn3 = RunWait($Runstr,@scriptdir,$doswindow) if $rtn3=0 then $rtn3="OK" $result = $result & $rtn3 & @CRLF ;$runstr = 'setacl -ot reg -on "' & $regUserSection & '_Classes" -ace "n:' & $thisSID & ';s:y;p:full" -actn ace -silent -log ' & $logfile ;$result = $result & "Add user as trustee of classes registry hive... " ;$rtn4 = RunWait($Runstr,@scriptdir,$doswindow) ;if $rtn4=0 then $rtn4="OK" ;$result = $result & $rtn4 & @CRLF $ruh1="undefined" $ruh2="undefined" if $rlh1 then $ruh1=RegUnLoadHive($thisHKU) if $rlh2 then $ruh2=RegUnLoadHive($thisHKU & "_Classes") ; msgbox(0,"Hive Unload",$ruh1 & " " & $ruh2) ;+msg $result = $result & @CRLF & "Do you wish to see the log file?" $msg=msgbox (68,"Profile Reassigned",$result) if $msg=6 then $runstr="notepad " & $logfile Run($runstr) endif endfunc ;==>prAssign func getprofiles($_pathtoscan="") $_listidx=0 if $_pathtoscan="" then $profdir=regread("HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList","ProfilesDirectory") $profdir=StringReplace($profdir,"%SystemDrive%",envget("SystemDrive")) $_pathtoscan=$profdir endif global $profileRoot=$_pathtoscan if stringright($_pathtoscan,1)<>"\" then $_pathtoscan = $_pathtoscan & "\" global $profdirs[10000] $_thisMask = $_pathToScan & "*.*" $_spSearch = FileFindFirstFile ( $_thisMask ) While 1 If $_spSearch = -1 then ExitLoop $_file = FileFindNextFile($_spSearch) If @error Then ExitLoop $_FQSrcName = $_pathtoscan & $_file $_srcFileAttribs = FileGetAttrib($_FQSrcName) if stringinstr($_srcFileAttribs,"D") then $_listidx=$_listidx+1 $profdirs[$_listidx]= $profileRoot & "\" & $_file endif WEnd $profdirs[0]=$_listidx endfunc ;==>getprofiles func getusers() ; Return string array of useraccounts containing Domain, Name, ImagePath, SID, FolderExists ; Element 0,0 is total accounts. $wbemFlagReturnImmediately = 0x10 $wbemFlagForwardOnly = 0x20 $colItems = "" $strComputer = "localhost" $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2") if @error then msgbox(16,"WMI Error","Unable to connect to the Windows Management Interface service. This may be due to the WMI service having been disabled, or due to a third-party firewall or other security software which is preventing or interfering-with access. We suggest as a starting-point that you run services.msc and check the condition of the WMI service." & @crlf & @crlf & "Unable to continue, therefore Exiting.",60) Exit endif $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_UserAccount", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly) global $users[10000][7] $ct=0 #cs 0=domain 1=name 2=pip 3=sid 4=folderexists 5=isLoggedOn 6=broken #ce If IsObj($colItems) then For $objItem In $colItems $ct=$ct+1 $users[$ct][0] = $objItem.Domain $users[$ct][1] = $objItem.Name $users[$ct][3] = $objItem.SID $users[$ct][5] = 0 $users[$ct][6] = 0 $piploc = "HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList\" & $users[$ct][3] $users[$ct][2] = RegRead($piploc,"ProfileImagePath") if @error or StringInStr($users[$ct][2],"\TEMP") then ; msgbox(0,"pip","notfound") $piploc = "HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList\" & $users[$ct][3] & ".bak" $tmp = RegRead($piploc,"ProfileImagePath") if @error=0 then $users[$ct][2] = $tmp $users[$ct][6] = 1 endif endif $users[$ct][2]=StringReplace($users[$ct][2],"%SystemDrive%",envget("SystemDrive")) if stringlen($users[$ct][2])>0 then if FileExists($users[$ct][2] & "\NTUSER.DAT") then $users[$ct][4]=1 else $users[$ct][4]=0 endif endif ;Find out if account is logged-on: $users[$ct][5]=0 $LogonItems = $objWMIService.ExecQuery("SELECT * FROM Win32_LoggedOnUser", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly) If IsObj($LogonItems) then For $LogonItem In $LogonItems $thisName=$LogonItem.Antecedent ; msgbox(0,"logon",$thisname) if stringinstr($LogonItem.Antecedent,'name="' & $users[$ct][1] & '"')then $users[$ct][5]=1 endif next endif Next $users[0][0]= $ct Else Msgbox(16,"WMI Error","The WMI service is required for this tool to function, and does not appear to be running. Cannot continue." ) Endif endfunc ;==>getusers func filename ($_pathtostrip) return stringmid($_pathtostrip,stringinstr($_pathtostrip,"\",0,-1) +1 ,255) endfunc ;==>filename ; === 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 ;==>RegLoadHive ; === 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 ; === 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*",0) if @error then msgbox(16,"Error","Unable to set permissions on user registry") return 0 endif 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*",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 ;==>SetPrivilege ; === SetPrivilege === func ReLaunch() ; (Not used with later script versions) if isAdmin() then return 1 $msg=MsgBox(52,"Administrative rights necessary","This utility needs adminstrative rights in order to perform its function, but has been started under an account with limited rights. Do you wish to attempt to re-start the app under the Administrator account?") if $msg=6 then $pwd=inputbox("Password Required","Please enter the Administrator password for this computer") RunAs("Administrator",@computername,$pwd,0,@scriptfullpath,@scriptdir) exit endif return 0 endfunc ;==>ReLaunch func prDelete() local $thisUser=$lvCtrl[GUICtrlRead($lvUsers)] local $thisProfile=$lvCtrl[GUICtrlRead($lvProfiles)] local $thisPath=$profdirs[$thisProfile] local $thisDomain=$users[$thisUser][0] local $thisName=$users[$thisUser][1] local $thisSID=$users[$thisUser][3] local $thisPIP=$users[$thisUser][2] if stringlen($thisPath)<5 then msgbox(64,"No action taken","Nothing selected to erase. Please highlight a profile-folder first.",10 ) return 0 endif if stringinstr(@AppDataDir,$thisPath) then msgbox(16,"Foot-Shooting Attempt Detected!","You are attempting to delete the active user's profile. If successful, this would cause system instability. Action blocked.",10 ) return 0 endif $msg=msgbox(52,"Caution - action removes data","Permanently ERASE " & $thisPath & " and all of its contents?." & @cr & @cr & "This folder may contain personal documents, pictures, email, etc. Do not proceed unless you are CERTAIN the data it contains is no longer needed." & @cr & @cr & "Under Windows XP it is generally OK to delete active profiles, in which case they will be re-created from the Default profile at next log-on. " & @cr & @cr & "However, under Vista or Windows 7, deleting a profile with a user still attached may lead to trouble with the account. "& @cr & @cr & " Proceed? ") if $msg=6 then if $allowDelete<>"YES" then $allowDelete=inputbox("Delete Data","To confirm this action, please type YES into the box below. ") if $allowDelete <> "YES" then return 0 endif $runstr="cmd /c rd /s /q " & $thisPath RunWait($runstr,@ScriptDir,$doswindow) $result=DirGetSize($thisPath) if $result=-1 then msgbox(64,"Profile Deleted","The selected profile-folder has been removed from the hard-disk.") else msgbox(48,"Profile Delete Attempted, " & $result / 1024 / 1024 & "MB Data Remaining","The attempt to remove the profile has not been entirely successful. This may be due to files being held-open by useraccounts which are presently logged-on, or to network shares within the profile-folder being accessed from other computers.It is suggested that a freah attempt is made after a restart, ensuring that only the Administrator account is allowed to log-on." ) endif $dirtyData=2 endif endfunc ;==>prDelete func prDetach() local $thisUser=$lvCtrl[GUICtrlRead($lvUsers)] local $thisProfile=$lvCtrl[GUICtrlRead($lvProfiles)] local $thisPath=$profdirs[$thisProfile] local $thisDomain=$users[$thisUser][0] local $thisName=$users[$thisUser][1] local $thisSID=$users[$thisUser][3] local $thisPIP=$users[$thisUser][2] $piploc = "HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList\" & $thisSID $confPIP= RegRead($piploc,"ProfileImagePath") if stringlen($thisPath)<5 or stringlen($thisName)=0 then msgbox(48,"Items Not Selected","Unable to proceed. Please highlight a user-account and a profile-folder which you wish to dissociate from each other, then try again.") return 0 endif if $thisPIP <> $thisPath then msgbox(48,"Not Associated","The specified user-account ("&$thisName&") is not presently a trustee of the selected data folder ("&$thisPath&") therefore no action has been taken.") return 0 endif $msg=msgbox(36,"Detach profile from useraccount","Do you wish to cancel the ownership of the data stored in " & @cr & $thisPIP & @cr & " by user " & @cr & $thisDomain & "\" & $thisName & " ?" & @cr & "(This action will not delete data, but it might make the data inaccessible to the user.)") if $msg <>6 then return 0 if $thisSID="" then return 0 ; Precaution against deleting profile-root key. if @osbuild>5000 then RegDelete($piploc) else RegDelete($piploc,"ProfileImagePath") endif $dirtyData=2 endfunc ;==>prDetach func prProperties($_mode="profile") local $thisUser=$lvCtrl[GUICtrlRead($lvUsers)] local $thisProfile=$lvCtrl[GUICtrlRead($lvProfiles)] local $thisPath=$profdirs[$thisProfile] local $thisDomain=$users[$thisUser][0] local $thisName=$users[$thisUser][1] local $thisSID=$users[$thisUser][3] local $thisPIP=$users[$thisUser][2] local $thisBAK="" local $thisON="" if $users[$thisUser][6] then $thisBAK="Warning: Temporary profile - Indicates problem with associated profile, or with registry ProfileImagePath pointer." & @lf if $users[$thisUser][5] then $thisON="Note: This account is active. Best to log off before making changes." & @lf $pParams="" $uParams="" if stringlen($thisPath)<5 then $pParams="Unable to get profile information, possibly none selected from list, or data is incomplete." & @lf endif $size = DirGetSize($thisPath,1) $tLL = FileGetTime($thisPath & "\NTUSER.DAT", 0) if @error =0 Then $lastLogon=$tLL[0] & "/" & $tLL[1] & "/" & $tLL[2] if IsArray($size) Then $pParams="Selected Profile Folder Information" & @lf & "Path: " & $thisPath & @lf & "Size: " & round($size[0]/1024/1024) & "MB" & @LF & "Files: " & $size[1] & @LF & "Dirs: " & $size[2] & @LF & "Last Interactive Logon (YMD): " & $lastLogon endif else $pParams="No information available, possibly this profile has never been logged-on interactively." & @lf EndIf if $thisName <>"" then if $thisPIP="" then $thisPIP="None Allocated" $uParams="Selected User Account Information" & @lf & "Name: " & $thisName & @LF & "Domain: " & $thisDomain & @LF & "SID(GUID): " & $thisSID & @LF & "Profile Image Path: " & $thisPIP & @LF & $thisBAK & $thisON else $uParams="Unable to get user information, possibly none selected from list, or account is damaged." & @lf endif Msgbox(64,"User and Profile Information",$UParams & @lf & "-------------" & @lf & @lf & $pParams,120 ) endfunc ;==>prProperties Func WMIDateStringToDate($dtmDate) Return (StringMid($dtmDate, 5, 2) & "/" & _ StringMid($dtmDate, 7, 2) & "/" & StringLeft($dtmDate, 4) _ & " " & StringMid($dtmDate, 9, 2) & ":" & StringMid($dtmDate, 11, 2) & ":" & StringMid($dtmDate,13, 2)) EndFuncAs per most of my scripts this is a system-level utility, so use with care.If compiling from source, use 3.3.6.1 Aut2EXE and libraries. Note that some features will NOT work correctly if run interpreted. Edited May 3, 2010 by Anteaus Link to comment Share on other sites More sharing options...
Fire Posted December 15, 2009 Share Posted December 15, 2009 (edited) Cool.Thanks for share & Respect.But Anteaus this script is unable get users profile which enter 2 local groups:Here is from console:(users => root and => user is restricted user and have not administrative rights)SSID for user: S-1-5-21-436374069-299502267-839522115-1005SSID for root:S-1-5-21-436374069-299502267-839522115-1003and if i try get Properties for this users from your script:(and from compiled version of your script too)script is terminated with error:Here is:Please fix it.Thanks againIn this case if i try get properties for this users:expandcollapse popupC:\Documents and Settings\user>net user Учетные записи пользователей для \\compname -------------------------------------------------------------------------- Admin ASPNET Domain DroppedRights HelpAssistant root SUPPORT_388945a0 user vmlinuz Администратор Гость Команда выполнена успешно. C:\Documents and Settings\user>net user root Имя пользователя root Полное имя Комментарий Комментарий пользователя Код страны 000 (Стандартный системный) Учетная запись активна Yes Учетная запись просрочена Никогда Последний пароль задан 4/26/2009 2:22 PM Действие пароля завершается Никогда Пароль допускает изменение 4/26/2009 2:22 PM Требуется пароль Yes Пользователь может изменить пароль No Разрешенные рабочие станции Все Сценарий входа Конфигурация пользователя Основной каталог Последний вход 8/20/2009 11:36 AM Разрешенные часы входа Все Членство в локальных группах *hiddengroup *Пользователи Членство в глобальных группах *Отсутствует Команда выполнена успешно. C:\Documents and Settings\user>net user user Имя пользователя user Полное имя Non Identified restricted user Комментарий Non Identified restricted user Комментарий пользователя Код страны 000 (Стандартный системный) Учетная запись активна Yes Учетная запись просрочена Никогда Последний пароль задан 4/8/2009 6:48 PM Действие пароля завершается Никогда Пароль допускает изменение 4/8/2009 6:48 PM Требуется пароль Yes Пользователь может изменить пароль No Разрешенные рабочие станции Все Сценарий входа Конфигурация пользователя Основной каталог Последний вход 12/15/2009 10:58 PM Разрешенные часы входа Все Членство в локальных группах *hiddengroup *Пользователи Членство в глобальных группах *Отсутствует Команда выполнена успешно. C:\Documents and Settings>net localgroup hiddengroup Имя псевдонима hiddengroup Комментарий Restricted users Члены --------------------------------------------------------------------- root user Команда выполнена успешно. Edited December 15, 2009 by Sh3llC043r [size="5"] [/size] Link to comment Share on other sites More sharing options...
Anteaus Posted December 15, 2009 Author Share Posted December 15, 2009 (edited) Update; Found problem. It isn't anything to do with groups or character-sets, rather it's simply that a request for Properties doesn't always trap a situation where there are none to be retrieved, as with a folder which has no associated user. Will flag for fixing with the next build. Thanks for pointing it out. Also worth mentioning that there are a few SBC issues with this project (which I started a while back and shelved) which mean the latest compiler can't be used with this source. Will update to use 3.3x when I get around to it. For the moment best to use the built version. -------------- You got me there. Hasn't been tested with international character-sets so I'm not sure what the issue is. It would be useful to know what error is displayed using the interpreter to run the script, since that would include a line number. From the look of the message it must be coming from a function which normally returns an array of values, but in this case returns null. I'll see if I can duplicate it, though I doubt if I can set-up the same test conditions here. Edited December 16, 2009 by Anteaus Link to comment Share on other sites More sharing options...
Anteaus Posted January 19, 2010 Author Share Posted January 19, 2010 Version 0.2 now online. Several enhancements. Link to comment Share on other sites More sharing options...
Anteaus Posted May 3, 2010 Author Share Posted May 3, 2010 Uploaded v0.3 today. Link to comment Share on other sites More sharing options...
engjcowi Posted January 6, 2011 Share Posted January 6, 2011 This is cool thanks Drunken Frat-Boy Monkey Garbage Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now