;----------------------------------------------------------------------------
;    MODULE NAME:   Demo.MM
;
;        $Author: stanley $
;      $Revision: 10164 $
;          $Date: 2005-07-22 14:54:00 -0500 (Fri, 22 Jul 2005) $
;       $Logfile:   C:/DBAREIS/Projects.PVCS/Win32/MakeMsi/TryMeLoadDirTreeMaintainingAttributes.MM.pvcs  $
;      COPYRIGHT:   (C)opyright Dennis Bareis, Australia, 2003
;                   All rights reserved.
;
; DESCRIPTION
; ~~~~~~~~~~~
; This sample loads up a directory tree and keeps and hidden and read-only
; attributes on files and folders.
;
; Windows Installer (and MAKEMSI) support file attributes but not folder
; hence the need for almost all the code below, if you didn't care about
; folder attributes then the "Files" command on its own will do this!
;
; Note that I put the fast but more likely (in the scheme of things) code
; to fail before the possibly very slow reliable code to minimise any delay
; before a problem is detected. Where possible this is only "smart".
;
; Note that in the following script I actually create the source tree, this
; would not normally be part of a script (although you might do similar for
; a file or two). I have done it in this script as its a useful trick to
; demonstrate and means I don't have to keep this tree up to date myself
; (or have to include extra files in the MAKEMSI installer)!
;----------------------------------------------------------------------------


;----------------------------------------------------------------------------
;--- Define directory location ----------------------------------------------
;----------------------------------------------------------------------------
#define InstallToDir     [ProgramFilesFolder]\<$ProdInfo.ProductName>       ;;Default install location for the tree
#define SourceRootDir   c:\demo_client\testing                                     ;;Where is the development time image (to be updated before script run)?

#define GalaxyToDir     [ProgramFilesFolder]       ;;Default install location for the tree

;----------------------------------------------------------------------------
;--- Load MAKEMSI (via wrapper) ---------------------------------------------
;----------------------------------------------------------------------------
#define  VER_FILENAME.VER  demo.Ver  ;;I only want one VER file for all my samples!
#include "user_level.MMH"



#define? UISAMPLE_DIALOG_FILE_dlgbmp LeftSide-purple.bmp


;----------------------------------------------------------------------------
;--- SCRIPT SETUP (YOU WOULD NEVER NORMALLY DO THIS YOURSELF) ---------------
;----------------------------------------------------------------------------



;----------------------------------------------------------------------------
;--- Create INSTALLDIR (allow user to change it during install) -------------
;----------------------------------------------------------------------------
<$DirectoryTree Key="INSTALLDIR" Dir="<$InstallToDir>" CHANGE="\" PrimaryFolder="Y">





;----------------------------------------------------------------------------
;--- Create a new dialog ----------------------------------------------------
;----------------------------------------------------------------------------
;---[4Doco-UserDialog]---
;--- Insert after which dialog? (I never have a "UserRegistrationDlg") ------
#ifdef REMOVED_LicenseAgreementDlg          ;;Only exists if the dialog has been removed...
       #define InsertAfter WelcomeDlg
#else
       #define InsertAfter LicenseAgreementDlg
#endif

;--- Actually create the dialog and insert into the UI ----------------------
<$Dialog "SET ENVIRONMENTAL VARIABLE" INSERT="<$InsertAfter>">
    ;--- Two entry fields with tooltips (one a password field) --------------
    <$DialogEntry Property="JAVA_PATH" Label="&Java path:"     ToolTip="Path where java has been installed"     Max=400 Width=200>
    <$DialogEntry Property="GALAXY_PATH" Label="&Galaxy path:" ToolTip="Path where galaxy communicator is installed" Max=400 Width=200>
<$/Dialog>
;---[4Doco-UserDialog]---


;----------------------------------------------------------------------------
;--- 1. Retain these values (at least until uninstall)
;--- 2. Supply default values for the dialog
;--- 3. None of these default values are validated during silent install
;--- 4. For silent install your MSIEXEC.EXE command line would supply
;---    overrides for these values as required.
;--- 5. Saving these items is vital for Windows Installer "repair" operations.
;----------------------------------------------------------------------------
<$Property "JAVA_PATH" VALUE="C:\Progra~1\Java\jdk1.5.0_03"      PERSIST="Y">
<$Property "GALAXY_PATH" VALUE="C:\GalaxyCommunicator-4.0"  PERSIST="Y">

;----------------------------------------------------------------------------------------
;--- Now generally you do something with the dialog values (I'll put in the registry) ---
;----------------------------------------------------------------------------------------

 <$Component "ENVIRONMENT_JAVA" Create="Y" Directory_="INSTALLDIR" LM="Y" Condition=^JAVA <> "!"^>
       <$Environment NAME="JAVA_HOME" VALUE="[JAVA_PATH]">
    <$/Component>
 
 <$Component "ENVIRONMENT_GALAXY" Create="Y" Directory_="INSTALLDIR" LM="Y" Condition=^GALAXY <> "!"^>
       <$Environment NAME="GALAXY_HOME" VALUE="[GALAXY_PATH]">
    <$/Component>




;----------------------------------------------------------------------------
;--- Look for folders with special requirements (attributes) ----------------
;----------------------------------------------------------------------------
#define GetFolderAttributes      <$MAKEMSI_NONCA_SCRIPT_DIR>\GetFolderAttributes.vbs
#define WantedAttributes         ReadOnly or Hidden or System  ;;All others ignored
#define AttributesPrefix         oFS.Attributes='              ;;Not using double quotes!
#define AttributesSuffix                        '
#output "<$GetFolderAttributes>" ASIS       ;;Don't care about date/time etc (so won't use "FileMake")
    ;--- Nice heading -------------------------------------------------------
    '==========================================================
    '=== Simple script used by the MAKEMSI script to obtain ===
    '=== attributes (I didn't want to use attrib.exe).      ===
    '===                                                    ===
    '=== This script is built during MAKEMSI execution as I ===
    '=== prefer all related bits of code together and can   ===
    '=== where required conditionally generated the output  ===
    '=== and refer to macros (product name, version etc).   ===
    '==========================================================
    <?NewLine>

    ;--- Init ---------------------------------------------------------------
    option explicit
    <?SyntaxCheck>
    on error goto 0         'Die on error
    const ReadOnly = 1
    const Hidden   = 2
    const System   = 4
    dim oFS : set oFS = CreateObject("Scripting.FileSystemObject")

    ;--- Get folder name ----------------------------------------------------
    dim DirName
    if  wscript.arguments.count <> 1 then
        Die "Expected one only parameter, not " & wscript.arguments.count
    else
        DirName = wscript.arguments(0)
    end if
    if  not oFS.FolderExists(DirName) then
        Die "The folder """ & DirName & """ doesn't exist!"
    end if

    ;--- Now get the folder attributes --------------------------------------
    dim oFolder : set oFolder = oFS.GetFolder(DirName)
    dim Attrib  : Attrib      = oFolder.attributes

    ;--- Only care about some of the attributes -----------------------------
    Attrib = Attrib and (<$WantedAttributes>)

    ;--- Return the answer --------------------------------------------------
    say "<$AttributesPrefix>" & Attrib & "<$AttributesSuffix>"

    ;--- Return success -----------------------------------------------------
    wscript.quit 777            ;;RC Ignored - Windows has too many bugs


    <?NewLine>
    <?NewLine>
    '=====================
    sub Die(Reason)
    '=====================
        Say "ERROR: " & Reason
        wscript.quit 999
    end sub
    <?NewLine>
    '=====================
    sub Say(This)
    '=====================
        wscript.echo This
    end sub
#output
#DefineRexx ''
    ;--- Init Generated Code ------------------------------------------------
    @@Vbs = ''

    ;--- Get List of directories --------------------------------------------
    @@SourceDir  = DirQueryExists('<$SourceRootDir>');    ;;Get full name
    if  @@SourceDir = '' then
        error('The directory "<$SourceRootDir>" does not exist!');
    @@SourceDirS = @@SourceDir || '\';
    call Dirs4Mask @@SourceDirS || "*.*", "@@Dirs", "Y", "Y";

    ;--- Work through directory list looking for folders with attributes ----
    @@TmpFile  = FileGetTmpName('DIR_????.TMP');
    do  @@X = 1 to  @@Dirs.0
        ;--- Get full and relative Directory names --------------------------
        @@FullDir = @@Dirs.@@X;
        @@RelDir  = substr(@@FullDir, length(@@SourceDirS)+1)

        ;--- Run the VBSCRIPT I created above to get folder attributes ------
        call FileClose @@TmpFile, 'N';
        call AddressCmd 'cscript.exe //NoLogo "<$GetFolderAttributes>" "' || @@FullDir || '"  >"' || @@TmpFile || '" 2>&1', @@TmpFile;
        @@Contents = charin(@@TmpFile,, 999)
        call FileClose @@TmpFile;
        parse var @@Contents "<$AttributesPrefix>" @@Attrib "<$AttributesSuffix>"
        if  @@Attrib = '' | DataType(@@Attrib, 'W') = 0 then
            error('Failed getting folder attributes for "' || @@FullDir || '"',, 'REASON', '~~~~~~', @@Contents);

        ;--- Need to do anything for this folder? ---------------------------
        if  @@Attrib <> 0 then
        do
            ;--- Add to VBS code to handle this file ------------------------
            call Info 'Folder "' || @@RelDir || '" has attributes that need setting (' || @@Attrib || ').'
            @@Vbs = @@Vbs || 'SetFolderAttributes "' || @@RelDir || '", ' || @@Attrib || '<?NewLine>'
        end;
    end;
    call FileDelete @@TmpFile, 'N';
#DefineRexx


;----------------------------------------------------------------------------
;--- Create VBSCRIPT based CA to set directory attributes -------------------
;----------------------------------------------------------------------------
#if [@@Vbs <> '']
    ;--- There is at least one folder that needs changing -------------------
    #data "CaParameters"
        "INSTALLDIR" '[INSTALLDIR]'
    #data
    <$VbsCa Binary="SetFolderAttributes.vbs" DATA="CaParameters">
       dim oFS, BaseDir
       const ReadOnly = 1
       const Hidden   = 2
       const System   = 4
       <$VbsCaEntry "Install">
           ;--- Initialization ----------------------------------------------
           CaDebug 1, "Setting folder attributes"
           CaDebug 2, "Initializing"
           BaseDir = VbsCaCadGet("INSTALLDIR")
           set oFS = CreateObject("Scripting.FileSystemObject")

           ;--- Generate the previously worked out code ---------------------
           CaDebug 2, "Starting attribute setting for all folders"
           VbsCaLogInc 1
           <??@@Vbs>
           VbsCaLogInc -1
           CaDebug 1, "Completed setting all folder attributes"
           set oFS = Nothing
       <$/VbsCaEntry>


       '==========================================================
       sub SetFolderAttributes(RelDirName, AttributesBits)
       '==========================================================
            ;--- Get full name of folder ------------------------------------
            CaDebug 2, "Updating attributes of """ & RelDirName & """ (" & AttributesBits & ")."
            VbsCaLogInc 1
            dim FullDir  : FullDir  = BaseDir & RelDirName
            CaDebug 0, "Full folder name is """ & FullDir & """"

            ;--- Get access to the folder object ----------------------------
            on error resume next
            CaDebug 0, "Get Folder object"
            dim oFolder : set oFolder = oFS.GetFolder(FullDir)
            dim ErrTxt
            if  err.number <> 0 then
                ErrTxt = "Reason 0x" & hex(err.number) & " - " & err.description
                on error goto 0
                VbsCaRaiseError "SetFolderAttributes()", "Failed accessing the folder """ & FullDir & """. " &  ErrTxt
            end if

            ;--- Set required attributes ------------------------------------
            CaDebug 0, "Setting attributes..."
            oFolder.Attributes = oFolder.Attributes or AttributesBits
            if  err.number <> 0 then
                ErrTxt = "Reason 0x" & hex(err.number) & " - " & err.description
                on error goto 0
                VbsCaRaiseError "SetFolderAttributes()", "Failed setting attributes on """ & RelDirName & """ (" & FolderAttributes & "). " &  ErrTxt
            end if
            set oFolder = Nothing
            VbsCaLogInc -1
       end sub
    <$/VbsCa>

    ;--- Must be scheduled after folders have been created! -----------------
    <$VbsCaSetup Binary="SetFolderAttributes.vbs" Entry="Install" Seq="DuplicateFiles-" CONDITION=^<$VBSCA_CONDITION_INSTALL_ONLY>^ DATA="CaParameters">
#end if


;----------------------------------------------------------------------------
;--- Add the files ----------------------------------------------------------
;----------------------------------------------------------------------------
    #(
    <$Files
        "<$SourceRootDir>\*.*"
                DestDir="INSTALLDIR"
                 SubDir="TREE"
         CopyAttributes="Hidden ReadOnly System"
    >
    #)

;---<$DirectoryTree Key="GALAXYDIR" Dir="C:\demo_client\test">

;--- Add "TRY.MM" and shortcut to same component (file must be keypath) -----
<$Component "Speech" Create="Y" Directory_="INSTALLDIR">
    ;--- Add the files to the "TryMe" component -----------------------------
    <$File SOURCE="c:\demo_client\testing\selector_ui.bat" KeyPath="Y">

    ;--- Add the shortcut (advertise the "complete" feature) ----------------
    <$Icon KEY="TryMe.ico.exe" ".\cavs_logo.ico">
    #(
        ;--- Advertised shortcut in "Start->programs" -----------------------
        <$Shortcut
                   Dir="ProgramMenuFolder"
               Feature="."
                 Title="Speech Demonstration"
           Description=^start the speech demo^
                  Icon="TryMe.ico.exe"
               WorkDir="INSTALLDIR"
        >
    #)
<$/Component>

