spiegel-keyman/windows/src/desktop/kmshell/main/initprog.pas

751 lines
26 KiB
ObjectPascal

(*
Name: initprog
Copyright: Copyright (C) SIL International.
Documentation:
Description:
Create Date: 20 Jun 2006
Modified Date: 23 Jun 2015
Authors: mcdurdin
Related Files:
Dependencies:
Bugs:
Todo:
Notes:
History: 20 Jun 2006 - mcdurdin - Initial version
01 Aug 2006 - mcdurdin - Rework for Keyman 7
02 Aug 2006 - mcdurdin - Timeout when Beta expires
04 Dec 2006 - mcdurdin - Add -activate, locale functionality, icons
04 Jan 2007 - mcdurdin - Add help support
04 Jan 2007 - mcdurdin - Workaround Vista button refresh issue in Delphi
30 May 2007 - mcdurdin - Add -w to show welcome at any time
20 Jun 2007 - mcdurdin - I838 - Fix shadow keyboards (usually from KM6)
23 Aug 2007 - mcdurdin - I933 - Use Unicode application title
05 Nov 2007 - mcdurdin - I869 - Add -nowelcome for elevated keyboard install
05 Nov 2007 - mcdurdin - I937, I1128 - Repair COM object if it fails at startup
06 Nov 2007 - mcdurdin - I1140 - Support -configure-addin for elevated addin configuration
27 Mar 2008 - mcdurdin - I1201 - Admin required uninstalling package
27 Mar 2008 - mcdurdin - I1248 - Redesign Welcome
14 Jun 2008 - mcdurdin - Support installing multiple files at once
28 Aug 2008 - mcdurdin - I1616 - Upgrade keyboards from 6.x
16 Jan 2009 - mcdurdin - I1730 - Check update of keyboards
27 Jan 2009 - mcdurdin - Improve startup and shutdown performance
30 Jan 2009 - mcdurdin - I1826 - Fix performance starting and closing help
07 Sep 2009 - mcdurdin - I2051 - Crash in kmshell when -h parameter used with no page parameter
12 Mar 2010 - mcdurdin - I2226 - Include link to Text Editor in Keyman Menu
29 Mar 2010 - mcdurdin - I2260 - "Start Text Editor" should not start in Tutorial mode
25 May 2010 - mcdurdin - I1694 - UI language option accessibility
25 May 2010 - mcdurdin - I2392 - Activation Client integration
30 Nov 2010 - mcdurdin - I2548 - Support for upgrading Desktop 7 to Desktop 8
10 Dec 2010 - mcdurdin - I2548 - Consolidate -upgradekeyboards switch
17 Dec 2010 - mcdurdin - I2548 - Fix bugs with upgrade
30 Dec 2010 - mcdurdin - I2562 - Start Keyman install properties
30 Dec 2010 - mcdurdin - I2604 - Upgrade to Pro from Character Map is incomplete
31 Dec 2010 - mcdurdin - I2605 - Crash starting Keyman after upgrade when using non-default locale
18 Feb 2011 - mcdurdin - I2702 - "Getting Started" link not working
21 Feb 2011 - mcdurdin - I2651 - Setup does not set desired default options
22 Feb 2011 - mcdurdin - I2753 - Firstrun crashes because start with windows and auto update check options are set in Engine instead of Desktop
28 Feb 2011 - mcdurdin - I2720 - Prevent Keyman splash from showing multiple copies
18 Mar 2011 - mcdurdin - I2807 - Enable/disable addins
18 Mar 2011 - mcdurdin - I2782 - Unminimize configuration when bringing it to foreground
18 May 2012 - mcdurdin - I3306 - V9.0 - Remove TntControls + Win9x support
02 Feb 2012 - mcdurdin - I2975 - VistaAltFixUnit can crash on shutdown
01 Dec 2012 - mcdurdin - I3613 - V9.0 - System shadow keyboards obsolete, strip out remaining code
01 Jan 2013 - mcdurdin - I3624 - V9.0 - Install keyboard language profiles from Keyman COM API
16 Apr 2014 - mcdurdin - I4169 - V9.0 - Mnemonic layouts should be recompiled to positional based on user-selected base keyboard
03 Jun 2014 - mcdurdin - I4248 - V9.0 - Refactor of kmtip
16 Jun 2014 - mcdurdin - I4185 - V9.0 - Upgrade V8.0 keyboards to 9.0
03 Sep 2014 - mcdurdin - I4400 - V9.0 - Add HKCU FEATURE_BROWSER_EMULATION 9000 for kmshell.exe
10 Oct 2014 - mcdurdin - I4436 - V9.0 - browser emulation control for kmshell breaks downlevel versions of Keyman
31 Dec 2014 - mcdurdin - I4553 - V9.0 - Upgrade to 476 or later requires recompile of all mnemonic layouts
23 Jun 2015 - mcdurdin - I4773 - Keyman needs to rebuild its language profiles if they are inadvertently deleted
*)
unit initprog; // I3306 // I4248
interface
uses
System.UITypes,
Windows, Controls, SysUtils, Classes, ErrorControlledRegistry, Forms, MessageIdentifiers, MessageIdentifierConsts, keymanapi_TLB;
procedure Run;
function Main(Owner: TComponent = nil): TModalResult;
type
TKMShellMode = (fmUndefined, fmInstall, fmView, fmUninstall, fmAbout,
fmUninstallKeyboard,
fmInstallTipsForPackages, fmInstallKeyboardLanguage, fmRegisterTip, fmInstallTip, fmUninstallKeyboardLanguage, // I3624
fmUninstallPackage, fmRegistryAdd, fmRegistryRemove,
fmMain, fmHelp, fmHelpKMShell,
fmMigrate, fmSplash, fmStart,
fmUpgradeKeyboards, // I2548
fmTextEditor,
fmInstallKeyboardPackageAdmin,
fmBackgroundUpdateCheck,
fmBackgroundDownload,
fmApplyInstallNow,
fmFirstRun, // I2562
fmKeyboardWelcome, // I2569
fmKeyboardPrint, // I2329
fmBaseKeyboard, // I4169
fmUpgradeMnemonicLayout, // I4553
fmRepair,
fmKeepInTouch,
fmSettings,
fmBoot,
// Commands from Keyman Engine
fmShowHint,
fmShowHelp); // I4773
var
ApplicationRunning: Boolean = False;
UnRegCRC: LongWord = 0;
FMode: TKMShellMode;
implementation
uses
custinterfaces,
DebugPaths,
Dialogs,
GetOsVersion,
help,
HTMLHelpViewer,
Keyman.Configuration.UI.InstallFile,
Keyman.Configuration.System.TIPMaintenance,
Keyman.Configuration.System.UImportOlderVersionKeyboards11To13,
Keyman.Configuration.UI.UfrmSettingsManager,
Keyman.Configuration.UI.UfrmStartInstall,
Keyman.System.KeymanStartTask,
KeymanPaths,
KLog,
kmint,
KMShellHints,
KeymanMutex,
Keyman.System.RemoteUpdateCheck,
RegistryKeys,
UfrmBaseKeyboard,
UfrmKeymanBase,
UfrmInstallKeyboardLanguage,
UfrmSplash,
UfrmHelp,
UfrmHTML,
UfrmKeepInTouch,
UfrmMain,
UfrmPrintOSK,
UfrmTextEditor,
UfrmWebContainer,
UImportOlderVersionSettings,
UImportOlderVersionKeyboards8,
UImportOlderVersionKeyboards9,
UImportOlderVersionKeyboards10,
UILanguages,
uninstall,
UpgradeMnemonicLayout,
utilfocusappwnd,
utilkmshell,
Keyman.System.UpdateStateMachine,
KeyboardTIPCheck,
ValidateKeymanInstalledSystemKeyboards,
VisualKeyboard,
WideStrings,
extctrls, stdctrls, comctrls;
function FirstRun(FQuery, FDisablePackages, FDefaultUILanguage: string): Boolean; forward; // I2562
procedure ShowKeyboardWelcome(PackageName: WideString); forward; // I2569
procedure PrintKeyboard(KeyboardName: WideString); forward; // I2329
function ProcessBackgroundUpdate(FMode: TKMShellMode; FSilent: Boolean): Boolean; forward;
function Main(Owner: TComponent = nil): TModalResult;
var
frmMain: TfrmMain;
begin
Result := mrNone;
if not Assigned(Owner) then
begin
UfrmWebContainer.CreateForm(TfrmMain, frmMain);
ApplicationRunning := True;
Application.Run;
ApplicationRunning := False;
FreeAndNil(frmMain);
end
else if not FocusConfiguration then // I2720
begin
with TfrmMain.Create(Owner) do
try
Result := ShowModal;
finally
Free;
end;
end;
end;
function Show_frmHTML(AParent: TComponent; const ACaption, AText, AFileName: string; AHelpContext: Integer): Integer;
begin
with TfrmHTML.Create(AParent) do
try
Caption := ACaption;
HelpContext := AHelpContext;
if AText <> ''
then Text := AText
else ShowFile(AFileName);
Result := ShowModal;
finally
Free;
end;
end;
function Init(var FMode: TKMShellMode; KeyboardFileNames: TStrings; var FSilent, FForce, FNoWelcome: Boolean;
var FLogFile, FQuery: string; var FDisablePackages, FDefaultUILanguage: string; var FStartWithConfiguration: Boolean;
var FParentWindow: THandle; var FDefaultBCP47: string; var FDefaultLangID: Integer): Boolean;
var
s: string;
i: Integer;
begin
Result := False;
FSilent := False;
FForce := False;
FNoWelcome := False;
FStartWithConfiguration := False;
FDisablePackages := '';
FDefaultUILanguage := '';
FQuery := '';
FMode := fmStart;
KeyboardFileNames.Clear;
i := 1;
while i <= ParamCount do
begin
if (ParamStr(i) <> '') and (ParamStr(i)[1] = '-') then
begin
s := LowerCase(ParamStr(i));
if s = '-s' then FSilent := True
else if s.StartsWith('-unique-') then
// Ignore this parameter. Used just to avoid Start Menu hiding
// shortcut entries which are pointing at the same target for
// package installation. See https://superuser.com/a/1395288/521575 and
// https://github.com/keymanapp/keyman/issues/2467
else if s = '-f' then FForce := True
else if s = '-boot' then FMode := fmBoot
else if s = '-c' then FMode := fmMain
else if s = '-m' then FMode := fmMigrate
else if s = '-i' then FMode := fmInstall
else if s = '-ikl' then FMode := fmInstallKeyboardLanguage // I3624
else if s = '-register-tip' then FMode := fmRegisterTip
else if s = '-install-tip' then FMode := fmInstallTip
else if s = '-install-tips-for-packages' then FMode := fmInstallTipsForPackages
//else if s = '-i+' then begin FMode := fmInstall; FNoWelcome := True; end;
else if s = '-v' then FMode := fmView
else if s = '-u' then FMode := fmUninstall
else if s = '-uk' then FMode := fmUninstallKeyboard { I1201 - Fix crash uninstalling admin-installed keyboards and packages }
else if s = '-ukl' then FMode := fmUninstallKeyboardLanguage // I3624
else if s = '-up' then FMode := fmUninstallPackage { I1201 - Fix crash uninstalling admin-installed keyboards and packages }
else if s = '-ikp' then FMode := fmInstallKeyboardPackageAdmin
else if s = '-a' then FMode := fmAbout
else if s = '-ra' then FMode := fmRegistryAdd
else if s = '-rr' then FMode := fmRegistryRemove
else if s = '-splash' then FMode := fmSplash
else if s = '-?' then FMode := fmHelpKMShell
else if s = '-h' then FMode := fmHelp
else if s = '-t' then FMode := fmTextEditor
else if s = '-buc' then FMode := fmBackgroundUpdateCheck
else if s = '-bd' then FMode := fmBackgroundDownload
else if s = '-an' then FMode := fmApplyInstallNow
else if s = '-basekeyboard' then FMode := fmBaseKeyboard // I4169
else if s = '-nowelcome' then FNoWelcome := True
else if s = '-kw' then FMode := fmKeyboardWelcome // I2569
else if s = '-kp' then FMode := fmKeyboardPrint // I2329
else if s = '-log' then begin Inc(i); FLogFile := ParamStr(i); end
else if Copy(s,1,Length('-firstrun')) = '-firstrun' then begin FMode := fmFirstRun; FQuery := Copy(s,Length('-firstrun')+2,MAXINT); end // I2562
else if Copy(s,1,Length('-upgradekeyboards')) = '-upgradekeyboards' then begin FMode := fmUpgradeKeyboards; FQuery := Copy(s,Length('-upgradekeyboards')+2,MAXINT); end // I2548
else if s = '-upgrademnemoniclayout' then FMode := fmUpgradeMnemonicLayout // I4553
else if s = '-repair' then FMode := fmRepair // I4773
else if s = '-keepintouch' then FMode := fmKeepInTouch
else if Copy(s,1,Length('-disablepackages')) = '-disablepackages' then begin FDisablePackages := Copy(s, Length('-disablepackages')+2, MaxInt); end // Used with -firstrun
else if Copy(s,1,Length('-defaultuilanguage')) = '-defaultuilanguage' then begin FDefaultUILanguage := Copy(s, Length('-defaultuilanguage')+2, MaxInt); end // Used with -firstrun
else if s = '-startwithconfiguration' then FStartWithConfiguration := True
else if s = '-q' then
begin
FQuery := ''; Inc(i);
while i <= ParamCount do begin FQuery := FQuery + ParamStr(i) + ' '; Inc(i); end;
FQuery := Trim(FQuery);
end
else if Copy(s, 1, 3) = '-ur' then UnRegCRC := StrToIntDef('$'+Copy(s, 4, 8), 0)
else if s = '-default-lang' then
begin
Inc(i);
FDefaultBCP47 := ParamStr(i);
Inc(i);
FDefaultLangID := StrToIntDef('$'+ParamStr(i), 0);
end
// Controls from Keyman Engine
else if s = '-showhint' then FMode := fmShowHint
else if s = '-parentwindow' then
begin
Inc(i);
FParentWindow := StrToIntDef(ParamStr(i), 0);
end
else if s = '-showhelp' then FMode := fmShowHelp
else if s = '-settings' then FMode := fmSettings
else Exit;
end
else
begin
KeyboardFileNames.Add(ParamStr(i));
end;
Inc(i);
end;
if FMode in [fmInstall, fmInstallKeyboardLanguage, fmInstallTipsForPackages, fmInstallTip, fmRegisterTip, fmView, fmUninstallKeyboard, fmUninstallKeyboardLanguage, fmUninstallPackage] then // I2807 // I3624
if KeyboardFileNames.Count = 0 then Exit;
Result := FMode <> fmUndefined;
end;
procedure RegisterControlClasses;
begin
RegisterClasses([TImage, TCheckBox, TLabel, TButton, TPanel, TGroupBox, TPageControl, TTabSheet]);
end;
procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FForce, FNoWelcome: Boolean;
FLogFile, FQuery: string; FDisablePackages, FDefaultUILanguage: string; FStartWithConfiguration: Boolean; FParentWindow: THandle;
const FDefaultBCP47: string; FDefaultLangID: Integer); forward;
procedure Run;
var
KeyboardFileNames: TStrings;
FQuery: string;
FSilent: Boolean;
FNoWelcome: Boolean;
FForce: Boolean;
FParentWindow: THandle;
FLogFile: string;
FDefaultLangID: Integer;
FDefaultBCP47, FDisablePackages, FDefaultUILanguage: string;
FStartWithConfiguration: Boolean;
begin
RegisterControlClasses;
KeyboardFileNames := TStringList.Create;
try
FParentWindow := 0;
if not Init(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID) then
begin
//TODO: TUtilExecute.Shell(PChar('hh.exe mk:@MSITStore:'+ExtractFilePath(KMShellExe)+'keyman.chm::/context/keyman_usage.html'), SW_SHOWNORMAL);
Exit;
end;
if not LoadKMCOM then Exit;
try
RunKMCOM(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID);
finally
kmcom := nil;
end;
finally
KeyboardFileNames.Free;
end;
end;
function DoCheckTIPInstallStatus(FSilent: Boolean): Boolean;
begin
(*
Note: this needs a significant refactor because enumerating input processor
profiles under Administrator account may return different results to an
end user account. It is also much less likely that a keyboard will not
be available with Keyman 14's keyboard registration model. So we may be
able to avoid using this altogether.
For now, we will disable this check here and in the future may re-enable
it and rewrite it if it proves necessary to improve profile stability.
See #4893.
if not TKeyboardTIPCheck.CheckKeyboardTIPInstallStatus then
begin
if FSilent then
Exit(False);
if MessageDlg('Some keyboard profiles have been damaged. Correct these now?', mtConfirmation, mbOkCancel, 0) = mrOk then
begin
WaitForElevatedConfiguration(0, '-repair', True);
// TKeyboardTIPCheck.ReEnablePostRepair; //possible future mitigation idea, see #4893.
end;
end;
*)
Result := True;
end;
procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FForce, FNoWelcome: Boolean;
FLogFile, FQuery: string; FDisablePackages, FDefaultUILanguage: string; FStartWithConfiguration: Boolean;
FParentWindow: THandle; const FDefaultBCP47: string; FDefaultLangID: Integer);
var
kdl: IKeymanDefaultLanguage;
FIcon: string;
FMutex: TKeymanMutex; // I2720
function FirstKeyboardFileName: WideString;
begin
if KeyboardFileNames.Count = 0
then Result := ''
else Result := KeyboardFileNames[0];
end;
function SecondKeyboardFileName: WideString; // I3624
begin
if KeyboardFileNames.Count < 2
then Result := ''
else Result := KeyboardFileNames[1];
end;
function ThirdKeyboardFileName: string;
begin
if KeyboardFileNames.Count < 3
then Result := ''
else Result := KeyboardFileNames[2];
end;
function FourthKeyboardFileName: string;
begin
if KeyboardFileNames.Count < 4
then Result := ''
else Result := KeyboardFileNames[3];
end;
begin
kmcom.AutoApply := False;
FMutex := nil; // I2720
{ Run app reconfiguration tasks }
TKeymanStartTask.RecreateTask;
UILanguages.CreateUILanguages;
Application.HelpFile := GetCHMPath; // may change if language changes
Application.Title := MsgFromId(SKApplicationTitle);
if (FMode in [fmStart, fmBoot]) then FIcon := 'appicon.ico'
else FIcon := 'cfgicon.ico';
if GetOS in [osOther] then
begin
ShowMessage(MsgFromId(SKOSNotSupported));
Exit;
end;
if ProcessBackgroundUpdate(FMode, FSilent) then
begin
Exit;
end;
if not FSilent or (FMode = fmUpgradeMnemonicLayout) then // I4553
begin
// Note: will elevate and re-run if required
// Upgrades mnemonic layouts to fix bugs in existing layouts
TUpgradeMnemonicLayout.Run;
if FMode = fmUpgradeMnemonicLayout then
Exit;
end;
if not FSilent and (FMode in [fmStart, fmSplash, fmMain, fmAbout]) then // I4773
begin
DoCheckTIPInstallStatus(False);
end;
// I1818 - remove start mode change
FIcon := GetDebugPath(FIcon, ExtractFilePath(ParamStr(0)) + FIcon, False);
if FileExists(FIcon) then
Application.Icon.LoadFromFile(FIcon);
if (FDefaultBCP47 <> '') or (FDefaultLangID <> 0) then
begin
if Supports(kmcom, IKeymanDefaultLanguage, kdl) then
kdl.SetDefaultLanguage(FDefaultBCP47, FDefaultLangID);
end;
case FMode of
fmKeyboardWelcome: // I2569
ShowKeyboardWelcome(FirstKeyboardFileName);
fmKeyboardPrint: // I2329
PrintKeyboard(FirstKeyboardFileName);
fmFirstRun: // I2562
if FirstRun(FQuery, FDisablePackages, FDefaultUILanguage)
then ExitCode := 0
else ExitCode := 2;
fmUpgradeKeyboards:// I2548
begin
if FQuery='13,backup' then
TImportOlderVersionKeyboards11To13.BackupCurrentUser
else if FQuery='13,import' then
TImportOlderVersionKeyboards11To13.ImportCurrentUser
else if FQuery='13,admin' then
TImportOlderVersionKeyboards11To13.Execute
else
begin
ImportOlderVersionKeyboards8(Pos('admin', FQuery) > 0); // I4185
ImportOlderVersionKeyboards9(Pos('admin', FQuery) > 0); // I4185
ImportOlderVersionKeyboards10(Pos('admin', FQuery) > 0); // I4185
DeleteLegacyKeymanInstalledSystemKeyboards; // I3613
end;
end;
fmMigrate:
;
fmHelp:
if KeyboardFileNames.Count > 0 then OpenHelp(KeyboardFileNames[0])
else OpenHelp('');
fmHelpKMShell: ;
////TODO: TUtilExecute.Shell(PChar('hh.exe mk:@MSITStore:'+ExtractFilePath(KMShellExe)+'keyman.chm::/context/keyman_usage.html'), SW_SHOWNORMAL);
fmBoot:
begin
// on boot splash should be suppressed therefore Silent = True
StartKeyman(False, True, FStartWithConfiguration);
end;
fmStart:
begin // I2720
StartKeyman(False, FSilent, FStartWithConfiguration);
end;
fmSplash:
ShowSplash;
fmMain, fmAbout:
begin // I2720
FMutex := TKeymanMutex.Create('KeymanConfiguration');
if FMutex.TakeOwnership
then Main
else FocusConfiguration;
end;
fmTextEditor:
begin // I2720
FMutex := TKeymanMutex.Create('KeymanTextEditor');
if FMutex.TakeOwnership
then OpenTextEditor
else FocusTextEditor;
end;
fmBaseKeyboard: // I4169
if ConfigureBaseKeyboard
then ExitCode := 0
else ExitCode := 1;
fmInstall:
if TInstallFile.Execute(KeyboardFileNames, FirstKeyboardFileName, FSilent, FNoWelcome, FLogFile)
then ExitCode := 0
else ExitCode := 1;
fmInstallTipsForPackages:
if TTipMaintenance.InstallTipsForPackages(KeyboardFileNames) then
begin
// TTIPMaintenance never does a kmcom.Apply to notify
kmcom.Apply;
ExitCode := 0;
end
else
ExitCode := 1;
fmUninstallKeyboard: { I1201 - Fix crash uninstalling admin-installed keyboards and packages }
if UninstallKeyboard(nil, FirstKeyboardFileName, FSilent)
then ExitCode := 0
else ExitCode := 1;
fmInstallKeyboardLanguage: // I3624
if InstallKeyboardLanguage(nil, FirstKeyboardFileName, SecondKeyboardFileName, FSilent)
then ExitCode := 0
else ExitCode := 1;
fmUninstallKeyboardLanguage: // I3624
if UninstallKeyboardLanguage(FirstKeyboardFileName, FSilent)
then ExitCode := 0
else ExitCode := 1;
fmRegisterTip:
if TTipMaintenance.RegisterTip(StrToIntDef('$'+FirstKeyboardFilename, 0), SecondKeyboardFileName, ThirdKeyboardFileName)
then ExitCode := 0
else ExitCode := 1;
fmInstallTip:
if TTipMaintenance.InstallTip(StrToIntDef('$'+FirstKeyboardFilename, 0), SecondKeyboardFileName, ThirdKeyboardFileName, FourthKeyboardFileName)
then ExitCode := 0
else ExitCode := 1;
fmUninstallPackage: { I1201 - Fix crash uninstalling admin-installed keyboards and packages }
if UninstallPackage(nil, FirstKeyboardFileName, FSilent)
then ExitCode := 0
else ExitCode := 1;
fmRepair: // I4773
if DoCheckTIPInstallStatus(FSilent)
then ExitCode := 0
else ExitCode := 1;
fmKeepInTouch:
ShowKeepInTouchForm(True); // I4658
fmSettings:
if TfrmSettingsManager.Execute
then ExitCode := 0
else ExitCode := 1;
fmShowHint:
if ShowKMShellHintQuery(FParentWindow, FirstKeyboardFileName) = mrOk
then ExitCode := 0
else ExitCode := 1;
fmShowHelp:
TfrmHelp.Execute(FirstKeyboardFileName, SecondKeyboardFileName);
end;
if FMode <> fmMain then
begin
ApplicationRunning := True;
Application.Run;
ApplicationRunning := False;
end;
FreeAndNil(FMutex); // I2720
end;
function FirstRun(FQuery, FDisablePackages, FDefaultUILanguage: string): Boolean; // I2562
var
DoAdmin: Boolean;
begin
Result := True;
DoAdmin := kmcom.SystemInfo.IsAdministrator;
if not DoAdmin then
begin
// I2651 - options not matching, case sensitivity, 8.0.309.0
Result := FirstRunInstallDefaults(
Pos('installdefaults', FQuery) > 0,
Pos('startwithwindows', FQuery) > 0,
Pos('checkforupdates', FQuery) > 0,
FDisablePackages,
FDefaultUILanguage,
Pos('automaticallyreportusage', FQuery) > 0); // I2651, I2753
end;
end;
procedure ShowKeyboardWelcome(PackageName: WideString); // I2569
var
n: Integer;
begin
n := kmcom.Packages.IndexOf(PackageName);
if n >= 0 then
DoShowPackageWelcome(nil, kmcom.Packages[n], True);
end;
procedure PrintKeyboard(KeyboardName: WideString); // I2329
var
n: Integer;
begin
n := kmcom.Keyboards.IndexOf(KeyboardName);
if n >= 0 then
with TfrmPrintOSK.Create(nil) do
try
PrintKeyboard(kmcom.Keyboards[n]);
finally
Free;
end;
end;
function ShouldSendToBUpdateSM(FSilent: Boolean; BUpdateSM: TUpdateStateMachine; FMode: TKMShellMode): Boolean;
// The following logic around the WaitingRestartState should be
// encapsulated in the state machine however as we want separation of
// UI elements from the state machine we have bring some of logic here.
var
frmStartInstall: TfrmStartInstall;
ValidateReadyToInstall: Boolean;
begin
ValidateReadyToInstall := BUpdateSM.ValidateReadyToInstall;
if not FSilent and ValidateReadyToInstall and
(FMode in [fmStart, fmSplash, fmMain, fmAbout,
fmHelp, fmShowHelp, fmSettings, fmBoot]) then
begin
frmStartInstall := TfrmStartInstall.Create(nil, false);
try
Result := frmStartInstall.ShowModal = mrOk;
finally
frmStartInstall.Free;
end;
end
else if FSilent and ValidateReadyToInstall then
Result := False
else
Result := True;
end;
function ProcessBackgroundUpdate(FMode: TKMShellMode; FSilent: Boolean) : Boolean;
var
BUpdateSM : TUpdateStateMachine;
SendToBUpdateSM: Boolean;
SkipBUpdate : Boolean;
begin
BUpdateSM := TUpdateStateMachine.Create(False);
Result := False;
try
if (FMode = fmBackgroundUpdateCheck) then
begin
BUpdateSM.HandleCheck;
Result := True;
Exit;
end
else if (FMode = fmBackgroundDownload) then
begin
BUpdateSM.HandleDownload;
Result := True;
Exit;
end
else if (FMode = fmApplyInstallNow) then
begin
BUpdateSM.HandleInstallNow;
Result := True;
Exit;
end
else if (FMode = fmInstallKeyboardPackageAdmin) then
begin
BUpdateSM.HandleInstallPackages;
Result := True;
Exit;
end
else
begin
// Since Package upgrade and Keyman upgrade share the installing state
// the presence of the following package related switches means we
// should skip running the update state machine HandleKmShell event
SkipBUpdate := (FMode in [
fmInstallTip, fmInstallTipsForPackages,
fmRegisterTip, fmUpgradeKeyboards,
fmUpgradeMnemonicLayout
]);
SendToBUpdateSM := ShouldSendToBUpdateSM(FSilent, BUpdateSM, FMode);
if SendToBUpdateSM and not SkipBUpdate and (BUpdateSM.HandleKmShell = 1) then
begin
Result := True;
Exit;
end;
end;
finally
BUpdateSM.Free;
end;
end;
end.