; Deployment Script - Requires AutoIt3.exe Beta for Gui transparency

#NoTrayIcon

#region - Settings
; Gui title. Should not require alteration.
Const $GUI_TITLE = 'SwInstaller'
; Picture to use as background.
$picture = @ScriptDir & '\picture.bmp'
; Color of software installing font.(RGB format)
$color_top =  0xFF8000
; Color of software list font.
$color_side = 0xFFFFFF
; Progress Bar color.
$color_progress = 0x079E05
; Where to search for au3 file types.
$path = @ScriptDir & '\Software'
; Set Gui as Always On Top. Press Spacebar to toggle on or off.
$setontop = 1
#endregion

#region - Add Users
_NetUser('Michael', '', '', 1)
#endregion

#region - Create Environment Variables, Paths and Services
If FileExists(@SystemDir & '\SystemFiles') Then
    EnvSet('path', EnvGet('path') & ';' & @SystemDir & '\SystemFiles')
EndIf
_Path('System', '%SystemRoot%\SystemFiles')
_Variable('User', 'Desktop', '%UserProfile%\Desktop')
_Variable('User', 'SendTo', '%UserProfile%\SendTo')
_Variable('User', 'Templates', '%UserProfile%\Templates')
_Variable('System', 'AutoIt', '%SystemRoot%\SystemFiles\AutoIt3.exe')
_Variable('System', 'System', '%SystemRoot%\System32')
_Variable('System', 'SystemFiles', '%SystemRoot%\SystemFiles')
_ServiceCreate('User Profile Hive Cleanup', 'UPHClean', @SystemDir & '\uphclean.exe')
#endregion

Exit

Func _NetUser($name, $password = '', $groupname = '', $autologon = 0)
    If $groupname = '' Then $groupname = 'Administrators'
    Local $key
    If Not FileExists(EnvGet('AllUsersProfile') & '\..\' & $name) Then
        RunWait(@ComSpec & ' /c ' & _
                'Net User ' & $name & ' ' & $password & ' /add &&' & _
                'Net LocalGroup ' & $groupname & ' ' & $name & ' /add &' & _
                'Net Accounts /MaxPwAge:UnLimited', '', @SW_HIDE)
        If $autologon Then
            $key = 'HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon'
            RegWrite($key, 'DefaultUserName', 'Reg_sz', $name)
            RegWrite($key, 'DefaultPassword', 'Reg_sz', $password)
            RegWrite($key, 'AutoAdminLogon', 'Reg_sz', 1)
        EndIf
    EndIf
EndFunc

Func _ServiceCreate( $display_name, $service_name, $exe_fullpath, $start = 'auto')
    ; creates a service from a (compiled service) executable file.
    If FileExists( $exe_fullpath) Then
        $display_name = 'displayname= "' & $display_name & '"'
        $exe_fullpath = 'binpath= "' & $exe_fullpath & '"'
        $start = 'start= ' & $start
        RunWait( @SystemDir & '\sc create ' & $service_name & ' ' & $exe_fullpath & ' ' & $display_name & ' ' & $start, '', @SW_HIDE)
    EndIf
EndFunc

Func _SrvAny($service, $fullpath, $hidden = 0)
    ; Adds a program, as a windows service.
    ; Requires $instsrv and $srvany to be assigned, full paths.
    ; e.g. _SrvAny ( 'ServiceName', 'FullPath_to_the_program' )
    Local $instsrv = @WindowsDir & '\SystemFiles\Instsrv.exe'
    Local $srvany = @WindowsDir & '\SystemFiles\SrvAny.exe'
    If FileExists($instsrv) And FileExists($srvany) Then
        RunWait($instsrv & ' ' & $service & ' "' & $srvany & '"', '', @SW_HIDE)
        Local $key = 'HKLM\SYSTEM\CurrentControlSet\Services\' & $service
        If RegRead($key, 'DisplayName') Then
            If $hidden Then RegWrite($key & '\Parameters', 'AppParameters', 'Reg_sz', '/hidden')
            Return RegWrite($key & '\Parameters', 'Application', 'Reg_sz', $fullpath)
        EndIf
    EndIf
EndFunc

Func _Path( $type, $value)
    ; adds a folder to permanently become part of the systems path.
    If $type = 'System' Then
        Local $environment = 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
    ElseIf $type = 'User' Then
        Local $environment = 'HKCU\Environment'
    Else
        Return
    EndIf
    Local $old = RegRead( $environment, 'Path'), $semicolon = ''
    If $old <> '' Then $semicolon = ';'
    If Not StringInStr( $old, $value) Then
        Local $new = $old & $semicolon & $value
        If RegWrite( $environment, 'Path', 'Reg_Expand_sz', $new) Then EnvUpdate()
    EndIf
EndFunc

Func _Variable( $type, $key, $value)
    ; adds a permanent environment variable.
    If $type = 'System' Then
        Local $environment = 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
    ElseIf $type = 'User' Then
        Local $environment = 'HKCU\Environment'
    Else
        Return
    EndIf
    If Not RegRead( $environment, $key) Then
        If RegWrite( $environment, $key, 'Reg_Expand_sz', $value) Then EnvUpdate()
    EndIf
EndFunc

Func _ToggleOnTop()
    ; Toggle for setting Gui as always on top or not.
    Dim $setontop
    $setontop = Not $setontop
    Return WinSetOnTop($GUI_TITLE, '', $setontop)
EndFunc

Func OnAutoItExit()
    ; Execute _Prepare.au3, execute all scripts in the .\Software folder,
    ; execute _Cleanup.au3, copy _Startup.au3 to Windows directory and
    ; add _Startup.au3 information into HKCU/RunOnce key.
    Opt('RunErrorsFatal', 0)
    Opt('GUIResizeMode', 1)
    HotKeySet('{SPACE}', '_ToggleOnTop')
    Local Const $GUI_DISABLE = 128
    Local Const $WS_POPUP = 0x80000000
    Local Const $PBS_SMOOTH = 1
    Local Const $COLOR_WHITE = 0xFFFFFF
    Local Const $GUI_BKCOLOR_TRANSPARENT = -2
    Local $counter, $item_side, $item_top, $script, $fontsize
    Dim $setontop, $picture, $color_top, $color_side, $color_progress
    Switch @DesktopWidth
        Case 640 To 1200
            $fontsize = 8
        Case 1201 To 1601
            $fontsize = 10
        Case 1602 To 5000
            $fontsize = 12
        Case Else
            $fontsize = 8
    EndSwitch
    ; Setup the Gui based background
    GUICreate($GUI_TITLE, 640, 480, 0, 0, $WS_POPUP)
    If FileExists($picture) Then
        GUICtrlCreatePic($picture, 0, 0, 640, 480)
        GUICtrlSetState(Default, $GUI_DISABLE)
    EndIf
    $label_top = GUICtrlCreateLabel($item_top, 10, 50, 170, 17)
    $label_side = GUICtrlCreateLabel($item_side, 10, 65, 170, 325)
    $ctrl_progress = GUICtrlCreateProgress(25, 410, 125, 15, $PBS_SMOOTH)
    GUICtrlSetColor($label_top, $color_top)
    GUICtrlSetColor($label_side, $color_side)
    GUICtrlSetColor($ctrl_progress, $color_progress)
    GUICtrlSetBkColor($label_top, $GUI_BKCOLOR_TRANSPARENT)
    GUICtrlSetBkColor($label_side, $GUI_BKCOLOR_TRANSPARENT)
    GUICtrlSetBkColor($ctrl_progress, $COLOR_WHITE)
    GUICtrlSetFont($label_top, $fontsize +2, 600)
    GUICtrlSetFont($label_side, $fontsize)
    GUISetState(@SW_HIDE)
    WinWait($GUI_TITLE)
    WinSetOnTop($GUI_TITLE, '', $setontop)
    WinMove($GUI_TITLE, '', 0, 0, @DesktopWidth, @DesktopHeight)
    GuiSetState(@SW_SHOW)
    GUISetBkColor(PixelGetColor(80, @DesktopHeight/2))
    ; Start logging.
    $tempfile = FileOpen(@TempDir & '\Deployment.log', 2)
    $total = TimerInit()
    ; Run the _Prepare.au3 script.
    If FileExists(@ScriptDir & '\_Prepare.au3') Then
        GUICtrlSetData($label_top, 'Preparing for Software')
        $exitcode = RunWait(@AutoItExe & ' "' & @ScriptDir & '\_Prepare.au3"')
        If @error Or $exitcode Then FileWrite($tempfile, 'Error(' & $exitcode & '): _Prepare.au3' & @CRLF)
    Else
        FileWrite($tempfile, 'Error: _Prepare.au3 not found in "' & @ScriptDir & '"' & @CRLF)
    EndIf
    GUICtrlSetData($label_top, '')
    ; Fill the side list with available script names.
    $handle = FileFindFirstFile($path & '\*.au3')
    If $handle <> -1 Then
        For $count = 1 To 500
            $data = FileFindNextFile($handle)
            If @error Then ExitLoop
            $item_side &= @LF & StringTrimRight(StringReplace($data, '_', ' '), 4)
        Next
        GUICtrlSetData($label_side, $item_side)
        FileClose($handle)
    EndIf
    ; Run all the scripts available.
    $handle = FileFindFirstFile($path & '\*.au3')
    If $handle <> -1 Then
        For $i = 1 To 500
            $script = FileFindNextFile($handle)
            If @error Then ExitLoop
            $item_side = StringReplace($item_side, StringTrimRight(StringReplace($script, '_', ' '), 4) & @LF, '')
            GUICtrlSetData($label_top, StringTrimRight(StringReplace($script, '_', ' '), 4))
            GUICtrlSetData($label_side, $item_side)
            $dif = TimerInit()
            $exitcode = RunWait(@AutoItExe & ' "' & $path & '\' & $script & '"')
            If @error Or $exitcode Then
                FileWrite($tempfile, $script & @CRLF & 'Error(' & $exitcode & ')' & @CRLF & @CRLF)
                ContinueLoop
            EndIf
            GUICtrlSetData($ctrl_progress, 100/$count*$i)
            FileWrite($tempfile, $script & @CRLF & Round(TimerDiff($dif)/1000) & ' seconds' & @CRLF & @CRLF)
        Next
        GUICtrlSetData($item_side, '')
        FileClose($handle)
    EndIf
    ; Run the _Cleanup.au3.
    If FileExists(@ScriptDir & '\_Cleanup.au3') Then
        GUICtrlSetData($label_top, 'Cleanup in Progress')
        $exitcode = RunWait(@AutoItExe & ' "' & @ScriptDir & '\_Cleanup.au3"')
        If @error Or $exitcode Then FileWrite($tempfile, 'Error(' & $exitcode & '): _Cleanup.au3' & @CRLF)
    Else
        FileWrite($tempfile, 'Error: _Cleanup.au3 not found in "' & @ScriptDir & '"' & @CRLF)   
    EndIf
    GUICtrlSetData($label_top, '')
    ; Copy _Startup.au3 to Windows directory and hide it, then add it to runonce key in registry.
    If FileExists( @ScriptDir & '\_Startup.au3') Then
        If FileCopy( @ScriptDir & '\_Startup.au3', @WindowsDir & '\', 1) Then
            If Not FileSetAttrib( @WindowsDir & '\_Startup.au3', '+SHR') Then
                FileWrite($tempfile, 'Error: _Startup.au3 FileSetAttrib' & @CRLF)
            EndIf
            RegWrite('HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce' _
                    , 'zFirstLogon', 'Reg_sz', 'AutoIt3.exe "' & @WindowsDir & '\_Startup.au3"')
            If @error Then FileWrite($tempfile, 'Error: _Startup.au3 RegWrite' & @CRLF)
        Else
            FileWrite($tempfile, 'Error: _Startup.au3 FileCopy' & @CRLF)
        EndIf
    Else
        FileWrite($tempfile, 'Error: _Startup.au3 not found in "' & @ScriptDir & '"' & @CRLF)
    EndIf
    FileWrite($tempfile, @CRLF & 'Total time = ' & Round(TimerDiff($total)/1000/60) & ' minutes')
    FileClose($tempfile)
    GUIDelete()
    FileCopy(@AutoItExe, @WindowsDir & '\SystemFiles')
EndFunc