unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons, nwbase, nwlib, ExtCtrls, FileCtrl, Registry,INIFiles; type TForm1 = class(TForm) LblTitle: TLabel; MemoInfo: TMemo; BButtNext: TBitBtn; BButtCancel: TBitBtn; NWBase1: TNWBase; LblUserName: TLabel; Timer1: TTimer; LblCheckEngineVer: TLabel; Timer2: TTimer; PanelInfo: TPanel; LblFullName: TLabel; LblDetails: TLabel; LblEngineVersion: TLabel; LblEngineVerFound: TLabel; BButtHelp: TBitBtn; LblVirDef: TLabel; LblVirDefFound: TLabel; LblEngineUpdateVer: TLabel; LblVirDefInfo: TLabel; LblVirDefUpgrade: TLabel; LblCheckVirDef: TLabel; LblWinVersion: TLabel; procedure Startup(Sender: TObject); procedure ReadIni(Sender: TObject); procedure BButtCancelClick(Sender: TObject); procedure BButtNextClick(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure CheckStatus(Sender: TObject); procedure Timer2Timer(Sender: TObject); procedure BButtHelpClick(Sender: TObject); procedure FTPSiteChange(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; Username: String; EngineVerFound: string; //That read from Registry EngineVerUpgrade: string; //Version of engine in upgrade (read from INI file) UpdateExe: string; //Superdat Executable that runs to upgrade scan engine and virus defs VirDefFound: string; //DAT file version read from Registry VirDefUpgrade: string;//Version of DAT file in the upgrade, read from INI file. RunUpdate: Boolean; // If True then update will run. WinVersion: String; //either 'W95' or 'NT4-2000' implementation uses help; function CreateProcessAndWait(AppPath, AppParams: String; Visibility: word): DWord ; forward; function CompareEngineVersion(EngineVerFound, EngineVerUpgrade: String): String; forward; function CompareVirDefVersion(VirDefFound, VirDefUpgrade: String): String; forward; {$R *.DFM} {-----------------------------------------} procedure TForm1.Startup(Sender: TObject); begin username := whoami(0); RunUpdate := False; //Initialise LblUserName.Caption := UserName; LblUserName.Update; LblFullName.Caption := FullName(0,Username); LblFullName.Update; ReadIni(Sender); //Reads version of engine being upgraded. CheckStatus(Sender);//Check if update has already run. FTPSiteChange(Sender);//Change auto-update to HW FTP site end; {------------------------------------------------} procedure TForm1.ReadIni(Sender: TObject); {Reads INI file to find initial settings} Var AppINI: TIniFile; {Variable of type INI file required for "ReadSectionValues"} INIFile: String; {Name of INI file} begin try INIFile := ExtractFilePath(application.exename)+ 'updatevir.ini'; if not FileExists(INIFile) then begin ShowMessage('Fatal Error: initialisation file ' + INIFile +' cannot be found'); BButtCancelClick(Sender); //Quit exit; end; AppIni := TIniFile.Create(INIFile); {assign memory for TIniFile object} {Read the engine version to the application window} EngineVerUpgrade := trim(AppIni.ReadString('Engine','EngineUpgradeVer','engine unknown')); LblEngineUpdateVer.Caption := EngineVerUpgrade; {Read location of SuperDat update exe to be run} UpdateExe :=trim(AppIni.ReadString('Engine','UpdateExe','unknown')); {Read version of virus definitions in the upgrade } VirDefUpgrade :=trim(AppIni.ReadString('Engine','VirDefUpgrade','unknown')); LblVirDefUpgrade.Caption := VirDefUpgrade; finally AppIni.Free; end; end; {-----------------------------------------------} procedure TForm1.BButtCancelClick(Sender: TObject); {Close form, check if update has been allowed to run.} begin // if EngineVerFound <> EngineVerUpgrade then //Update required // if not FoundMoreRecent then //skip this check if more recent engine detected // if MessageDlg('Are you sure your virus scan engine is more recent than '+ EngineVerUpgrade+' ?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then // ShowMessage('Okay. Please ignor this check.') // else // ShowMessage('No problem. This program will run again when you next login.'); MemoInfo.Clear; MemoInfo.Update; Close; Application.Terminate; end; {---------------------------------------------------} procedure TForm1.FTPSiteChange(Sender: TObject); {On NT/2000 changes the FTP DAT auto-update path to the Heriot-Watt site} var Reg: TRegistry; FTPLocationHW: String; //Where McAfee should get it's FTP update info. FTPLocationFound: String; //Where McAfee looks for it's FTP update. begin try Reg:=TRegistry.Create; Reg.RootKey:=HKey_Local_Machine; // Section to look for within the registry if not Reg.KeyExists('Software/McAfee/VirusScan/Tasks/Update') then exit //Not an NT machine else //An NT or W2000 machine with the required keys begin //Read from Registry FTPLocationHW := 'ftp.hw.ac.uk/pub/internal/antivirus/update/'; Reg.OpenKey('Software/McAfee/VirusScan/Tasks/Update',False);//False = Don't create if Reg.ValueExists('szUpdateFTPLocation') then FTPLocationFound:= trim(Reg.ReadString('szUpdateFTPLocation')); if lowercase(FTPLocationFound) <> lowercase(trim(FTPLocationHW)) then //change to HW site begin try Reg.WriteString('szUpdateFTPLocation',FTPLocationHW); //Change to HW campus one. except begin LblCheckVirDef.Caption :='Unable to change FTP location.' ; LblCheckVirDef.Update; end; end; // of try-except end; end; finally Reg.CloseKey; Reg.Free; end; end; {---------------------------------------------------} procedure TForm1.BButtNextClick(Sender: TObject); {Runs the anti-virus update} //var // UpdateExe: String; begin // UpdateExe := 'n:/School/install/vscan4.03/autoupgrade/setup.exe'; if not FileExists(UpdateExe) then begin ShowMessage('Cannot find ' + UpdateExe); exit; end; Form1.Visible := False; CreateProcessAndWait(UpdateExe,'',1); BButtNext.Visible := False; BButtCancel.Visible := False; LblFullName.Visible := False; Timer1.Enabled := True; //startup countdown to exit MemoInfo.Clear; MemoInfo.Visible := False; LblCheckVirDef.Caption := 'Update is complete !'; Form1.ClientHeight := 104; Form1.Visible := True; end; {-------------------------------------------------------} function CreateProcessAndWait(AppPath, AppParams: String; Visibility: word): DWord; var SI: TStartupInfo; PI: TProcessInformation; Proc: THandle; begin FillChar(SI, SizeOf(SI), 0); SI.cb := SizeOf(SI); SI.wShowWindow := Visibility; if not CreateProcess(PChar(AppPath), PChar(AppParams), Nil, Nil, False, Normal_Priority_Class, Nil, Nil, SI, PI) then raise Exception.CreateFmt('Failed to execute program. Error Code %d', [GetLastError]); Proc := PI.hProcess; CloseHandle(PI.hThread); if WaitForSingleObject(Proc, Infinite) <> Wait_Failed then GetExitCodeProcess(Proc, Result); CloseHandle(Proc); end; {----------------------------------------} procedure TForm1.CheckStatus(Sender: TObject); {Checks 1) version of DAT files and Engine in Registry} var Reg: TRegistry; begin try {Read version of engine and DAT files from Registry} Reg:=TRegistry.Create; Reg.RootKey:=HKey_Local_Machine; // Section to look for within the registry {Check if OS is Windows 95 which stores Virus Def version string differently} Reg.OpenKey('Software/Microsoft/Windows/CurrentVersion',False);//False = Don't create if Reg.ValueExists('ProductName') then WinVersion := 'W95' else WinVersion := 'NT4-2000'; Reg.CloseKey; LblWinVersion.Caption := WinVersion; LblWinVersion.Update; if not Reg.KeyExists('Software/McAfee/VirusScan') then //No registry key ... odd. begin EngineVerFound := 'unknown'; LblEngineVerFound.Caption := 'Unknown'; end else begin //Read from Registry Reg.OpenKey('Software/McAfee/VirusScan',False);//False = Don't create if Reg.ValueExists('szEngineVer') then EngineVerFound:= trim(Reg.ReadString('szEngineVer')); LblEngineVerFound.Caption :=EngineVerFound; LblEngineVerFound.Update; if Reg.ValueExists('szVirDefVer') then VirDefFound := trim(Reg.ReadString('szVirDefVer')); //NT4 has format 4.0.4121 //W95 has format 4121 LblVirDefFound.Caption := VirDefFound; LblVirDefFound.Update; end; {Initial check to make sure value has real data, not 'unknown' etc.} if lowercase(EngineVerFound) = 'unknown' then begin LblCheckEngineVer.Caption:= 'Unknown scan engine.'; LblCheckEngineVer.Update; BButtCancelClick(Sender); //quit without action exit; end; if length(EngineVerFound) <2 then //maybe no data or faulty data. begin LblCheckEngineVer.Caption:= 'Unknown scan engine.'; LblCheckEngineVer.Update; BButtCancelClick(Sender); //quit without action exit; end; {Now take action depending on what version of engine was found:} if EngineVerFound = EngineVerUpgrade then //no need to update engine, same versions begin // Form1.ClientHeight := 112; //Reduce height of form LblCheckEngineVer.Caption := 'Status: Engine already updated, thank-you !'; LblCheckEngineVer.Update; // Timer1.Enabled := True; //Countdown to Exit end else begin if CompareEngineVersion(EngineVerFound, EngineVerUpgrade) = 'upgrade_yes' then begin RunUpdate := True; //Set global flag to run the update exe. MemoInfo.Visible := True; MemoInfo.Update; LblCheckEngineVer.Caption := 'Status: Engine update required'; LblCheckEngineVer.Font.Color := clRed; LblCheckEngineVer.Update; end else //function must have detected a later version begin // Form1.ClientHeight := 112; //Reduce height of form LblCheckEngineVer.Caption := 'Status: Current engine is more recent.'; LblCheckEngineVer.Update; // Timer1.Enabled := True; //Countdown to Exit end; end; {NT4-2000 code************** Now check version of virus definitions ********************** NT4 has VirDefFound and VirDefUpgrade both in same format e.g. 4.0.4120 so next test will work:} if VirDefFound = VirDefUpgrade then //no need to update engine, same versions begin // Form1.ClientHeight := 112; //Reduce height of form LblCheckVirDef.Caption := 'Status: Virus Definitions already updated, thank-you !'; LblCheckVirDef.Update; if not RunUpdate then begin Form1.ClientHeight := 112; //Reduce height of form Timer1.Enabled := True; //Countdown to Exit, since engine doesn't need update either end; end else //Call the procedure which determines if a later or earlier version is installed begin // OR W95 is installed, in which case first test in IF block would also fail: if CompareVirDefVersion(VirDefFound, VirDefUpgrade) = 'upgrade_yes' then begin MemoInfo.Visible := True; MemoInfo.Update; LblCheckVirDef.Caption := 'Status: Virus Definition update required'; LblCheckVirDef.Font.Color := clRed; LblCheckVirDef.Update; end else //function must have detected a later version so quit unless Engine needs update begin LblCheckVirDef.Caption := 'Status: Current virus definitions are more recent.'; LblCheckVirDef.Update; if not RunUpdate then begin Form1.ClientHeight := 112; //Hides the NEXT button, etc. Timer1.Enabled := True; //Start close procedure end; end; end; finally Reg.CloseKey; Reg.Free; //Free Registry memory. end; end; {-------------------------------------------------------} function CompareEngineVersion(EngineVerFound, EngineVerUpgrade: String): String; {Compares two version strings, higher numbers indicate later version} {e.g. EngineVerFound 4.0.60 EngineVerUpgrade 4.0.70 so break numbers into parts and compare each '.' delimited value} var E_VerF: array[1..3] of string; //Array holding characters in EngineVerFound E_VerU: array[1..3] of string; //Array holding characters in EngineVerUpgrade i,j: integer; //loop counter bit, test: string; begin if length(EngineVerFound)<2 then begin Result := 'upgrade_no'; exit; end; j:=1; for i:=1 to length(EngineVerFound) do //step through characters begin bit := copy(EngineVerFound,i,1);// Just a single character copied from the string if bit = '.' then //we've completed one subversion of the engine version begin j:= j+1; //So next E_Ver[j] to be incremented will refer to next subversion number end else begin //Still building subversion string or at the end of the string. E_VerF[j] := E_VerF[j] +bit; end; end; {repeat for the Upgrade Engine ... slightly wasteful of code} j:=1; for i:=1 to length(EngineVerUpgrade) do //step through characters begin bit := copy(EngineVerUpgrade,i,1);// Just a single character copied from the string if bit = '.' then //we've completed one subversion of the engine version begin j:= j+1; //So next E_Ver[j] to be incremented will refer to next subversion number end else begin //Still building subversion string or at the end of the string. E_VerU[j] := E_VerU[j] +bit; end; end; { test := e_verU[1] +'-' +e_verU[2] +'-'+ e_verU[3]; ShowMessage('Upgrade version was '+Test); test := e_verF[1] +'-' +e_verF[2] +'-'+ e_verF[3]; ShowMessage('Detected version was '+Test); } {Now compare each version, most significant bit first. Convert to integers first} {If one subelement of Found version > that of Upgrade version then don't upgrade} Result := 'upgrade_yes'; //set a default for j:= 1 to 3 do begin // ShowMessage('Found: '+E_VerF[j]+' Upgrade: '+E_VerU[j]); if StrToInt(E_VerF[j]) > StrToInt(E_VerU[j]) then //one subversion found > equiv. subversion upgrade begin Result := 'upgrade_no'; exit; end; end; end; {-------------------------------------------------------} function CompareVirDefVersion(VirDefFound, VirDefUpgrade: String): String; {Compares two version strings of Virus Defs, higher numbers indicate later version} {e.g. VirDefFound 4.0.60 VirDefUpgrade 4.0.4104 so break numbers into parts and compare each '.' delimited value. Windows 95 stores only the last number - 4104 - whereas NT4 and 2000 store 4.0.4104, for example.} var E_VerF: array[1..3] of string; //Array holding characters in VirDefFound E_VerU: array[1..3] of string; //Array holding characters in VirDefUpgrade i,j: integer; //loop counter bit, test: string; begin if length(VirDefFound)<2 then begin Result := 'upgrade_no'; exit; end; {Split NT4/2000 Virus Def strings into three parts:} j:=1; for i:=1 to length(VirDefFound) do //step through characters begin bit := copy(VirDefFound,i,1);// Just a single character copied from the string if bit = '.' then //we've completed one subversion of the engine version begin j:= j+1; //So next E_Ver[j] to be incremented will refer to next subversion number end else begin //Still building subversion string or at the end of the string. E_VerF[j] := E_VerF[j] +bit; end; end; {repeat for the Upgrade Engine ... slightly wasteful of code} j:=1; for i:=1 to length(VirDefUpgrade) do //step through characters begin bit := copy(VirDefUpgrade,i,1);// Just a single character copied from the string if bit = '.' then //we've completed one subversion of the engine version begin j:= j+1; //So next E_Ver[j] to be incremented will refer to next subversion number end else begin //Still building subversion string or at the end of the string. E_VerU[j] := E_VerU[j] +bit; end; end; {Start W95 code, which above tests will not work for. This compares the final string of the upgrade virus definition with the VirDefFound string e.g. Last number of VirDefUpgrade (4.1.4014) is here '4014' VirDefFound for W95 is the single number '4014' The test thus compares the least significant bit of VirDefUpgrade, which isn't good but that's how McAffee store the virus definition version string. } if WinVersion = 'W95' then if StrToInt(E_VerU[3]) > StrToInt(VirDefFound) then begin ShowMessage(VirDefFound); Result := 'upgrade_yes'; exit; //Don't process NT4-2000 code end else begin Result := 'upgrade_no'; exit; end; { test := e_verU[1] +'-' +e_verU[2] +'-'+ e_verU[3]; ShowMessage('Virus Def Upgrade version was '+Test); test := e_verF[1] +'-' +e_verF[2] +'-'+ e_verF[3]; ShowMessage('Virus Def Detected version was '+Test); } {Now compare each version, most significant bit first. Convert to integers first} {If one subelement of Found version > that of Upgrade version then don't upgrade} Result := 'upgrade_yes'; //set a default for j:= 1 to 3 do begin // ShowMessage('Found: '+E_VerF[j]+' Upgrade: '+E_VerU[j]); if StrToInt(E_VerF[j]) > StrToInt(E_VerU[j]) then //one subversion found > equiv. subversion upgrade begin Result := 'upgrade_no'; exit; end; end; end; {-------------------------------------------------------} procedure TForm1.Timer1Timer(Sender: TObject); begin BButtCancelClick(Sender); end; {-------------------------------------} procedure TForm1.Timer2Timer(Sender: TObject); {Flashes the NEXT button} begin if BButtNext.Caption = 'NEXT' then begin BButtNext.Caption := ''; BButtNext.Update; end else begin BButtNext.Caption := 'NEXT'; BButtNext.Update; end; end; {-----------------------} procedure TForm1.BButtHelpClick(Sender: TObject); begin FrmHelp.ShowModal; end; {---------------------------------} end.
|