fix(windows): pass basekeyboardid to installation api
Some checks are pending
Keyman Build Summary / Summarize build status checks (push) Waiting to run

The updates all the apis so that the basekeyboardid or klid
can be passed in as an argument. This in needed so that
elevated process required to compile the keyboard has
the call users keyboard base id.
This commit is contained in:
rc-swag 2026-08-31 15:34:45 +10:00
parent 62dd0de786
commit 82fb40002b
13 changed files with 264 additions and 69 deletions

View file

@ -18,9 +18,9 @@ type
FPackage: IKeymanPackageInstalled; const BCP47: string); static;
public
class function BrowseAndInstallKeyboardFromFile(Owner: TComponent): Boolean; static;
class function Execute(KeyboardFileNames: TStrings; const FirstKeyboardFileName: string; FSilent, FNoWelcome: Boolean; const LogFile: string): Boolean; overload; static;
class function Execute(Owner: TComponent; const FileName: string; ASilent, ANoWelcome: Boolean; const LogFile, BCP47: string): Boolean; overload; static;
class function Execute(Owner: TComponent; const FileNames: TStrings; ASilent: Boolean): Boolean; overload; static;
class function Execute(KeyboardFileNames: TStrings; const FirstKeyboardFileName: string; FSilent, FNoWelcome: Boolean; const LogFile: string; BaseKeyboardID: Integer): Boolean; overload; static;
class function Execute(Owner: TComponent; const FileName: string; ASilent, ANoWelcome: Boolean; const LogFile, BCP47: string; BaseKeyboardID: Integer): Boolean; overload; static;
class function Execute(Owner: TComponent; const FileNames: TStrings; ASilent: Boolean; BaseKeyboardID: Integer): Boolean; overload; static;
end;
implementation
@ -35,29 +35,30 @@ uses
Keyman.Configuration.UI.KeymanProtocolHandler,
Keyman.Configuration.UI.MitigationForWin10_1803,
kmint,
KeymanOptionNames,
UfrmHTML,
UfrmInstallKeyboard;
class function TInstallFile.Execute(KeyboardFileNames: TStrings; const FirstKeyboardFileName: string; FSilent, FNoWelcome: Boolean;
const LogFile: string): Boolean;
const LogFile: string; BaseKeyboardID: Integer): Boolean;
begin
if TKeymanProtocolHandler.CanHandle(FirstKeyboardFileName) then
begin
Result := TKeymanProtocolHandler.Handle(nil, FirstKeyboardFileName, FSilent, FNoWelcome, LogFile);
Result := TKeymanProtocolHandler.Handle(nil, FirstKeyboardFileName, FSilent, FNoWelcome, LogFile, BaseKeyboardID);
end
else if (KeyboardFileNames.Count > 1) or (Pos('=', FirstKeyboardFileName) > 0) then
begin
Result := TInstallFile.Execute(nil, KeyboardFileNames, FSilent)
Result := TInstallFile.Execute(nil, KeyboardFileNames, FSilent, BaseKeyboardID)
end
// TODO: support bare package ids from command line (if it does not include a file extension, assume it is a .kmp and try and download it)
// else if IsNotPackageOrKeyboardFile then
else
begin
Result := TInstallFile.Execute(nil, FirstKeyboardFileName, FSilent, FNoWelcome, LogFile, '');
Result := TInstallFile.Execute(nil, FirstKeyboardFileName, FSilent, FNoWelcome, LogFile, '', BaseKeyboardID);
end;
end;
class function TInstallFile.Execute(Owner: TComponent; const FileName: string; ASilent, ANoWelcome: Boolean; const LogFile, BCP47: string): Boolean;
class function TInstallFile.Execute(Owner: TComponent; const FileName: string; ASilent, ANoWelcome: Boolean; const LogFile, BCP47: string; BaseKeyboardID: Integer): Boolean;
var
n: Integer;
InstalledKeyboards: array of IKeymanKeyboardInstalled;
@ -77,7 +78,7 @@ begin
begin
if ASilent then
begin
InstallKeyboard(LogFile, BCP47);
InstallKeyboard(LogFile, BCP47, BaseKeyboardID);
Result := True;
end
else
@ -139,7 +140,7 @@ end;
/// This is the handler for the `-i` parameter, e.g.
/// kmshell -i khmer_angkor.kmp c:\temp\sil_euro_latin.kmp=fr
/// </summary>
class function TInstallFile.Execute(Owner: TComponent; const FileNames: TStrings; ASilent: Boolean): Boolean;
class function TInstallFile.Execute(Owner: TComponent; const FileNames: TStrings; ASilent: Boolean; BaseKeyboardID: Integer): Boolean;
var
i, j: Integer;
FPackage: IKeymanPackageInstalled;
@ -170,7 +171,7 @@ begin
end;
if IsPackage then
begin
FPackage := (kmcom.Packages as IKeymanPackagesInstalled2).Install2(FileName, True);
FPackage := (kmcom.Packages as IKeymanPackagesInstalled3).Install3(FileName, True, BaseKeyboardID);
if Length(FilenameBCP47) > 1
then RegisterKeyboardPackageLanguage(FPackage, FilenameBCP47[1])
else RegisterKeyboardPackageLanguage(FPackage, '');
@ -178,7 +179,7 @@ begin
end
else
begin
FKeyboard := (kmcom.Keyboards as IKeymanKeyboardsInstalled2).Install2(FileName, True);
FKeyboard := (kmcom.Keyboards as IKeymanKeyboardsInstalled3).Install3(FileName, True, BaseKeyboardID);
if (Length(FilenameBCP47) > 1) and (Trim(FilenameBCP47[1]) <> '')
then BCP47Tag := FilenameBCP47[1]
else BCP47Tag := TTIPMaintenance.GetFirstLanguage(FKeyboard);
@ -209,6 +210,7 @@ end;
class function TInstallFile.BrowseAndInstallKeyboardFromFile(Owner: TComponent): Boolean;
var
dlgOpen: TOpenDialog;
BaseKeyboardID : Integer;
begin
dlgOpen := TOpenDialog.Create(nil);
try
@ -216,9 +218,9 @@ begin
'Keyman files (*.kmx, *.kxx, *.kmp)|*.kmx;*.kxx;*.kmp|Keyman keyboards (*.kmx,*.kxx)' +
'|*.kmx;*.kxx|Keyman packages (*.kmp)|*.kmp|All files (*.*)|*.*';
dlgOpen.Title := 'Install Keyman Keyboard';
BaseKeyboardID := kmcom.Options[KeymanOptionName(koBaseLayout)].Value;
if dlgOpen.Execute then
Result := Execute(Owner, dlgOpen.FileName, False, False, '', '')
Result := Execute(Owner, dlgOpen.FileName, False, False, '', '', BaseKeyboardID)
else
Result := False;
finally

View file

@ -17,13 +17,13 @@ type
FDownloadURL: string;
frmDownloadProgress: TfrmDownloadProgress;
function DoHandle(Owner: TComponent; const url: string; ASilent,
ANoWelcome: Boolean; const ALogFile: string): Boolean;
ANoWelcome: Boolean; const ALogFile: string; BaseKeyboardID: Integer): Boolean;
procedure DoDownload(AOwner: TfrmDownloadProgress; var Result: Boolean);
procedure HttpReceiveData(const Sender: TObject; AContentLength,
AReadCount: Int64; var Abort: Boolean);
public
class function CanHandle(const url: string): Boolean; static;
class function Handle(Owner: TComponent; const url: string; ASilent, ANoWelcome: Boolean; const ALogFile: string): Boolean; static;
class function Handle(Owner: TComponent; const url: string; ASilent, ANoWelcome: Boolean; const ALogFile: string; BaseKeyboardID: Integer): Boolean; static;
end;
implementation
@ -51,13 +51,13 @@ end;
class function TKeymanProtocolHandler.Handle(Owner: TComponent;
const url: string; ASilent, ANoWelcome: Boolean;
const ALogFile: string): Boolean;
const ALogFile: string; BaseKeyboardID: Integer): Boolean;
var
h: TKeymanProtocolHandler;
begin
h := TKeymanProtocolHandler.Create;
try
Result := h.DoHandle(Owner, url, ASilent, ANoWelcome, ALogFile);
Result := h.DoHandle(Owner, url, ASilent, ANoWelcome, ALogFile, BaseKeyboardID);
finally
h.Free;
end;
@ -65,7 +65,7 @@ end;
function TKeymanProtocolHandler.DoHandle(Owner: TComponent;
const url: string; ASilent, ANoWelcome: Boolean;
const ALogFile: string): Boolean;
const ALogFile: string; BaseKeyboardID: Integer): Boolean;
var
FTempDir: string;
PackageID, BCP47: string;
@ -98,7 +98,7 @@ begin
end;
// TODO: this makes a circular dependency, refactor it out!
Result := TInstallFile.Execute(nil, FDownloadFilename, False, False, '', BCP47);
Result := TInstallFile.Execute(nil, FDownloadFilename, False, False, '', BCP47, BaseKeyboardID);
finally
if FileExists(FDownloadFilename) then

View file

@ -74,6 +74,7 @@ uses
Vcl.StdCtrls,
keymanapi_TLB,
KeymanOptionNames,
UfrmKeymanBase,
UfrmWebContainer;
@ -102,7 +103,7 @@ type
protected
procedure FireCommand(const command: WideString; params: TStringList); override;
public
procedure InstallKeyboard(const ALogFile, BCP47Tag: string);
procedure InstallKeyboard(const ALogFile, BCP47Tag: string; BaseKeyboardID: Integer);
property DefaultBCP47Tag: string read FDefaultBCP47Tag write SetDefaultBCP47Tag;
property InstallFile: string read FInstallFile write SetInstallFile;
property Silent: Boolean read FSilent write FSilent;
@ -271,6 +272,7 @@ end;
procedure TfrmInstallKeyboard.FireCommand(const command: WideString; params: TStringList);
var
BCP47Tag: string;
BaseKeyboardID :Integer;
begin
BCP47Tag := '';
if (command = 'keyboard_install') and kmcom.SystemInfo.IsAdministrator then // I4172
@ -283,7 +285,8 @@ begin
Manager.Title := 'Installing Keyboard';
Manager.CanCancel := False;
Manager.UpdateProgress('Installing Keyboard', 0, 0);
InstallKeyboard('', BCP47Tag);
BaseKeyboardID := kmcom.Options[KeymanOptionName(koBaseLayout)].Value;
InstallKeyboard('', BCP47Tag, BaseKeyboardID);
Result := True;
end
);
@ -299,6 +302,7 @@ begin
var
t: TTempFile;
ExecParams: string;
BaseKeyboardString :string;
begin
KL.MethodEnter(Self, '"keyboard_install"', [params.Text]);
try
@ -306,8 +310,9 @@ begin
Manager.CanCancel := False;
Manager.UpdateProgress('Installing Keyboard', 0, 0);
t := TTempFileManager.Get('.log');
BaseKeyboardString := IntToHex(kmcom.Options[KeymanOptionName(koBaseLayout)].Value, 8);
try
ExecParams := '-log "'+t.Name+'" -s -i "'+FInstallFile+'='+BCP47Tag+'"'+
ExecParams := '-log "'+t.Name+'" -bkd "'+BaseKeyboardString+'" -s -i "'+FInstallFile+'='+BCP47Tag+'"'+
' -nowelcome '+TTIPMaintenance.GetUserDefaultLangParameterString;
KL.Log('Calling elevated kmshell %s', [ExecParams]);
if WaitForElevatedConfiguration(GetForegroundWindow, ExecParams) = 0 then
@ -358,7 +363,7 @@ end;
------------------------------------------------------------------------------}
// TODO: move this to TInstallFile
procedure TfrmInstallKeyboard.InstallKeyboard(const ALogFile, BCP47Tag: string);
procedure TfrmInstallKeyboard.InstallKeyboard(const ALogFile, BCP47Tag: string; BaseKeyboardID: Integer);
var
i: Integer;
kbd: IKeymanKeyboardInstalled;
@ -400,7 +405,7 @@ begin
kbd := nil;
kmcom.Keyboards.Apply;
kmcom.Keyboards.Refresh;
FInstalledKeyboard := (FKeyboard as IKeymanKeyboardFile2).Install2(True);
FInstalledKeyboard := (FKeyboard as IKeymanKeyboardFile3).Install3(True, BaseKeyboardID);
if not InstallTipForKeyboard(BCP47Tag) then
begin
// TODO can we return a failure code?
@ -461,7 +466,7 @@ begin
kmcom.Keyboards.Apply;
kmcom.Keyboards.Refresh; // I2169
(FPackage as IKeymanPackageFile2).Install2(True);
(FPackage as IKeymanPackageFile3).Install3(True, BaseKeyboardID);
kmcom.Refresh;

View file

@ -87,6 +87,7 @@ uses
Keyman.Configuration.UI.InstallFile,
Keyman.System.LocaleStrings,
kmint,
KeymanOptionNames,
MessageIdentifierConsts,
Upload_Settings,
utilfiletypes,
@ -213,6 +214,7 @@ end;
procedure TfrmInstallKeyboardFromWeb.DownloadAndInstallPackage(const PackageID, BCP47: string);
var
FTempDir: string;
BaseKeyboardID: Integer;
begin
FTempDir := IncludeTrailingPathDelimiter(CreateTempPath); // I1679
try
@ -230,8 +232,8 @@ begin
finally
frmDownloadProgress.Free;
end;
if TInstallFile.Execute(Self, FDownloadFilename, False, False, '', BCP47) then
BaseKeyboardID := kmcom.Options[KeymanOptionName(koBaseLayout)].Value;
if TInstallFile.Execute(Self, FDownloadFilename, False, False, '', BCP47, BaseKeyboardID) then
ModalResult := mrOk;
finally

View file

@ -206,7 +206,7 @@ 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 FParentWindow: THandle; var FDefaultBCP47: string; var FDefaultLangID, FBaseKeyboard: Integer): Boolean;
var
s: string;
i: Integer;
@ -263,6 +263,7 @@ begin
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 = 'bkd' then begin Inc(i); FBaseKeyboard := ParamStr(i); end
else if s = '-mcompilekbds' then
begin
FMode := fmMCompileKbds;
@ -329,7 +330,7 @@ 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;
const FDefaultBCP47: string; FDefaultLangID, FBaseKeyboard: Integer); forward;
procedure Run;
var
@ -340,7 +341,7 @@ var
FForce: Boolean;
FParentWindow: THandle;
FLogFile: string;
FDefaultLangID: Integer;
FDefaultLangID, FBaseKeyboard: Integer;
FDefaultBCP47, FDisablePackages, FDefaultUILanguage: string;
FStartWithConfiguration: Boolean;
begin
@ -349,7 +350,7 @@ begin
KeyboardFileNames := TStringList.Create;
try
FParentWindow := 0;
if not Init(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID) then
if not Init(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID, FBaseKeyboard) then
begin
//TODO: TUtilExecute.Shell(PChar('hh.exe mk:@MSITStore:'+ExtractFilePath(KMShellExe)+'keyman.chm::/context/keyman_usage.html'), SW_SHOWNORMAL);
Exit;
@ -357,7 +358,7 @@ begin
if not LoadKMCOM then Exit;
try
RunKMCOM(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID);
RunKMCOM(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID, FBaseKeyboard);
finally
kmcom := nil;
end;
@ -396,7 +397,7 @@ 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);
FParentWindow: THandle; const FDefaultBCP47: string; FDefaultLangID, FBaseKeyboard: Integer);
var
kdl: IKeymanDefaultLanguage;
FIcon: string;
@ -559,7 +560,7 @@ begin
else ExitCode := 1;
fmInstall:
if TInstallFile.Execute(KeyboardFileNames, FirstKeyboardFileName, FSilent, FNoWelcome, FLogFile)
if TInstallFile.Execute(KeyboardFileNames, FirstKeyboardFileName, FSilent, FNoWelcome, FLogFile, FBaseKeyboard)
then ExitCode := 0
else ExitCode := 1;

View file

@ -37,7 +37,7 @@ uses
keymankeyboard, keymancontext, Classes, PackageInfo, keymankeyboardlanguagesfile;
type
TKeymanKeyboardFile = class(TKeymanKeyboard, IKeymanKeyboardFile, IKeymanKeyboardFile2)
TKeymanKeyboardFile = class(TKeymanKeyboard, IKeymanKeyboardFile, IKeymanKeyboardFile2, IKeymanKeyboardFile3)
private
FFileName: WideString;
FError: Boolean;
@ -52,6 +52,7 @@ type
{ IKeymanKeyboardFile }
procedure Install(Force: WordBool); safecall;
function Install2(Force: WordBool): IKeymanKeyboardInstalled; safecall;
function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; safecall;
{ IKeymanKeyboard }
function Get_Copyright: WideString; override; safecall;
@ -252,7 +253,7 @@ procedure TKeymanKeyboardFile.Install(Force: WordBool);
begin
with TKPInstallKeyboard.Create(Context) do
try
Execute(FFileName, '', [ikLegacyRegisterAndInstallProfiles], nil, Force);
Execute(FFileName, '', [ikLegacyRegisterAndInstallProfiles], nil, Force, 0);
finally
Free;
end;
@ -264,7 +265,23 @@ var
begin
with TKPInstallKeyboard.Create(Context) do
try
Execute(FFileName, '', [], nil, Force);
Execute(FFileName, '', [], nil, Force, 0);
finally
Free;
end;
kki := Context.Keyboards as IKeymanKeyboardsInstalled;
kki.Refresh;
Result := kki.Items[FFileName];
end;
function TKeymanKeyboardFile.Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled;
var
kki: IKeymanKeyboardsInstalled;
begin
with TKPInstallKeyboard.Create(Context) do
try
Execute(FFileName, '', [], nil, Force, BaseKeyboardID);
finally
Free;
end;

View file

@ -37,7 +37,8 @@ uses
keymanerrorcodes, keymankeyboardinstalled, keymankeyboard, internalinterfaces;
type
TKeymanKeyboardsInstalled = class(TKeymanAutoCollectionObject, IKeymanKeyboardsInstalled, IKeymanKeyboardsInstalled2, IIntKeymanKeyboardsInstalled) // I4376
TKeymanKeyboardsInstalled = class(TKeymanAutoCollectionObject, IKeymanKeyboardsInstalled,
IKeymanKeyboardsInstalled2, IIntKeymanKeyboardsInstalled, IKeymanKeyboardsInstalled3) // I4376
private
FKeyboards: TKeyboardList;
procedure TriggerWindowsLanguageSync;
@ -55,6 +56,7 @@ type
procedure Install(const Filename: WideString; Force: WordBool); safecall;
procedure Apply; safecall;
function Install2(const Filename: WideString; Force: WordBool): IKeymanKeyboardInstalled; safecall;
function Install3(const Filename: WideString; Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; safecall;
procedure RefreshInstalledKeyboards; safecall;
{ IIntKeymanKeyboardsInstalled }
@ -101,7 +103,7 @@ procedure TKeymanKeyboardsInstalled.Install(const Filename: WideString; Force: W
begin
with TKPInstallKeyboard.Create(Context) do
try
Execute(FileName, '', [ikLegacyRegisterAndInstallProfiles], nil, Force);
Execute(FileName, '', [ikLegacyRegisterAndInstallProfiles], nil, Force, 0);
finally
Free;
end;
@ -112,7 +114,21 @@ function TKeymanKeyboardsInstalled.Install2(const Filename: WideString;
begin
with TKPInstallKeyboard.Create(Context) do
try
Execute(FileName, '', [], nil, Force);
Execute(FileName, '', [], nil, Force, 0);
finally
Free;
end;
DoRefresh;
Result := Get_Items(FileName);
end;
function TKeymanKeyboardsInstalled.Install3(const Filename: WideString;
Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled;
begin
with TKPInstallKeyboard.Create(Context) do
try
Execute(FileName, '', [], nil, Force, BaseKeyboardID);
finally
Free;
end;

View file

@ -1,18 +1,18 @@
(*
Name: keymanpackagefile
Copyright: Copyright (C) SIL International.
Documentation:
Description:
Documentation:
Description:
Create Date: 20 Jun 2006
Modified Date: 29 Mar 2010
Authors: mcdurdin
Related Files:
Dependencies:
Related Files:
Dependencies:
Bugs:
Todo:
Notes:
Bugs:
Todo:
Notes:
History: 20 Jun 2006 - mcdurdin - Initial version
01 Aug 2006 - mcdurdin - Avoid processmessages in unzip
04 Dec 2006 - mcdurdin - Add Serialize function, support ShortcutRootPath in installation
@ -37,7 +37,7 @@ uses
keymanpackagecontentfiles, StdVcl, kmpinffile, KeymanContext, Graphics, Classes, internalinterfaces;
type
TKeymanPackageFile = class(TKeymanAutoObject, IKeymanPackage, IKeymanPackageFile, IKeymanPackageFile2)
TKeymanPackageFile = class(TKeymanAutoObject, IKeymanPackage, IKeymanPackageFile, IKeymanPackageFile2, IKeymanPackageFile3)
private
FSourcePath: string;
FSubFiles: IKeymanPackageContentFiles;
@ -74,6 +74,7 @@ type
{ IKeymanPackageFile }
procedure Install(Force: WordBool); safecall;
function Install2(Force: WordBool): IKeymanPackageInstalled; safecall;
function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; safecall;
public
constructor Create(AContext: TKeymanContext; const Filename: Widestring);
destructor Destroy; override;
@ -175,7 +176,7 @@ begin
o := [ipLegacyRegisterAndInstallProfiles];
if Force then
Include(o, ipForce);
Execute(FFileName, o);
Execute(FFileName, o, 0);
finally
Free;
end;
@ -191,7 +192,27 @@ begin
o := [];
if Force then
Include(o, ipForce);
Execute(FFileName, o);
Execute(FFileName, o, 0);
finally
Free;
end;
kpi := Context.Packages as IKeymanPackagesInstalled;
kpi.Refresh;
Result := kpi.Items[FFileName];
end;
function TKeymanPackageFile.Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled;
var
o: TKPInstallPackageOptions;
kpi: IKeymanPackagesInstalled;
begin
with TKPInstallPackage.Create(Context) do
try
o := [];
if Force then
Include(o, ipForce);
Execute(FFileName, o, BaseKeyboardID);
finally
Free;
end;
@ -211,7 +232,7 @@ var
begin
if not FileExists(FFileName) then
raise Exception.Create('File '+FFileName+' does not exist.');
if GetTempPath(260, buf) = 0 then
raise Exception.Create('Unable to get temporary path: ' + IntToHex(GetLastError, 8) + ' ' + SysErrorMessage(GetLastError));
FTempOutPath := buf;

View file

@ -38,7 +38,8 @@ type
property Items[Index: Integer]: IIntKeymanPackageInstalled read GetItem write SetItem; default;
end;
TKeymanPackagesInstalled = class(TKeymanAutoCollectionObject, IKeymanPackagesInstalled, IKeymanPackagesInstalled2)
TKeymanPackagesInstalled = class(TKeymanAutoCollectionObject,
IKeymanPackagesInstalled, IKeymanPackagesInstalled2, IKeymanPackagesInstalled3)
private
FPackages: TPackageList;
protected
@ -51,6 +52,7 @@ type
function IndexOf(const ID: WideString): Integer; safecall;
procedure Install(const Filename: WideString; Force: WordBool); safecall;
function Install2(const Filename: WideString; Force: WordBool): IKeymanPackageInstalled; safecall;
function Install3(const Filename: WideString; Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; safecall;
public
constructor Create(AContext: TKeymanContext);
destructor Destroy; override;
@ -118,7 +120,7 @@ begin
o := [ipLegacyRegisterAndInstallProfiles];
if Force then
Include(o, ipForce);
Execute(Filename, o);
Execute(Filename, o, 0);
finally
Free;
end;
@ -136,7 +138,29 @@ begin
o := [];
if Force then
Include(o, ipForce);
Execute(Filename, o);
Execute(Filename, o, 0);
finally
Free;
end;
DoRefresh;
Result := Get_Items(Filename);
KL.MethodExit(Self, 'Install2');
end;
function TKeymanPackagesInstalled.Install3(const Filename: WideString;
Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled;
var
o: TKPInstallPackageOptions;
begin
KL.MethodEnter(Self, 'Install2', [Filename, Force]);
with TKPInstallPackage.Create(Context) do
try
o := [];
if Force then
Include(o, ipForce);
Execute(Filename, o, BaseKeyboardID);
finally
Free;
end;

View file

@ -1569,6 +1569,17 @@ type
procedure RefreshInstalledKeyboards; safecall;
end;
// *********************************************************************//
// Interface: IKeymanKeyboardsInstalled3
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}
// *********************************************************************//
IKeymanKeyboardsInstalled3 = interface(IKeymanKeyboardsInstalled)
['{B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641}']
function Install3(const Filename: WideString; Force: WordBool; BasePackageID: Integer): IKeymanKeyboardInstalled; safecall;
procedure RefreshInstalledKeyboards; safecall;
end;
// *********************************************************************//
// Interface: IKeymanKeyboardInstalled2
// Flags: (4416) Dual OleAutomation Dispatchable
@ -1610,6 +1621,16 @@ type
function Install2(const Filename: WideString; Force: WordBool): IKeymanPackageInstalled; safecall;
end;
// *********************************************************************//
// Interface: IKeymanPackagesInstalled3
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458}
// *********************************************************************//
IKeymanPackagesInstalled3 = interface(IKeymanPackagesInstalled)
['{3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458}']
function Install3(const Filename: WideString; Force: WordBool; BasePackageID: Integer): IKeymanPackageInstalled; safecall;
end;
// *********************************************************************//
// DispIntf: IKeymanPackagesInstalled2Disp
// Flags: (4416) Dual OleAutomation Dispatchable
@ -1639,6 +1660,16 @@ type
function Install2(Force: WordBool): IKeymanKeyboardInstalled; safecall;
end;
// *********************************************************************//
// Interface: IKeymanKeyboardFile3
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {EDE4326B-51F4-42D5-8251-B20B71993EC8}
// *********************************************************************//
IKeymanKeyboardFile3 = interface(IKeymanKeyboardFile)
['{8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4}']
function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanKeyboardInstalled; safecall;
end;
// *********************************************************************//
// DispIntf: IKeymanKeyboardFile2Disp
// Flags: (4416) Dual OleAutomation Dispatchable
@ -1677,6 +1708,17 @@ type
function Install2(Force: WordBool): IKeymanPackageInstalled; safecall;
end;
// *********************************************************************//
// Interface: IKeymanPackageFile3
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}
// *********************************************************************//
IKeymanPackageFile3 = interface(IKeymanPackageFile)
['{C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7}']
function Install3(Force: WordBool; BaseKeyboardID: Integer): IKeymanPackageInstalled; safecall;
end;
// *********************************************************************//
// DispIntf: IKeymanPackageFile2Disp
// Flags: (4416) Dual OleAutomation Dispatchable

View file

@ -66,6 +66,10 @@ library keymanapi
interface IKeymanPackageFile2;
interface IKeymanKeyboardLanguageInstalled2;
interface IKeymanKeyboardLanguagesInstalled2;
interface IKeymanKeyboardFile3;
interface IKeymanPackageFile3;
interface IKeymanKeyboardsInstalled3;
interface IKeymanPackagesInstalled3;
interface IKeymanBCP47Canonicalization;
interface IKeymanDefaultLanguage;
@ -976,6 +980,60 @@ library keymanapi
HRESULT _stdcall Install2([in] VARIANT_BOOL Force, [out, retval] IKeymanKeyboardInstalled** KeyboardResult);
};
[
uuid(8F4B2D91-6C37-4A05-BE82-1D9F7C53A6E4),
version(19.0),
helpstring("http://help.keyman.com/developer/engine/desktop/19.0/api/IKeymanKeyboardFile3"),
dual,
oleautomation
]
interface IKeymanKeyboardFile3: IKeymanKeyboardFile
{
[id(0x00000121)]
HRESULT _stdcall Install3([in] VARIANT_BOOL Force, [in] long BaseKeyboardID, [out, retval] IKeymanKeyboardInstalled** KeyboardResult);
};
[
uuid(C27A6E4B-9D13-47F8-A052-6B8E31D4F9C7),
version(19.0),
helpstring("http://help.keyman.com/developer/engine/desktop/19.0/api/IKeymanPackageFile3"),
dual,
oleautomation
]
interface IKeymanPackageFile3: IKeymanPackageFile
{
[id(0x00000124)]
HRESULT _stdcall Install3([in] VARIANT_BOOL Force, [in] long BaseKeyboardID, [out, retval] IKeymanPackageFile** Package);
};
[
uuid(B7D3A8F1-6C42-4E95-AB17-93F0C2D8E641),
version(19.0),
helpstring("https://help.keyman.com/developer/engine/windows/19.0/api/IKeymanKeyboardInstalled2\3"),
dual,
oleautomation
]
interface IKeymanKeyboardsInstalled3: IKeymanKeyboardsInstalled
{
[id(0x00000122)]
HRESULT _stdcall Install3([in] BSTR Filename, [in] VARIANT_BOOL Force, [in] long BaseKeyboardID, [out, retval] IKeymanKeyboardInstalled** KeyboardResult);
};
[
uuid(3F8C2D71-94A6-4B0E-87D5-C1E3A9F62458),
version(19.0),
helpstring("http://help.keyman.com/developer/engine/desktop/19.0/api/IKeymanPackagesInstalled3"),
dual,
oleautomation
]
interface IKeymanPackagesInstalled3: IKeymanPackagesInstalled
{
[id(0x00000123)]
HRESULT _stdcall Install3([in] BSTR Filename, [in] VARIANT_BOOL Force, [in] long BaseKeyboardID, [out, retval] IKeymanPackageInstalled** PackageResult);
};
[
uuid(9B43B6BC-C622-47EF-915E-6780CF53BAAA),
version(14.0),

View file

@ -64,7 +64,7 @@ type
ikLegacyRegisterAndInstallProfiles);
TKPInstallKeyboard = class(TKPBase)
procedure Execute(const FileName, PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; Languages: TPackageKeyboardLanguageList; Force: Boolean);
procedure Execute(const FileName: string; const PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; Languages: TPackageKeyboardLanguageList; Force: Boolean; BaseKeyboardID: Integer);
procedure RegisterProfiles(const FileName, PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; PackageLanguageMetadata: TPackageKeyboardLanguageList);
private
procedure LegacyRegisterAndInstallLanguageProfile(Langs: array of Integer;
@ -112,7 +112,7 @@ uses
utiltsf,
keymanapi_TLB;
procedure TKPInstallKeyboard.Execute(const FileName, PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; Languages: TPackageKeyboardLanguageList; Force: Boolean);
procedure TKPInstallKeyboard.Execute(const FileName: string; const PackageID: string; FInstallOptions: TKPInstallKeyboardOptions; Languages: TPackageKeyboardLanguageList; Force: Boolean; BaseKeyboardID: Integer);
var
ki: TKeyboardInfo;
FDestPath: string;
@ -125,7 +125,9 @@ var
FExitCode: Integer;
FKVKName: WideString;
FCreatedIcon: Boolean;
BaseKeyboardID: Integer;
ElevatedBaseKeyboardID: Integer;
KeymanContext: TKeymanContext;
RecompileMnemonicKeyboard: TKPRecompileMnemonicKeyboard;
begin
KL.MethodEnter(Self, 'Execute', [FileName,PackageID,ikPartOfPackage in FInstallOptions ,Force]);
try
@ -246,14 +248,19 @@ begin
KL.Log(FLogText);
end;
// Recompile a mnemonic layout to the user's selected base layout
// Recompile a mnemonic layout to the user's selected base layout. If
// the baselayout has not been passed through (=0) then use the current
// process configured value which is likely the Admin user
if ki.MnemonicLayout then // I4169
begin
with Context as TKeymanContext do
BaseKeyboardID := (Options as IKeymanOptions).Items['koBaseLayout'].Value;
with TKPRecompileMnemonicKeyboard.Create(Context) do
KeymanContext := Context as TKeymanContext;
ElevatedBaseKeyboardID := (KeymanContext.Options as IKeymanOptions).Items['koBaseLayout'].Value;
RecompileMnemonicKeyboard := TKPRecompileMnemonicKeyboard.Create(Context);
try
Execute(FDestFileName, PackageID, BaseKeyboardID);
if (BaseKeyboardID = 0) then
RecompileMnemonicKeyboard.Execute(FDestFileName, PackageID, ElevatedBaseKeyboardID)
else
RecompileMnemonicKeyboard.Execute(FDestFileName, PackageID, BaseKeyboardID);
finally
Free;
end;

View file

@ -50,7 +50,7 @@ type
TKPInstallPackage = class(TKPBase)
public
procedure Execute(const FileName: string; Options: TKPInstallPackageOptions);
procedure Execute(const FileName: string; Options: TKPInstallPackageOptions; BaseKeyboardID: Integer);
end;
implementation
@ -85,7 +85,7 @@ uses
{ TKPInstallPackage }
procedure TKPInstallPackage.Execute(const FileName: string; Options: TKPInstallPackageOptions);
procedure TKPInstallPackage.Execute(const FileName: string; Options: TKPInstallPackageOptions; BaseKeyboardID: Integer);
function GetHHIcon: string;
var
buf: array[0..260] of char;
@ -112,7 +112,7 @@ var
FErrorValue: Cardinal;
FSrcFileName: string;
procedure InstallKeyboard(FileName: string);
procedure InstallKeyboard(FileName: string; BaseKeyboardID: Integer);
var
FOptions: TKPInstallKeyboardOptions;
kbd: TPackageKeyboard;
@ -132,7 +132,7 @@ var
with TKPInstallKeyboard.Create(Context) do
try
Execute(FileName, PackageName, FOptions, FLanguages, ipForce in Options);
Execute(FileName, PackageName, FOptions, FLanguages, ipForce in Options, BaseKeyboardID);
finally
Free;
end;
@ -253,12 +253,12 @@ begin
begin
case inf.Files[i].FileType of
ftKeymanFile:
InstallKeyboard(dest + inf.Files[i].FileName);
InstallKeyboard(dest + inf.Files[i].FileName, BaseKeyboardID);
ftPackageFile:
with TKPInstallPackage.Create(Context) do
try
Execute(dest + inf.Files[i].FileName, Options);
Execute(dest + inf.Files[i].FileName, Options, BaseKeyboardID);
finally
Free;
end;