git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.jcl@20 c37d764d-f447-7644-a108-883140d013fb
297 lines
10 KiB
ObjectPascal
297 lines
10 KiB
ObjectPascal
{**************************************************************************************************}
|
|
{ }
|
|
{ Project JEDI Code Library (JCL) extension }
|
|
{ }
|
|
{ The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); }
|
|
{ you may not use this file except in compliance with the License. You may obtain a copy of the }
|
|
{ License at http://www.mozilla.org/MPL/ }
|
|
{ }
|
|
{ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF }
|
|
{ ANY KIND, either express or implied. See the License for the specific language governing rights }
|
|
{ and limitations under the License. }
|
|
{ }
|
|
{ The Original Code is JediProfiles.pas. }
|
|
{ }
|
|
{ The Initial Developer of the Original Code is Florent Ouchet. Portions created by Florent Ouchet }
|
|
{ are Copyright (C) of Florent Ouchet. All Rights Reserved. }
|
|
{ }
|
|
{ Contributors: }
|
|
{ }
|
|
{**************************************************************************************************}
|
|
{ }
|
|
{ Core unit to manipulate multiple users' profiles at install time }
|
|
{ }
|
|
{**************************************************************************************************}
|
|
{ }
|
|
{ Last modified: $Date:: 2008-09-09 21:32:17 +0200 (mar., 09 sept. 2008) $ }
|
|
{ Revision: $Rev:: 2461 $ }
|
|
{ Author: $Author:: outchy $ }
|
|
{ }
|
|
{**************************************************************************************************}
|
|
|
|
unit JediProfiles;
|
|
|
|
{$I jcl.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF MSWINDOWS}
|
|
Windows,
|
|
{$ENDIF MSWINDOWS}
|
|
SysUtils,
|
|
Classes,
|
|
JediInstall;
|
|
|
|
type
|
|
{$IFDEF MSWINDOWS}
|
|
TJediProfile = record
|
|
UserName: string;
|
|
SID: string;
|
|
LocalProfile: string;
|
|
UserKey: HKEY;
|
|
CloseKey: Boolean;
|
|
UnloadKey: Boolean;
|
|
end;
|
|
{$ENDIF MSWINDOWS}
|
|
|
|
TJediProfilesManager = class(TInterfacedObject, IJediProfilesManager)
|
|
private
|
|
FMultipleProfileMode: Boolean;
|
|
{$IFDEF MSWINDOWS}
|
|
FProfiles: array of TJediProfile;
|
|
procedure LoadProfiles;
|
|
{$ENDIF MSWINDOWS}
|
|
public
|
|
destructor Destroy; override;
|
|
{ IJediProfileManager }
|
|
function CheckPrerequisites: Boolean;
|
|
function GetMultipleProfileMode: Boolean;
|
|
function GetProfileKey(Index: Integer): LongWord; // HKEY is Windows specific
|
|
function GetProfileCount: Integer;
|
|
function GetProfileName(Index: Integer): string;
|
|
procedure SetMultipleProfileMode(Value: Boolean);
|
|
property MultipleProfileMode: Boolean read GetMultipleProfileMode write SetMultipleProfileMode;
|
|
end;
|
|
|
|
implementation
|
|
|
|
{$IFDEF MSWINDOWS}
|
|
uses
|
|
JclAnsiStrings,
|
|
JclFileUtils,
|
|
JclRegistry,
|
|
JclSecurity,
|
|
JclShell,
|
|
JclSysInfo,
|
|
JclWin32;
|
|
|
|
const
|
|
RegProfileListKey = 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList';
|
|
{$ENDIF MSWINDOWS}
|
|
|
|
//=== { TJediProfileManager } ================================================
|
|
|
|
destructor TJediProfilesManager.Destroy;
|
|
{$IFDEF MSWINDOWS}
|
|
var
|
|
Index: Integer;
|
|
{$ENDIF MSWINDOWS}
|
|
begin
|
|
{$IFDEF MSWINDOWS}
|
|
for Index := Low(FProfiles) to High(FProfiles) do
|
|
begin
|
|
if FProfiles[Index].CloseKey then
|
|
begin
|
|
Windows.RegFlushKey(FProfiles[Index].UserKey);
|
|
Windows.RegCloseKey(FProfiles[Index].UserKey);
|
|
end;
|
|
|
|
if FProfiles[Index].UnloadKey then
|
|
Windows.RegUnLoadKey(HKUS, PChar(FProfiles[Index].SID));
|
|
end;
|
|
SetLength(FProfiles, 0);
|
|
{$ENDIF MSWINDOWS}
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJediProfilesManager.CheckPrerequisites: Boolean;
|
|
{$IFDEF MSWINDOWS}
|
|
var
|
|
InstallGUI: IJediInstallGUI;
|
|
Fork: Boolean;
|
|
Parameters: string;
|
|
Index: Integer;
|
|
{$ENDIF MSWINDOWS}
|
|
begin
|
|
{$IFDEF MSWINDOWS}
|
|
FMultipleProfileMode := FMultipleProfileMode and IsWinNT;
|
|
Result := not FMultipleProfileMode;
|
|
if not Result then
|
|
begin
|
|
Result := IsElevated;
|
|
if not Result then
|
|
begin
|
|
// attempt to fork as an administrator
|
|
InstallGUI := InstallCore.InstallGUI;
|
|
if Assigned(InstallGUI) then
|
|
Fork := InstallGUI.Dialog('Installation requires administrator privilege, do you want to run installer with' +
|
|
' administrator rights?', dtConfirmation, [drYes, drNo]) = drYes
|
|
else
|
|
Fork := True;
|
|
if Fork then
|
|
begin
|
|
Parameters := '';
|
|
for Index := 1 to ParamCount do
|
|
Parameters := Parameters + AnsiQuotedStr(ParamStr(Index), AnsiDoubleQuote);
|
|
ShellExecEx(ParamStr(0), Parameters, 'runas');
|
|
Result := False;
|
|
end
|
|
else
|
|
begin
|
|
// single profile installation for current user
|
|
FMultipleProfileMode := False;
|
|
Result := True;
|
|
end;
|
|
end;
|
|
end;
|
|
if FMultipleProfileMode and Result then
|
|
LoadProfiles;
|
|
{$ENDIF MSWINDOWS}
|
|
{$IFDEF UNIX}
|
|
// don't know how to enumerate profiles on Linux
|
|
Result := not FMultipleProfileMode;
|
|
FMultipleProfileMode := False;
|
|
{$ENDIF UNIX}
|
|
end;
|
|
|
|
function TJediProfilesManager.GetMultipleProfileMode: Boolean;
|
|
begin
|
|
Result := FMultipleProfileMode;
|
|
end;
|
|
|
|
function TJediProfilesManager.GetProfileCount: Integer;
|
|
begin
|
|
{$IFDEF MSWINDOWS}
|
|
if FMultipleProfileMode then
|
|
Result := Length(FProfiles)
|
|
else
|
|
{$ENDIF MSWINDOWS}
|
|
Result := 0;
|
|
end;
|
|
|
|
function TJediProfilesManager.GetProfileKey(Index: Integer): LongWord;
|
|
{$IFDEF MSWINDOWS}
|
|
var
|
|
NtUserFileName: string;
|
|
Key: HKEY;
|
|
{$ENDIF MSWINDOWS}
|
|
begin
|
|
{$IFDEF MSWINDOWS}
|
|
if FMultipleProfileMode then
|
|
begin
|
|
if FProfiles[Index].UserKey = 0 then
|
|
begin
|
|
if AnsiSameText(FProfiles[Index].UserName, GetLocalUserName) then
|
|
FProfiles[Index].UserKey := HKCU
|
|
else
|
|
begin
|
|
NtUserFileName := PathAddSeparator(FProfiles[Index].LocalProfile) + 'NTUSER.DAT';
|
|
if not RegKeyExists(HKUS, '\' + FProfiles[Index].SID) then
|
|
begin
|
|
EnableProcessPrivilege(True, SE_RESTORE_NAME);
|
|
EnableProcessPrivilege(True, SE_BACKUP_NAME);
|
|
if RegLoadKey(HKUS, PChar(FProfiles[Index].SID), PChar(NtUserFileName)) = ERROR_SUCCESS then
|
|
FProfiles[Index].UnloadKey := True
|
|
else
|
|
{$IFDEF COMPILER5}
|
|
RaiseLastWin32Error;
|
|
{$ELSE ~COMPILER5}
|
|
RaiseLastOSError;
|
|
{$ENDIF ~COMPILER5}
|
|
end;
|
|
if RegOpenKey(HKUS, PChar(FProfiles[Index].SID), Key) = ERROR_SUCCESS then
|
|
FProfiles[Index].CloseKey := True
|
|
else
|
|
raise EJclSecurityError.CreateFmt('Unable to load profile for user "%s"', [FProfiles[Index].UserName]);
|
|
FProfiles[Index].UserKey := Key;
|
|
end;
|
|
end;
|
|
Result := FProfiles[Index].UserKey;
|
|
end
|
|
else
|
|
Result := HKCU;
|
|
{$ENDIF MSWINDOWS}
|
|
{$IFDEF LINUX}
|
|
Result := 0;
|
|
{$ENDIF LINUX}
|
|
end;
|
|
|
|
function TJediProfilesManager.GetProfileName(Index: Integer): string;
|
|
begin
|
|
{$IFDEF MSWINDOWS}
|
|
if FMultipleProfileMode then
|
|
Result := FProfiles[Index].UserName
|
|
else
|
|
{$ENDIF MSWINDOWS}
|
|
Result := '';
|
|
end;
|
|
|
|
{$IFDEF MSWINDOWS}
|
|
procedure TJediProfilesManager.LoadProfiles;
|
|
var
|
|
Index: Integer;
|
|
SID: PSID;
|
|
DataSize: Cardinal;
|
|
Name, Domain: WideString;
|
|
KeyName, SIDStr, ProfileDir: string;
|
|
RegProfiles: TStrings;
|
|
begin
|
|
if FMultipleProfileMode then
|
|
begin
|
|
RegProfiles := TStringList.Create;
|
|
try
|
|
GetMem(SID, SECURITY_MAX_SID_SIZE);
|
|
try
|
|
if RegGetKeyNames(HKLM, RegProfileListKey, RegProfiles) then
|
|
for Index := 0 to RegProfiles.Count - 1 do
|
|
begin
|
|
KeyName := RegProfileListKey + '\' + RegProfiles.Strings[Index];
|
|
if RegReadBinaryEx(HKLM, KeyName, 'Sid', SID^, SECURITY_MAX_SID_SIZE, DataSize, False)
|
|
and RegReadStringEx(HKLM, KeyName, 'ProfileImagePath', ProfileDir, False) then
|
|
begin
|
|
try
|
|
SIDStr := SIDToString(SID);
|
|
LookupAccountBySid(SID, Name, Domain);
|
|
if SameText(Domain, GetLocalComputerName) then
|
|
begin
|
|
SetLength(FProfiles, Length(FProfiles) + 1);
|
|
FProfiles[High(FProfiles)].UserName := Name;
|
|
FProfiles[High(FProfiles)].SID := SIDStr;
|
|
FProfiles[High(FProfiles)].LocalProfile := ProfileDir;
|
|
FProfiles[High(FProfiles)].UserKey := 0;
|
|
FProfiles[High(FProfiles)].CloseKey := False;
|
|
FProfiles[High(FProfiles)].UnloadKey := False;
|
|
end;
|
|
except
|
|
// trap deleted accounts
|
|
end;
|
|
end;
|
|
end;
|
|
finally
|
|
FreeMem(SID);
|
|
end;
|
|
finally
|
|
RegProfiles.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
{$ENDIF MSWINDOWS}
|
|
|
|
procedure TJediProfilesManager.SetMultipleProfileMode(Value: Boolean);
|
|
begin
|
|
FMultipleProfileMode := Value;
|
|
end;
|
|
|
|
end.
|