////////////////////////////////////////////////////////////////////////////////
//
// !!! IMPORTANT !!!
//
// Are you getting a Cannot convert Variant type into string (Null)????
// Remove all comments from the XML file. The XML parser is old and appearently weird
//
////////////////////////////////////////////////////////////////////////////////
// Change list
//
// Release 4.0
//  * Added elevation on load (program needs admin rights)
//  * Update of plugins will no longer use the registry but rather
//    look up the upd file in the repository online
//
// Release 3.4.0.0
//  * Added option to run CM2 or editor after installation
//  * Added option to run CM2 or editor after update
//  * Added option to run CM2 or Editor after Plugin repository browsing
//  * Added GDI+ Support
//
// Release 3.3.1.0
//  * Changed installation detection
//  * Uninstallation has been given a major overhaul
//
// Release 3.3.0.1
//  * downloading bug corrected
//
// Release 3.3.0.0
//  * BETA RELEASE
//  * If no installation is detected it will go straight to the installation.
//  * Installer updated
//  * TProgressBar out of range corrected
//
// Release 3.1.0.0
//  * Window will no longer maximize
//  * Offline UPD scan no longer active
//  * unregistering plugins will no longer happen if chosen not to
//  * Uninstaller finished
//
// Release 3.0.0.0
//  * Can now update self, though you need the CMU add-on, available on wiki
//  * Ability to run CM2 after update, will use last ran config file, if core
//    is version 0.6 or above
//  * If Core, editor or Plugin Manager is open CMU will close them (Prompted)
//  * CMLx plugins are now scanned for update
////////////////////////////////////////////////////////////////////////////////
// Show list
//
// 0.0 Selfchecking (SELFCHECK)
//     * Goes online to update AU's upd
// 0.1 Choose operation (CHOOSEOPERATION)
//     * A list between (Install, Update, PlugIn Repository, UnInstall) will guide the user onto the correct Tab
// 2.0 Installer (INSTALLER)
//     * A general installer information page
// 2.2 Choose Installation Type (INSTYPE)
//     * Normal
//     * Expert
// 2.3 (Only shows if expert installation is chosen) - Set directory (INSFOLDER)
//     * Directory selector box
// 2.4 (Only shows if expert installation is chosen) - Parts to install (INSOBJECTS)
//     * Regular checkboxes list to the main items of CM2
// 2.5 Download and resolve UPD's (INSUPDPROGRESS)
//     Progress tab on downloading and analsys of UPD's
// 2.6 Installation (INSPROGRESS)
//     * Downloading of files and installing
// 2.7 Post installation dialog (INSPOSTINS)
//     * Run CM2 checkbox
//     * Launch getting started page
// 2.8 Not visible, it's a cleanup and terminate thing (INSDOTERMINATE)
// 3.0 Auto Update (AUTOUPDATER)
//     * Shows auto update information
// 3.1 Scan for elements (AUSCANELEMENTS)
// 3.2 Download Information (AUDOWNLOADUPDS)
// 3.3 Choose what to update (AUCHOOSE)
// 3.4 Download updates (AUDOWNLOADUPDATES)
//     * Download a file and override original (if it's a plugin then uninstall prior to overwritting, then installer afterwards)
// 3.5 Post update information dialog (AUPOSTAU)
// 3.6 No visible, it's a cleanup and terminate thing (AUDOTERMINATE)
// 4.0 PlugIn Repository
//     --==--< Details needs to be worked out >--==--
// 5.0 Uninstall (UNINSTALLER)
// 5.1 Prompt for uninstalling of all install plugins (UNINSPROMPT)
// 5.2 Kill all CM2 processes (
// 5.3 Uninstalling ...
//     * Unregister plugins
//     * Delete Files
//     * Delete folders, do this in level order, highest level first
//     * Create Run-Once delete procedure on self
////////////////////////////////////////////////////////////////////////////////
//
// Ignore following errors
// EVariantTypeCastError
//
// Failure on fouth run trhough of the download code (per breakpoint)
// The file jSystemInfo was never downloaded in the first place, so trying to extract causes an error
// Why was it never downloaded?
// After all the UPD'd have been process only a fraction of the files exists in the /temp/ dir.
// Is that how it is meant to be or am I hitting a type of error?
//
////////////////////////////////////////////////////////////////////////////////

{$WARN UNIT_PLATFORM OFF}
unit CM2update;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ComCtrls, jpeg, Registry, CM2MMRB,
  FileVersion, lpl_SysUtils, lplDownload, enviroment, DFUnRar,
  ImgList, CM2RegisterTools, ShellCtrls, Buttons, XMLSystem, xmldom,
  XMLIntf, msxmldom, XMLDoc, filter, Link, repositorysystem, PNGImage,
  FileCtrl, GDIPenable, Win32Dlg, Windows10;

type
  TDLPanel = Record
   Panel: TPanel;
   Caption: TLabel;
   Status: TLabel;
   Bar: TProgressBar;
   ProgressLabel: TLabel;
   Image: TImage;
  End;
  TUpdateInfo = record
   DLPanel: TDLPanel;
   DoList: Boolean;
   Name: String;
   Location: String;
   ProgType: String;
   Version: TMMRB;
   UpdFile: String;
   DoDownload: Boolean;
   RegLocation: String;
   // Go online for these values
   UpdVersion: TMMRB;
   WhatsNew: String;
   // If updated download this file
   DownloadFile: String;
   LocalFile: String; // Where does it go
  end;
  TUpdateInfoList = class(TObject)
  private
   fList: Array of TUpdateInfo;
    function GET_UPDATEINFO(Index: Integer): TUpdateInfo;
    function GetCount: Integer;
    procedure SET_UPDATEINFO(Index: Integer; const Value: TUpdateInfo);
  public
   Function Add(Name, ProgType: String): Integer;
   Property Count: Integer read GetCount;
   Property Items[Index: Integer]: TUpdateInfo read GET_UPDATEINFO write SET_UPDATEINFO; default;
  end;
  TForm1 = class(TForm)
    Panel1: TPanel;
    PageControl1: TPageControl;
    AutoUpdater: TTabSheet;
    Bevel1: TBevel;
    Bevel2: TBevel;
    quit: TButton;
    next: TButton;
    back: TButton;
    Label1: TLabel;
    Label2: TLabel;
    AuScanElements: TTabSheet;
    Label3: TLabel;
    FlashNext: TTimer;
    updatelog: TListBox;
    fv: TFileVersion;
    AuDownloadUPDS: TTabSheet;
    Label4: TLabel;
    ProgressBar1: TProgressBar;
    download: TlplDownload;
    AuChoose: TTabSheet;
    ListView1: TListView;
    Splitter1: TSplitter;
    Memo1: TMemo;
    AuDownloadUpdates: TTabSheet;
    Label10: TLabel;
    AuPostAU: TTabSheet;
    unrar: TDFUnRar;
    Label11: TLabel;
    Chooseoperation: TTabSheet;
    SelfCheck: TTabSheet;
    Label13: TLabel;
    Panel2: TPanel;
    Image1: TImage;
    ScrollBox2: TScrollBox;
    coreimg: TImage;
    editorimg: TImage;
    generalimg: TImage;
    visualimg: TImage;
    Panel3: TPanel;
    Label5: TLabel;
    ListBox1: TListBox;
    UNINSProgress: TTabSheet;
    autoupdate: TRadioButton;
    Browse: TRadioButton;
    Uninstall: TRadioButton;
    Label6: TLabel;
    Installer: TTabSheet;
    PlugInRepository: TTabSheet;
    UnInstaller: TTabSheet;
    INSType: TTabSheet;
    INSFolder: TTabSheet;
    INSObjects: TTabSheet;
    INSUPDProgress: TTabSheet;
    InsPostIns: TTabSheet;
    InsDoTerminate: TTabSheet;
    InsEula: TTabSheet;
    Label7: TLabel;
    CheckBox1: TCheckBox;
    Label8: TLabel;
    Label9: TLabel;
    Label14: TLabel;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    Label15: TLabel;
    Label16: TLabel;
    Label17: TLabel;
    Label18: TLabel;
    Label19: TLabel;
    GroupBox1: TGroupBox;
    destfolderLBL: TLabel;
    SpeedButton1: TSpeedButton;
    Label21: TLabel;
    Edit1: TEdit;
    XML: TXMLDocument;
    AUDoTerminate: TTabSheet;
    xmldownload: TlplDownload;
    eula: TRichEdit;
    TreeView1: TTreeView;
    ImageList1: TImageList;
    originallist: TImageList;
    Label22: TLabel;
    Label23: TLabel;
    ProgressBar2: TProgressBar;
    Label24: TLabel;
    upddownload: TlplDownload;
    Label25: TLabel;
    Label26: TLabel;
    INSProgress: TTabSheet;
    GroupBox2: TGroupBox;
    overallprogress: TProgressBar;
    Label27: TLabel;
    Label28: TLabel;
    Label29: TLabel;
    Label30: TLabel;
    Label31: TLabel;
    Label32: TLabel;
    GroupBox3: TGroupBox;
    itemprogress: TProgressBar;
    Bevel3: TBevel;
    InsDownload: TlplDownload;
    Link1: TLink;
    Button1: TButton;
    Button2: TButton;
    Label20: TLabel;
    Label33: TLabel;
    UNINSPrompt: TTabSheet;
    Label34: TLabel;
    Label35: TLabel;
    Label36: TLabel;
    Label37: TLabel;
    RadioGroup1: TRadioGroup;
    Label38: TLabel;
    Label39: TLabel;
    Label40: TLabel;
    Label41: TLabel;
    killimg: TImage;
    uninstallimglist: TImageList;
    unregimg: TImage;
    delimg: TImage;
    folderimg: TImage;
    Label42: TLabel;
    UNINSComplete: TTabSheet;
    Label43: TLabel;
    Label44: TLabel;
    RepBrowse: TTabSheet;
    ImageList2: TImageList;
    Label50: TLabel;
    Label49: TLabel;
    Label48: TLabel;
    Label47: TLabel;
    Label46: TLabel;
    Label45: TLabel;
    outlawedimg: TImage;
    Image2: TImage;
    Bevel4: TBevel;
    TreeView2: TTreeView;
    Label51: TLabel;
    Label52: TLabel;
    Label53: TLabel;
    Label54: TLabel;
    Shape1: TShape;
    RepInstall: TTabSheet;
    Label55: TLabel;
    GroupBox4: TGroupBox;
    repitembar: TProgressBar;
    GroupBox5: TGroupBox;
    RepTotalBar: TProgressBar;
    Bevel5: TBevel;
    Label56: TLabel;
    TabSheet1: TTabSheet;
    Label57: TLabel;
    RepDoTerminate: TTabSheet;
    repdownload: TlplDownload;
    DirectoryListBox1: TDirectoryListBox;
    DriveComboBox1: TDriveComboBox;
    RadioGroup2: TRadioGroup;
    UninsPost: TTabSheet;
    RadioGroup3: TRadioGroup;
    RadioGroup4: TRadioGroup;
    GDIPenable1: TGDIPenable;
    procedure quitClick(Sender: TObject);
    procedure nextClick(Sender: TObject);
    procedure backClick(Sender: TObject);
    procedure FlashNextTimer(Sender: TObject);
    Procedure StopFlash;
    procedure AddToUpdateLog(Str: String);
    procedure AppendToUpdateLog(Str: String);
    procedure FormCreate(Sender: TObject);
    procedure PageControl1Change(Sender: TObject);
    procedure ListView1Change(Sender: TObject; Item: TListItem;
      Change: TItemChange);
    procedure downloadComplete(Sender: TObject);
    procedure downloadProgress(Sender: TObject; Readed, TotalSize: Int64);
    procedure downloadError(Sender: TObject; ErrorCode: Integer);
    procedure unrarError(Sender: TObject; Message: String;
      MessageID: Integer);
    procedure unrarProgress(Sender: TObject; FilesProcessed, FileCount,
      SizeProcessed, SizeCount: Cardinal);
    procedure FormActivate(Sender: TObject);
    procedure xmldownloadComplete(Sender: TObject);
    procedure CheckBox1Click(Sender: TObject);
    procedure TreeView1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure TreeView1Collapsing(Sender: TObject; Node: TTreeNode;
      var AllowCollapse: Boolean);
    procedure upddownloadError(Sender: TObject; ErrorCode: Integer);
    procedure upddownloadProgress(Sender: TObject; Readed,
      TotalSize: Int64);
    procedure upddownloadComplete(Sender: TObject);
    procedure TreeView1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure InsDownloadError(Sender: TObject; ErrorCode: Integer);
    procedure InsDownloadProgress(Sender: TObject; Readed,
      TotalSize: Int64);
    procedure SpeedButton1Click(Sender: TObject);
    procedure Edit1Change(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure SpeedButton2Click(Sender: TObject);
    procedure TreeView2MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure TreeView2Click(Sender: TObject);
    procedure TreeView2Change(Sender: TObject; Node: TTreeNode);
    procedure repdownloadProgress(Sender: TObject; Readed,
      TotalSize: Int64);
    procedure unrarFileProcessing(Sender: TObject;
      hdrData: TDFRARHeaderData; status: Integer);
    procedure DirectoryListBox1Change(Sender: TObject);
  private
    ChangeEditBox: boolean;
    Reppluginstall: String;
    VRep: TRepositoryList;
    GRep: TRepositoryList;
    OverallSize: Integer;
    OverallProgressInt: Integer;
    ShowInstall: Boolean;
    ShowAutoUpdate: Boolean;
    ShowPlugInRep: Boolean;
    ShowUnInstall: Boolean;
    ForceInstall: Boolean;
    Offline: Boolean;
    OfflineOverride: Boolean;
    Procedure LoadRep(Rep: TRepository);
    Function GetUPDFromRepository(PluginName: String; var upd: string): boolean;
  public
    BypassSelfCheck: Boolean;
    ExtractPath: String;
    InstallDir: String;
    UpdList: TupdateinfoList;
    CleanUpFiles: TStrings;
    RarFileList: TStrings;
    UnInstallLog: TStrings;
    InstallItemList: TItemList;
    InstallItemGroupList: TItemGroupList;
    InstallLinkList: TLinkList;
    RegList: TRegList;
    XMLProceed: Boolean;
    Function ApoToQuotes(Str: String): String;
    Function InstallParser(Str: String): String;
    Function ElementIDParser(Str: String; SelfItem: TItem): String;
    Procedure XMLBuildGroupList(Node: IXMLNode);
    Procedure XMLBuildLinkList(Node: IXMLNode);
    Procedure XMLBuildRegistryList(Node: IXMLNode);
    Procedure XMLElement(Node: IXMLNode);
    Procedure ResolveInstallXML(Filename: String);
    Procedure ShowDescription(Node: TTreenode);
    procedure SetSELFCHECK;
    Procedure SetINSTALLER;
    procedure SetAUTOUPDATER;
    Procedure SetAUSCANELEMENTS;
    Procedure SetAUDOWNLOADUPDS;
    procedure SetAUCHOOSE;
    Procedure SetAUDOWNLOADUPDATES;
    Procedure SetAUPOSTAU;
    procedure SetAUDOTERMINATE;
    Procedure SetCHOOSEOPERATION;
    Procedure SetINSEULA;
    Procedure SetINSType;
    Procedure SetINSFolder;
    Procedure SetINSObjects;
    Procedure SetINSUPDProgress;
    Procedure SetINSProgress;
    Procedure SetINSDoTerminate;
    PRocedure SetINSPostIns;
    Procedure SetUnInstaller;
    Procedure SetUnInsPrompt;
    Procedure SetUninsProgress;
    Procedure SetUnInsComplete;
    Procedure SetRepSelect;
    Procedure SetRepBrowse;
    Procedure SetRepInstall;
    Procedure SetRepComplete;
    Procedure SetRepDoTerminate;
  end;

var
  Form1: TForm1;
  FirstRun: Boolean = true;
  EditorPath, RegToolsPath: String;

Const
 // Globals
 InstallLocation = '\Software\The CoolMon Project\CoolMon2\Installation';
 GenPlugLocation = '\Software\The CoolMon Project\CertifiedPlugins\General';
 VisPlugLocation = '\Software\The CoolMon Project\CertifiedPlugins\Visual';
 CMLxPlugLocation = '\Software\The CoolMon Project\CertifiedPlugins\CMLX';

 // URLS

 // Server locations
 Server = 'http://coolmon.blackstar.solar';
 ServerUpdate = Server + '/update';
 ServerRepository = Server + '/download/plugins';

 // Update files
 SelfUpdateFile = ServerUpdate + '/autoupdate.upd';
 CoreUpdateFile = ServerUpdate + '/core.upd';
 OutlawEdUpdateFile = ServerUpdate + '/outlawed.upd';
 PMUpdateFile = ServerUpdate + '/pm.upd';
 RegisterToolsFile = ServerUpdate + '/registertools.upd';
 PluginMgrFile = ServerUpdate + '/pluginmgr.upd';

 // Repository files
 RepVisual = ServerRepository + '/visual.xml';
 RepGeneral = ServerRepository + '/general.xml';

  // Online Installation Script location
  CM2IIFile = Server + '/download/installation/cm2ii.rar';


implementation

{$R *.dfm}
uses
  Tlhelp32, Unit2;

function KillTask(ExeFileName: string): Integer;
const
  PROCESS_TERMINATE = $0001;
var
  ContinueLoop: BOOL;
  FSnapshotHandle: THandle;
  FProcessEntry32: TProcessEntry32;
begin
  ExeFileName := Extractfilename(ExeFileName);
  Result := 0;
  FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
  ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);

  while Integer(ContinueLoop) <> 0 do
  begin
    if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =
      UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) =
      UpperCase(ExeFileName))) then
      Result := Integer(TerminateProcess(
                        OpenProcess(PROCESS_TERMINATE,
                                    BOOL(0),
                                    FProcessEntry32.th32ProcessID),
                                    0));
     ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
  end;
  CloseHandle(FSnapshotHandle);
end;

Function CreatePanel(Parent: TScrollBox; Caption: String; Status: string; ImgFile: String): TDLPanel;
Begin
 Result.Panel := TPanel.Create(Parent);
 Result.Panel.Parent := Parent;
 Result.Panel.Height := 44;
 Result.Panel.Align := alTop;
 Result.Image := TImage.Create(result.panel);
 Result.Image.Parent := Result.panel;
 Result.Image.Left := 5;
 Result.Image.Top := 5;
 Result.Image.Width := 36;
 Result.Image.Height := 36;
 Try
  If Fileexists(ImgFile) then Result.Image.Picture.LoadFromFile(ImgFile);
 except
 end;
 Result.Caption := TLabel.Create(Result.Panel);
 Result.Caption.Parent := Result.Panel;
 Result.Caption.Left := 43;
 Result.Caption.Top := 1;
 Result.Caption.Caption := Caption;
 Result.Caption.Transparent := true;
 Result.Status := TLabel.Create(Result.Panel);
 Result.Status.Parent := REsult.Panel;
 Result.Status.Left := 43;
 Result.Status.Top := 16;
 Result.Status.Caption := Status;
 Result.Status.Transparent := true;
 Result.Bar := TProgressBar.Create(Result.Panel);
 Result.Bar.Parent := Result.Panel;
 Result.Bar.Left := 43;
 Result.Bar.Top := 31;
 Result.Bar.Width := 140;
 Result.Bar.Height := 11;
 Result.Bar.Position := 0;
// Result.Bar.Smooth := true;
 Result.ProgressLabel := TLabel.Create(Result.Panel);
 Result.ProgressLabel.Parent := Result.Panel;
 Result.ProgressLabel.Left := 188;
 Result.ProgressLabel.Top := 28;
 Result.ProgressLabel.Caption := '0 kb/s';
 Result.ProgressLabel.Transparent := true;
End;

{ TUpdateInfoList }

function TUpdateInfoList.Add(Name, ProgType: String): Integer;
begin
 SetLength(fList, Length(fList) + 1);
 fList[Length(fList) - 1].Name := Name;
 fList[Length(fList) - 1].ProgType := ProgType;
 Result := length(fList) - 1;
end;

function TUpdateInfoList.GET_UPDATEINFO(Index: Integer): TUpdateInfo;
begin
 Result := fList[Index];
end;

function TUpdateInfoList.GetCount: Integer;
begin
 Result := length(fList);
end;

procedure TUpdateInfoList.SET_UPDATEINFO(Index: Integer;
  const Value: TUpdateInfo);
begin
 fList[Index] := Value;
end;

{ TForm1 }

procedure TForm1.PageControl1Change(Sender: TObject);
begin
 Case PageControl1.ActivePageIndex of
  0: SetSELFCHECK;
  1: SetCHOOSEOPERATION;
  2: SetAUTOUPDATER;
  3: SetAUSCANELEMENTS;
  4: SetAUDOWNLOADUPDS;
  5: SetAUCHOOSE;
  6: SetAUDOWNLOADUPDATES;
  7: SetAUPOSTAU;
  8: SetAUDOTERMINATE;
  9: SetINSTALLER;
 10: SetINSEULA;
 11: SetINSType;
 12: SetINSFolder;
 13: SetINSObjects;
 14: SetINSUPDProgress;
 15: SetINSProgress;
 16: SetINSPostIns;
 17: SetINSDoTerminate;
 19: SetUnInstaller;
 20: SetUnInsPrompt;
 21: SetUnInsProgress;
 22: SetUnInsComplete;
 // 23 is uninstall post page
 24: SetRepBrowse;
 25: SetRepInstall;
 26: SetRepComplete;
 27: SetRepDoTerminate;
 End;
end;

procedure TForm1.quitClick(Sender: TObject);
begin
 if MessageDlg('Are you sure you wish to quit ?', mtWarning, [mbYes,mbNo], 0) = mrNo then exit;
 Application.Terminate;
end;

procedure TForm1.nextClick(Sender: TObject);
begin
 If PageControl1.ActivePageIndex = 22 then begin
  application.Terminate;
  application.ProcessMessages;
 end;
 If PageControl1.ActivePageIndex = 1 Then begin
  // Choose page
  If AutoUpdate.Checked then begin
   PageControl1.ActivePage := AutoUpdater;
  end;
  If Browse.Checked then begin
   PageControl1.ActivePage := RepBrowse;
   PageControl1Change(self);
  end;
  If UnInstall.Checked then begin
   PageControl1.ActivePage := Uninstaller;
  end;
  exit;
 end;
 If PageControl1.ActivePage = InsType then begin
  If Radiobutton2.checked then begin
   // Custom install
   PageControl1.ActivePage := InsObjects;
   PageControl1Change(self);
   exit;
  end;
  If Radiobutton1.Checked then begin
   SetINSObjects;
   PageControl1.ActivePage := INSUPDProgress;
   PageControl1Change(self);
   exit;
  end;
 end;
 Pagecontrol1.SelectNextPage(true);
end;

procedure TForm1.backClick(Sender: TObject);
begin
 If PageControl1.ActivePage = InsObjects then begin
  PageControl1.ActivePage := InsType;
  PageControl1Change(self);
  exit;
 end;
 PageControl1.SelectNextPage(false);
end;


procedure TForm1.FlashNextTimer(Sender: TObject);
begin
 If Next.Font.Style = [fsBold] then Next.Font.Style := []
  else Next.Font.Style := [fsBold];
 Update;
end;

procedure TForm1.AddToUpdateLog(Str: String);
begin
 UpdateLog.Items.Add(Str);
 UpdateLog.TopIndex := UpdateLog.Items.count - 1;
 update;
 sleep(50);
end;

procedure TForm1.FormCreate(Sender: TObject);
Var
 Reg: TRegistry;
 I: Integer;
 S: String;
begin
 If not HasAdminAccess then begin
  Windows10.RestartApplicationWithElevatedPriviliges;
 end;

 OfflineOverride := False;
 BypassSelfCheck := False;
 Reg := TRegistry.Create;
 Reg.RootKey := HKEY_CURRENT_USER;
 Reg.OpenKey('\Software\The CoolMon Project\CMU', true);
 Reg.WriteString('', Application.ExeName);
 Reg.CloseKey;
 FreeAndNil(Reg);
 Self.UpdList := TupdateinfoList.Create;
 Self.CleanUpFiles := TStringList.Create;
 Self.RarFileList := TStringList.Create;
 ShowInstall := False;
 ShowAutoUpdate := False;
 ShowPluginRep := True;
 ShowUninstall := false;
 ForceInstall := false;
 ExtractPath := Extractfilepath(application.ExeName);
 InstallDir := PathToOk(GetProgramFilesDir) + 'CoolMon 2';
 For I := 1 to paramcount do begin
  if uppercase(paramstr(I)) = '/BYPASSSELFCHECK' then Bypassselfcheck := true;
  if uppercase(copy(paramstr(I), 1, length('/CHDIR:'))) = '/CHDIR:' then begin
   S := Copy(Paramstr(I), length('/CHDIR:') + 1, length(Paramstr(I)));
   Chdir(S);
  end;
  if uppercase(paramstr(I)) = '/ACCEPTEULA' then checkbox1.Checked := true;
  if uppercase(paramstr(I)) = '/FORCEINSTALL' then forceinstall := true;
  if uppercase(paramstr(I)) = '/OFFLINE' then OfflineOverride := true;
 end;
 Pagecontrol1.ActivePageIndex := 0;
end;

function TForm1.GetUPDFromRepository(PluginName: String;
  var upd: string): boolean;
Var
 I: Integer;
begin
 result := false;

 For I := 0 to GRep.Count - 1 do begin
  If uppercase(PluginName) = uppercase(GRep[I].Title) then begin
   upd := GRep[I].UpdFile;
   Result := true;
   exit;
  end;
 end;

 For I := 0 to VRep.Count - 1 do begin
  If Uppercase(PluginName) = uppercase(VRep[I].Title) then begin
   upd := VRep[I].UpdFile;
   Result := true;
   exit;
  end;
 end;


end;

procedure TForm1.AppendToUpdateLog(Str: String);
begin
 Str := UpdateLog.Items[UpdateLog.Count - 1] + Str;
 UpdateLog.Items[UpdateLog.Count - 1] := Str;
 UpdateLog.TopIndex := UpdateLog.Items.count - 1;
 update;
 sleep(50);
end;

procedure TForm1.StopFlash;
begin
 FlashNext.Enabled := False;
 Next.Font.Style := []; 
end;

procedure TForm1.ListView1Change(Sender: TObject; Item: TListItem;
  Change: TItemChange);
begin
 If Item.SubItems.Count < 3 then exit;
 Memo1.Text := updList[StrToInt(Listview1.items[Item.Index].SubItems[3])].WhatsNew;
end;

procedure TForm1.downloadComplete(Sender: TObject);
begin
 CleanUpFiles.Add(download.Filename);
end;

procedure TForm1.downloadProgress(Sender: TObject; Readed,
  TotalSize: Int64);
begin
 If download.Tag = -1 then exit;
 updlist[Download.Tag].DLPanel.Bar.Max  := Totalsize;
 updlist[Download.Tag].DLPanel.Bar.Position := Readed;
 updlist[Download.Tag].DLPanel.ProgressLabel.Caption := FormatFloat('##.##" Kb/s."', Download.BytesPerSec / 1024);
 Application.ProcessMessages;
end;

procedure TForm1.downloadError(Sender: TObject; ErrorCode: Integer);
begin
 If uppercase(extractfileext(download.Filename)) <> '.UPD' then
  MessageDlg('Internet Error: ' + IntToStr(ErrorCode) + #13#10 + 'When trying to access' + #13#10 + Download.URL, mtError, [mbOK], 0);
end;

procedure TForm1.unrarError(Sender: TObject; Message: String;
  MessageID: Integer);
begin
 MessageDlg('Unpacking Error [' + IntToStr(MEssageID) + ']'+#13+#10+Message, mtError, [mbOK], 0);
end;

procedure TForm1.unrarProgress(Sender: TObject; FilesProcessed, FileCount,
  SizeProcessed, SizeCount: Cardinal);
begin
//( updlist[Download.Tag].DLPanel.Bar.Max  := SizeCount;
// updlist[Download.Tag].DLPanel.Bar.Position := SizeProcessed;
 Application.ProcessMessages;
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
 If firstrun then begin
  FirstRun := False;
  SetSELFCHECK;
 End;
end;

procedure TForm1.ResolveInstallXML(Filename: String);
Var
 I: Integer;
 MainNode, GroupInfo, LinkInfo, Registry: IXMLNode;
begin
 InstallItemList := TItemList.Create;
 InstallItemGroupList := TItemGroupList.Create;
 InstallLinkList := TLinkList.Create;
 RegList := TRegList.Create;
 XML.LoadFromFile(filename);
 XML.Active := true;

 // Dump file for debug
 XML.SaveToFile('C:\temp.xml');

 MainNode := XML.ChildNodes['CM2Installer'];
 If (MainNode = nil) then begin
  Warning('XML MainNode is nil');
 End;
 GroupInfo := MainNode.ChildNodes['GroupInfo'];
 If GroupInfo = nil then begin
  Warning('GroupInfo Childnodes is empty');
 End;
 LinkInfo := MainNode.ChildNodes['LinkInfo'];
 If LinkInfo = nil then begin
  Warning('LinkInfo Childnodes are empty');
 End;
 Registry := MainNode.ChildNodes['Registry'];
 If Registry = nil then begin
  Warning('Registry Childnodes are empty');
 end;


 XMLBuildGroupList(GroupInfo);
 XMLBuildLinkList(LinkInfo);
 XMLBuildRegistryList(Registry);
 For I := 0 to MainNode.ChildNodes.Count - 1 do begin
  XMLElement(MainNode.ChildNodes[I]);
 end;
 XML.Active := false;
end;

procedure TForm1.XMLElement(Node: IXMLNode);
begin
 If uppercase(Node.nodename) = 'GROUPINFO' then exit; // group information shall not be evaluated
 If uppercase(Node.NodeName) = 'LINKINFO' then exit; // Link information shall not be evaluated
 If uppercase(Node.NodeName) = 'UNINSTALLINFO' then exit; // Uninstall information shall not be evaluated
 If uppercase(Node.Nodename) = 'REGISTRY' then exit;
 With InstallItemList.AddItem do begin
  GroupName := Node.NodeName;
  Name := Node.ChildValues['Name'];
  ElementID := Node.Attributes['ELEMENTID'];
  Description := Node.ChildValues['Description'];
  InstallTo := Node.ChildValues['InstallTo'];
  Filename := Node.ChildValues['Filename'];
  Required := uppercase(Node.ChildValues['Required']) = 'YES';
  URL := Node.ChildValues['URL'];
  Local := Node.ChildValues['Local'];
 end;
end;

procedure TForm1.InsDownloadError(Sender: TObject; ErrorCode: Integer);
begin
 MessageDlg('Downloading Error'+#13+#10+ IntToStr(ErrorCode) + ' ' + insdownload.GetErrorCodeDes(errorcode) +#13+#10+'while downloading' + insdownload.url, mtError, [mbOK], 0);
end;

procedure TForm1.InsDownloadProgress(Sender: TObject; Readed,
  TotalSize: Int64);
begin
 ItemProgress.Position := readed;
 overallprogress.Position := overallprogressint + readed;
 label32.caption := inttostr(insdownload.BytesPerSec div 1024) + ' Kb./Sec';
 Application.ProcessMessages;
end;


procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
 edit1.text := installdir;
 pagecontrol1.ActivePage := insfolder;
 PageControl1Change(self);
 Next.Enabled := False;
 Back.Enabled := false;
 application.ProcessMessages;
 update;
end;

procedure TForm1.Edit1Change(Sender: TObject);
begin
 if directoryexists(edit1.text) then begin
  If edit1.text[length(edit1.text)] = ':' then exit;
  ChangeEditBox := false;
  DirectoryListBox1.Directory := Edit1.text;
  ChangeEditBox := true;
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 InstallDir := Edit1.text;
 PageControl1.ActivePage := InsType;
 PageControl1Change(self);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 PageControl1.ActivePage := InsType;
 PageControl1Change(self);
end;

procedure TForm1.upddownloadError(Sender: TObject; ErrorCode: Integer);
begin
 MessageDlg('Unable to download the following UPD file [Error: ' + IntToStr(ErrorCode) + ' ]' + #13#10 + upddownload.URL + #13#10 + #13#10 + 'The server might be down, should the problem persist we suggest you visit the CoolMon 2 forum for any news or post it yourself if you can''t find any information on the problem', mtError, [mbOK], 0);
end;

procedure TForm1.upddownloadProgress(Sender: TObject; Readed,
  TotalSize: Int64);
begin
  application.ProcessMessages;

end;

procedure TForm1.upddownloadComplete(Sender: TObject);
begin
 CleanUpFiles.Add(upddownload.Filename);
 application.ProcessMessages;
end;

procedure TForm1.TreeView1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
Var
 Node: TTreenode;
begin
 Node := treeview1.GetNodeAt(x, y);
 ShowDescription(Node);
end;

procedure TForm1.ShowDescription(Node: TTreenode);
begin
 if Node = nil then exit;
 If node.ImageIndex < 3 then begin
  Label26.caption := installitemlist[node.StateIndex].Description;
 end
  else
 begin
  Label26.Caption := InstallItemGroupList.GetByScreenname(node.Text).Description;
 end;
 Update;
end;

function TForm1.InstallParser(Str: String): String;
Var
 I: Integer;
 S: String;
begin
 // InstallDir
 // CommonFiles
 // ProgramFiles
 // StartUp "Startmenu\Startup"
 // StartMenu
 // Programs
 // Windows
 // system
 // temp
 If str = '' then begin
  Result := '';
  exit;
 end;
 I := 1;
 Repeat
  if Str[I] = '[' then begin
   If uppercase(copy(str, I, length('[INSTALLDIR]'))) = '[INSTALLDIR]' then begin
    S := InstallDir;
    If S[Length(S)] = '\' then S := copy(S, 1, length(s) - 1);
    Str := Copy(Str, 1, I - 1) + S + Copy(Str, I + length('[INSTALLDIR]'), length(S));
   end;
   If uppercase(copy(str, I, Length('[COMMONFILES]'))) = '[COMMONFILES]' then begin
    S := Enviroment.GetCommonFilesDir;
    If S[Length(S)] = '\' then S := copy(S, 1, length(s) - 1);
    Str := Copy(Str, 1, I - 1) + S + Copy(Str, I + length('[COMMONFILES]'), length(S));
   end;
   If uppercase(copy(str, I, Length('[PROGRAMFILES]'))) = '[PROGRAMFILES]' then begin
    S := Enviroment.GetProgramFilesDir;
    If S[Length(S)] = '\' then S := copy(S, 1, length(s) - 1);
    Str := Copy(Str, 1, I - 1) + S + Copy(Str, I + length('[PROGRAMFILES]'), length(S));
   end;
   If uppercase(copy(str, I, Length('[STARTUP]'))) = '[STARTUP]' then begin
    S := Enviroment.GetStartUp;
    If S[Length(S)] = '\' then S := copy(S, 1, length(s) - 1);
    Str := Copy(Str, 1, I - 1) + S + Copy(Str, I + length('[STARTUP]'), length(S));
   end;
   If uppercase(copy(str, I, Length('[STARTMENU]'))) = '[STARTMENU]' then begin
    S := Enviroment.GetStartMenu;
    If S[Length(S)] = '\' then S := copy(S, 1, length(s) - 1);
    Str := Copy(Str, 1, I - 1) + S + Copy(Str, I + length('[STARTMENI]'), length(S));
   end;
   If uppercase(copy(str, I, Length('[PROGRAMS]'))) = '[PROGRAMS]' then begin
    S := Enviroment.GetStartMenuPrograms;
    If S[Length(S)] = '\' then S := copy(S, 1, length(s) - 1);
    Str := Copy(Str, 1, I - 1) + S + Copy(Str, I + length('[PROGRAMS]'), length(S));
   end;
   If uppercase(copy(str, I, Length('[WINDOWS]'))) = '[WINDOWS]' then begin
    S := Enviroment.GetSystemRoot;
    If S[Length(S)] = '\' then S := copy(S, 1, length(s) - 1);
    Str := Copy(Str, 1, I - 1) + S + Copy(Str, I + length('[WINDOWS]'), length(S));
   end;
   If uppercase(copy(str, I, Length('[SYSTEM]'))) = '[SYSTEM]' then begin
    S := PathToOk(Enviroment.GetSystemRoot) + 'SYSTEM32';
    If S[Length(S)] = '\' then S := copy(S, 1, length(s) - 1);
    Str := Copy(Str, 1, I - 1) + S + Copy(Str, I + length('[SYSTEM]'), length(S));
   end;
   If uppercase(copy(str, I, Length('[TEMPDIR]'))) = '[TEMPDIR]' then begin
    S := Enviroment.GetTemp;
    If S[Length(S)] = '\' then S := copy(S, 1, length(s) - 1);
    Str := Copy(Str, 1, I - 1) + S + Copy(Str, I + length('[TEMPDIR]'), length(S));
   end;
  end;
  Inc(I);
 until I > length(Str);
 Result := Str;
end;

function TForm1.ElementIDParser(Str: String; SelfItem: TItem): String;
Var
 I, I2: Integer;
 EID, S: String;
 FoundAt: Integer;
begin
 If Str = '' then begin
  Result := '';
  exit;
 end;
 I := 1;
 Repeat
  if Str[I] = '[' then begin
   If uppercase(copy(str, I, length('[SELF]'))) = '[SELF]' then begin
    S := PathToOk(InstallParser(SelfItem.InstallTo)) + SelfItem.Filename;
    If S[Length(S)] = '\' then S := copy(S, 1, length(s) - 1);
    Str := Copy(Str, 1, I - 1) + S + Copy(Str, I + length('[SELF]'), length(S));
   end;
   If uppercase(copy(str, I, length('[ELEMENTID_'))) = '[ELEMENTID_' then begin
    EID := uppercase(copy(str, I + Length('[ELEMENTID_'), length(str)));
    EID := GetFilt(EID, 1, ']');
    FoundAt := -1;
    For I2 := 0 to installitemlist.Count - 1 do begin
     If EID = uppercase(installItemlist[I2].ElementID) then begin
      FoundAt := I2;
     end;
    end;
    If FoundAt = -1 then MessageDlg('ELEMENTID not found' + #13#10 + EID, mtError, [mbOK], 0);
    S := PathToOk(InstallParser(InstallItemList[FoundAt].InstallTo)) + InstallItemList[FoundAt].Filename;
    If not InstallItemList[FoundAt].InstallItem then S := '';
    If S <> '' then
     If S[Length(S)] = '\' then S := copy(S, 1, length(s) - 1);
    Str := Copy(Str, 1, I - 1) + S + Copy(Str, I + length('[ELEMENTID_') + Length(EID) + 1, length(S));
   end;
  end;
  Inc(I);
 until I > length(Str);
 Result := Str;
end;

procedure TForm1.xmldownloadComplete(Sender: TObject);
begin
 XMLProceed :=true;
end;

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
 next.enabled := checkbox1.Checked;
end;

procedure TForm1.SetInsType;
begin
 next.Enabled := true;
 back.Enabled := true;
 Panel1.Caption := 'Selection Installation Type';
 Update;
 destfolderLBL.Caption := InstallDir;
end;

procedure TForm1.TreeView1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
Var
 Node: TTreenode;
begin
 if button = mbLeft then begin
  Node := Treeview1.GetNodeAt(x,y);
  If Node = nil then exit;
  If (node.ImageIndex < 3) and (node.ImageIndex > 0) then begin
   node.ImageIndex := node.ImageIndex + 1;
   If node.ImageIndex = 3 then node.ImageIndex := 1;
   node.SelectedIndex := node.ImageIndex;;
  end;
  If node.ImageIndex < 3 then begin
   Label26.caption := installitemlist[node.StateIndex].Description;
  end;
  treeview1.Selected := nil;
  Update;
 end;
end;

procedure TForm1.TreeView1Collapsing(Sender: TObject; Node: TTreeNode;
  var AllowCollapse: Boolean);
begin
 allowcollapse := False;
end;

procedure TForm1.XMLBuildLinkList(Node: IXMLNode);
Var
 I: Integer;
begin
 For I := 0 to node.childnodes.count - 1 do begin
  If uppercase(node.ChildNodes[I].NodeName) = 'LINK' then begin
   With InstallLinkList.Add do begin
    Title := Node.ChildNodes[I].ChildNodes['Title'].NodeValue;
    Execute := Node.ChildNodes[I].ChildNodes['LinkTo'].NodeValue;
    Try
     Parameters := Node.ChildNodes[I].ChildNodes['Parameters'].NodeValue;
    except
     on EVariantTypeCastError do begin
      Parameters := '';
     end;
    end;
    CreateIn := Node.ChildNodes[I].ChildNodes['CreateIn'].NodeValue;
    Icon := Node.ChildNodes[I].ChildNodes['Icon'].NodeValue;
    IconIndex := StrToInt(Node.ChildNodes[I].ChildNodes['IconIndex'].NodeValue);
   end;
  end;
 end;
end;

procedure TForm1.XMLBuildGroupList(Node: IXMLNode);
Var
 I: Integer;
begin
 For I := 0 to node.ChildNodes.count - 1 do begin
  With InstallItemGroupList.Add do begin
   Name := node.ChildNodes[I].NodeName;
   ScreenName := node.ChildNodes[I].ChildNodes['Screenname'].NodeValue;
   Description := node.ChildNodes[I].ChildNodes['Description'].NodeValue;
   ListIndex := strtoint(node.ChildNodes[I].ChildNodes['ListIndex'].NodeValue);
   IconFileName := pathtoOk(extractpath) + node.ChildNodes[I].ChildNodes['iconfilename'].NodeValue;
//   Try
//    TreatAs := Node.ChildNodes[I].ChildNodes['TreatAs'].NodeValue;
//   except
//    TreatAs := 'Unknown';
//   end;
  end;
 end;
end;

procedure TForm1.XMLBuildRegistryList(Node: IXMLNode);
Var
 II, I, Sel: Integer;
 Root, Path: String;
 N, V: String;
begin
 For I := 0 to node.ChildNodes.Count - 1 do begin
  If uppercase(Node.ChildNodes[I].NodeName) = 'KEY' then begin
   Root := Node.ChildNodes[I].Attributes['root'];
   Path := Node.ChildNodes[I].Attributes['path'];
   Sel := RegList.Add(Root, Path);
   For II := 0 to node.ChildNodes[I].ChildNodes.Count - 1 do begin
    If uppercase(node.ChildNodes[I].ChildNodes[II].NodeName) = 'ITEM' then begin
     N := Node.ChildNodes[I].ChildNodes[II].Attributes['name'];
     If uppercasE(N) = '(DEFAULT)' then N := '';
     V := Node.ChildNodes[I].ChildNodes[II].Attributes['value'];
     V := ApoToQuotes(V); // Replace ' with "
     RegList[Sel].Add(N, V);
    end;
   end;
  end;
 end;
end;

{ SET PAGE PROCEDURES }

procedure TForm1.SetSELFCHECK;
Var
 W: Word;
 List: TStrings;
 RC, RS: string;
 DelFile: Boolean;
 IISDir: String;
begin
 If not bypassselfcheck then begin
  Panel1.Caption := 'Self Check';
  Application.ProcessMessages;

  If Not HasAdminAccess then
   RestartApplicationWithElevatedPriviliges;

  If OfflineOverride then Offline := true
   else Offline := Download.PingURL(Server, RS, RC) = -1;
  If not offline then begin
   Download.Filename := PathToOk(GetTemp) + 'autoupdate.upd';
   Download.URL := selfupdatefile;
   // does the file exists
   // Old method
   // If Download.PingURL(Download.URL, RC, RS) = 200 then begin
   // component embedded method
   If Download.DoesURLExists then begin
    Download.DownloadFile;
    FV.Filename := Application.ExeName;
    W := MMRBToWord(CM2MMRB.StrWithPeriodToMMRB(FV.FileVersion));
    List := TStringlist.Create;
    List.LoadFromFile(Download.Filename);
    If StrToInt(List[0]) > W then begin
     RS := List[1];
     List.Delete(0);
     List.Delete(0);
  //   RC := List.Text + #13#10 + #13#10 + 'Do you wish to download the new version now ?' + #13#10 + '(this version of autoupdate has just been rendered invalid)';
  //   if MessageDlg(RC, mtInformation, [mbYes,mbNo], 0) = mrYes then begin
  //    ExecApp(RS);
  //   end;
     If fileexists(extractfilepath(application.exename) + '\cmuupd.exe') then begin
      execapp(extractfilepath(application.exename) + '\cmuupd.exe', '"/URL=' + RS + '" "/CMU=' + Application.exename +'"');
     end
      else
     begin
      MessageDlg('A new version of CMU is available online, you will have to download this in order to continue.'+#13+#10+''+#13+#10+'You will now be taken to the CoolMon website where you can download the file.', mtWarning, [mbOK], 0);
      execapp(server);
     end;
     Application.Terminate;
     exit;
    End;
    List.Free;
   End
    else
   begin
    If MessageDlg('NOTICE:'+#13+#10+'The version information file available online cannot be found. '+#13+#10+'This could be due to several reasons.'+#13+#10+''+#13+#10+'* No internet connection'+#13+#10+'* Server is down/overworked'+#13+#10+'* File has been moved'+#13+#10+'* Server has moved'+#13+#10+''+#13+#10+'Would you like to be taken to the coolmon website to perhaps '+#13+#10+'download an update ?' + #13#10+#13#10 + 'ERROR: ' + RS + ' (' + RC + ')', mtError, [mbYes,mbNo], 0) = mrYes then begin
     ExecApp(Server);
    End;
    Application.Terminate;
    Exit;
   End;
  end;
 end;
 DelFile := False;
 XMLDownload.URL := CM2IIFile;
 IISDir := pathtook(Extractfilepath(Application.ExeName)) +'cm2ii';
 If Not DirectoryExists(IISDir) then begin
  MkDir(IISDir);
 end;
 XMLDownload.Filename := pathtook(IISDir) + 'cm2ii.rar';
 If not fileexists((IISDir) + 'cm2ii.rar') then begin
  If XMLDownload.PingURL(XMLDownload.URL, RS, RC) <> 200 then  begin
(* Commented out because of the uninstall function *)
//   MessageDlg('No active internet connection was found and since there is no data to perform an offline installation, this tool will now close.', mtError, [mbOK], 0);
//   Application.Terminate;
//   exit;
  end;
  XMLDownload.DownloadFile;
  DelFile := True;
 end;
 If fileexists(XMLDownload.Filename) then begin
  UnRar.FileName := xmldownload.filename;
  UnRar.OverrideEvent := OR_ALWAYS;
  UnRar.Directory := IISDir;
  UnRar.Mode := DFRAR_EXTRACT;
  UnRar.Extract;
 End;
 If DelFile then deletefile(XMLDownload.Filename);
 If Offline then Caption := Caption + ' [Offline]';
 PageControl1.SelectNextPage(true);
end;

procedure TForm1.SetAUTOUPDATER;
// WELCOME
begin
 PAnel1.Caption := 'Auto Updater';
 StopFlash;
 back.Enabled := False;
 next.Enabled := true;
 quit.enabled := true;
end;

procedure TForm1.SetAUSCANELEMENTS;
// GATHER INFORMATION
Var
 Reg: TRegistry;
 U, N, F, S: String;
 V, Sel: Integer;
 ui: TUpdateInfo;
 List: TStrings;
 I: Integer;
begin
 Panel1.Caption := 'Scanning for installed Elements';
 next.Enabled := false;
 back.enabled := false;
 StopFlash;
 update;

 If updList.Count > 0 then begin
  next.Enabled := true;
  back.Enabled := true;
  Self.FlashNext.Enabled := true;
  Exit;
 End;

 updatelog.Items.Clear;

 // Download repository to look up active upd locations
 GRep := TRepositoryList.Create;
 VRep := TRepositoryList.Create;

 AddToUpdateLog('Loading Repository');
 AddToUpdateLog('General ... ');

 XMLDOwnload.URL := RepGeneral;
 XMLDownload.Filename := PathToOk(GetTemp) + 'general.xml';
 XMLProceed := false;
 If not XMLDownload.DownloadFile then begin
  Error('Could not find repository file' + #13#10#13#10 +
        'URL = ' + XMLDownload.URL + #13#10 +
        'Filename = ' + XMLDownload.Filename);
 end;
 GRep.LoadXMl(PathToOk(GetTemp) + 'general.xml');

 AppendToUpdateLog('Done');
 AddToUpdateLog('Visual ... ');

 XMLDOwnload.URL := RepVisual;
 XMLDownload.Filename := PathToOk(GetTemp) + 'visual.xml';
 XMLProceed := false;
 If not XMLDownload.DownloadFile then begin
  Error('Could not find repository file' + #13#10#13#10 +
        'URL = ' + XMLDownload.URL + #13#10 +
        'Filename = ' + XMLDownload.Filename);
 end;
 VRep.LoadXMl(PathToOk(GetTemp) + 'visual.xml');

 AppendToUpdateLog('Done');

 AddToUpdateLog('--== Scanning Core Elements ==--');

 Reg := TRegistry.Create;

 // First check current version of core
 AddToUpdateLog('Core ... ');
 If Reg.OpenKey('\software\the coolmon project\CoolMon2\', false) then begin
  S := reg.ReadString('');
  If fileexists(S) then begin
   If IsFileInUse(S) then begin
    If MessageDlg('The core is running, it cannot be updated if it''s running.'+#13+#10+'Would you like us to close it for you ?', mtWarning, [mbYes, mbNo], 0) = mrYes then begin
     KillTask(S);
     repeat
      Application.ProcessMessages;
     until not IsFileInUse(S);
    end;
   end;
   If not IsFileInUse(S) then begin
    Sel := updList.Add('Core', 'Program');
    ui := updList[Sel];
    ui.UpdFile := CoreUpdateFile;
    ui.Location := S;
    fv.Filename := S;
    ui.Version := CM2MMRB.StrWithPeriodToMMRB(Fv.FileVersion);
    updList[Sel] := ui;
    AppendToUpdateLog(fv.FileVersion);
   end
    else AppendToUpdateLog('In Use, Removing from update list');
  end
   else AppendtoUpdateLog('Not found');
 End;

  // check for Outlawed editor
 AddToUpdateLog('OutlawEd ... ');
 If Reg.OpenKey('\software\the coolmon project\coolmon2\editor', false) then begin
  S := reg.ReadString('');
  EditorPath := Extractfilepath(S);
  If fileexists(S) then begin
   If IsFileInUse(S) then begin
    If MessageDlg('OutlawEd is running, it cannot be updated if it''s running.'+#13+#10+'Would you like us to close it for you ?', mtWarning, [mbYes, mbNo], 0) = mrYes then begin
     KillTask(S);
     repeat
      Application.ProcessMessages;
     until not IsFileInUse(S);
    end;
   end;
   If not IsFileInUse(S) then begin
    Sel := updList.Add('OutlawEd', 'Program');
    ui := updList[Sel];
    ui.UpdFile := OutlawEdUpdateFile;
    ui.Location := S;
    fv.Filename := S;
    ui.Version := CM2MMRB.StrWithPeriodToMMRB(Fv.FileVersion);
    updList[Sel] := ui;
    AppendToUpdateLog(fv.FileVersion);
   end
    else AppendToUpdateLog('In use, removing from update list');
  end
   else AppendtoUpdateLog('Not found');
 End;

 // check for Plugin Manager
 AddToUpdateLog('PlugIn Manager ... ');
 If Reg.OpenKey('\software\the coolmon project\Plugin Management', false) then begin
  S := reg.ReadString('');
  EditorPath := Extractfilepath(S);
  If fileexists(S) then begin
   If IsFileInUse(S) then begin
    If MessageDlg('The plugin manager is running, it cannot be updated if it''s running.'+#13+#10+'Would you like us to close it for you ?', mtWarning, [mbYes, mbNo], 0) = mrYes then begin
     KillTask(S);
     repeat
      Application.ProcessMessages;
     until not IsFileInUse(S);
    end;
   end;
   If not IsFileInUse(S) then begin
    Sel := updList.Add('PlugIn Manager', 'Program');
    ui := updList[Sel];
    ui.UpdFile := PMUpdateFile;
    ui.Location := S;
    fv.Filename := S;
    ui.Version := CM2MMRB.StrWithPeriodToMMRB(Fv.FileVersion);
    updList[Sel] := ui;
    AppendToUpdateLog(fv.FileVersion);
   end
    else AppendToUpdateLog('In use, removing from update list');
  end
   else AppendtoUpdateLog('Not found');
 End;

 // Check for general plugins
 AddToUpdateLog('--== Scanning General Plugins ==--');
 List := TStringlist.Create;
 If Reg.OpenKey(GenPlugLocation, false) then begin
  Reg.GetKeyNames(List);
  For I := 0 to list.count - 1 do begin
   Reg.OpenKey(PathToOk(GenPlugLocation) + list[I], true);
   N := reg.ReadString('');
   AddToUpdateLog(N + ' ... ');
   F := reg.ReadString('Filename');
   If not IsFileInUse(F) then begin
    If Reg.ValueExists('Version') then begin
     V := Reg.ReadInteger('Version');
     //U := Reg.ReadString('UpdateFile');
     If Not GetUPDFromRepository(N, U) then begin
      AppendToUpdateLog('"' + N + '" UPD file not found');
     end;
     If U <> '' then begin
      Sel := updList.Add(N, 'General Plugin');
      ui := updList[Sel];
      ui.Location := F;
      ui.Version := WordToMMRB(V);
      ui.UpdFile := U;
//      ui.RegLocation := PathToOk(GenPlugLocation) + list[I];
      updList[Sel] := ui;
      AppendToUpdateLog(WordToStr(V));
     end
      else
     begin
      AppendToUpdateLog('Not supported');
     end;
    End
     else
    Begin
     AppendToUpdateLog('Autoupdate disabled');
    End;
   end
    else
   begin
    AppendToUpdateLog('In use, removing from update list');
   End;
  End;
 End
  else AddToUpdateLog('No General Plugins found');

 // Check for Visual plugins
 AddToUpdateLog('--== Scanning Visual Plugins ==--');
 If Reg.OpenKey(VisPlugLocation, false) then begin
  Reg.GetKeyNames(List);
  For I := 0 to list.count - 1 do begin
   Reg.OpenKey(PathToOk(VisPlugLocation) + list[I], true);
   N := reg.ReadString('');
   AddToUpdateLog(N + ' ... ');
   F := reg.ReadString('Filename');
   If not IsfileInUse(F) Then begin
    If Reg.ValueExists('Version') then begin
     //U := Reg.ReadString('UpdateFile');
     If Not GetUPDFromRepository(N, U) then begin
      AppendToUpdateLog('"' + N + '" UPD file not found');
     end;
     If U <> '' then begin
      V := Reg.ReadInteger('Version');
      AppendToUpdateLog(WordToStr(V));
      Sel := updList.Add(N, 'Visual Plugin');
      ui := updList[Sel];
      ui.Location := F;
      ui.Version := WordToMMRB(V);
      ui.UpdFile := U;
//      ui.RegLocation := PathToOk(VisPlugLocation) + list[I];
      updList[Sel] := ui;
     End
      else
     begin
      AppendToUpdateLog('Not Supported');
     End;
    End
     else
    Begin
     AppendToUpdateLog('Autoupdate disabled');
    End;
   end
    else AppendToUpdateLog('In Use, removing from update list');
  End;
 End
  else AddToUpdateLog('No Visual Plugins found');

 // Check for CMLx plugins
 AddToUpdateLog('--== Scanning CMLx Plugins ==--');
 If Reg.OpenKey(CMLxPlugLocation, false) then begin
  Reg.GetKeyNames(List);
  For I := 0 to list.count - 1 do begin
   Reg.OpenKey(PathToOk(CMLxPlugLocation) + list[I], true);
   N := reg.ReadString('');
   AddToUpdateLog(N + ' ... ');
   F := reg.ReadString('Filename');
   If not IsfileInUse(F) Then begin
    If Reg.ValueExists('Version') then begin
     U := Reg.ReadString('UpdateFile');
     If U <> '' then begin
      V := Reg.ReadInteger('Version');
      AppendToUpdateLog(WordToStr(V));
      Sel := updList.Add(N, 'CMLx Plugin');
      ui := updList[Sel];
      ui.Location := F;
      ui.Version := WordToMMRB(V);
      ui.UpdFile := U;
      updList[Sel] := ui;
     End
      else
     begin
      AppendToUpdateLog('Not Supported');
     End;
    End
     else
    Begin
     AppendToUpdateLog('Autoupdate disabled');
    End;
   end
    else AppendToUpdateLog('In Use, removing from update list');
  End;
 End
  else AddToUpdateLog('No CMLx Plugins found');

 Reg.Free;
 Self.FlashNext.Enabled := true;
 next.Enabled := true;
 back.Enabled := true;
 update;
end;


procedure TForm1.SetAUDOWNLOADUPDS;
// Download upd files
Var
 I: Integer;
 ui: TUpdateInfo;
 List: TStrings;
begin
 Panel1.Caption := 'Downloading Update information';
 next.Enabled := false;
 back.enabled := false;
 StopFlash;
 update;

 List := TStringList.Create;
 progressbar1.Max := updlist.count;
 progressbar1.Position := 0;
 For I := 0 to updlist.Count - 1 do begin
  ui := updList[I];
  download.Filename := PathToOk(GetTemp) + 'cm2au.upd';
  download.URL := ui.UpdFile;
  Download.DownloadFile;
  If fileexists(PathToOk(GetTemp) + 'cm2au.upd') then begin
   List.LoadFromFile(PathToOk(GetTemp) + 'cm2au.upd');
   Deletefile(PathToOk(GetTemp) + 'cm2au.upd');
   ui.DoList := true;
   Try
    ui.UpdVersion := WordToMMRB(StrToInt(List[0]));
    ui.DownloadFile := List[1];
    list.Delete(0);
    List.Delete(0);
    ui.WhatsNew := list.Text;
   except
    ui.UpdVersion := WordToMMRB(0);
   end;
  end
   else
  begin
   ui.DoList := false;
  end;
  updList[I] := ui;
  progressbar1.Position := progressbar1.Position + 1;
  Application.ProcessMessages;
 End;
 List.Free;
 // Do next page
 Self.nextClick(self);
end;

procedure TForm1.SetAUCHOOSE;
// Select what to download
Var
 ListItem: TListItem;
 I: Integer;
begin
 Panel1.caption := 'Please select what items to update';
 Listview1.Items.clear;
 For I := 0 to updList.Count - 1 do begin
  If updList[I].DoList then begin
   ListItem := Listview1.Items.Add;
   ListItem.Caption := updList[I].Name;
   ListItem.SubItems.Add(updList[I].ProgType);
   ListItem.SubItems.Add(MMRBToStr(updList[I].Version));
   ListItem.SubItems.Add(MMRBToStr(updList[I].UpdVersion));
   ListItem.SubItems.Add(IntToStr(I));
   If MMRBToWord(updList[I].Version) < MMRBToWord(updList[I].UpdVersion) then listitem.Checked := true;
  end;
 End;
 next.Enabled := True;
 FlashNext.Enabled := true;
end;

procedure TForm1.SetAUDOWNLOADUPDATES;
// Download
Var
 Cnt, I: Integer;
 ui: TUpdateInfo;
 RT: TRegisterTools;
 RA: TRegisterAs;
begin
 RT := TRegisterTools.Create;
 panel1.caption := 'Downloading updates';
 StopFlash;
 next.Enabled := false;
 back.enabled := false;
 For I := Listview1.items.Count - 1 downto 0 do begin
  If Listview1.Items[I].Checked then Begin
   ui := updList[StrToInt(Listview1.items[I].SubItems[3])];
   ui.DoDownload := True;
   ui.DLPanel := CreatePanel(Scrollbox2, ui.Name, 'Waiting', '');
   If (ui.ProgType = 'Program') and (ui.Name = 'Core') then begin
    ui.DLPanel.Image.Picture.Graphic := CoreImg.Picture.Graphic;
   End;
   If (ui.ProgType = 'Program') and (ui.Name = 'Editor') then begin
    ui.DLPanel.Image.Picture.Graphic := EditorImg.Picture.Graphic;
   End;
   If (ui.ProgType = 'Program') and (ui.Name = 'OutlawEd') then begin
    ui.DLPanel.Image.Picture.Graphic := OutlawedImg.Picture.Graphic;
   End;
   If uppercase(ui.ProgType) = 'GENERAL PLUGIN' then begin
    ui.DLPanel.Image.Picture.Graphic := Generalimg.Picture.Graphic;
   End;
   If uppercase(ui.ProgType) = 'VISUAL PLUGIN' then begin
    ui.DLPanel.Image.Picture.Graphic := Visualimg.Picture.Graphic;
   End;
   updList[StrToInt(Listview1.items[I].SubItems[3])] := ui;
  End;
 End;
 application.ProcessMessages;
 cnt := 0;
 For I := 0 to updList.Count - 1 do begin
  if updList[I].DoDownload then begin
   ui := updList[I];
   ui.dlpanel.Panel.Align := albottom;
   ui.dlpanel.Panel.Align := alTop;
   ui.DLPanel.Panel.BevelInner := bvnone;
   ui.DLPanel.Panel.BevelOuter := bvNone;
   If cnt = 0 then begin
    ui.DLPanel.Panel.Color := clwhite;
   end
    else
   begin
    ui.DLPanel.Panel.Color := $00FF8000;
    ui.DLPanel.Caption.Font.Color := clwhite;
    ui.DLPanel.Status.Font.Color := clWhite;
    ui.DLPanel.ProgressLabel.Font.Color := clWhite;
   end;
   inc(cnt);
   if cnt = 2 then cnt := 0;
  end;
 End;
 For I := 0 to updList.Count - 1 do begin
  If updList[I].DoDownload then begin
   ui := updList[I];
   ui.LocalFile := PathToOk(GetTemp) + ui.Name + '.rar';
   ui.DLPanel.Status.Caption := 'Downloading ...';
//   Label8.Caption := ui.Name;
   Application.ProcessMessages;
   // Download file
   Download.Filename := ui.LocalFile;
   Download.URL := ui.DownloadFile;
   Download.Tag := I;
   Download.DownloadFile;
   ui.DLPanel.Status.Caption := 'Unpacking ...';
   Application.ProcessMessages;
   // Unpack file using RAR
   If fileexists(Download.Filename) then begin
    UnRar.FileName := ui.LocalFile;
    UnRar.OverrideEvent := OR_ALWAYS;
    UnRar.Directory := extractfilepath(ui.Location);
    UnRar.Mode := DFRAR_EXTRACT;
    UnRar.Extract;
   End;
   ui.DLPanel.Status.Caption := 'UnInstalling ...';
   ui.DLPanel.Bar.Position := 33;
   Application.ProcessMessages;
   If uppercase(ui.ProgType) <> 'PROGRAM' then RT.UninstallPlugIn(ui.Location);
   ui.DLPanel.Status.Caption := 'Installing ...';
   ui.DLPanel.Bar.Position := 66;
   Application.ProcessMessages;
   If uppercase(ui.ProgType) <> 'PROGRAM' then RT.InstallPlugIn(ui.Location, RA);
   // Above line might trigger an "Interface not supported", it's supposed if it's a VISUAL PLUGIN that's installing
   ui.DLPanel.Status.Caption := 'Complete';
   ui.DLPanel.Bar.Max := 100;
   ui.DLPanel.Bar.Position := 100;
   ui.DLPanel.ProgressLabel.Caption := '';
   Application.ProcessMessages;
   updList[I] := ui;
  End;
  Application.ProcessMessages;
 End;
 FreeAndNil(RT);
 PageControl1.SelectNextPage(true);
end;


procedure TForm1.SetAUPOSTAU;
// Complete
Var
 I: Integer;
begin
 // Add Clean up
 Panel1.Caption := 'Update Completed';
 For I := 0 to updlist.Count - 1 do begin
  If not updlist[I].DoList then begin
   Listbox1.Items.Add(updlist[I].Name);
  end;
 End;
 If listbox1.Items.count > 0 then panel3.Visible := true
  else panel3.visible := False;
 Back.Visible := false;
 Quit.Enabled := false;
 Next.Caption := 'Finish';
 Next.Enabled := true;
end;

procedure TForm1.SetAUDOTERMINATE;
// Empty, terminate
Var
 I: Integer;
 Reg: TRegistry;
 CM2Location: String;
 ConfigFile: String;
begin
 For I := 0 to CleanUpFiles.count - 1 do begin
  DeleteFile(CleanUpFiles[I]);
 End;
 Reg := TRegistry.Create;
 Reg.RootKey := HKEY_CURRENT_USER;
 Case Radiogroup3.ItemIndex of
  0: begin
      if Reg.OpenKey('\software\the coolmon project\CoolMon2\', false) then begin
       CM2Location := Reg.ReadString('');
       ConfigFile := '';
       if Reg.ValueExists('lastconfig') then begin
        ConfigFile := '"' + reg.ReadString('lastconfig') + '"';
       end;
       Execapp(CM2Location, ConfigFile);
      end;
     end;
  1: begin
      if reg.openkey('\software\the coolmon project\CoolMon2\Editor', false) then begin
       Execapp(reg.readstring(''));
      end;
     end;
 end;
 FreeAndNil(Reg);
 Application.Terminate;
end;

procedure TForm1.SetCHOOSEOPERATION;
Var
 Reg: TRegistry;
 IsInstalled: Boolean;
begin
 StopFlash;
 back.Enabled := False;
 next.Enabled := True;
 quit.Enabled := true;
 Panel1.Caption := 'Choose ...';
 Update;
 // Detect abilities
 Reg := TRegistry.Create;
 Reg.RootKey := HKEY_CURRENT_USER;
 IsInstalled := Reg.OpenKey('\Software\The CoolMon Project\CoolMon2\Installation', false);
 If (not IsInstalled) or (ForceInstall) or
    ((offline) and (Fileexists(pathtook(Extractfilepath(Application.ExeName)) + 'cm2ii\installation.xml'))) then begin
  Pagecontrol1.ActivePage := Installer;
  PageControl1Change(self);
  exit;
 end;
 ShowInstall := Not IsInstalled;
 If forceinstall Then showinstall := true;
 ShowUnInstall := IsInstalled;
 ShowAutoUpdate := Reg.OpenKey('\software\the coolmon project\CertifiedPlugins\general', false);
 If not showautoupdate then
  ShowAutoUpdate := Reg.OpenKey('\software\the coolmon project\CertifiedPlugins\visual', false);
 // Detect uninstall
 If Reg.OpenKey(InstallLocation, false) then begin
  If Reg.ValueExists('Uninstalllog') then ShowUnInstall := true;
  UnInstallLog := TStringList.Create;
  If fileexists(reg.readstring('uninstalllog')) then
   UnInstallLog.LoadFromFile(Reg.ReadString('UninstallLog'));
 end;
 // Set Abilities
 AutoUpdate.Enabled := ShowAutoUpdate;
 Browse.Enabled := ShowPlugInRep;
 Uninstall.Enabled := ShowUnInstall;
 FreeAndnil(Reg);
 If AutoUpdate.Enabled then begin
  autoupdate.Checked := true;
  exit;
 end;
 If ((Autoupdate.Enabled = false) and (uninstall.Enabled  =false)) then begin
  Next.Enabled := false;
  Next.Default := false;
  Quit.SetFocus;
  Quit.Default := true;
 end;
end;

procedure TForm1.SetINSTALLER;
begin
 back.Enabled := False;
 next.Enabled := True;
 quit.enabled := true;
 Panel1.Caption := 'Welcome to the CM2 Installer';
 Update;
 ResolveInstallXML(pathtook(Extractfilepath(Application.ExeName)) + 'cm2ii\installation.xml');
end;

procedure TForm1.SetINSEULA;
begin
 Panel1.Caption := 'License Agreement';
 Update;
 back.Enabled := true;
 Next.Enabled := Checkbox1.Checked;
end;

procedure TForm1.SetINSObjects;
Var
 Icon: TIcon;
 I, I2: Integer;
 IG: TItemGroup;
 TN, TN2: TTreeNode;
begin
 Treeview1.Items.clear;
 Imagelist1.Clear;
 Imagelist1.AddImages(originallist);
 For I := 0 to InstallItemGroupList.Count - 1 do begin
  IG := InstallItemGroupList.GetByListIndex(I);
  Icon := TICon.Create;
  Icon.LoadFromFile(IG.IconFileName);
  Imagelist1.AddIcon(Icon);
  FreeAndNil(Icon);
  TN := Treeview1.Items.Add(nil, IG.ScreenName);
  TN.ImageIndex := I + originallist.Count;
  TN.SelectedIndex := I + originallist.Count;
  TN.StateIndex := I + originallist.Count;
  For I2 := 0 to installitemlist.Count - 1 do begin
   If IG.Name = installItemList[I2].GroupName then begin
    TN2 := Treeview1.Items.AddChild(TN, InstallItemList[I2].Name);
    If InstallItemList[I2].Required then TN2.ImageIndex := 0
     else TN2.ImageIndex := 1;
    TN2.SelectedIndex := TN2.ImageIndex;
    TN2.StateIndex := I2;
   end;
  end;
 end;
 treeview1.FullExpand;
 treeview1.TopItem := treeview1.Items[0];
end;

procedure TForm1.SetINSFolder;
begin
end;


procedure TForm1.SetINSUPDProgress;
Var
 I, Cnt, Size: Integer;
 List: TStrings;
begin
 List := TStringList.Create;
 back.enabled := false;
 next.enabled := false;
 quit.enabled := false;
 Panel1.Caption := 'Please Wait ...';
 update;
 // By default make all items installed [Can be editing in custom installation dialog by user later]
 For I := 0 to treeview1.items.Count - 1 do begin
  If treeview1.Items[I].ImageIndex < 2 then begin
   installitemlist[treeview1.Items[I].StateIndex].InstallItem := true;
  end;
 end;
 // Calc how many upd's that needs download and analyse
 Cnt := 0;
 for I := 0 to installitemlist.count - 1 do begin
  If InstallItemList[I].InstallItem then begin
   if (uppercase(extractfileext(installitemlist[I].URL)) = '.UPD') then Inc(Cnt)
    else installitemlist[I].DirectURL := installitemlist[I].URL;
  end;
 end;
 progressbar2.Max := cnt;
 progressbar2.Position := 0;
 For I := 0 to installitemlist.count - 1 do begin
  if (InstallItemList[I].InstallItem) then begin
   InstallItemList[I].InstallFromLocal := fileexists(pathtook(extractfilepath(application.exename)) + InstallItemList[I].Local);
   If (uppercase(extractfileext(installitemlist[I].URL)) = '.UPD') and (not InstallItemList[I].InstallFromLocal) and (not offline) then begin
    Label42.caption := GetLastFilt(installitemlist[I].URL, '/');
    update;
    If not fileexists(pathtook(extractfilepath(application.exename)) + InstallItemList[I].Local) then begin
     InstallItemList[I].InstallFromLocal := false;
     repeat
      upddownload.url := installitemlist[I].URL;
      upddownload.Filename := pathtook(gettemp) + getfilt(upddownload.URL, countfilt(upddownload.URL, '/'), '/');
      if fileexists(upddownload.filename) then deletefile(upddownload.filename);

      If updDownload.DoesURLExists then begin
       upddownload.DownloadFile;
       if fileexists(upddownload.Filename) then begin
        List.LoadFromFile(upddownload.filename);
        if uppercase(extractfileext(List[1])) <> '.UPD' then installitemlist[I].DirectURL := list[1]
         else installitemlist[I].URL := List[1];
       end
        else
       begin
        Warning('Failed to properly download the file' + #13#10 + #13#10 +
                'URL = ' + upddownload.URL + #13#10 +
                'Filename = ' + updDownload.Filename);
        InstallItemList[I].DirectURL := '-';
       end;
      end
       else
      begin
       // File to be downloaded doesn't exist online
       Error('URL Object doesn''t exist' + #13#10 + #13#10 +
             'URL: ' + updDownload.URL);     
      end;
     until installitemlist[I].DirectURL <> '';
    end;
   end;
   If (Progressbar2.Position + 1) <= Progressbar2.Max then begin
    progressbar2.Position := progressbar2.Position + 1;
   end;
   application.ProcessMessages;
  end;
  If InstallItemList[I].InstallItem then begin
   updDownload.URL := InstallItemList[I].DirectURL;
   If not updDownload.GetSize(Size) then size := 0;
   InstallItemList[I].ItemSize := Size;
   InstallItemList[I].InstallTo := InstallParser(InstallItemList[I].InstallTo);
  end;
 end;
// SpeedButton2Click(self);
 PageControl1.SelectNextPage(true);
end;

procedure TForm1.SetINSProgress;
Var
 II, I: Integer;
// UninstallLog: TStrings;
 RT: TRegisterTools;
 RA: TRegisterAs;
 UnInstallNode, Node: IXMLNode;
 Reg: TRegistry;
 S: String;
begin
 Panel1.Caption := 'Installation in Progress';
 Label29.Caption := '';
 Label30.Caption := '-';
 Label32.Caption := '-';
 Update;
 OverallSize := 0;
 OverallProgressInt := 0;
 For I := 0 to installitemlist.Count - 1 do begin
  if installitemlist[I].InstallItem then inc(overallsize, installitemlist[I].ItemSize);
 end;
 If overallSize < 0 then begin
  overallprogress.Max := 1;
 end
  else
 begin
  overallprogress.Max := overallsize;
 end;
 RT := TRegisterTools.Create;
 If not assigned(Uninstalllog) then UninstallLog := TStringlist.Create;
 UnInstallLog.Clear;
 UnInstallLog.Add('[CM2II UL1]');
 For I := 0 to installitemlist.Count - 1 do begin
  If InstallItemList[I].InstallItem then begin
   Label29.Caption := InstallItemList[I].Name;
   Label30.Caption := 'Downloading ...';
   If not directoryexists(installitemlist[I].InstallTo) then begin
    If ForceDirectories(installItemList[I].InstallTo) then Uninstalllog.Add('Directory:' + InstallItemList[I].InstallTo)
     else MessageDlg('Unable to create following directory' + #13#10 + InstallItemList[I].InstallTo, mtWarning, [mbIgnore], 0);
   end;
   If not InstallItemList[I].InstallFromLocal then begin
    If not offline then begin
     itemprogress.Position := 0;
     itemprogress.Max := installitemlist[I].ItemSize;
     InsDownload.URL := InstallItemList[I].DirectURL;
     If uppercase(extractfileext(InstallItemList[I].DirectURL)) = '.RAR' then begin
      InsDownload.Filename := PathToOk(GetTemp) + GetFilt(InstallItemList[I].DirectURL, Countfilt(installitemlist[I].DirectURL, '/'), '/');
     end
      else
     begin
      InsDownload.Filename := pathtook(InstallItemList[I].InstallTo) + InstallITemList[I].Filename;
     end;
     If countfilt(insdownload.filename, '=') > 1 then begin
      Insdownload.filename := GetLastFilt(Insdownload.filename, '=');
     end;
     If InsDownload.DoesURLExists then begin
      InsDownload.DownloadFile;
     end
      else
     begin
      Error('URL Object doesn''t exist' + #13#10#13#10 +
            'URL = ' + InsDownload.URL + #13#10 +
            'Filename = ' + InsDownload.Filename);
     end;
    end
     else
    begin
     // File needed from internet and no active internet, warning perhaps ???
     Warning('No internet connection. Since we checked before you got here, did it just drop out?');
    end;
   end
    else
   begin
    InsDownload.Filename := InstallItemList[I].Local;
   end;
   // Extract if required
   If uppercase(extractfileext(insdownload.filename)) = '.RAR' then begin
    If not InstallItemList[I].InstallFromLocal then CleanUpFiles.Add(insdownload.filename);
    Label30.caption := 'Extracting ...';
    update;
    If countfilt(insdownload.filename, '=') > 1 then begin
     Insdownload.filename := GetLastFilt(Insdownload.filename, '=');
    end;
    UnRar.FileName := insdownload.filename;

    If Not Fileexists(Unrar.Filename) then begin
     Error('Oops - Download failure!' + #13#10 + 'The file doesn''t exist' + #13#10 + Unrar.Filename);
    End;

    UnRar.OverrideEvent := OR_ALWAYS;
    UnRar.Directory := installitemlist[I].InstallTo;
    UnRar.Mode := DFRAR_EXTRACT;
    UnRar.Extract;
   end;
   Uninstalllog.Add('file:'+pathtook(pathtook(InstallItemList[I].InstallTo)) + InstallITemList[I].Filename);
   // install if required
   If uppercase(extractfileext(InstallItemlist[I].Filename)) = '.DLL' then begin
    label30.Caption := 'Registering Plugin ...';
    update;
    ra := raUnknown;
    RT.InstallPlugIn(pathtook(InstallItemList[I].InstallTo) + InstallITemList[I].Filename, ra);
    uninstalllog.Add('registerplugin:' + pathtook(pathtook(InstallItemList[I].InstallTo)) + InstallITemList[I].Filename);
   end;
   Inc(OverallprogressInt, installitemlist[I].ItemSize);
  end;
 end;
 FreeAndNil(RT);
 Application.ProcessMessages;
 For I := 0 to installlinklist.Count - 1 do begin
  InstallLinkList[I].Execute := ElementIDParser(InstallLinkList[I].Execute, nil);
  InstallLinkList[I].Parameters := ElementIDParser(InstallLinkList[I].Parameters, nil);
  InstallLinkList[I].Icon := ElementIDParser(InstallLinkList[I].Icon, nil);
  If InstallLinkList[I].Execute <> '' then begin
   InstallLinkList[I].CreateIn := InstallParser(InstallLinkList[I].CreateIn);
   If not directoryexists(installlinklist[I].CreateIn) then begin
    If ForceDirectories(installlinkList[I].CreateIn) then Uninstalllog.Add('Directory:' + InstallLinkList[I].CreateIn)
     else MessageDlg('Unable to create following directory' + #13#10 + InstallLinkList[I].CreateIn, mtWarning, [mbIgnore], 0);
   end;
   link1.LinkFile := pathtoOk(installlinklist[I].CreateIn) + InstallLinkList[I].Title + '.lnk';
   Link1.Link := InstallLinkList[I].Execute;
   Link1.Arguments := InstallLinkList[I].Parameters;
   Link1.WorkingDir := ExtractFilepath(InstallLinkList[I].Execute);
   Link1.IconFile := InstallLinkList[I].Icon;
   Link1.IconIndex := InstallLinkList[I].IconIndex;
   Link1.CreateFile;
   Application.ProcessMessages;
   UninstallLog.Add('File:' + Link1.LinkFile);
  end;
 end;
// FreeAndNil(UnInstallLog);
 Application.ProcessMessages;
 XML.Active := true;
 UninstallNode := XML.ChildNodes['CM2Installer'].ChildNodes['UnInstallInfo'];
 If UninstallNode = nil then exit;
 Reg := TRegistry.Create;
 For I := 0 to RegList.Count - 1 do begin
  Reg.RootKey := RegList[I].RootKey;
  Reg.OpenKey(RegList[I].Path, true);
  For II := 0 to RegList[I].Count - 1 do begin
   Reg.WriteString(RegList[I][II].Name, ElementIDParser(RegList[I][II].Value, nil));
   UnInstallLog.Add('REG:' + HKEYToStr(Reg.RootKey) + ':' + RegList[I].Path + ':' + RegList[I][II].Name);
  end;
 end;
 Reg.CloseKey;
 Reg.RootKey := HKEY_LOCAL_MACHINE;
 Reg.OpenKey('\Software\Microsoft\Windows\CurrentVersion\Uninstall\CoolMon 2', true);
 For I := 0 to uninstallNode.ChildNodes.count - 1 do begin
  Node := UninstallNode.Childnodes[I];
  S := Node.NodeValue;
  S := ElementIDParser(S, nil);
  S := InstallParser(s);
  Reg.WriteExpandString(Node.NodeName, S);
 end;
 Reg.CloseKey;
 Reg.RootKey := HKEY_CURRENT_USER;
 Reg.OpenKey(InstallLocation, true);
 Reg.WriteString('uninstalllog', pathtook(InstallDir) + 'uninstall.log');
 Reg.CloseKey;
 Uninstalllog.SaveToFile(pathtook(InstallDir) + 'uninstall.log');
 XML.Active := False;
 FreeAndNil(Reg);
 Application.ProcessMessages;
 Pagecontrol1.SelectNextPage(true);
end;

procedure TForm1.SetINSDoTerminate;
Var
 I: Integer;
 Reg: TRegistry;
begin
 For I := 0 to CleanUpFiles.count - 1 do
  deletefile(cleanupfiles[I]);
 Reg := TRegistry.Create;
 Reg.RootKey := HKEY_CURRENT_USER;
 Case Radiogroup2.ItemIndex of
  0: begin
      If Reg.openkey('\Software\the coolmon project\coolmon2', false) then begin
       Execapp(Reg.ReadString(''));
      end
       else
      begin
       MessageDlg('Unable to find CoolMon 2 Core program', mtError, [mbOK], 0);
      end;
     end;
  1: begin
      If Reg.openkey('\Software\the coolmon project\coolmon2\editor', false) then begin
       Execapp(Reg.ReadString(''));
      end
       else
      begin
       MessageDlg('Unable to find The Outlaw Ed program', mtError, [mbOK], 0);
      end;
     end;
 end;
 FreeAndNil(Reg);
 application.Terminate;
end;

procedure TForm1.SetINSPostIns;
begin
 Back.Enabled := False;
 Next.Enabled := true;
 Next.Caption := 'Finish';
 Quit.Enabled := False;
 Panel1.Caption := 'Operation Complete';
end;

procedure TForm1.SetUninsProgress;
Var
 pIMG, dIMG, fIMG, iImg: TIcon;
 I: Integer;
 RT: TRegisterTools;
 MasterDir, Filename, S: String;
 List, List2: TStrings;
 Level, At: Integer;
 Reg: TRegistry;
 rKey, rPath, rName: String;
 KList: TStringlist;
begin
 next.Enabled := false;
 back.Enabled := false;
 quit.Enabled := false;
 Panel1.Caption := 'Uninstall Progress';
 pIMG := TIcon.Create;
 dIMG := TIcon.Create;
 fIMG := TIcon.Create;
 iIMG := TIcon.Create;
 UninstallImgList.GetIcon(0, dIMG);
 UninstallImgList.GetIcon(1, fIMG);
 UninstallImgList.GetIcon(2, pIMG);
 UninstallImgList.GetIcon(3, iIMG);
 Unregimg.Picture.Icon := pIMG;
 delImg.Picture.Icon := pIMG;
 folderimg.Picture.Icon := pIMG;
 killImg.Picture.Icon := dIMG;
 application.ProcessMessages;
 // Kill progress
 Killtask('cm2alpha.exe');
 KillTask('Coolmon2.exe');
 Killtask('editor.exe');
 KillTask('outlawed.exe');
 Killtask('pm.exe');
 sleep(1000);
 KillImg.Picture.Icon := fIMG;
 // Un register plugins
 unregimg.Picture.icon := dIMG;
 application.ProcessMessages;
 if uppercase(copy(Uninstalllog[1], 1, length('Directory:'))) = 'DIRECTORY:' then begin
  MasterDir := Copy(UninstallLog[1], length('directory:') + 1, length(uninstalllog[1]));
 end;
 Reg := TRegistry.Create;
 List := TStringlist.Create;
 List2 := TStringList.Create;
 if RadioGroup1.ItemIndex = 0 then begin
  RT := TRegisterTools.Create;
  If reg.OpenKey(GenPlugLocation, false) then begin
   Reg.GetKeyNames(List);
   For I := 0 to List.Count - 1 do begin
    If reg.OpenKey(Pathtook(GenPlugLocation) + list[I], false) then begin
     Filename := Reg.ReadString('filename');
     If fileexists(filename) then begin
      RT.UninstallPlugIn(Filename);
      UninstallLog.Add('file:' + filename);
     end;
    end;
    Application.ProcessMessages;
   end;
  end;
  If reg.OpenKey(VisPlugLocation, false) then begin
   Reg.GetKeyNames(List);
   For I := 0 to List.Count - 1 do begin
    If reg.OpenKey(Pathtook(VisPlugLocation) + list[I], false) then begin
     Filename := Reg.ReadString('filename');
     If fileexists(filename) then begin
      RT.UninstallPlugIn(Filename);
      UninstallLog.Add('file:' + filename);
     end;
    end;
   end;
  end;
  If reg.OpenKey(CMLxPlugLocation, false) then begin
   Reg.GetKeyNames(List);
   For I := 0 to List.Count - 1 do begin
    If reg.OpenKey(Pathtook(CMLxPlugLocation) + list[I], false) then begin
     Filename := Reg.ReadString('filename');
     If fileexists(filename) then begin
      RT.UninstallPlugIn(Filename);
      UninstallLog.Add('file:' + filename);
     end;
    end;
   end;
  end;

  Freeandnil(RT);
  unregimg.Picture.Icon := fIMG;
 end
  else UnRegImg.Picture.Icon := iIMG;
 // delete files
 delImg.Picture.Icon := dIMG;
 application.ProcessMessages;
// showmessage(uninstalllog.text);
 For I := 0 to uninstalllog.count - 1 do begin
  if lowercase(copy(uninstalllog[I], 1, length('file:'))) = 'file:' then begin
   S := Copy(Uninstalllog[I], Length('file:')+1, length(uninstalllog[I]));
   DeleteFile(S);
  end;
 end;
 delimg.picture.Icon := fIMG;
 // delete folders
 folderimg.Picture.Icon := dIMG;
 application.ProcessMessages;
 For I := 0 to uninstalllog.count - 1 do begin
  if lowercase(copy(Uninstalllog[I], 1, length('Directory:'))) = 'directory:' then begin
   S := Copy(Uninstalllog[I], length('Directory:') + 1, length(uninstalllog[I]));
   list.add(S);
  end;
 end;
 Level := 0;
 While list.Count > 0 do begin
  Inc(Level);
  At := 0;
  While At < List.Count do begin
   If CountFilt(List[At], '\') = Level then begin
    List2.Add(List[At]);
    List.Delete(At);
   end
    else
   begin
    Inc(At);
   end;
  end;
 end;
 For I := list2.count - 1 downto 0 do begin
  Removedir(List2[I]);
 end;
 Reg.DeleteKey('\Software\The CoolMon Project\Coolmon2\installation');
 Reg.RootKey := HKEY_LOCAL_MACHINE;
 Reg.DeleteKey('\Software\Microsoft\Windows\CurrentVersion\Uninstall\CoolMon 2');
// Reg.DeleteKey('\Software\The CoolMon Project');
//   UnInstallLog.Add('REG:' + HKEYToStr(Reg.RootKey) + ':' + RegList[I].Path + ':' + RegList[I][II].Name);
 KList := TStringList.Create;
 For I := 0 to UninstallLog.Count - 1 do begin
  If uppercase(copy(UninstallLog[I], 1, length('reg:'))) = 'REG:' then begin
   Reg.CloseKey;
   rKey := GetFilt(UninstallLog[I], 2, ':');
   rPath := GetFilt(UninstallLog[I], 3, ':');
   rName := GetFilt(UninstallLog[I], 4, ':');
   Reg.RootKey := StrToHKEY(rKey);
   If Reg.OpenKey(rPath, false) then begin
    Reg.DeleteValue(rName);
    If not Reg.HasSubKeys then begin
     KList.Clear;
     Reg.GetValueNames(KList);
     If KList.Count < 2 then begin
      Reg.DeleteKey(rPath);
     end;
    end;
   end;
  end;
  Application.ProcessMessages;
 end;
 freeAndnil(KList);
 freeandnil(reg);
 application.ProcessMessages;
 PageControl1.SelectNextPage(true);
end;

procedure TForm1.SetUnInsPrompt;
begin
 Panel1.Caption := 'Uninstaller';
end;

procedure TForm1.SetUnInstaller;
begin
 Panel1.Caption := 'Uninstaller';
 back.Enabled := true;
end;

procedure TForm1.SetUnInsComplete;
begin
 next.Enabled := true;
 Next.Caption := 'Finish!';
end;

procedure TForm1.SpeedButton2Click(Sender: TObject);
{Var
 Node: TTreeNode;
 I: Integer;}
begin
{ form2.treeview1.Items.clear;
 For I := 0 to InstallItemList.Count - 1 do begin
  node := Form2.TreeView1.Items.Add(nil, InstallItemList[I].Name);
  Form2.TreeView1.Items.addchild(node, 'ElementID = ' + InstallItemList[I].ElementID);
  Form2.TreeView1.Items.addchild(node, 'Description = ' + InstallItemList[I].Description);
  Form2.TreeView1.Items.addchild(node, 'Filename = ' + InstallItemList[I].Filename);
  Form2.TreeView1.Items.addchild(node, 'InstallTo = ' + InstallItemList[I].InstallTo);
  Form2.TreeView1.Items.addchild(node, 'URL = ' + InstallItemList[I].URL);
  Form2.TreeView1.Items.addchild(node, 'DirectURL = ' + InstallItemList[I].DirectURL);
  Form2.TreeView1.Items.addchild(node, 'GroupName = ' + InstallItemList[I].GroupName);
  Form2.TreeView1.Items.addchild(node, 'Local = ' + InstallItemList[I].Local);
  Form2.TreeView1.Items.AddChild(Node, 'InstallFromLocal = ' + BooleanToStr(InstallItemList[I].InstallFromLocal))
 end;
 form2.ShowModal;}
end;

procedure TForm1.SetRepBrowse;
Var
 I: Integer;
 N, VN: TTreeNode;
begin
 // Download XML
 GRep := TRepositoryList.Create;
 VRep := TRepositoryList.Create;
 XMLDOwnload.URL := RepGeneral;
 XMLDownload.Filename := PathToOk(GetTemp) + 'general.xml';
 XMLProceed := false;
 If not XMLDownload.DownloadFile then begin
  Error('Could not find repository file' + #13#10#13#10 +
        'URL = ' + XMLDownload.URL + #13#10 +
        'Filename = ' + XMLDownload.Filename);
 end;
 // Load XML into TRep
 GRep.LoadXMl(PathToOk(GetTemp) + 'general.xml');
 // Check for installed and then init plugin list with all unchecked
 Treeview2.Items.Clear;
 VN := Treeview2.Items.Add(nil, 'General');
 VN.ImageIndex := 0;
 VN.SelectedIndex := 0;
 For I := 0 to GRep.Count - 1 do begin
  N := Treeview2.Items.AddChild(VN, GRep[I].Title);
  If IsPlugInInstalled(GRep[I].Title, ptGeneral) then begin
   N.ImageIndex := 3;
   N.SelectedIndex := 3;
  end
   else
  begin
   N.ImageIndex := 2;
   N.SelectedIndex := 2;
  end;
 end;

 XMLDOwnload.URL := RepVisual;
 XMLDownload.Filename := PathToOk(GetTemp) + 'visual.xml';
 XMLProceed := false;
 If not XMLDownload.DownloadFile then begin
  Error('Could not find repository file' + #13#10#13#10 +
        'URL = ' + XMLDownload.URL + #13#10 +
        'Filename = ' + XMLDownload.Filename);
 end;
 // Load XML into TRep
 VRep.LoadXMl(PathToOk(GetTemp) + 'visual.xml');
 // Check for installed and then init plugin list with all unchecked
 VN := Treeview2.Items.Add(nil, 'Visual');
 VN.ImageIndex := 0;
 VN.SelectedIndex := 0;
 For I := 0 to VRep.Count - 1 do begin
  N := Treeview2.Items.AddChild(VN, VRep[I].Title);
  If IsPlugInInstalled(VRep[I].Title, ptVisual) then begin
   N.ImageIndex := 3;
   N.SelectedIndex := 3;
  end
   else
  begin
   N.ImageIndex := 2;
   N.SelectedIndex := 2;
  end;
 end;

 VN.Item[0].Selected := true;
 Panel1.Caption := 'Available Plugins';
 back.Enabled := true;
 TreeView2.FullExpand;
 Treeview2.Visible := true;
end;

procedure TForm1.SetRepSelect;
begin
end;


procedure TForm1.LoadRep(Rep: TRepository);
begin
 Label45.caption := Rep.Title;
 Label46.Caption := 'By ' + Rep.Creator;
 Label48.Caption := Rep.Description;
 Label49.Caption := 'Reviewer Comment (By ' + Rep.ReviewedBy + ')';
 Label50.Caption := Rep.ReviewComment;
end;


function TForm1.ApoToQuotes(Str: String): String;
Var
 I: Integer;
begin
 Result := '';
 For I := 1 to countfilt(Str, #39) do begin
  Result := Result + '"' + GetFilt(Str, I, #39);
 end;
 Result := Copy(Result, 2, length(Result));
end;

procedure TForm1.TreeView2MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
Var
 N: TTreeNode;
begin
 // no need for root nodes
 // 14, 37
 If (x < 14) then exit;
 If (X > 37) then begin
  TreeView2Click(self);
  exit;
 end;
 If button = mbLeft then begin
  N := Treeview2.GetNodeAt(X, Y);
  If N = nil then exit;
  Case N.ImageIndex of
   0: Exit;
   1: N.ImageIndex := 2;
   2: N.ImageIndex := 1;
   3: Exit;
  end;
  N.SelectedIndex := N.ImageIndex;
 end;

end;

procedure TForm1.TreeView2Click(Sender: TObject);
Var
 I: Integer;
 Rep: TRepositoryList;
begin
 If Treeview2.Selected = nil then exit;
 If Treeview2.Selected.Level = 0 then exit;
 Rep := nil;
 If uppercase(Treeview2.Selected.Parent.Text) = 'GENERAL' then Rep := GRep;
 If uppercase(Treeview2.Selected.Parent.Text) = 'VISUAL' then Rep := VRep;
 If Rep = nil then exit;
 For I := 0 to Rep.Count - 1 do begin
  If uppercase(rep[I].Title) = uppercase(TreeView2.Selected.Text) then begin
   LoadRep(Rep[I]);
   If Rep[I].Screen = 'NOFILE' then begin
    Image2.Visible := false;
    Shape1.Visible := true;
    Label51.Visible := true;
    Label52.Visible := true;
    Label53.Visible := true;
    Label54.Visible := true;
   end
    else
   begin
    Image2.Visible := true;
    Shape1.Visible := false;
    Label51.Visible := false;
    Label52.Visible := false;
    Label53.Visible := false;
    Label54.Visible := false;
    XMLDownload.URL := Rep[I].Screen;
    XMLDownload.Filename := PathToOk(GetTemp) + GetLastFilt(Rep[I].Screen, '/');
    Screen.Cursor := crHourGlass;
    If not fileexists(XMLDownload.Filename) then begin
     XMLDownload.DownloadFile;
    end;
    Image2.Picture.LoadFromFile(XMLDownload.Filename);
    Screen.Cursor := crDefault;
   end;
   exit;
  end;
 end;
end;

procedure TForm1.TreeView2Change(Sender: TObject; Node: TTreeNode);
begin
 TreeView2Click(self);
end;

procedure TForm1.SetRepInstall;
Var
 CM2Path: String;
 Reg: TRegistry;
 II, I: Integer;
 RDL: TRepDownloadlist;
 VN, GN: TTreenode;
 RD: TRepDownload;
 List: TStringlist;
 RT: TRegisterTools;
 RA: TRegisterAs;
begin
 Panel1.Caption := 'Installing';
 Treeview2.Visible := false;
 Label55.Caption := 'Current Item: All ...';
 Label56.Caption := 'Status: Gathering information ...';
 update;
 // status = label56
 // current file = label55
 Reg := TRegistry.Create;
 Reg.RootKey := HKEY_CURRENT_USER;
 If not Reg.Openkey('\software\the coolmon project\Coolmon2', false) then begin
  FreeAndNil(Reg);
  PageControl1.SelectNextPage(true);
  exit;
 end;
 CM2Path := Reg.ReadString('');
 CM2Path := PathToOk(ExtractFilepath(CM2Path)) + 'Plugins\';
 FreeAndnil(reg);
 RDL := TRepDownloadList.Create;
 VN := nil; GN := nil;
 For I := 0 to treeview2.Items.Count - 1 do begin
  If uppercase(Treeview2.items[I].Text) = 'VISUAL' then begin
   VN := Treeview2.Items[I];
  end;
  If uppercase(Treeview2.items[I].Text) = 'GENERAL' then begin
   GN := Treeview2.items[I];
  end;
 end;
 For I := 0 to VN.Count - 1 do begin
  If VN[I].ImageIndex = 1 then begin
   RDL.Add(VN[I].Text, itVisual, CM2Path + 'Visual');
  end;
 end;
 For I := 0 to GN.Count - 1 do begin
  If GN[I].ImageIndex = 1 then begin
   RDL.Add(GN[I].Text, itGeneral, CM2Path + 'General');
  end;
 end;
 If RDL.Count = 0 then begin
  // If there where no selected items
  FreeAndNil(Reg);
  PageControl1.SelectNextPage(true);
  exit;
 end;
 Screen.Cursor := crHourglass;
 List := TStringlist.Create;
 For I := 0 to RDL.Count - 1 do begin
  Case RDL[I].ItemType of
   itVisual: begin
              For II := 0 to VRep.Count - 1 do begin
               IF uppercase(RDL[I].Name) = uppercase(Vrep[II].Title) then begin
                RD := RDL[I];
                RD.UPD := VRep[II].UpdFile;
                RDL[I] := RD;
               end;
              end;
             end;
   itGeneral: begin
               For II := 0 to GRep.Count - 1 do begin
                If uppercase(RDL[I].Name) = uppercase(GRep[II].Title) then begin
                RD := RDL[I];
                RD.UPD := GRep[II].UpdFile;
                RDL[I] := RD;
                end;
               end;
              end;
  end;
 end;
 Label56.Caption := 'Status: Getting Size information ...';
 Update;
 For I := 0 to RDL.Count - 1 do begin
  Label55.Caption := 'Current Item: ' + RDL[I].Name;
  Update;
  upddownload.URL := RDL[I].UPD;
  updDownload.Filename := PathToOk(GetTemp) + GetlastFilt(upddownload.URL, '/');
  updDownload.DownloadFile;
  If fileexists(upddownload.Filename) then begin
   list.LoadFromFile(upddownload.Filename);
   // UPD unlimited resolve until rar file is hit ?????
   RD := RDL[I];
   RD.DirectURL := List[1];
   UPDDownload.URL := RD.DirectURL;
   UPDDownload.GetSize(RD.Size);
   RDL[I] := RD;
  end;
 end;
 OverallProgressInt := 0;
 OverallSize := RDL.TotalSize;
 RT := TRegisterTools.Create;
 For I := 0 To RDL.Count - 1 do begin
  Label55.Caption := 'Current Item: ' + RDL[I].Name;
  Label56.Caption := 'Status: Downloading ...';
  repDownload.Url := RDL[I].DirectURL;
  repDownload.Filename := PathToOk(GetTemp) + GetLastFilt(RDL[I].DirectURL, '/');
  repDownload.DownloadFile;
  Inc(OverallProgressInt, RDL[I].Size);
  // Unpack
  If fileexists(repDownload.Filename) then begin
   Label56.Caption := 'Status: Unpacking ...';
   Update;
   UnRar.FileName := repdownload.filename;
   UnRar.OverrideEvent := OR_ALWAYS;
   UnRar.Directory := RDL[I].ExtractTo;
   UnRar.Mode := DFRAR_EXTRACT;
   UnRar.Extract;
   Label56.Caption := 'Status: Installing ...';
   with UnRar do begin
    Mode := DFRAR_LIST;
    CanProgress := false;
    OverrideEvent := OR_EVENT;
    StopProcessing := false;
    Extract;
   end;
   If Fileexists(pathtook(Unrar.Directory) + Reppluginstall) then begin
    RT.InstallPlugIn(pathtook(Unrar.Directory) + Reppluginstall, ra);
   end;
  End;
 end;
 Screen.Cursor := crDefault;
 FreeAndnil(List);
 Freeandnil(RDL);
 FreeAndnil(RT);
 PageControl1.SelectNextPage(true);
end;

procedure TForm1.SetRepComplete;
begin
 Panel1.Caption := 'Installation Complete';
 next.Caption := '&Finish';
end;

procedure TForm1.SetRepDoTerminate;
Var
 Reg: TRegistry;
begin
 Reg := TRegistry.Create;
 Reg.RootKey := HKEY_CURRENT_USER;
 Case Radiogroup4.ItemIndex of
  0: begin
      If Reg.openkey('\Software\the coolmon project\coolmon2', false) then begin
       Execapp(Reg.ReadString(''));
      end
       else
      begin
       MessageDlg('Unable to find CoolMon 2 Core program', mtError, [mbOK], 0);
      end;
     end;
  1: begin
      If Reg.openkey('\Software\the coolmon project\coolmon2\editor', false) then begin
       Execapp(Reg.ReadString(''));
      end
       else
      begin
       MessageDlg('Unable to find The Outlaw Ed program', mtError, [mbOK], 0);
      end;
     end;
 end;
 FreeAndNil(Reg);
 Application.Terminate;
end;

procedure TForm1.repdownloadProgress(Sender: TObject; Readed,
  TotalSize: Int64);
begin
 RepItemBar.Position := Round((Readed/TotalSize)*100);
 RepTotalBar.Position := Round(((Readed + OverallProgressInt)/OverallSize)*100);
 update;
end;

procedure TForm1.unrarFileProcessing(Sender: TObject;
  hdrData: TDFRARHeaderData; status: Integer);
begin
 If uppercase(extractfileext(hdrData.FileName)) = '.DLL' then begin
  Reppluginstall := hdrData.Filename;
 end;
end;

procedure TForm1.DirectoryListBox1Change(Sender: TObject);
begin
 If not changeeditbox then exit;
 Edit1.Text := DirectoryListBox1.Directory;
end;

end.
