Merge branch 'novista'. Did a few final tweaks during merge.

This commit is contained in:
Martijn Laan 2024-04-02 12:17:05 +02:00
commit 91b75da1e2
73 changed files with 725 additions and 3221 deletions

View File

@ -23,7 +23,7 @@ interface
!!!! Not all special cases have been implemented in WriteRegRef(). !!!! Not all special cases have been implemented in WriteRegRef().
} }
uses Sysutils, windows, classes, contnrs; uses Sysutils, Windows, Classes, Contnrs;
type type
TModMode = (mmNaked, mmDeref, mmDisp8, mmDisp32); TModMode = (mmNaked, mmDeref, mmDisp8, mmDisp32);

View File

@ -2,7 +2,7 @@ unit FolderTreeView;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2018 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -24,7 +24,6 @@ type
private private
FDestroyingHandle: Boolean; FDestroyingHandle: Boolean;
FDirectory: String; FDirectory: String;
FFriendlyTree: Boolean;
FItemExpanding: Boolean; FItemExpanding: Boolean;
FOnChange: TNotifyEvent; FOnChange: TNotifyEvent;
FOnRename: TFolderRenameEvent; FOnRename: TFolderRenameEvent;
@ -329,34 +328,6 @@ begin
end; end;
end; end;
function UseFriendlyTree: Boolean;
{ Returns True if running Windows XP or 2003 and the "Display simple folder
view" option in Explorer is enabled (by default, it is).
Note: Windows Vista also has this option, but regardless of how it is set,
folders never expand with a single click in Explorer. So on Vista and later,
False is always returned. }
var
Ver: Word;
K: HKEY;
Typ, Value, Size: DWORD;
begin
Ver := Word(GetVersion);
if (Lo(Ver) = 5) and (Hi(Ver) >= 1) then begin
Result := True;
if RegOpenKeyEx(HKEY_CURRENT_USER,
'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced',
0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin
Size := SizeOf(Value);
if (RegQueryValueEx(K, 'FriendlyTree', nil, @Typ, @Value, @Size) = ERROR_SUCCESS) and
(Typ = REG_DWORD) and (Size = SizeOf(Value)) then
Result := (Value <> 0);
RegCloseKey(K);
end;
end
else
Result := False;
end;
{ TCustomFolderTreeView } { TCustomFolderTreeView }
type type
@ -377,8 +348,6 @@ begin
Height := 97; Height := 97;
ParentColor := False; ParentColor := False;
TabStop := True; TabStop := True;
if Lo(GetVersion) < 6 then
Cursor := crArrow; { prevent hand cursor from appearing in TVS_TRACKSELECT mode }
if SystemParametersInfo(SPI_GETICONTITLELOGFONT, SizeOf(LogFont), @LogFont, 0) then if SystemParametersInfo(SPI_GETICONTITLELOGFONT, SizeOf(LogFont), @LogFont, 0) then
Font.Handle := CreateFontIndirect(LogFont); Font.Handle := CreateFontIndirect(LogFont);
end; end;
@ -394,15 +363,7 @@ begin
with Params do begin with Params do begin
Style := Style or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or TVS_LINESATROOT or Style := Style or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or TVS_LINESATROOT or
TVS_HASBUTTONS or TVS_SHOWSELALWAYS or TVS_EDITLABELS; TVS_HASBUTTONS or TVS_SHOWSELALWAYS or TVS_EDITLABELS;
FFriendlyTree := UseFriendlyTree; Style := Style or TVS_TRACKSELECT;
if FFriendlyTree then
Style := Style or TVS_TRACKSELECT or TVS_SINGLEEXPAND
else begin
if Lo(GetVersion) >= 6 then
Style := Style or TVS_TRACKSELECT
else
Style := Style or TVS_HASLINES;
end;
ExStyle := ExStyle or WS_EX_CLIENTEDGE; ExStyle := ExStyle or WS_EX_CLIENTEDGE;
WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW); WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
end; end;
@ -420,8 +381,8 @@ begin
if csDesigning in ComponentState then if csDesigning in ComponentState then
Exit; Exit;
{ On Vista, enable the new Explorer-style look } { Enable the new Explorer-style look }
if (Lo(GetVersion) >= 6) and Assigned(SetWindowTheme) then begin if Assigned(SetWindowTheme) then begin
SetWindowTheme(Handle, 'Explorer', nil); SetWindowTheme(Handle, 'Explorer', nil);
{ Like Explorer, enable double buffering to avoid flicker when the mouse { Like Explorer, enable double buffering to avoid flicker when the mouse
is moved across the items } is moved across the items }
@ -489,7 +450,7 @@ end;
procedure TCustomFolderTreeView.WMEraseBkgnd(var Message: TWMEraseBkgnd); procedure TCustomFolderTreeView.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin begin
{ For TVS_EX_DOUBLEBUFFER to be truly flicker-free on Vista, we must use { For TVS_EX_DOUBLEBUFFER to be truly flicker-free, we must use
comctl32's default WM_ERASEBKGND handling, not the VCL's (which calls comctl32's default WM_ERASEBKGND handling, not the VCL's (which calls
FillRect). } FillRect). }
DefaultHandler(Message); DefaultHandler(Message);
@ -555,19 +516,8 @@ const
if Assigned(Item) then begin if Assigned(Item) then begin
if HitTestInfo.flags and TVHT_ONITEMBUTTON <> 0 then if HitTestInfo.flags and TVHT_ONITEMBUTTON <> 0 then
TreeView_Expand(Handle, Item, TVE_TOGGLE) TreeView_Expand(Handle, Item, TVE_TOGGLE)
else begin else if TreeView_GetSelection(Handle) <> Item then
if TreeView_GetSelection(Handle) <> Item then SelectItem(Item);
SelectItem(Item)
else begin
{ In 'friendly tree' mode, if the item is already selected, ensure
it's expanded.
Note: We do this only if SelectItem wasn't called, since newly
selected items are expanded automatically. If we were to call this
unconditionally, any error message would be shown twice. }
if FFriendlyTree and (HitTestInfo.flags and TVHT_ONITEM <> 0) then
TreeView_Expand(Handle, Item, TVE_EXPAND);
end;
end;
end; end;
end; end;
@ -687,25 +637,6 @@ begin
HandleClick; HandleClick;
Message.Result := 1; Message.Result := 1;
end; end;
TVN_SINGLEEXPAND:
begin
Hdr := PNMTreeView(Message.NMHdr);
{ Trying to emulate Windows XP's Explorer here:
Only collapse old item if it's at the same level as the new item. }
if Assigned(Hdr.itemOld.hItem) and Assigned(Hdr.itemNew.hItem) and
(TreeView_GetParent(Handle, Hdr.itemNew.hItem) <>
TreeView_GetParent(Handle, Hdr.itemOld.hItem)) then
Message.Result := Message.Result or TVNRET_SKIPOLD;
{ Selecting expanded items shouldn't collapse them }
if Assigned(Hdr.itemNew.hItem) then begin
TVItem.mask := TVIF_STATE;
TVItem.hItem := Hdr.itemNew.hItem;
TVItem.stateMask := TVIS_EXPANDED;
if TreeView_GetItem(Handle, TVItem) and
(TVItem.state and TVIS_EXPANDED <> 0) then
Message.Result := Message.Result or TVNRET_SKIPNEW;
end;
end;
end; end;
end; end;
@ -1205,5 +1136,5 @@ end;
initialization initialization
InitThemeLibrary; InitThemeLibrary;
SHPathPrepareForWriteFunc := GetProcAddress(LoadLibrary(PChar(AddBackslash(GetSystemDir) + shell32)), SHPathPrepareForWriteFunc := GetProcAddress(LoadLibrary(PChar(AddBackslash(GetSystemDir) + shell32)),
{$IFDEF UNICODE}'SHPathPrepareForWriteW'{$ELSE}'SHPathPrepareForWriteA'{$ENDIF}); 'SHPathPrepareForWriteW');
end. end.

View File

@ -93,10 +93,9 @@ type
procedure LBDeleteString(var Message: TMessage); message LB_DELETESTRING; procedure LBDeleteString(var Message: TMessage); message LB_DELETESTRING;
procedure LBResetContent(var Message: TMessage); message LB_RESETCONTENT; procedure LBResetContent(var Message: TMessage); message LB_RESETCONTENT;
procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE; procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
procedure WMGetObject(var Message: TMessage); message $003D; //WM_GETOBJECT procedure WMGetObject(var Message: TMessage); message WM_GETOBJECT;
procedure WMKeyDown(var Message: TWMKeyDown); message WM_KEYDOWN; procedure WMKeyDown(var Message: TWMKeyDown); message WM_KEYDOWN;
procedure WMMouseMove(var Message: TWMMouseMove); message WM_MOUSEMOVE; procedure WMMouseMove(var Message: TWMMouseMove); message WM_MOUSEMOVE;
procedure WMMouseWheel(var Message: TMessage); message $020A; //WM_MOUSEWHEEL
procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST;
procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS; procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
procedure WMSize(var Message: TWMSize); message WM_SIZE; procedure WMSize(var Message: TWMSize); message WM_SIZE;
@ -239,9 +238,6 @@ const
IID_IAccessible: TGUID = ( IID_IAccessible: TGUID = (
D1:$618736e0; D2:$3c3d; D3:$11cf; D4:($81,$0c,$00,$aa,$00,$38,$9b,$71)); D1:$618736e0; D2:$3c3d; D3:$11cf; D4:($81,$0c,$00,$aa,$00,$38,$9b,$71));
var
CanQueryUIState: Boolean;
type type
TWinControlAccess = class (TWinControl); TWinControlAccess = class (TWinControl);
@ -623,8 +619,8 @@ begin
FlipRect(rcItem, ClientRect, FUseRightToLeft); FlipRect(rcItem, ClientRect, FUseRightToLeft);
end; end;
{ Don't let TCustomListBox.CNDrawItem draw the focus } { Don't let TCustomListBox.CNDrawItem draw the focus }
if FWantTabs or (CanQueryUIState and if FWantTabs or
(SendMessage(Handle, WM_QUERYUISTATE, 0, 0) and UISF_HIDEFOCUS <> 0)) then (SendMessage(Handle, WM_QUERYUISTATE, 0, 0) and UISF_HIDEFOCUS <> 0) then
itemState := itemState and not ODS_FOCUS; itemState := itemState and not ODS_FOCUS;
inherited; inherited;
end; end;
@ -775,10 +771,7 @@ begin
FlipRect(Rect, SavedClientRect, FUseRightToLeft); FlipRect(Rect, SavedClientRect, FUseRightToLeft);
ItemState := ItemStates[Index]; ItemState := ItemStates[Index];
if CanQueryUIState then UIState := SendMessage(Handle, WM_QUERYUISTATE, 0, 0);
UIState := SendMessage(Handle, WM_QUERYUISTATE, 0, 0)
else
UIState := 0; //no UISF_HIDEACCEL and no UISF_HIDEFOCUS
Disabled := not Enabled or not ItemState.Enabled; Disabled := not Enabled or not ItemState.Enabled;
with Canvas do begin with Canvas do begin
if not FWantTabs and (odSelected in State) and Focused then begin if not FWantTabs and (odSelected in State) and Focused then begin
@ -1751,39 +1744,6 @@ begin
UpdateHotIndex(NewHotIndex); UpdateHotIndex(NewHotIndex);
end; end;
procedure TNewCheckListBox.WMMouseWheel(var Message: TMessage);
const
WHEEL_DELTA = 120;
begin
{ Work around a Windows bug (reproducible on 2000/XP/2003, but not Vista):
On an ownerdraw-variable list box, scrolling up or down more than one item
at a time with animation enabled causes a strange effect: first all visible
items appear to scroll off the bottom, then the items are all repainted in
the correct position. To avoid that, we implement our own mouse wheel
handling that scrolls only one item at a time.
(Note: The same problem exists when scrolling a page at a time using the
scroll bar. But because it's not as obvious, we don't work around it.) }
if (Lo(GetVersion) = 5) and
(Message.WParam and (MK_CONTROL or MK_SHIFT) = 0) then begin
Inc(FWheelAccum, Smallint(Message.WParam shr 16));
if Abs(FWheelAccum) >= WHEEL_DELTA then begin
while FWheelAccum >= WHEEL_DELTA do begin
SendMessage(Handle, WM_VSCROLL, SB_LINEUP, 0);
Dec(FWheelAccum, WHEEL_DELTA);
end;
while FWheelAccum <= -WHEEL_DELTA do begin
SendMessage(Handle, WM_VSCROLL, SB_LINEDOWN, 0);
Inc(FWheelAccum, WHEEL_DELTA);
end;
SendMessage(Handle, WM_VSCROLL, SB_ENDSCROLL, 0);
end;
end
else
{ Like the default handling, don't scroll if Control or Shift are down,
and on Vista always use the default handling since it isn't bugged. }
inherited;
end;
procedure TNewCheckListBox.WMNCHitTest(var Message: TWMNCHitTest); procedure TNewCheckListBox.WMNCHitTest(var Message: TWMNCHitTest);
var var
I: Integer; I: Integer;
@ -2144,18 +2104,6 @@ begin
RegisterComponents('JR', [TNewCheckListBox]); RegisterComponents('JR', [TNewCheckListBox]);
end; end;
procedure InitCanQueryUIState;
var
OSVersionInfo: TOSVersionInfo;
begin
CanQueryUIState := False;
if Win32Platform = VER_PLATFORM_WIN32_NT then begin
OSVersionInfo.dwOSVersionInfoSize := SizeOf(OSVersionInfo);
if GetVersionEx(OSVersionInfo) then
CanQueryUIState := OSVersionInfo.dwMajorVersion >= 5;
end;
end;
{ Note: This COM initialization code based on code from DBTables } { Note: This COM initialization code based on code from DBTables }
var var
SaveInitProc: Pointer; SaveInitProc: Pointer;
@ -2172,7 +2120,6 @@ initialization
SaveInitProc := InitProc; SaveInitProc := InitProc;
InitProc := @InitCOM; InitProc := @InitCOM;
end; end;
InitCanQueryUIState;
InitThemeLibrary; InitThemeLibrary;
NotifyWinEventFunc := GetProcAddress(GetModuleHandle(user32), 'NotifyWinEvent'); NotifyWinEventFunc := GetProcAddress(GetModuleHandle(user32), 'NotifyWinEvent');
finalization finalization

View File

@ -2,13 +2,13 @@ unit NewProgressBar;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2018 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
TNewProgressBar component - a smooth 32 bit TProgressBar TNewProgressBar component - a smooth 32 bit TProgressBar
Note: themed Vista and newer animate progress bars and don't immediately show changes. Note: themed animated progress bars and don't immediately show changes.
This applies both to Position and State. For example if you set State while the This applies both to Position and State. For example if you set State while the
progress bar is still moving towards a new Position, the new State doesnt show until progress bar is still moving towards a new Position, the new State doesnt show until
the moving animation has finished. the moving animation has finished.
@ -59,9 +59,6 @@ implementation
uses uses
Windows, CommCtrl; Windows, CommCtrl;
var
XP, Vista: Boolean;
procedure Register; procedure Register;
begin begin
RegisterComponents('JR', [TNewProgressBar]); RegisterComponents('JR', [TNewProgressBar]);
@ -85,7 +82,7 @@ begin
inherited; inherited;
CreateSubClass(Params, PROGRESS_CLASS); CreateSubClass(Params, PROGRESS_CLASS);
Params.Style := Params.Style or PBS_SMOOTH; Params.Style := Params.Style or PBS_SMOOTH;
if XP and (Style = npbstMarquee) then if Style = npbstMarquee then
Params.Style := Params.Style or PBS_MARQUEE; Params.Style := Params.Style or PBS_MARQUEE;
end; end;
@ -97,8 +94,7 @@ begin
SendMessage(Handle, PBM_SETRANGE, 0, MAKELPARAM(0, 65535)); SendMessage(Handle, PBM_SETRANGE, 0, MAKELPARAM(0, 65535));
SetPosition(FPosition); SetPosition(FPosition);
SetState(FState); SetState(FState);
if XP then SendMessage(Handle, PBM_SETMARQUEE, WPARAM(FStyle = npbstMarquee), 0);
SendMessage(Handle, PBM_SETMARQUEE, WPARAM(FStyle = npbstMarquee), 0);
end; end;
procedure TNewProgressBar.SetMin(Value: LongInt); procedure TNewProgressBar.SetMin(Value: LongInt);
@ -132,16 +128,14 @@ const
PBM_SETSTATE = WM_USER+16; PBM_SETSTATE = WM_USER+16;
States: array[TNewProgressBarState] of UINT = (PBST_NORMAL, PBST_ERROR, PBST_PAUSED); States: array[TNewProgressBarState] of UINT = (PBST_NORMAL, PBST_ERROR, PBST_PAUSED);
begin begin
if Vista then begin FState := Value;
FState := Value; if HandleAllocated then
if HandleAllocated then SendMessage(Handle, PBM_SETSTATE, States[Value], 0);
SendMessage(Handle, PBM_SETSTATE, States[Value], 0);
end;
end; end;
procedure TNewProgressBar.SetStyle(Value: TNewProgressBarStyle); procedure TNewProgressBar.SetStyle(Value: TNewProgressBarStyle);
begin begin
if XP and (FStyle <> Value) then begin if FStyle <> Value then begin
FStyle := Value; FStyle := Value;
RecreateWnd; RecreateWnd;
end; end;
@ -158,13 +152,4 @@ begin
DefaultHandler(Message); DefaultHandler(Message);
end; end;
var
OSVersionInfo: TOSVersionInfo;
initialization
OSVersionInfo.dwOSVersionInfoSize := SizeOf(OSVersionInfo);
if GetVersionEx(OSVersionInfo) then begin
Vista := OSVersionInfo.dwMajorVersion >= 6;
XP := Vista or ((OSVersionInfo.dwMajorVersion = 5) and (OSVersionInfo.dwMinorVersion >= 1));
end;
end. end.

View File

@ -1,22 +1,12 @@
unit NewStaticText; unit NewStaticText;
{ {
TNewStaticText - similar to TStaticText on D3+ but with multi-line AutoSize TNewStaticText - similar to TStaticText but with multi-line AutoSize
support and a WordWrap property support and a WordWrap property
} }
interface interface
{$IFNDEF VER90}
{$IFNDEF VER100}
{$IFNDEF VER120}
{$IFNDEF VER130}
{$DEFINE Delphi6OrHigher}
{$ENDIF}
{$ENDIF}
{$ENDIF}
{$ENDIF}
uses uses
Windows, Messages, SysUtils, Classes, Controls, Forms; Windows, Messages, SysUtils, Classes, Controls, Forms;
@ -44,7 +34,7 @@ type
procedure CreateParams(var Params: TCreateParams); override; procedure CreateParams(var Params: TCreateParams); override;
procedure Loaded; override; procedure Loaded; override;
procedure Notification(AComponent: TComponent; Operation: TOperation); override; procedure Notification(AComponent: TComponent; Operation: TOperation); override;
procedure SetAutoSize(Value: Boolean); {$IFDEF Delphi6OrHigher}override;{$ENDIF} procedure SetAutoSize(Value: Boolean); override;
public public
constructor Create(AOwner: TComponent); override; constructor Create(AOwner: TComponent); override;
function AdjustHeight: Integer; function AdjustHeight: Integer;
@ -95,38 +85,6 @@ begin
RegisterComponents('JR', [TNewStaticText]); RegisterComponents('JR', [TNewStaticText]);
end; end;
procedure DrawTextACP(const DC: HDC; const S: String; var R: TRect;
const AFormat: UINT);
{ Draws an ANSI string using the system's code page (CP_ACP), unlike DrawTextA
which uses the code page defined by the selected font. }
{$IFDEF UNICODE}
begin
DrawText(DC, PChar(S), Length(S), R, AFormat);
end;
{$ELSE}
var
SLen, WideLen: Integer;
WideStr: PWideChar;
begin
SLen := Length(S);
if SLen = 0 then
Exit;
if Win32Platform = VER_PLATFORM_WIN32_NT then begin
if SLen > High(Integer) div SizeOf(WideChar) then
Exit;
GetMem(WideStr, SLen * SizeOf(WideChar));
try
WideLen := MultiByteToWideChar(CP_ACP, 0, PChar(S), SLen, WideStr, SLen);
DrawTextW(DC, WideStr, WideLen, R, AFormat);
finally
FreeMem(WideStr);
end;
end
else
DrawText(DC, PChar(S), SLen, R, AFormat);
end;
{$ENDIF}
{ TNewStaticText } { TNewStaticText }
constructor TNewStaticText.Create(AOwner: TComponent); constructor TNewStaticText.Create(AOwner: TComponent);
@ -234,15 +192,7 @@ begin
DC := GetDC(0); DC := GetDC(0);
try try
SelectObject(DC, Font.Handle); SelectObject(DC, Font.Handle);
{ On NT platforms, static controls are Unicode-based internally; when DrawText(DC, PChar(S), Length(S), R, DT_CALCRECT or GetDrawTextFlags);
ANSI text is assigned to them, it is converted to Unicode using the
system code page (ACP). We must be sure to use the ACP here, too,
otherwise the calculated size could be incorrect. The code page used
by DrawTextA is defined by the font, and not necessarily equal to the
ACP, so we can't use it. (To reproduce: with the ACP set to Hebrew
(1255), try passing Hebrew text to DrawTextA with the font set to
"Lucida Console". It appears to use CP 1252, not 1255.) }
DrawTextACP(DC, S, R, DT_CALCRECT or GetDrawTextFlags);
finally finally
ReleaseDC(0, DC); ReleaseDC(0, DC);
end; end;

View File

@ -2,17 +2,11 @@ unit PathFunc;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2010 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
This unit provides some path-related, MBCS-aware functions. This unit provides some path-related functions.
These functions should always be used in lieu of their SysUtils counterparts
since they aren't MBCS-aware on Delphi 2, and sometimes not MBCS-aware on
Delphi 6 and 7 either (see QC#5096).
$jrsoftware: issrc/Components/PathFunc.pas,v 1.43 2010/04/19 21:43:01 jr Exp $
} }
interface interface
@ -66,20 +60,9 @@ begin
end; end;
function PathCharLength(const S: String; const Index: Integer): Integer; function PathCharLength(const S: String; const Index: Integer): Integer;
{ Returns the length in bytes of the character at Index in S. { Returns the length in characters of the character at Index in S. }
Notes:
1. If Index specifies the last character in S, 1 will always be returned,
even if the last character is a lead byte.
2. If a lead byte is followed by a null character (e.g. #131#0), 2 will be
returned. This mimics the behavior of MultiByteToWideChar and CharPrev,
but not CharNext(P)-P, which would stop on the null. }
begin begin
{$IFNDEF UNICODE} Result := 1;
if IsDBCSLeadByte(Ord(S[Index])) and (Index < Length(S)) then
Result := 2
else
{$ENDIF}
Result := 1;
end; end;
function PathCharIsSlash(const C: Char): Boolean; function PathCharIsSlash(const C: Char): Boolean;
@ -188,8 +171,7 @@ function PathDrivePartLengthEx(const Filename: String;
'x:\file' -> 3 ('x:\') 'x:\file' -> 3 ('x:\')
'\\server\share\file' -> 14 ('\\server\share') '\\server\share\file' -> 14 ('\\server\share')
'\file' -> 1 ('\') '\file' -> 1 ('\')
Note: This is MBCS-safe, unlike the Delphi's ExtractFileDrive function. }
(Computer and share names can include multi-byte characters!) }
var var
Len, I, C: Integer; Len, I, C: Integer;
begin begin
@ -392,8 +374,8 @@ begin
end; end;
function PathLastChar(const S: String): PChar; function PathLastChar(const S: String): PChar;
{ Returns pointer to last character in the string. Is MBCS-aware. Returns nil { Returns pointer to last character in the string. Returns nil if the string is
if the string is empty. } empty. }
begin begin
if S = '' then if S = '' then
Result := nil Result := nil
@ -426,37 +408,11 @@ end;
function PathLowercase(const S: String): String; function PathLowercase(const S: String): String;
{ Converts the specified path name to lowercase } { Converts the specified path name to lowercase }
{$IFNDEF UNICODE}
var
I, L: Integer;
{$ENDIF}
begin begin
{$IFNDEF UNICODE} Result := AnsiLowerCase(S);
if (Win32Platform <> VER_PLATFORM_WIN32_NT) and
(GetSystemMetrics(SM_DBCSENABLED) <> 0) then begin
{ Japanese Windows 98's handling of double-byte Roman characters in
filenames is case sensitive, so we can't change the case of double-byte
characters. (Japanese Windows NT/2000 is case insensitive, on both FAT
and NTFS, in my tests.) Based on code from AnsiLowerCaseFileName. }
Result := S;
L := Length(Result);
I := 1;
while I <= L do begin
if Result[I] in ['A'..'Z'] then begin
Inc(Byte(Result[I]), 32);
Inc(I);
end
else
Inc(I, PathCharLength(Result, I));
end;
end
else
{$ENDIF}
Result := AnsiLowerCase(S);
end; end;
function PathPos(Ch: Char; const S: String): Integer; function PathPos(Ch: Char; const S: String): Integer;
{ This is an MBCS-aware Pos function. }
var var
Len, I: Integer; Len, I: Integer;
begin begin
@ -499,7 +455,7 @@ end;
function PathStartsWith(const S, AStartsWith: String): Boolean; function PathStartsWith(const S, AStartsWith: String): Boolean;
{ Returns True if S starts with (or is equal to) AStartsWith. Uses path casing { Returns True if S starts with (or is equal to) AStartsWith. Uses path casing
rules, and is MBCS-aware. } rules. }
var var
AStartsWithLen: Integer; AStartsWithLen: Integer;
begin begin
@ -513,35 +469,24 @@ begin
end; end;
function PathStrNextChar(const S: PChar): PChar; function PathStrNextChar(const S: PChar): PChar;
{ Returns pointer to the character after S, unless S points to a null (#0). { Returns pointer to the character after S, unless S points to a null (#0). }
Is MBCS-aware. }
begin begin
{$IFNDEF UNICODE}
Result := CharNext(S);
{$ELSE}
Result := S; Result := S;
if Result^ <> #0 then if Result^ <> #0 then
Inc(Result); Inc(Result);
{$ENDIF}
end; end;
function PathStrPrevChar(const Start, Current: PChar): PChar; function PathStrPrevChar(const Start, Current: PChar): PChar;
{ Returns pointer to the character before Current, unless Current = Start. { Returns pointer to the character before Current, unless Current = Start. }
Is MBCS-aware. }
begin begin
{$IFNDEF UNICODE}
Result := CharPrev(Start, Current);
{$ELSE}
Result := Current; Result := Current;
if Result > Start then if Result > Start then
Dec(Result); Dec(Result);
{$ENDIF}
end; end;
function PathStrScan(const S: PChar; const C: Char): PChar; function PathStrScan(const S: PChar; const C: Char): PChar;
{ Returns pointer to first occurrence of C in S, or nil if there are no { Returns pointer to first occurrence of C in S, or nil if there are no
occurrences. Like StrScan, but MBCS-aware. occurrences. As with StrScan, specifying #0 for the search character is legal. }
Note: As with StrScan, specifying #0 for the search character is legal. }
begin begin
Result := S; Result := S;
while Result^ <> C do begin while Result^ <> C do begin

View File

@ -1,21 +1,13 @@
unit RestartManager; unit RestartManager;
{ {
Basic RestartManager API interface Unit for Delphi 2 and higher Basic RestartManager API interface unit by Martijn Laan
by Martijn Laan
} }
{$IFNDEF VER90}
{$IFNDEF VER93}
{$DEFINE Delphi3orHigher}
{$ENDIF}
{$ENDIF}
interface interface
uses uses
{$IFNDEF Delphi3orHigher} OLE2, {$ELSE} ActiveX, {$ENDIF} ActiveX, Windows;
Windows;
procedure FreeRestartManagerLibrary; procedure FreeRestartManagerLibrary;
function InitRestartManagerLibrary: Boolean; function InitRestartManagerLibrary: Boolean;
@ -151,8 +143,7 @@ function InitRestartManagerLibrary: Boolean;
begin begin
Inc(ReferenceCount); Inc(ReferenceCount);
{ Only attempt to load rstrtmgr.dll if running Windows Vista or later } if RestartManagerLibrary = 0 then
if (RestartManagerLibrary = 0) and (Lo(GetVersion) >= 6) then
begin begin
RestartManagerLibrary := LoadLibrary(PChar(AddBackslash(GetSystemDir) + restartmanagerlib)); RestartManagerLibrary := LoadLibrary(PChar(AddBackslash(GetSystemDir) + restartmanagerlib));
if RestartManagerLibrary <> 0 then if RestartManagerLibrary <> 0 then

View File

@ -72,9 +72,6 @@ uses
ShellApi, BidiUtils, PathFunc, ComObj; ShellApi, BidiUtils, PathFunc, ComObj;
const const
{ Note: There is no 'W' 1.0 class }
RICHEDIT_CLASS10A = 'RICHEDIT';
RICHEDIT_CLASSA = 'RichEdit20A';
RICHEDIT_CLASSW = 'RichEdit20W'; RICHEDIT_CLASSW = 'RichEdit20W';
MSFTEDIT_CLASS = 'RICHEDIT50W'; MSFTEDIT_CLASS = 'RICHEDIT50W';
EM_AUTOURLDETECT = WM_USER + 91; EM_AUTOURLDETECT = WM_USER + 91;
@ -116,7 +113,7 @@ type
TTextRange = record TTextRange = record
chrg: TCharRange; chrg: TCharRange;
lpstrText: {$IFDEF UNICODE} PWideChar {$ELSE} PAnsiChar {$ENDIF}; lpstrText: PWideChar;
end; end;
var var
@ -136,22 +133,12 @@ procedure LoadRichEdit;
begin begin
if RichEditUseCount = 0 then begin if RichEditUseCount = 0 then begin
{$IFDEF UNICODE}
RichEditVersion := 4; RichEditVersion := 4;
RichEditModule := LoadLibrary(PChar(AddBackslash(GetSystemDir) + 'MSFTEDIT.DLL')); RichEditModule := LoadLibrary(PChar(AddBackslash(GetSystemDir) + 'MSFTEDIT.DLL'));
{$ELSE}
RichEditModule := 0;
{$ENDIF}
if RichEditModule = 0 then begin if RichEditModule = 0 then begin
RichEditVersion := 2; RichEditVersion := 2;
RichEditModule := LoadLibrary(PChar(AddBackslash(GetSystemDir) + 'RICHED20.DLL')); RichEditModule := LoadLibrary(PChar(AddBackslash(GetSystemDir) + 'RICHED20.DLL'));
end; end;
{$IFNDEF UNICODE}
if RichEditModule = 0 then begin
RichEditVersion := 1;
RichEditModule := LoadLibrary(PChar(AddBackslash(GetSystemDir) + 'RICHED32.DLL'));
end;
{$ENDIF}
end; end;
Inc(RichEditUseCount); Inc(RichEditUseCount);
end; end;
@ -266,17 +253,10 @@ begin
end; end;
inherited; inherited;
if UseRichEdit then begin if UseRichEdit then begin
{$IFDEF UNICODE}
if RichEditVersion = 4 then if RichEditVersion = 4 then
CreateSubClass(Params, MSFTEDIT_CLASS) CreateSubClass(Params, MSFTEDIT_CLASS)
else else
CreateSubClass(Params, RICHEDIT_CLASSW); CreateSubClass(Params, RICHEDIT_CLASSW);
{$ELSE}
if RichEditVersion = 2 then
CreateSubClass(Params, RICHEDIT_CLASSA)
else
CreateSubClass(Params, RICHEDIT_CLASS10A);
{$ENDIF}
end else end else
{ Inherited handler creates a subclass of 'EDIT'. { Inherited handler creates a subclass of 'EDIT'.
Must have a unique class name since it uses two different classes Must have a unique class name since it uses two different classes

View File

@ -2,7 +2,7 @@ unit ScintEdit;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2020 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -25,7 +25,7 @@ type
TScintEditCharAddedEvent = procedure(Sender: TObject; Ch: AnsiChar) of object; TScintEditCharAddedEvent = procedure(Sender: TObject; Ch: AnsiChar) of object;
TScintEditDropFilesEvent = procedure(Sender: TObject; X, Y: Integer; TScintEditDropFilesEvent = procedure(Sender: TObject; X, Y: Integer;
AFiles: TStrings) of object; AFiles: TStrings) of object;
TScintHintInfo = {$IFDEF UNICODE} Controls. {$ENDIF} THintInfo; TScintHintInfo = Controls.THintInfo;
TScintEditHintShowEvent = procedure(Sender: TObject; TScintEditHintShowEvent = procedure(Sender: TObject;
var Info: TScintHintInfo) of object; var Info: TScintHintInfo) of object;
TScintEditMarginClickEvent = procedure(Sender: TObject; MarginNumber: Integer; TScintEditMarginClickEvent = procedure(Sender: TObject; MarginNumber: Integer;
@ -43,7 +43,7 @@ type
StartPos, EndPos: Integer; StartPos, EndPos: Integer;
end; end;
TScintRawCharSet = set of AnsiChar; TScintRawCharSet = set of AnsiChar;
TScintRawString = type {$IFDEF UNICODE} RawByteString {$ELSE} AnsiString {$ENDIF}; TScintRawString = type RawByteString;
TScintRectangle = record TScintRectangle = record
Left, Top, Right, Bottom: Integer; Left, Top, Right, Bottom: Integer;
end; end;
@ -327,9 +327,6 @@ type
protected protected
procedure CheckIndexRange(const Index: Integer); procedure CheckIndexRange(const Index: Integer);
procedure CheckIndexRangePlusOne(const Index: Integer); procedure CheckIndexRangePlusOne(const Index: Integer);
{$IFNDEF UNICODE}
class procedure Error(Msg: PResStringRec; Data: Integer);
{$ENDIF}
function Get(Index: Integer): String; override; function Get(Index: Integer): String; override;
function GetCount: Integer; override; function GetCount: Integer; override;
function GetTextStr: String; override; function GetTextStr: String; override;
@ -552,7 +549,6 @@ begin
end; end;
function TScintEdit.ConvertRawStringToString(const S: TScintRawString): String; function TScintEdit.ConvertRawStringToString(const S: TScintRawString): String;
{$IFDEF UNICODE}
var var
SrcLen, DestLen: Integer; SrcLen, DestLen: Integer;
DestStr: UnicodeString; DestStr: UnicodeString;
@ -569,22 +565,14 @@ begin
end; end;
Result := DestStr; Result := DestStr;
end; end;
{$ELSE}
begin
Result := S;
end;
{$ENDIF}
function TScintEdit.ConvertPCharToRawString(const Text: PChar; function TScintEdit.ConvertPCharToRawString(const Text: PChar;
const TextLen: Integer): TScintRawString; const TextLen: Integer): TScintRawString;
var var
{$IFDEF UNICODE}
DestLen: Integer; DestLen: Integer;
{$ENDIF}
DestStr: TScintRawString; DestStr: TScintRawString;
begin begin
if TextLen > 0 then begin if TextLen > 0 then begin
{$IFDEF UNICODE}
DestLen := WideCharToMultiByte(FCodePage, 0, Text, TextLen, nil, 0, nil, nil); DestLen := WideCharToMultiByte(FCodePage, 0, Text, TextLen, nil, 0, nil, nil);
if DestLen <= 0 then if DestLen <= 0 then
Error('WideCharToMultiByte failed'); Error('WideCharToMultiByte failed');
@ -592,20 +580,13 @@ begin
if WideCharToMultiByte(FCodePage, 0, Text, TextLen, @DestStr[1], Length(DestStr), if WideCharToMultiByte(FCodePage, 0, Text, TextLen, @DestStr[1], Length(DestStr),
nil, nil) <> DestLen then nil, nil) <> DestLen then
Error('Unexpected result from WideCharToMultiByte'); Error('Unexpected result from WideCharToMultiByte');
{$ELSE}
SetString(DestStr, Text, TextLen);
{$ENDIF}
end; end;
Result := DestStr; Result := DestStr;
end; end;
function TScintEdit.ConvertStringToRawString(const S: String): TScintRawString; function TScintEdit.ConvertStringToRawString(const S: String): TScintRawString;
begin begin
{$IFDEF UNICODE}
Result := ConvertPCharToRawString(PChar(S), Length(S)); Result := ConvertPCharToRawString(PChar(S), Length(S));
{$ELSE}
Result := S;
{$ENDIF}
end; end;
procedure TScintEdit.CopyToClipboard; procedure TScintEdit.CopyToClipboard;
@ -633,12 +614,6 @@ begin
Call(SCI_SETSCROLLWIDTHTRACKING, 1, 0); Call(SCI_SETSCROLLWIDTHTRACKING, 1, 0);
{ The default popup menu conflicts with the VCL's PopupMenu on Delphi 3 } { The default popup menu conflicts with the VCL's PopupMenu on Delphi 3 }
Call(SCI_USEPOPUP, 0, 0); Call(SCI_USEPOPUP, 0, 0);
{$IFNDEF UNICODE}
{ This hack is needed because non-Unicode VCL replaces the Scintilla's
default Unicode window proc with an ANSI one }
if Win32Platform = VER_PLATFORM_WIN32_NT then
Call(SCI_SETKEYSUNICODE, 1, 0);
{$ENDIF}
SetDefaultWordChars; SetDefaultWordChars;
ApplyOptions; ApplyOptions;
UpdateStyleAttributes; UpdateStyleAttributes;
@ -1021,11 +996,9 @@ end;
procedure TScintEdit.InitRawString(var S: TScintRawString; const Len: Integer); procedure TScintEdit.InitRawString(var S: TScintRawString; const Len: Integer);
begin begin
SetString(S, nil, Len); SetString(S, nil, Len);
{$IFDEF UNICODE}
//experimental, dont need this ATM: //experimental, dont need this ATM:
if FCodePage <> 0 then if FCodePage <> 0 then
System.SetCodePage(RawByteString(S), FCodePage, False); System.SetCodePage(RawByteString(S), FCodePage, False);
{$ENDIF}
end; end;
function TScintEdit.IsPositionInViewVertically(const Pos: Integer): Boolean; function TScintEdit.IsPositionInViewVertically(const Pos: Integer): Boolean;
@ -1869,13 +1842,6 @@ begin
FEdit.ReplaceRawTextRange(StartPos, EndPos, ''); FEdit.ReplaceRawTextRange(StartPos, EndPos, '');
end; end;
{$IFNDEF UNICODE}
class procedure TScintEditStrings.Error(Msg: PResStringRec; Data: Integer);
begin
TList.Error(LoadResString(Msg), Data);
end;
{$ENDIF}
function TScintEditStrings.Get(Index: Integer): String; function TScintEditStrings.Get(Index: Integer): String;
begin begin
Result := FEdit.ConvertRawStringToString(GetRawLine(Index)); Result := FEdit.ConvertRawStringToString(GetRawLine(Index));

View File

@ -44,7 +44,7 @@
{ } { }
{******************************************************************************} {******************************************************************************}
{ Simplified by Martijn Laan for Inno Setup and Delphi 2 } { Simplified by Martijn Laan for Inno Setup }
unit UxTheme; unit UxTheme;
@ -1088,19 +1088,6 @@ end;
function InitThemeLibrary: Boolean; function InitThemeLibrary: Boolean;
function IsWindowsXP: Boolean;
var
Info: TOSVersionInfo;
begin
Result := False;
Info.dwOSVersionInfoSize := SizeOf(Info);
if GetVersionEx(Info) then
if Info.dwPlatformId = VER_PLATFORM_WIN32_NT then
if (Info.dwMajorVersion > 5) or
((Info.dwMajorVersion = 5) and (Info.dwMinorVersion >= 1)) then
Result := True;
end;
function GetSystemDir: String; function GetSystemDir: String;
var var
Buf: array[0..MAX_PATH-1] of Char; Buf: array[0..MAX_PATH-1] of Char;
@ -1112,15 +1099,9 @@ function InitThemeLibrary: Boolean;
begin begin
Inc(ReferenceCount); Inc(ReferenceCount);
{ Only attempt to load uxtheme.dll if running Windows XP or later; otherwise if ThemeLibrary = 0 then begin
if uxtheme.dll happens to exist on Windows 2000 (it shouldn't unless a
bugged installer put it there) we get a "RtlUnhandledExceptionFilter could
not be located in the dynamic link library ntdll.dll" error message }
if (ThemeLibrary = 0) and IsWindowsXP then
begin
ThemeLibrary := LoadLibrary(PChar(AddBackslash(GetSystemDir) + themelib)); ThemeLibrary := LoadLibrary(PChar(AddBackslash(GetSystemDir) + themelib));
if ThemeLibrary <> 0 then if ThemeLibrary <> 0 then begin
begin
OpenThemeData := GetProcAddress(ThemeLibrary, 'OpenThemeData'); OpenThemeData := GetProcAddress(ThemeLibrary, 'OpenThemeData');
CloseThemeData := GetProcAddress(ThemeLibrary, 'CloseThemeData'); CloseThemeData := GetProcAddress(ThemeLibrary, 'CloseThemeData');
DrawThemeBackground := GetProcAddress(ThemeLibrary, 'DrawThemeBackground'); DrawThemeBackground := GetProcAddress(ThemeLibrary, 'DrawThemeBackground');

View File

@ -2,29 +2,21 @@
http://www.gumpi.com/Blog/2009/01/20/Alpha1OfWindows7ControlsForDelphi.aspx http://www.gumpi.com/Blog/2009/01/20/Alpha1OfWindows7ControlsForDelphi.aspx
MPL licensed } MPL licensed }
{ D2/D3 support and correct IID consts added by Martijn Laan for Inno Setup }
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2010 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
This unit provides the ITaskbarList3 interface for Windows 7 taskbar progress indicators. This unit provides the ITaskbarList3 interface for Windows 7 taskbar progress indicators.
$jrsoftware: issrc/Components/dwTaskbarList.pas,v 1.5 2010/10/21 02:14:14 jr Exp $
} }
{$IFDEF VER90}
{$DEFINE DELPHI2}
{$ENDIF}
unit dwTaskbarList; unit dwTaskbarList;
interface interface
uses uses
Windows {$IFDEF DELPHI2}, OLE2 {$ENDIF}; Windows;
const const
CLSID_TaskbarList: TGUID = ( CLSID_TaskbarList: TGUID = (
@ -86,34 +78,6 @@ type
end; end;
type type
{$IFDEF DELPHI2}
ITaskbarList = class(IUnknown)
function HrInit: HRESULT; virtual; stdcall; abstract;
function AddTab(hwnd: Cardinal): HRESULT; virtual; stdcall; abstract;
function DeleteTab(hwnd: Cardinal): HRESULT; virtual; stdcall; abstract;
function ActivateTab(hwnd: Cardinal): HRESULT; virtual; stdcall; abstract;
function SetActiveAlt(hwnd: Cardinal): HRESULT; virtual; stdcall; abstract;
end;
ITaskbarList2 = class(ITaskbarList)
function MarkFullscreenWindow(hwnd: Cardinal; fFullscreen: Bool): HRESULT; virtual; stdcall; abstract;
end;
ITaskbarList3 = class(ITaskbarList2)
function SetProgressValue(hwnd: Cardinal; ullCompleted, ullTotal: dwInteger64): HRESULT; virtual; stdcall; abstract;
function SetProgressState(hwnd: Cardinal; tbpFlags: DWORD): HRESULT; virtual; stdcall; abstract;
function RegisterTab(hwndTab: Cardinal; hwndMDI: Cardinal): HRESULT; virtual; stdcall; abstract;
function UnregisterTab(hwndTab: Cardinal): HRESULT; virtual; stdcall; abstract;
function SetTabOrder(hwndTab: Cardinal; hwndInsertBefore: Cardinal): HRESULT; virtual; stdcall; abstract;
function SetTabActive(hwndTab: Cardinal; hwndMDI: Cardinal; tbatFlags: DWORD): HRESULT; virtual; stdcall; abstract;
function ThumbBarAddButtons(hwnd: Cardinal; cButtons: UINT; Button: THUMBBUTTONLIST): HRESULT; virtual; stdcall; abstract;
function ThumbBarUpdateButtons(hwnd: Cardinal; cButtons: UINT; pButton: THUMBBUTTONLIST): HRESULT; virtual; stdcall; abstract;
function ThumbBarSetImageList(hwnd: Cardinal; himl: Cardinal): HRESULT; virtual; stdcall; abstract;
function SetOverlayIcon(hwnd: Cardinal; hIcon: HICON; pszDescription: LPCWSTR): HRESULT; virtual; stdcall; abstract;
function SetThumbnailTooltip(hwnd: Cardinal; pszTip: LPCWSTR): HRESULT; virtual; stdcall; abstract;
function SetThumbnailClip(hwnd: Cardinal; prcClip: PRect): HRESULT; virtual; stdcall; abstract;
end;
{$ELSE}
ITaskbarList = interface ITaskbarList = interface
['{56FDF342-FD6D-11D0-958A-006097C9A090}'] ['{56FDF342-FD6D-11D0-958A-006097C9A090}']
function HrInit: HRESULT; stdcall; function HrInit: HRESULT; stdcall;
@ -143,7 +107,6 @@ type
function SetThumbnailTooltip(hwnd: Cardinal; pszTip: LPCWSTR): HRESULT; stdcall; function SetThumbnailTooltip(hwnd: Cardinal; pszTip: LPCWSTR): HRESULT; stdcall;
function SetThumbnailClip(hwnd: Cardinal; prcClip: PRect): HRESULT; stdcall; function SetThumbnailClip(hwnd: Cardinal; prcClip: PRect): HRESULT; stdcall;
end; end;
{$ENDIF}
implementation implementation

View File

@ -23,13 +23,6 @@ uses
Windows, Windows,
SysUtils; SysUtils;
{$IFNDEF UNICODE}
function CharInSet(C: AnsiChar; const CharSet: TSysCharSet): Boolean;
begin
Result := C in CharSet;
end;
{$ENDIF}
constructor TIsxclassesParser.Create(); constructor TIsxclassesParser.Create();
begin begin
inherited; inherited;

View File

@ -101,7 +101,7 @@ Inno Setup is a <i>free</i> installer for Windows programs by Jordan Russell and
<ul> <ul>
<li>Support for every Windows release since 2006, including: Windows 11, Windows 10, Windows 10 on ARM, Windows Server 2019, Windows Server 2016, Windows 8.1, Windows 8, Windows Server 2012, Windows 7, Windows Server 2008 R2, Windows Server 2008, and Windows Vista. (No service packs are required.)</li> <li>Support for every Windows release since 2009, including: Windows 11, Windows 10, Windows 10 on ARM, Windows Server 2019, Windows Server 2016, Windows 8.1, Windows 8, Windows Server 2012, Windows 7, and Windows Server 2008 R2. (No service packs are required.)</li>
<li>Extensive support for installation of <link topic="32vs64bitinstalls">64-bit</link> applications on the 64-bit editions of Windows. The x64, ARM64 and Itanium architectures are all supported.</li> <li>Extensive support for installation of <link topic="32vs64bitinstalls">64-bit</link> applications on the 64-bit editions of Windows. The x64, ARM64 and Itanium architectures are all supported.</li>
@ -1953,11 +1953,6 @@ Filename: "http://www.example.com/"
<flag name="excludefromshowinnewinstall"> <flag name="excludefromshowinnewinstall">
<p>Prevents the Start menu entry for the new shortcut from receiving a highlight on Windows 7 and additionally prevents the new shortcut from being automatically pinned the Start screen on Windows 8 (or later). Ignored on earlier Windows versions.</p> <p>Prevents the Start menu entry for the new shortcut from receiving a highlight on Windows 7 and additionally prevents the new shortcut from being automatically pinned the Start screen on Windows 8 (or later). Ignored on earlier Windows versions.</p>
</flag> </flag>
<flag name="foldershortcut">
<p>Creates a special type of shortcut known as a "Folder Shortcut". Normally, when a shortcut to a folder is present on the Start Menu, clicking the item causes a separate Explorer window to open showing the target folder's contents. In contrast, a "folder shortcut" will show the contents of the target folder as a submenu instead of opening a separate window.</p>
<p>This flag is currently ignored when running on Windows 7 (or later), as folder shortcuts do not expand properly on the Start Menu anymore. It is not known whether this is a bug in Windows 7 or a removed feature.</p>
<p>When this flag is used, a folder name must be specified in the <tt>Filename</tt> parameter. Specifying the name of a file will result in a non-working shortcut.</p>
</flag>
<flag name="preventpinning"> <flag name="preventpinning">
<p>Prevents a Start menu entry from being pinnable to Taskbar or the Start Menu on Windows 7 (or later). This also makes the entry ineligible for inclusion in the Start menu's Most Frequently Used (MFU) list. Ignored on earlier Windows versions.</p> <p>Prevents a Start menu entry from being pinnable to Taskbar or the Start Menu on Windows 7 (or later). This also makes the entry ineligible for inclusion in the Start menu's Most Frequently Used (MFU) list. Ignored on earlier Windows versions.</p>
</flag> </flag>
@ -4144,21 +4139,10 @@ Name: portablemode; Description: "Portable Mode"</pre></example>
<setupvalid><tt>admin</tt>, or <tt>lowest</tt></setupvalid> <setupvalid><tt>admin</tt>, or <tt>lowest</tt></setupvalid>
<setupdefault><tt>admin</tt></setupdefault> <setupdefault><tt>admin</tt></setupdefault>
<body> <body>
<!--
<p>The effect of this directive depends on which version of Windows the user is running:</p>
<p><b>On Windows Vista and later:</b></p>
-->
<p>This directive affects whether elevated rights are requested (via a User Account Control dialog) when the installation is started.</p> <p>This directive affects whether elevated rights are requested (via a User Account Control dialog) when the installation is started.</p>
<p>When set to <tt>admin</tt> (the default), Setup will always run with administrative privileges and in <link topic="admininstallmode">administrative install mode</link>. If Setup was started by an unprivileged user, Windows will ask for the password to an account that has administrative privileges, and Setup will then run under that account.</p> <p>When set to <tt>admin</tt> (the default), Setup will always run with administrative privileges and in <link topic="admininstallmode">administrative install mode</link>. If Setup was started by an unprivileged user, Windows will ask for the password to an account that has administrative privileges, and Setup will then run under that account.</p>
<!-- <p>When set to <tt>none</tt>, Setup will only run with administrative privileges if it was started by a member of the Administrators group. Do not use this setting unless you are sure your installation will run successfully on unprivileged accounts.</p> --> <!-- <p>When set to <tt>none</tt>, Setup will only run with administrative privileges if it was started by a member of the Administrators group. Do not use this setting unless you are sure your installation will run successfully on unprivileged accounts.</p> -->
<p>When set to <tt>lowest</tt>, Setup will not request to be run with administrative privileges even if it was started by a member of the Administrators group and will always run in <link topic="admininstallmode">non administrative install mode</link>. Do not use this setting unless you are sure your installation will run successfully on unprivileged accounts.</p> <p>When set to <tt>lowest</tt>, Setup will not request to be run with administrative privileges even if it was started by a member of the Administrators group and will always run in <link topic="admininstallmode">non administrative install mode</link>. Do not use this setting unless you are sure your installation will run successfully on unprivileged accounts.</p>
<!--
<p><b>On earlier versions of Windows:</b></p>
<p>This directive specifies the minimum user privileges required to run the installation.</p>
<p>When set to <tt>admin</tt> (the default), Setup will only run if the user is a member of the Administrators group and will always run in <link topic="admininstallmode">administrative install mode</link>. Otherwise, it will display the following message and exit: "You must be logged in as an administrator when installing this program."</p>
<p>When set to <tt>none</tt> Setup will not check the user's group membership. Do not use this setting unless you are sure your installation will run successfully on unprivileged accounts.</p>
<p>When set to <tt>lowest</tt> Setup will not check the user's group membership and will always run in <link topic="admininstallmode">non administrative install mode</link>. Do not use this setting unless you are sure your installation will run successfully on unprivileged accounts.</p>
-->
<p><b>See also:</b><br/> <p><b>See also:</b><br/>
<link topic="setup_privilegesrequiredoverridesallowed">PrivilegesRequiredOverridesAllowed</link> <link topic="setup_privilegesrequiredoverridesallowed">PrivilegesRequiredOverridesAllowed</link>
</p> </p>
@ -5646,15 +5630,14 @@ SignTool=byparam format c:
<p>The versions specified in <tt>MinVersion</tt> and <tt>OnlyBelowVersion</tt> can optionally include build numbers and/or service pack levels.</p> <p>The versions specified in <tt>MinVersion</tt> and <tt>OnlyBelowVersion</tt> can optionally include build numbers and/or service pack levels.</p>
<examples> <examples>
<pre> <pre>
5.0.2195 6.1sp1
5.0sp4 10.0.22000
5.0.2195sp4
</pre> </pre>
</examples> </examples>
<p>If a build number is not specified or is zero, Setup will not check the system's build number.</p> <p>If a build number is not specified or is zero, Setup will not check the system's build number.</p>
<p>If a service pack level is not specified or is zero, Setup will not check the system's service pack level.</p> <p>If a service pack level is not specified or is zero, Setup will not check the system's service pack level.</p>
<p>When a service pack level is specified, Setup will only compare it against the system's service pack level if the specified major and minor versions match the system's version. For example, if <tt>MinVersion</tt> specifies <tt>5.0sp4</tt>, Setup will only check for SP4 on Windows 2000 (5.0) systems.</p> <p>When a service pack level is specified, Setup will only compare it against the system's service pack level if the specified major and minor versions match the system's version. For example, if <tt>MinVersion</tt> specifies <tt>6.1sp1</tt>, Setup will only check for SP1 on Windows 7 and Windows Server 2008 R2 (6.1) systems.</p>
<p>In an <tt>OnlyBelowVersion</tt> parameter, if the specified version matches the system's version, then Setup will normally consider the system's version to be too high. However, when a service pack level is specified, the specified version is allowed to match the system's version. For example, on Windows 2000 SP4, values of <tt>5.0</tt> and <tt>5.0.2195</tt> will fail the <tt>OnlyBelowVersion</tt> test, but <tt>5.0sp5</tt> and <tt>5.0.2195sp5</tt> will pass (as SP4 &lt; <tt>sp5</tt>).</p> <p>In an <tt>OnlyBelowVersion</tt> parameter, if the specified version matches the system's version, then Setup will normally consider the system's version to be too high. However, when a service pack level is specified, the specified version is allowed to match the system's version.<!-- For example, on Windows 2000 SP4, values of <tt>5.0</tt> and <tt>5.0.2195</tt> will fail the <tt>OnlyBelowVersion</tt> test, but <tt>5.0sp5</tt> and <tt>5.0.2195sp5</tt> will pass (as SP4 &lt; <tt>sp5</tt>). --></p>
</body> </body>
</topic> </topic>
@ -5662,8 +5645,6 @@ SignTool=byparam format c:
<keyword value="Windows Versions" /> <keyword value="Windows Versions" />
<body> <body>
<table> <table>
<tr><td>6.0.6000</td><td>Windows Vista</td></tr>
<tr><td>6.0.6001</td><td>Windows Vista with Service Pack 1<br/>or Windows Server 2008</td></tr>
<tr><td>6.1.7600</td><td>Windows 7<br/>or Windows Server 2008 R2</td></tr> <tr><td>6.1.7600</td><td>Windows 7<br/>or Windows Server 2008 R2</td></tr>
<tr><td>6.1.7601</td><td>Windows 7 with Service Pack 1<br/>or Windows Server 2008 R2 with Service Pack 1</td></tr> <tr><td>6.1.7601</td><td>Windows 7 with Service Pack 1<br/>or Windows Server 2008 R2 with Service Pack 1</td></tr>
<tr><td>6.2.9200</td><td>Windows 8<br/>or Windows Server 2012</td></tr> <tr><td>6.2.9200</td><td>Windows 8<br/>or Windows Server 2012</td></tr>
@ -5688,7 +5669,7 @@ SignTool=byparam format c:
<tr><td>10.0.22621</td><td>Windows 11 Version 22H2 (2022 Update)</td></tr> <tr><td>10.0.22621</td><td>Windows 11 Version 22H2 (2022 Update)</td></tr>
<tr><td>10.0.22631</td><td>Windows 11 Version 23H2 (2023 Update)</td></tr> <tr><td>10.0.22631</td><td>Windows 11 Version 23H2 (2023 Update)</td></tr>
</table> </table>
<p>Note that there is normally no need to specify the build numbers (i.e., you may simply use "6.2" for Windows 8).</p> <p>Note that except for Windows 11 there is normally no need to specify the build numbers (i.e., you may simply use "6.2" for Windows 8).</p>
</body> </body>
</topic> </topic>

View File

@ -2,13 +2,11 @@ unit BrowseFunc;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2010 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
Functions for browsing for folders/files Functions for browsing for folders/files
$jrsoftware: issrc/Projects/BrowseFunc.pas,v 1.9 2010/09/10 01:08:44 jr Exp $
} }
interface interface
@ -33,7 +31,7 @@ function NewGetSaveFileName(const Prompt: String; var FileName: String;
implementation implementation
uses uses
CommDlg, ShlObj, {$IFNDEF Delphi3orHigher} Ole2, {$ELSE} ActiveX, {$ENDIF} CommDlg, ShlObj, ActiveX,
PathFunc; PathFunc;
function BrowseCallback(Wnd: HWND; uMsg: UINT; lParam, lpData: LPARAM): Integer; stdcall; function BrowseCallback(Wnd: HWND; uMsg: UINT; lParam, lpData: LPARAM): Integer; stdcall;

View File

@ -2,7 +2,7 @@ unit CmnFunc;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2010 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -209,62 +209,10 @@ begin
end; end;
end; end;
{$IFNDEF IS_D4}
function MoveAppWindowToActiveWindowMonitor(var OldRect: TRect): Boolean;
{ This moves the application window (Application.Handle) to the same monitor
as the active window, so that a subsequent call to Application.MessageBox
displays the message box on that monitor. Based on code from D4+'s
TApplication.MessageBox. }
type
HMONITOR = type THandle;
TMonitorInfo = record
cbSize: DWORD;
rcMonitor: TRect;
rcWork: TRect;
dwFlags: DWORD;
end;
const
MONITOR_DEFAULTTONEAREST = $00000002;
var
ActiveWindow: HWND;
Module: HMODULE;
MonitorFromWindow: function(hwnd: HWND; dwFlags: DWORD): HMONITOR; stdcall;
GetMonitorInfo: function(hMonitor: HMONITOR; var lpmi: TMonitorInfo): BOOL; stdcall;
MBMonitor, AppMonitor: HMONITOR;
Info: TMonitorInfo;
begin
Result := False;
ActiveWindow := GetActiveWindow;
if ActiveWindow = 0 then Exit;
Module := GetModuleHandle(user32);
MonitorFromWindow := GetProcAddress(Module, 'MonitorFromWindow');
GetMonitorInfo := GetProcAddress(Module, 'GetMonitorInfoA');
if Assigned(MonitorFromWindow) and Assigned(GetMonitorInfo) then begin
MBMonitor := MonitorFromWindow(ActiveWindow, MONITOR_DEFAULTTONEAREST);
AppMonitor := MonitorFromWindow(Application.Handle, MONITOR_DEFAULTTONEAREST);
if MBMonitor <> AppMonitor then begin
Info.cbSize := SizeOf(Info);
if GetMonitorInfo(MBMonitor, Info) then begin
GetWindowRect(Application.Handle, OldRect);
SetWindowPos(Application.Handle, 0,
Info.rcMonitor.Left + ((Info.rcMonitor.Right - Info.rcMonitor.Left) div 2),
Info.rcMonitor.Top + ((Info.rcMonitor.Bottom - Info.rcMonitor.Top) div 2),
0, 0, SWP_NOACTIVATE or SWP_NOREDRAW or SWP_NOSIZE or SWP_NOZORDER);
Result := True;
end;
end;
end;
end;
{$ENDIF}
function AppMessageBox(const Text, Caption: PChar; Flags: Longint): Integer; function AppMessageBox(const Text, Caption: PChar; Flags: Longint): Integer;
var var
ActiveWindow: HWND; ActiveWindow: HWND;
WindowList: Pointer; WindowList: Pointer;
{$IFNDEF IS_D4}
DidMove: Boolean;
OldRect: TRect;
{$ENDIF}
begin begin
if MessageBoxRightToLeft then if MessageBoxRightToLeft then
Flags := Flags or (MB_RTLREADING or MB_RIGHT); Flags := Flags or (MB_RTLREADING or MB_RIGHT);
@ -289,31 +237,7 @@ begin
Exit; Exit;
end; end;
{$IFDEF IS_D4}
{ On Delphi 4+, simply call Application.MessageBox }
Result := Application.MessageBox(Text, Caption, Flags); Result := Application.MessageBox(Text, Caption, Flags);
{$ELSE}
{ Use custom implementation on Delphi 2 and 3. The Flags parameter is
incorrectly declared as a Word on Delphi 2's Application.MessageBox, and
there is no support for multiple monitors. }
DidMove := MoveAppWindowToActiveWindowMonitor(OldRect);
try
ActiveWindow := GetActiveWindow;
WindowList := DisableTaskWindows(0);
try
Result := MessageBox(Application.Handle, Text, Caption, Flags);
finally
EnableTaskWindows(WindowList);
SetActiveWindow(ActiveWindow);
end;
finally
if DidMove then
SetWindowPos(Application.Handle, 0,
OldRect.Left + ((OldRect.Right - OldRect.Left) div 2),
OldRect.Top + ((OldRect.Bottom - OldRect.Top) div 2),
0, 0, SWP_NOACTIVATE or SWP_NOREDRAW or SWP_NOSIZE or SWP_NOZORDER);
end;
{$ENDIF}
finally finally
TriggerMessageBoxCallbackFunc(Flags, True); TriggerMessageBoxCallbackFunc(Flags, True);
end; end;
@ -429,9 +353,6 @@ begin
FOwnerWnd := CreateWindowEx(0, WindowDisablerWndClassName, '', FOwnerWnd := CreateWindowEx(0, WindowDisablerWndClassName, '',
WS_POPUP or WS_DISABLED, 0, 0, 0, 0, HWND_DESKTOP, 0, HInstance, nil); WS_POPUP or WS_DISABLED, 0, 0, 0, 0, HWND_DESKTOP, 0, HInstance, nil);
if FOwnerWnd <> 0 then begin if FOwnerWnd <> 0 then begin
{ Note: We give the window a valid title since the user can see it in the
Alt+Tab list (on 2000 and XP, but not Vista, which appears to exclude
zero-width/height windows). }
FFallbackWnd := CreateWindowEx(0, WindowDisablerWndClassName, FFallbackWnd := CreateWindowEx(0, WindowDisablerWndClassName,
PChar(Application.Title), WS_POPUP, 0, 0, 0, 0, FOwnerWnd, 0, PChar(Application.Title), WS_POPUP, 0, 0, 0, 0, FOwnerWnd, 0,
HInstance, nil); HInstance, nil);

View File

@ -2,7 +2,7 @@ unit CmnFunc2;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2010 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -18,28 +18,11 @@ interface
uses uses
Windows, SysUtils; Windows, SysUtils;
{ Delphi 2.01's RegStr unit should never be used because it contains many
wrong declarations. Delphi 3's RegStr unit doesn't have this problem, but
for backward compatibility, it defines a few of the correct registry key
constants here. }
const const
{ Do NOT localize any of these }
NEWREGSTR_PATH_SETUP = 'Software\Microsoft\Windows\CurrentVersion';
NEWREGSTR_PATH_EXPLORER = NEWREGSTR_PATH_SETUP + '\Explorer';
NEWREGSTR_PATH_SPECIAL_FOLDERS = NEWREGSTR_PATH_EXPLORER + '\Shell Folders';
NEWREGSTR_PATH_UNINSTALL = NEWREGSTR_PATH_SETUP + '\Uninstall';
NEWREGSTR_VAL_UNINSTALLER_DISPLAYNAME = 'DisplayName';
NEWREGSTR_VAL_UNINSTALLER_COMMANDLINE = 'UninstallString';
KEY_WOW64_64KEY = $0100; KEY_WOW64_64KEY = $0100;
type type
{$IFNDEF UNICODE} TOneShotTimer = record
PLeadByteSet = ^TLeadByteSet;
TLeadByteSet = set of AnsiChar;
{$ENDIF}
TOneShotTimer = {$IFDEF UNICODE} record {$ELSE} object {$ENDIF}
private private
FLastElapsed: Cardinal; FLastElapsed: Cardinal;
FStartTick: DWORD; FStartTick: DWORD;
@ -88,7 +71,6 @@ function StringChange(var S: String; const FromStr, ToStr: String): Integer;
function StringChangeEx(var S: String; const FromStr, ToStr: String; function StringChangeEx(var S: String; const FromStr, ToStr: String;
const SupportDBCS: Boolean): Integer; const SupportDBCS: Boolean): Integer;
function AdjustLength(var S: String; const Res: Cardinal): Boolean; function AdjustLength(var S: String; const Res: Cardinal): Boolean;
function UsingWinNT: Boolean;
function ConvertConstPercentStr(var S: String): Boolean; function ConvertConstPercentStr(var S: String): Boolean;
function ConvertPercentStr(var S: String): Boolean; function ConvertPercentStr(var S: String): Boolean;
function ConstPos(const Ch: Char; const S: String): Integer; function ConstPos(const Ch: Char; const S: String): Integer;
@ -111,10 +93,6 @@ function IsAdminLoggedOn: Boolean;
function IsPowerUserLoggedOn: Boolean; function IsPowerUserLoggedOn: Boolean;
function IsMultiByteString(const S: AnsiString): Boolean; function IsMultiByteString(const S: AnsiString): Boolean;
function FontExists(const FaceName: String): Boolean; function FontExists(const FaceName: String): Boolean;
{$IFNDEF IS_D5}
procedure FreeAndNil(var Obj);
function SafeLoadLibrary(const Filename: String; ErrorMode: UINT): HMODULE;
{$ENDIF}
function GetUILanguage: LANGID; function GetUILanguage: LANGID;
function RemoveAccelChar(const S: String): String; function RemoveAccelChar(const S: String): String;
function GetTextWidth(const DC: HDC; S: String; const Prefix: Boolean): Integer; function GetTextWidth(const DC: HDC; S: String; const Prefix: Boolean): Integer;
@ -125,20 +103,9 @@ function IsWildcard(const Pattern: String): Boolean;
function WildcardMatch(const Text, Pattern: PChar): Boolean; function WildcardMatch(const Text, Pattern: PChar): Boolean;
function IntMax(const A, B: Integer): Integer; function IntMax(const A, B: Integer): Integer;
function Win32ErrorString(ErrorCode: Integer): String; function Win32ErrorString(ErrorCode: Integer): String;
{$IFNDEF UNICODE}
procedure GetLeadBytes(var ALeadBytes: TLeadByteSet);
{$ENDIF}
{$IFNDEF IS_D3}
function CompareMem(P1, P2: Pointer; Length: Integer): Boolean;
{$ENDIF}
function DeleteDirTree(const Dir: String): Boolean; function DeleteDirTree(const Dir: String): Boolean;
function SetNTFSCompression(const FileOrDir: String; Compress: Boolean): Boolean; function SetNTFSCompression(const FileOrDir: String; Compress: Boolean): Boolean;
procedure AddToWindowMessageFilterEx(const Wnd: HWND; const Msg: UINT); procedure AddToWindowMessageFilterEx(const Wnd: HWND; const Msg: UINT);
{$IFNDEF UNICODE}
type
TSysCharSet = set of AnsiChar;
function CharInSet(C: AnsiChar; const CharSet: TSysCharSet): Boolean;
{$ENDIF}
function ShutdownBlockReasonCreate(Wnd: HWND; const Reason: String): Boolean; function ShutdownBlockReasonCreate(Wnd: HWND; const Reason: String): Boolean;
function ShutdownBlockReasonDestroy(Wnd: HWND): Boolean; function ShutdownBlockReasonDestroy(Wnd: HWND): Boolean;
function TryStrToBoolean(const S: String; var BoolResult: Boolean): Boolean; function TryStrToBoolean(const S: String; var BoolResult: Boolean): Boolean;
@ -147,17 +114,10 @@ function MoveFileReplace(const ExistingFileName, NewFileName: String): Boolean;
procedure TryEnableAutoCompleteFileSystem(Wnd: HWND); procedure TryEnableAutoCompleteFileSystem(Wnd: HWND);
procedure CreateMutex(const MutexName: String); procedure CreateMutex(const MutexName: String);
{$IFNDEF UNICODE}
var
ConstLeadBytes: PLeadByteSet = nil;
{$ENDIF}
implementation implementation
uses uses
{$IFNDEF Delphi3orHigher} OLE2, ShlObj, {$ENDIF} PathFunc; PathFunc;
{$IFDEF Delphi3orHigher}
{ Avoid including Variants (via ActiveX and ShlObj) in SetupLdr (SetupLdr uses CmnFunc2), saving 26 KB. } { Avoid including Variants (via ActiveX and ShlObj) in SetupLdr (SetupLdr uses CmnFunc2), saving 26 KB. }
@ -194,9 +154,8 @@ function SHGetMalloc(var ppMalloc: IMalloc): HResult; stdcall; external shell32
function SHGetSpecialFolderLocation(hwndOwner: HWND; nFolder: Integer; function SHGetSpecialFolderLocation(hwndOwner: HWND; nFolder: Integer;
var ppidl: PItemIDList): HResult; stdcall; external shell32 name 'SHGetSpecialFolderLocation'; var ppidl: PItemIDList): HResult; stdcall; external shell32 name 'SHGetSpecialFolderLocation';
function SHGetPathFromIDList(pidl: PItemIDList; pszPath: PChar): BOOL; stdcall; function SHGetPathFromIDList(pidl: PItemIDList; pszPath: PChar): BOOL; stdcall;
external shell32 name {$IFDEF UNICODE}'SHGetPathFromIDListW'{$ELSE}'SHGetPathFromIDListA'{$ENDIF}; external shell32 name 'SHGetPathFromIDListW';
{$ENDIF}
function InternalGetFileAttr(const Name: String): Integer; function InternalGetFileAttr(const Name: String): Integer;
begin begin
@ -592,11 +551,6 @@ begin
Exit; Exit;
end; end;
end; end;
else
{$IFNDEF UNICODE}
if S[Result] in ConstLeadBytes^ then
Inc(Result);
{$ENDIF}
end; end;
Inc(Result); Inc(Result);
end; end;
@ -641,11 +595,6 @@ begin
Delete(S, I+1, 2); Delete(S, I+1, 2);
S[I] := Chr(C); S[I] := Chr(C);
end; end;
else
{$IFNDEF UNICODE}
if S[I] in ConstLeadBytes^ then
Inc(I);
{$ENDIF}
end; end;
Inc(I); Inc(I);
end; end;
@ -670,13 +619,8 @@ begin
if I = 0 then if I = 0 then
Break; Break;
end end
else begin else
{$IFNDEF UNICODE}
if S[I] in ConstLeadBytes^ then
Inc(I);
{$ENDIF}
Inc(I); Inc(I);
end;
end; end;
end; end;
@ -737,19 +681,13 @@ function GetSysWow64Dir: String;
Returns '' if there is no SysWow64 directory (e.g. running 32-bit Windows). } Returns '' if there is no SysWow64 directory (e.g. running 32-bit Windows). }
var var
GetSystemWow64DirectoryFunc: function( GetSystemWow64DirectoryFunc: function(
lpBuffer: {$IFDEF UNICODE} PWideChar {$ELSE} PAnsiChar {$ENDIF}; lpBuffer: PWideChar; uSize: UINT): UINT; stdcall;
uSize: UINT): UINT; stdcall;
Res: Integer; Res: Integer;
Buf: array[0..MAX_PATH] of Char; Buf: array[0..MAX_PATH] of Char;
begin begin
Result := ''; Result := '';
GetSystemWow64DirectoryFunc := GetProcAddress(GetModuleHandle(kernel32), GetSystemWow64DirectoryFunc := GetProcAddress(GetModuleHandle(kernel32),
{$IFDEF UNICODE} 'GetSystemWow64DirectoryW');
'GetSystemWow64DirectoryW'
{$ELSE}
'GetSystemWow64DirectoryA'
{$ENDIF} );
{ Note: This function does exist on 32-bit XP, but always returns 0 }
if Assigned(GetSystemWow64DirectoryFunc) then begin if Assigned(GetSystemWow64DirectoryFunc) then begin
Res := GetSystemWow64DirectoryFunc(Buf, SizeOf(Buf) div SizeOf(Buf[0])); Res := GetSystemWow64DirectoryFunc(Buf, SizeOf(Buf) div SizeOf(Buf[0]));
if (Res > 0) and (Res < SizeOf(Buf) div SizeOf(Buf[0])) then if (Res > 0) and (Res < SizeOf(Buf) div SizeOf(Buf[0])) then
@ -764,9 +702,8 @@ begin
{ From MSDN: 32-bit applications can access the native system directory by { From MSDN: 32-bit applications can access the native system directory by
substituting %windir%\Sysnative for %windir%\System32. WOW64 recognizes substituting %windir%\Sysnative for %windir%\System32. WOW64 recognizes
Sysnative as a special alias used to indicate that the file system should Sysnative as a special alias used to indicate that the file system should
not redirect the access. The Sysnative alias was added starting not redirect the access. }
with Windows Vista. } if IsWin64 then
if IsWin64 and (Lo(GetVersion) >= 6) then
{ Note: Avoiding GetWinDir here as that might not return the real Windows { Note: Avoiding GetWinDir here as that might not return the real Windows
directory under Terminal Services } directory under Terminal Services }
Result := PathExpand(AddBackslash(GetSystemDir) + '..\Sysnative') { Do not localize } Result := PathExpand(AddBackslash(GetSystemDir) + '..\Sysnative') { Do not localize }
@ -786,13 +723,11 @@ begin
Result := GetEnv('TEMP'); Result := GetEnv('TEMP');
if (Result <> '') and DirExists(Result) then if (Result <> '') and DirExists(Result) then
goto 1; goto 1;
if Win32Platform = VER_PLATFORM_WIN32_NT then begin { Like Windows 2000's GetTempPath, return USERPROFILE when TMP and TEMP
{ Like Windows 2000's GetTempPath, return USERPROFILE when TMP and TEMP are not set }
are not set } Result := GetEnv('USERPROFILE');
Result := GetEnv('USERPROFILE'); if (Result <> '') and DirExists(Result) then
if (Result <> '') and DirExists(Result) then goto 1;
goto 1;
end;
Result := GetWinDir; Result := GetWinDir;
1:Result := AddBackslash(PathExpand(Result)); 1:Result := AddBackslash(PathExpand(Result));
end; end;
@ -851,13 +786,6 @@ begin
SetLength(S, Res); SetLength(S, Res);
end; end;
function UsingWinNT: Boolean;
{ Returns True if system is running any version of Windows NT. Never returns
True on Windows 95 or 3.1. }
begin
Result := Win32Platform = VER_PLATFORM_WIN32_NT;
end;
function InternalRegQueryStringValue(H: HKEY; Name: PChar; var ResultStr: String; function InternalRegQueryStringValue(H: HKEY; Name: PChar; var ResultStr: String;
Type1, Type2: DWORD): Boolean; Type1, Type2: DWORD): Boolean;
var var
@ -939,33 +867,8 @@ end;
function RegValueExists(H: HKEY; Name: PChar): Boolean; function RegValueExists(H: HKEY; Name: PChar): Boolean;
{ Returns True if the specified value exists. Requires KEY_QUERY_VALUE access { Returns True if the specified value exists. Requires KEY_QUERY_VALUE access
to the key. } to the key. }
var
I: Integer;
EnumName: array[0..1] of Char;
Count: DWORD;
ErrorCode: Longint;
begin begin
Result := RegQueryValueEx(H, Name, nil, nil, nil, nil) = ERROR_SUCCESS; Result := RegQueryValueEx(H, Name, nil, nil, nil, nil) = ERROR_SUCCESS;
if Result and ((Name = nil) or (Name^ = #0)) and
(Win32Platform <> VER_PLATFORM_WIN32_NT) then begin
{ On Win9x/Me a default value always exists according to RegQueryValueEx,
so it must use RegEnumValue instead to check if a default value
really exists }
Result := False;
I := 0;
while True do begin
Count := SizeOf(EnumName) div SizeOf(EnumName[0]);
ErrorCode := RegEnumValue(H, I, EnumName, Count, nil, nil, nil, nil);
if (ErrorCode <> ERROR_SUCCESS) and (ErrorCode <> ERROR_MORE_DATA) then
Break;
{ is it the default value? }
if (ErrorCode = ERROR_SUCCESS) and (EnumName[0] = #0) then begin
Result := True;
Break;
end;
Inc(I);
end;
end;
end; end;
function RegCreateKeyExView(const RegView: TRegView; hKey: HKEY; lpSubKey: PChar; function RegCreateKeyExView(const RegView: TRegView; hKey: HKEY; lpSubKey: PChar;
@ -989,8 +892,7 @@ end;
var var
RegDeleteKeyExFunc: function(hKey: HKEY; RegDeleteKeyExFunc: function(hKey: HKEY;
lpSubKey: {$IFDEF UNICODE} PWideChar {$ELSE} PAnsiChar {$ENDIF}; lpSubKey: PWideChar; samDesired: REGSAM; Reserved: DWORD): Longint; stdcall;
samDesired: REGSAM; Reserved: DWORD): Longint; stdcall;
function RegDeleteKeyView(const RegView: TRegView; const Key: HKEY; function RegDeleteKeyView(const RegView: TRegView; const Key: HKEY;
const Name: PChar): Longint; const Name: PChar): Longint;
@ -1000,11 +902,7 @@ begin
else begin else begin
if @RegDeleteKeyExFunc = nil then if @RegDeleteKeyExFunc = nil then
RegDeleteKeyExFunc := GetProcAddress(GetModuleHandle(advapi32), RegDeleteKeyExFunc := GetProcAddress(GetModuleHandle(advapi32),
{$IFDEF UNICODE} 'RegDeleteKeyExW');
'RegDeleteKeyExW'
{$ELSE}
'RegDeleteKeyExA'
{$ENDIF} );
if Assigned(RegDeleteKeyExFunc) then if Assigned(RegDeleteKeyExFunc) then
Result := RegDeleteKeyExFunc(Key, Name, KEY_WOW64_64KEY, 0) Result := RegDeleteKeyExFunc(Key, Name, KEY_WOW64_64KEY, 0)
else else
@ -1026,32 +924,30 @@ begin
Result := ERROR_INVALID_PARAMETER; Result := ERROR_INVALID_PARAMETER;
Exit; Exit;
end; end;
if Win32Platform = VER_PLATFORM_WIN32_NT then begin if RegOpenKeyExView(RegView, Key, Name, 0, KEY_ENUMERATE_SUB_KEYS, H) = ERROR_SUCCESS then begin
if RegOpenKeyExView(RegView, Key, Name, 0, KEY_ENUMERATE_SUB_KEYS, H) = ERROR_SUCCESS then begin try
try SetString(KeyName, nil, 256);
SetString(KeyName, nil, 256); I := 0;
I := 0; while True do begin
while True do begin KeyNameCount := Length(KeyName);
KeyNameCount := Length(KeyName); ErrorCode := RegEnumKeyEx(H, I, @KeyName[1], KeyNameCount, nil, nil, nil, nil);
ErrorCode := RegEnumKeyEx(H, I, @KeyName[1], KeyNameCount, nil, nil, nil, nil); if ErrorCode = ERROR_MORE_DATA then begin
if ErrorCode = ERROR_MORE_DATA then begin { Double the size of the buffer and try again }
{ Double the size of the buffer and try again } if Length(KeyName) >= 65536 then begin
if Length(KeyName) >= 65536 then begin { Sanity check: If we tried a 64 KB buffer and it's still saying
{ Sanity check: If we tried a 64 KB buffer and it's still saying there's more data, something must be seriously wrong. Bail. }
there's more data, something must be seriously wrong. Bail. }
Break;
end;
SetString(KeyName, nil, Length(KeyName) * 2);
Continue;
end;
if ErrorCode <> ERROR_SUCCESS then
Break; Break;
if RegDeleteKeyIncludingSubkeys(RegView, H, PChar(KeyName)) <> ERROR_SUCCESS then end;
Inc(I); SetString(KeyName, nil, Length(KeyName) * 2);
Continue;
end; end;
finally if ErrorCode <> ERROR_SUCCESS then
RegCloseKey(H); Break;
if RegDeleteKeyIncludingSubkeys(RegView, H, PChar(KeyName)) <> ERROR_SUCCESS then
Inc(I);
end; end;
finally
RegCloseKey(H);
end; end;
end; end;
Result := RegDeleteKeyView(RegView, Key, Name); Result := RegDeleteKeyView(RegView, Key, Name);
@ -1106,8 +1002,7 @@ var
StringSid: PWideChar; StringSid: PWideChar;
begin begin
Result := ''; Result := '';
if not OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, if not OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, Token) then
{$IFDEF Delphi3orHigher} Token {$ELSE} @Token {$ENDIF}) then
Exit; Exit;
UserInfo := nil; UserInfo := nil;
try try
@ -1133,7 +1028,7 @@ end;
function IsMemberOfGroup(const DomainAliasRid: DWORD): Boolean; function IsMemberOfGroup(const DomainAliasRid: DWORD): Boolean;
{ Returns True if the logged-on user is a member of the specified local { Returns True if the logged-on user is a member of the specified local
group. Always returns True on Windows 9x/Me. } group. }
const const
SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority =
(Value: (0, 0, 0, 0, 0, 5)); (Value: (0, 0, 0, 0, 0, 5));
@ -1150,11 +1045,6 @@ var
GroupInfo: PTokenGroups; GroupInfo: PTokenGroups;
I: Integer; I: Integer;
begin begin
if Win32Platform <> VER_PLATFORM_WIN32_NT then begin
Result := True;
Exit;
end;
Result := False; Result := False;
if not AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2, if not AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2,
@ -1168,22 +1058,18 @@ begin
access token. This function eliminates potential misinterpretations of access token. This function eliminates potential misinterpretations of
the active group membership if changes to access tokens are made in the active group membership if changes to access tokens are made in
future releases." } future releases." }
CheckTokenMembership := nil; CheckTokenMembership := GetProcAddress(GetModuleHandle(advapi32),
if Lo(GetVersion) >= 5 then 'CheckTokenMembership');
CheckTokenMembership := GetProcAddress(GetModuleHandle(advapi32),
'CheckTokenMembership');
if Assigned(CheckTokenMembership) then begin if Assigned(CheckTokenMembership) then begin
if CheckTokenMembership(0, Sid, IsMember) then if CheckTokenMembership(0, Sid, IsMember) then
Result := IsMember; Result := IsMember;
end end
else begin else begin { Should never happen }
GroupInfo := nil; GroupInfo := nil;
if not OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True, if not OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True, Token) then begin
{$IFDEF Delphi3orHigher} Token {$ELSE} @Token {$ENDIF}) then begin
if GetLastError <> ERROR_NO_TOKEN then if GetLastError <> ERROR_NO_TOKEN then
Exit; Exit;
if not OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, if not OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, Token) then
{$IFDEF Delphi3orHigher} Token {$ELSE} @Token {$ENDIF}) then
Exit; Exit;
end; end;
try try
@ -1217,7 +1103,7 @@ end;
function IsAdminLoggedOn: Boolean; function IsAdminLoggedOn: Boolean;
{ Returns True if the logged-on user is a member of the Administrators local { Returns True if the logged-on user is a member of the Administrators local
group. Always returns True on Windows 9x/Me. } group. }
const const
DOMAIN_ALIAS_RID_ADMINS = $00000220; DOMAIN_ALIAS_RID_ADMINS = $00000220;
begin begin
@ -1226,7 +1112,7 @@ end;
function IsPowerUserLoggedOn: Boolean; function IsPowerUserLoggedOn: Boolean;
{ Returns True if the logged-on user is a member of the Power Users local { Returns True if the logged-on user is a member of the Power Users local
group. Always returns True on Windows 9x/Me. } group. }
const const
DOMAIN_ALIAS_RID_POWER_USERS = $00000223; DOMAIN_ALIAS_RID_POWER_USERS = $00000223;
begin begin
@ -1265,42 +1151,6 @@ begin
end; end;
end; end;
{$IFNDEF IS_D5}
procedure FreeAndNil(var Obj);
var
Temp: TObject;
begin
Temp := TObject(Obj);
Pointer(Obj) := nil;
Temp.Free;
end;
{$ENDIF}
{$IFNDEF IS_D5}
function SafeLoadLibrary(const Filename: String; ErrorMode: UINT): HMODULE;
var
SaveErrorMode: UINT;
SaveFPUControlWord: Word;
begin
SaveErrorMode := SetErrorMode(ErrorMode);
try
asm
FNSTCW SaveFPUControlWord
end;
try
Result := LoadLibrary(PChar(Filename));
finally
asm
FNCLEX
FLDCW SaveFPUControlWord
end;
end;
finally
SetErrorMode(SaveErrorMode);
end;
end;
{$ENDIF}
function GetUILanguage: LANGID; function GetUILanguage: LANGID;
{ Platform-independent version of GetUserDefaultUILanguage. May return 0 in { Platform-independent version of GetUserDefaultUILanguage. May return 0 in
case of failure. } case of failure. }
@ -1313,24 +1163,14 @@ begin
GetUserDefaultUILanguage := GetProcAddress(GetModuleHandle(kernel32), GetUserDefaultUILanguage := GetProcAddress(GetModuleHandle(kernel32),
'GetUserDefaultUILanguage'); 'GetUserDefaultUILanguage');
if Assigned(GetUserDefaultUILanguage) then if Assigned(GetUserDefaultUILanguage) then
{ This function is available on Windows 2000, Me, and later }
Result := GetUserDefaultUILanguage Result := GetUserDefaultUILanguage
else begin else begin
if Win32Platform = VER_PLATFORM_WIN32_NT then begin { GetUserDefaultUILanguage is available on Windows 2000, Me, and later so
{ Windows NT 4.0 } should never get here }
if RegOpenKeyExView(rvDefault, HKEY_USERS, '.DEFAULT\Control Panel\International', if RegOpenKeyExView(rvDefault, HKEY_USERS, '.DEFAULT\Control Panel\International',
0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin 0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin
RegQueryStringValue(K, 'Locale', S); RegQueryStringValue(K, 'Locale', S);
RegCloseKey(K); RegCloseKey(K);
end;
end
else begin
{ Windows 95/98 }
if RegOpenKeyExView(rvDefault, HKEY_CURRENT_USER, 'Control Panel\Desktop\ResourceLocale',
0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin
RegQueryStringValue(K, '', S);
RegCloseKey(K);
end;
end; end;
Val('$' + S, Result, E); Val('$' + S, Result, E);
if E <> 0 then if E <> 0 then
@ -1493,49 +1333,6 @@ begin
SetString(Result, Buffer, Len); SetString(Result, Buffer, Len);
end; end;
{$IFNDEF UNICODE}
procedure GetLeadBytes(var ALeadBytes: TLeadByteSet);
var
AnsiCPInfo: TCPInfo;
I: Integer;
J: Byte;
begin
ALeadBytes := [];
if GetCPInfo(CP_ACP, AnsiCPInfo) then
with AnsiCPInfo do begin
I := 0;
while (I < MAX_LEADBYTES) and ((LeadByte[I] or LeadByte[I+1]) <> 0) do begin
for J := LeadByte[I] to LeadByte[I+1] do
Include(ALeadBytes, AnsiChar(J));
Inc(I, 2);
end;
end;
end;
{$ENDIF}
{$IFNDEF IS_D3}
function CompareMem(P1, P2: Pointer; Length: Integer): Boolean;
asm
PUSH ESI
PUSH EDI
MOV ESI,P1
MOV EDI,P2
MOV EDX,ECX
XOR EAX,EAX
AND EDX,3
SHR ECX,1
SHR ECX,1
REPE CMPSD
JNE @@2
MOV ECX,EDX
REPE CMPSB
JNE @@2
@@1: INC EAX
@@2: POP EDI
POP ESI
end;
{$ENDIF}
function DeleteDirTree(const Dir: String): Boolean; function DeleteDirTree(const Dir: String): Boolean;
{ Removes the specified directory including any files/subdirectories inside { Removes the specified directory including any files/subdirectories inside
it. Returns True if successful. } it. Returns True if successful. }
@ -1603,8 +1400,7 @@ var
action: DWORD; pChangeFilterStruct: Pointer): BOOL; stdcall; action: DWORD; pChangeFilterStruct: Pointer): BOOL; stdcall;
procedure AddToWindowMessageFilter(const Msg: UINT); procedure AddToWindowMessageFilter(const Msg: UINT);
{ Adds a single message number to the process-wide message filter on Windows { Adds a single message number to the process-wide message filter. }
Vista and later. Has no effect on prior Windows versions. }
const const
MSGFLT_ADD = 1; MSGFLT_ADD = 1;
begin begin
@ -1618,9 +1414,9 @@ begin
end; end;
procedure AddToWindowMessageFilterEx(const Wnd: HWND; const Msg: UINT); procedure AddToWindowMessageFilterEx(const Wnd: HWND; const Msg: UINT);
{ Adds a single message number to Wnd's window-specific message filter, which { Adds a single message number to Wnd's window-specific message filter. Falls
is supported on Windows 7 and later. On Windows Vista, it falls back to back to modifying the process-wide message filter but in reality that should
modifying the process-wide message filter. } never happen. }
const const
MSGFLT_ALLOW = 1; MSGFLT_ALLOW = 1;
begin begin
@ -1635,34 +1431,18 @@ begin
AddToWindowMessageFilter(Msg); AddToWindowMessageFilter(Msg);
end; end;
{$IFNDEF UNICODE}
function CharInSet(C: AnsiChar; const CharSet: TSysCharSet): Boolean;
begin
Result := C in CharSet;
end;
{$ENDIF}
function ShutdownBlockReasonCreate(Wnd: HWND; const Reason: String): Boolean; function ShutdownBlockReasonCreate(Wnd: HWND; const Reason: String): Boolean;
var var
ShutdownBlockReasonCreateFunc: function(Wnd: HWND; pwszReason: LPCWSTR): Bool; stdcall; ShutdownBlockReasonCreateFunc: function(Wnd: HWND; pwszReason: LPCWSTR): Bool; stdcall;
{$IFNDEF UNICODE}
Buf: array[0..4095] of WideChar;
{$ENDIF}
begin begin
{ MSDN doesn't say whether you must call Destroy before a second Create, but it does say a Destroy { MSDN doesn't say whether you must call Destroy before a second Create, but it does say a Destroy
without a previous Create is a no-op, so call Destroy for safety. } without a previous Create is a no-op, so call Destroy for safety. }
ShutdownBlockReasonDestroy(Wnd); ShutdownBlockReasonDestroy(Wnd);
ShutdownBlockReasonCreateFunc := GetProcAddress(GetModuleHandle(user32), 'ShutdownBlockReasonCreate'); ShutdownBlockReasonCreateFunc := GetProcAddress(GetModuleHandle(user32), 'ShutdownBlockReasonCreate');
if Assigned(ShutdownBlockReasonCreateFunc) then begin if Assigned(ShutdownBlockReasonCreateFunc) then
{$IFDEF UNICODE} Result := ShutdownBlockReasonCreateFunc(Wnd, PChar(Reason))
Result := ShutdownBlockReasonCreateFunc(Wnd, PChar(Reason)); else
{$ELSE}
Buf[MultiByteToWideChar(CP_ACP, 0, PChar(Reason), Length(Reason), Buf,
(SizeOf(Buf) div SizeOf(Buf[0])) - 1)] := #0;
Result := ShutdownBlockReasonCreateFunc(Wnd, Buf);
{$ENDIF}
end else
Result := False; Result := False;
end; end;
@ -1698,15 +1478,8 @@ end;
function MoveFileReplace(const ExistingFileName, NewFileName: String): Boolean; function MoveFileReplace(const ExistingFileName, NewFileName: String): Boolean;
begin begin
if Win32Platform = VER_PLATFORM_WIN32_NT then begin Result := MoveFileEx(PChar(ExistingFileName), PChar(NewFileName),
Result := MoveFileEx(PChar(ExistingFileName), PChar(NewFileName), MOVEFILE_REPLACE_EXISTING);
MOVEFILE_REPLACE_EXISTING);
end
else begin
Result := DeleteFile(PChar(NewFileName));
if Result or (GetLastError = ERROR_FILE_NOT_FOUND) then
Result := MoveFile(PChar(ExistingFileName), PChar(NewFileName));
end;
end; end;
var var

View File

@ -2,7 +2,7 @@ unit CompExeUpdate;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2020 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -17,23 +17,22 @@ uses
{$I VERSION.INC} {$I VERSION.INC}
procedure UpdateSetupPEHeaderFields(const F: TCustomFile; procedure UpdateSetupPEHeaderFields(const F: TCustomFile;
const IsVistaCompatible, IsTSAware, IsDEPCompatible, IsASLRCompatible: Boolean); const IsTSAware, IsDEPCompatible, IsASLRCompatible: Boolean);
procedure UpdateIcons(const FileName, IcoFileName: String; const DeleteUninstallIcon: Boolean); procedure UpdateIcons(const FileName, IcoFileName: String; const DeleteUninstallIcon: Boolean);
procedure UpdateVersionInfo(const F: TCustomFile; procedure UpdateVersionInfo(const F: TCustomFile;
const NewBinaryFileVersion, NewBinaryProductVersion: TFileVersionNumbers; const NewBinaryFileVersion, NewBinaryProductVersion: TFileVersionNumbers;
const NewCompanyName, NewFileDescription, NewTextFileVersion, NewLegalCopyright, const NewCompanyName, NewFileDescription, NewTextFileVersion, NewLegalCopyright,
NewProductName, NewTextProductVersion, NewOriginalFileName: String; NewProductName, NewTextProductVersion, NewOriginalFileName: String;
const SetFileVersionAndDescription: Boolean); const SetFileVersionAndDescription: Boolean);
procedure RemoveManifestDllHijackProtection(const F: TCustomFile; const TestBlockOnly: Boolean);
procedure PreventCOMCTL32Sideloading(const F: TCustomFile); procedure PreventCOMCTL32Sideloading(const F: TCustomFile);
implementation implementation
uses uses
ResUpdate{$IFDEF UNICODE}, Math{$ENDIF}, Int64Em; ResUpdate, Math, Int64Em;
procedure UpdateSetupPEHeaderFields(const F: TCustomFile; procedure UpdateSetupPEHeaderFields(const F: TCustomFile;
const IsVistaCompatible, IsTSAware, IsDEPCompatible, IsASLRCompatible: Boolean); const IsTSAware, IsDEPCompatible, IsASLRCompatible: Boolean);
function SeekToPEHeader(const F: TCustomFile): Boolean; function SeekToPEHeader(const F: TCustomFile): Boolean;
var var
@ -69,9 +68,6 @@ var
Header: TImageFileHeader; Header: TImageFileHeader;
Ofs: Cardinal; Ofs: Cardinal;
OptMagic, DllChars, OrigDllChars: Word; OptMagic, DllChars, OrigDllChars: Word;
VersionRecord: packed record
Major, Minor: Word;
end;
begin begin
if SeekToPEHeader(F) then begin if SeekToPEHeader(F) then begin
if (F.Read(Header, SizeOf(Header)) = SizeOf(Header)) and if (F.Read(Header, SizeOf(Header)) = SizeOf(Header)) and
@ -79,32 +75,6 @@ begin
Ofs := F.Position.Lo; Ofs := F.Position.Lo;
if (F.Read(OptMagic, SizeOf(OptMagic)) = SizeOf(OptMagic)) and if (F.Read(OptMagic, SizeOf(OptMagic)) = SizeOf(OptMagic)) and
(OptMagic = IMAGE_NT_OPTIONAL_HDR32_MAGIC) then begin (OptMagic = IMAGE_NT_OPTIONAL_HDR32_MAGIC) then begin
if IsVistaCompatible then begin
{ Update OS/Subsystem version }
VersionRecord.Major := 6;
VersionRecord.Minor := 0;
F.Seek(Ofs + OffsetOfOperatingSystemVersion);
F.WriteBuffer(VersionRecord, SizeOf(VersionRecord));
F.Seek(Ofs + OffsetOfSubsystemVersion);
F.WriteBuffer(VersionRecord, SizeOf(VersionRecord));
end;
{ Update MajorImageVersion and MinorImageVersion to 6.0.
Works around apparent bug in Vista (still present in Vista SP1;
not reproducible on Server 2008): When UAC is turned off,
launching an uninstaller (as admin) from ARP and answering No at the
ConfirmUninstall message box causes a "This program might not have
uninstalled correctly" dialog to be displayed, even if the EXE
has a proper "Vista-aware" manifest. I discovered that if the EXE's
image version is set to 6.0, like the EXEs that ship with Vista
(notepad.exe), the dialog does not appear. (This is reproducible
with notepad.exe too if its image version is changed to anything
other than 6.0 exactly.) }
VersionRecord.Major := 6;
VersionRecord.Minor := 0;
F.Seek(Ofs + OffsetOfImageVersion);
F.WriteBuffer(VersionRecord, SizeOf(VersionRecord));
{ Update DllCharacteristics } { Update DllCharacteristics }
F.Seek(Ofs + OffsetOfDllCharacteristics); F.Seek(Ofs + OffsetOfDllCharacteristics);
if F.Read(DllChars, SizeOf(DllChars)) = SizeOf(DllChars) then begin if F.Read(DllChars, SizeOf(DllChars)) = SizeOf(DllChars) then begin
@ -247,11 +217,7 @@ procedure UpdateVersionInfo(const F: TCustomFile;
begin begin
if not QueryValue(P, Path, Pointer(Value), ValueLen) then if not QueryValue(P, Path, Pointer(Value), ValueLen) then
ResUpdateError('Unexpected version resource format (1)'); ResUpdateError('Unexpected version resource format (1)');
{$IFDEF UNICODE}
Move(Pointer(NewValue)^, Value^, (Min(Length(NewValue), lstrlenW(Value)))*SizeOf(Char)); Move(Pointer(NewValue)^, Value^, (Min(Length(NewValue), lstrlenW(Value)))*SizeOf(Char));
{$ELSE}
MultiByteToWideChar(CP_ACP, 0, PChar(NewValue), Length(NewValue), Value, lstrlenW(Value));
{$ENDIF}
ReplaceWithRealCopyrightSymbols(Value); ReplaceWithRealCopyrightSymbols(Value);
end; end;
@ -426,9 +392,6 @@ var
N: Cardinal; N: Cardinal;
NewGroupIconDirSize: LongInt; NewGroupIconDirSize: LongInt;
begin begin
if Win32Platform <> VER_PLATFORM_WIN32_NT then
ResUpdateError('Only supported on Windows NT and above');
Ico := nil; Ico := nil;
try try
@ -500,35 +463,6 @@ begin
end; end;
end; end;
procedure RemoveManifestDllHijackProtection(const F: TCustomFile; const TestBlockOnly: Boolean);
const
BlockStartText: AnsiString = '<file name="';
BlockLength = 380;
var
S: AnsiString;
Offset: Integer64;
P: Integer;
begin
{ Read the manifest resource into a string }
SetString(S, nil, SeekToResourceData(F, 24, 1));
Offset := F.Position;
F.ReadBuffer(S[1], Length(S));
{ Locate and update the block with file elements }
P := Pos(BlockStartText, S);
if P = 0 then
ResUpdateError('Block not found');
if Copy(S, P+BlockLength, 11) <> '</assembly>' then
ResUpdateError('Block too short (BlockLength should be '+string(IntToStr(Pos('</assembly>', string(S))-P)+'): '+string(Copy(S, P+BlockLength, 11))));
if TestBlockOnly then
Exit;
Inc64(Offset, P-1);
F.Seek64(Offset);
F.WriteAnsiString(AnsiString(Format('%*s', [BlockLength, ' '])));
end;
procedure PreventCOMCTL32Sideloading(const F: TCustomFile); procedure PreventCOMCTL32Sideloading(const F: TCustomFile);
const const
DependencyStartTag: AnsiString = '<dependency>'; DependencyStartTag: AnsiString = '<dependency>';

View File

@ -511,17 +511,13 @@ type
procedure WMStartNormally(var Message: TMessage); message WM_StartNormally; procedure WMStartNormally(var Message: TMessage); message WM_StartNormally;
procedure WMSettingChange(var Message: TMessage); message WM_SETTINGCHANGE; procedure WMSettingChange(var Message: TMessage); message WM_SETTINGCHANGE;
procedure WMThemeChanged(var Message: TMessage); message WM_THEMECHANGED; procedure WMThemeChanged(var Message: TMessage); message WM_THEMECHANGED;
{$IFDEF IS_D4}
protected protected
procedure WndProc(var Message: TMessage); override; procedure WndProc(var Message: TMessage); override;
{$ENDIF}
public public
{ Public declarations } { Public declarations }
constructor Create(AOwner: TComponent); override; constructor Create(AOwner: TComponent); override;
destructor Destroy; override; destructor Destroy; override;
{$IFDEF IS_D5}
function IsShortCut(var Message: TWMKey): Boolean; override; function IsShortCut(var Message: TWMKey): Boolean; override;
{$ENDIF}
end; end;
var var
@ -759,13 +755,6 @@ begin
editor's autocompletion list } editor's autocompletion list }
SetFakeShortCut(BStopCompile, VK_ESCAPE, []); SetFakeShortCut(BStopCompile, VK_ESCAPE, []);
{$IFNDEF IS_D103RIO}
{ TStatusBar needs manual scaling before Delphi 10.3 Rio }
StatusBar.Height := ToPPI(StatusBar.Height);
for I := 0 to StatusBar.Panels.Count-1 do
StatusBar.Panels[I].Width := ToPPI(StatusBar.Panels[I].Width);
{$ENDIF}
PopupMenu := TCompileFormMemoPopupMenu.Create(Self); PopupMenu := TCompileFormMemoPopupMenu.Create(Self);
FMemosStyler := TInnoSetupStyler.Create(Self); FMemosStyler := TInnoSetupStyler.Create(Self);
@ -951,7 +940,6 @@ begin
UpdateStatusPanelHeight(StatusPanel.Height); UpdateStatusPanelHeight(StatusPanel.Height);
end; end;
{$IFDEF IS_D4}
procedure TCompileForm.WndProc(var Message: TMessage); procedure TCompileForm.WndProc(var Message: TMessage);
begin begin
{ Without this, the status bar's owner drawn panels sometimes get corrupted and show { Without this, the status bar's owner drawn panels sometimes get corrupted and show
@ -964,11 +952,9 @@ begin
if (CtlType = ODT_MENU) and not IsMenu(hwndItem) then if (CtlType = ODT_MENU) and not IsMenu(hwndItem) then
CtlType := ODT_STATIC; CtlType := ODT_STATIC;
end; end;
inherited inherited
end; end;
{$ENDIF}
{$IFDEF IS_D5}
function TCompileForm.IsShortCut(var Message: TWMKey): Boolean; function TCompileForm.IsShortCut(var Message: TWMKey): Boolean;
begin begin
{ Key messages are forwarded by the VCL to the main form for ShortCut { Key messages are forwarded by the VCL to the main form for ShortCut
@ -980,7 +966,6 @@ begin
else else
Result := False; Result := False;
end; end;
{$ENDIF}
procedure TCompileForm.UpdateCaption; procedure TCompileForm.UpdateCaption;
var var
@ -1720,8 +1705,8 @@ begin
ElapsedTime := GetTickCount - StartTime; ElapsedTime := GetTickCount - StartTime;
ElapsedSeconds := ElapsedTime div 1000; ElapsedSeconds := ElapsedTime div 1000;
StatusMessage(smkStartEnd, Format(SCompilerStatusFinished, [TimeToStr(Time), StatusMessage(smkStartEnd, Format(SCompilerStatusFinished, [TimeToStr(Time),
Format('%.2u%s%.2u%s%.3u', [ElapsedSeconds div 60, {$IFDEF IS_DXE}FormatSettings.{$ENDIF}TimeSeparator, Format('%.2u%s%.2u%s%.3u', [ElapsedSeconds div 60, FormatSettings.TimeSeparator,
ElapsedSeconds mod 60, {$IFDEF IS_DXE}FormatSettings.{$ENDIF}DecimalSeparator, ElapsedTime mod 1000])])); ElapsedSeconds mod 60, FormatSettings.DecimalSeparator, ElapsedTime mod 1000])]));
finally finally
AppData.Lines.Free; AppData.Lines.Free;
FCompiling := False; FCompiling := False;
@ -3889,11 +3874,10 @@ procedure TCompileForm.MemoHintShow(Sender: TObject; var Info: TScintHintInfo);
S: TScintRawString; S: TScintRawString;
U: String; U: String;
begin begin
{ On the Unicode build, [Code] lines get converted from the editor's { [Code] lines get converted from the editor's UTF-8 to UTF-16 Strings when
UTF-8 to UTF-16 Strings when passed to the compiler. This can lead to passed to the compiler. This can lead to column number discrepancies
column number discrepancies between Scintilla and ROPS. This code between Scintilla and ROPS. This code simulates the conversion to try to
simulates the conversion to try to find out where ROPS thinks a Pos find out where ROPS thinks a Pos resides. }
resides. }
LinePos := FActiveMemo.GetPositionFromLine(FActiveMemo.GetLineFromPosition(Pos)); LinePos := FActiveMemo.GetPositionFromLine(FActiveMemo.GetLineFromPosition(Pos));
S := FActiveMemo.GetRawTextRange(LinePos, Pos); S := FActiveMemo.GetRawTextRange(LinePos, Pos);
U := FActiveMemo.ConvertRawStringToString(S); U := FActiveMemo.ConvertRawStringToString(S);
@ -4636,21 +4620,18 @@ begin
Info.lpDirectory := PChar(WorkingDir); Info.lpDirectory := PChar(WorkingDir);
Info.nShow := SW_SHOWNORMAL; Info.nShow := SW_SHOWNORMAL;
{ Disable windows so that the user can't click other things while a "Run as" { Disable windows so that the user can't click other things while a "Run as"
dialog is up on Windows 2000/XP (they aren't system modal like on Vista) } dialog is up but is not system modal (which it is currently) }
SaveFocusWindow := GetFocus; SaveFocusWindow := GetFocus;
WindowList := DisableTaskWindows(0); WindowList := DisableTaskWindows(0);
try try
{ Also temporarily remove the focus since a disabled window's children can { Also temporarily remove the focus since a disabled window's children can
still receive keystrokes. This is needed on Vista if the UAC dialog still receive keystrokes. This is needed if the UAC dialog doesn't come to
doesn't come to the foreground for some reason (e.g. if the following the foreground for some reason (e.g. if the following SetActiveWindow call
SetActiveWindow call is removed). } is removed). }
Windows.SetFocus(0); Windows.SetFocus(0);
{ On Vista, when disabling windows, we have to make the application window { We have to make the application window the active window, otherwise the
the active window, otherwise the UAC dialog doesn't come to the UAC dialog doesn't come to the foreground automatically. }
foreground automatically. Note: This isn't done on older versions simply SetActiveWindow(Application.Handle);
to avoid unnecessary title bar flicker. }
if Win32MajorVersion >= 6 then
SetActiveWindow(Application.Handle);
ShellExecuteResult := ShellExecuteEx(@Info); ShellExecuteResult := ShellExecuteEx(@Info);
ErrorCode := GetLastError; ErrorCode := GetLastError;
finally finally
@ -5043,8 +5024,8 @@ begin
if ASecondsRemaining >= 0 then if ASecondsRemaining >= 0 then
StatusBar.Panels[spExtraStatus].Text := Format( StatusBar.Panels[spExtraStatus].Text := Format(
' Estimated time remaining: %.2d%s%.2d%s%.2d Average KB/sec: %.0n', ' Estimated time remaining: %.2d%s%.2d%s%.2d Average KB/sec: %.0n',
[(ASecondsRemaining div 60) div 60, {$IFDEF IS_DXE}FormatSettings.{$ENDIF}TimeSeparator, [(ASecondsRemaining div 60) div 60, FormatSettings.TimeSeparator,
(ASecondsRemaining div 60) mod 60, {$IFDEF IS_DXE}FormatSettings.{$ENDIF}TimeSeparator, (ASecondsRemaining div 60) mod 60, FormatSettings.TimeSeparator,
ASecondsRemaining mod 60, ABytesCompressedPerSecond / 1024]) ASecondsRemaining mod 60, ABytesCompressedPerSecond / 1024])
else else
StatusBar.Panels[spExtraStatus].Text := ''; StatusBar.Panels[spExtraStatus].Text := '';

View File

@ -119,7 +119,7 @@ begin
end; end;
procedure AddFileToRecentDocs(const Filename: String); procedure AddFileToRecentDocs(const Filename: String);
{ Notifies the shell that a document has been opened. On Windows 7, this will { Notifies the shell that a document has been opened. This will
add the file to the Recent section of the app's Jump List. add the file to the Recent section of the app's Jump List.
It is only necessary to call this function when the shell is unaware that It is only necessary to call this function when the shell is unaware that
a file is being opened. Files opened through Explorer or common dialogs get a file is being opened. Files opened through Explorer or common dialogs get
@ -354,8 +354,8 @@ var
begin begin
if LineNumber = 0 then begin if LineNumber = 0 then begin
{ Don't forget about ListBox's DrawItem if you change the format of the following timestamp. } { Don't forget about ListBox's DrawItem if you change the format of the following timestamp. }
Insert(Format('[%.2u%s%.2u%s%.2u%s%.3u] ', [ST.wHour, {$IFDEF IS_DXE}FormatSettings.{$ENDIF}TimeSeparator, Insert(Format('[%.2u%s%.2u%s%.2u%s%.3u] ', [ST.wHour, FormatSettings.TimeSeparator,
ST.wMinute, {$IFDEF IS_DXE}FormatSettings.{$ENDIF}TimeSeparator, ST.wSecond, {$IFDEF IS_DXE}FormatSettings.{$ENDIF}DecimalSeparator, ST.wMinute, FormatSettings.TimeSeparator, ST.wSecond, FormatSettings.DecimalSeparator,
ST.wMilliseconds]), S, 1); ST.wMilliseconds]), S, 1);
end else begin end else begin
Insert(#9, S, 1); { Not actually painted - just for Ctrl+C } Insert(#9, S, 1); { Not actually painted - just for Ctrl+C }
@ -466,10 +466,7 @@ var
StartupInfo: TStartupInfo; StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation; ProcessInfo: TProcessInformation;
begin begin
if Win32Platform = VER_PLATFORM_WIN32_NT then Dir := GetSystemDir;
Dir := GetSystemDir
else
Dir := GetWinDir;
FillChar(StartupInfo, SizeOf(StartupInfo), 0); FillChar(StartupInfo, SizeOf(StartupInfo), 0);
StartupInfo.cb := SizeOf(StartupInfo); StartupInfo.cb := SizeOf(StartupInfo);

View File

@ -2,7 +2,7 @@ unit CompMsgs;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2021 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -184,15 +184,13 @@ const
SCompilerEntryInvalid2 = 'Value of [%s] section directive "%s" is invalid'; SCompilerEntryInvalid2 = 'Value of [%s] section directive "%s" is invalid';
SCompilerEntryAlreadySpecified = '[%s] section directive "%s" already specified'; SCompilerEntryAlreadySpecified = '[%s] section directive "%s" already specified';
SCompilerAppVersionOrAppVerNameRequired = 'The [Setup] section must include an AppVersion or AppVerName directive'; SCompilerAppVersionOrAppVerNameRequired = 'The [Setup] section must include an AppVersion or AppVerName directive';
SCompilerMinVersionWinMustBeZero = 'Minimum Windows version specified by MinVersion must be 0. (Windows 95/98/Me are no longer supported.)'; SCompilerMinVersionWinMustBeZero = 'Minimum non NT version specified by MinVersion must be 0. (Windows 95/98/Me are no longer supported.)';
SCompilerMinVersionNTTooLow = 'Minimum NT version specified by MinVersion must be at least %s. (Windows 2000/XP/Server 2003 are no longer supported.)'; SCompilerMinVersionNTTooLow = 'Minimum version specified by MinVersion must be at least %s. (Windows Vista/Server 2008 are no longer supported.)';
SCompilerMinVersionRecommendation = 'Minimum NT version is set to %s but using %s instead (which is the default) is recommended.'; SCompilerMinVersionRecommendation = 'Minimum version is set to %s but using %s instead (which is the default) is recommended.';
SCompilerDiskSliceSizeInvalid = 'DiskSliceSize must be between %d and %d, or "max"'; SCompilerDiskSliceSizeInvalid = 'DiskSliceSize must be between %d and %d, or "max"';
SCompilerDiskClusterSizeInvalid = 'DiskClusterSize must be between 1 and 32768'; SCompilerDiskClusterSizeInvalid = 'DiskClusterSize must be between 1 and 32768';
SCompilerInstallModeObsolete = 'The [%s] section directive "%s" is obsolete and ignored in this version of Inno Setup. Use command line parameters instead.'; SCompilerInstallModeObsolete = 'The [%s] section directive "%s" is obsolete and ignored in this version of Inno Setup. Use command line parameters instead.';
SCompilerMessagesFileObsolete = 'The MessagesFile directive is obsolete and no longer supported. Use the [Languages] section instead.'; SCompilerMessagesFileObsolete = 'The MessagesFile directive is obsolete and no longer supported. Use the [Languages] section instead.';
SCompilerDirectiveIsNTOnly = 'The [%s] section directive "%s" may not be used when compiling on Windows 95/98/Me';
SCompilerDirectiveRequiresWindows2000 = 'The [%s] section directive "%s" may not be used when compiling on Windows 95/98/Me/NT4';
SCompilerMustUseDisableStartupPrompt = 'DisableStartupPrompt must be set to "yes" when AppName includes constants'; SCompilerMustUseDisableStartupPrompt = 'DisableStartupPrompt must be set to "yes" when AppName includes constants';
SCompilerMustNotUsePreviousLanguage = 'UsePreviousLanguage must be set to "no" when AppId includes constants'; SCompilerMustNotUsePreviousLanguage = 'UsePreviousLanguage must be set to "no" when AppId includes constants';
SCompilerMustNotUsePreviousPrivileges = 'UsePreviousPrivileges must be set to "no" when AppId includes constants and PrivilegesRequiredOverridesAllowed allows "dialog"'; SCompilerMustNotUsePreviousPrivileges = 'UsePreviousPrivileges must be set to "no" when AppId includes constants and PrivilegesRequiredOverridesAllowed allows "dialog"';
@ -200,8 +198,6 @@ const
SCompilerDirectiveNotUsingPreferredDefault = 'The [Setup] section directive "%s" is defaulting to %s because %s includes constants.'; SCompilerDirectiveNotUsingPreferredDefault = 'The [Setup] section directive "%s" is defaulting to %s because %s includes constants.';
SCompilerDirectivePatternTooLong = 'The [Setup] section directive "%s" contains a pattern that is too long'; SCompilerDirectivePatternTooLong = 'The [Setup] section directive "%s" contains a pattern that is too long';
SCompilerOutputBaseFileNameSetup = 'Setting the [Setup] section directive "OutputBaseFileName" to "setup" is not recommended: all executables named "setup.exe" are shimmed by Windows application compatibility to load additional DLLs, such as version.dll.' + ' These DLLs are loaded unsafely by Windows and can be hijacked. Use a different name, for example "mysetup".'; SCompilerOutputBaseFileNameSetup = 'Setting the [Setup] section directive "OutputBaseFileName" to "setup" is not recommended: all executables named "setup.exe" are shimmed by Windows application compatibility to load additional DLLs, such as version.dll.' + ' These DLLs are loaded unsafely by Windows and can be hijacked. Use a different name, for example "mysetup".';
SCompilerRemoveManifestDllHijackProtection = 'Setting the [Setup] section directive "MinVersion" below %s is not recommended: Windows Vista doesn''t support some of Setup''s security measures against potential DLL preloading attacks so these have been' + ' removed by the compiler making your installer less secure on all versions of Windows.';
SCompilerDidntRemoveManifestDllHijackProtection = 'Setup will not run on Windows Vista: MinVersion must be below %s.';
SCompilerWizImageRenamed = 'Wizard image "%s" has been renamed. Use "%s" instead or consider removing the directive to use modern built-in wizard images.'; SCompilerWizImageRenamed = 'Wizard image "%s" has been renamed. Use "%s" instead or consider removing the directive to use modern built-in wizard images.';
{ Signing } { Signing }
@ -355,8 +351,6 @@ const
SCompilerFilesCantHaveNonExternalExternalSize = 'Parameter "ExternalSize" may only be used when ' + SCompilerFilesCantHaveNonExternalExternalSize = 'Parameter "ExternalSize" may only be used when ' +
'the "external" flag is used'; 'the "external" flag is used';
SCompilerFilesExcludeTooLong = 'Parameter "Excludes" contains a pattern that is too long'; SCompilerFilesExcludeTooLong = 'Parameter "Excludes" contains a pattern that is too long';
SCompilerFilesCantReadVersionInfoOn64BitImage = 'In order for it to be able to read version info on 64-bit images, ' +
'the compiler must be run under Windows 2000 or later';
SCompilerFilesUnsafeFile = 'Unsafe file detected: %s.' + SNewLine2 + SCompilerFilesUnsafeFile = 'Unsafe file detected: %s.' + SNewLine2 +
'See the "Unsafe Files" topic in the help file for more information'; 'See the "Unsafe Files" topic in the help file for more information';
SCompilerFilesSystemDirUsed = 'Attempt to deploy DLL file from own Windows System directory.' + SNewLine2 + SCompilerFilesSystemDirUsed = 'Attempt to deploy DLL file from own Windows System directory.' + SNewLine2 +

View File

@ -89,7 +89,7 @@ object OptionsForm: TOptionsForm
Top = 196 Top = 196
Width = 265 Width = 265
Height = 17 Height = 17
Caption = '*' Caption = 'Always &launch Setup/Uninstall as administrator'
TabOrder = 9 TabOrder = 9
end end
object ColorizeCompilerOutputCheck: TCheckBox object ColorizeCompilerOutputCheck: TCheckBox

View File

@ -2,7 +2,7 @@ unit CompOptions;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2020 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -72,16 +72,6 @@ procedure TOptionsForm.FormCreate(Sender: TObject);
begin begin
InitFormFont(Self); InitFormFont(Self);
{ On Windows Vista, you can only select administrator accounts in a "Run as"
dialog. On Windows 2000/XP/2003, you can select any account. Earlier
versions of Windows don't support "Run as" at all, so disable the check
box there. }
if Win32MajorVersion >= 6 then
RunAsDifferentUserCheck.Caption := 'Always &launch Setup/Uninstall as administrator'
else
RunAsDifferentUserCheck.Caption := 'Always &launch Setup/Uninstall as different user';
RunAsDifferentUserCheck.Enabled := (Win32MajorVersion >= 5);
{ Order must match TThemeType. } { Order must match TThemeType. }
ThemeComboBox.Items.Add('Light'); ThemeComboBox.Items.Add('Light');
ThemeComboBox.Items.Add('Dark'); ThemeComboBox.Items.Add('Dark');

View File

@ -2,7 +2,7 @@ program Compil32;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2019 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -46,11 +46,13 @@ uses
BidiUtils in '..\Components\BidiUtils.pas', BidiUtils in '..\Components\BidiUtils.pas',
DropListBox in '..\Components\DropListBox.pas', DropListBox in '..\Components\DropListBox.pas',
NewCheckListBox in '..\Components\NewCheckListBox.pas', NewCheckListBox in '..\Components\NewCheckListBox.pas',
NewNotebook in '..\Components\NewNotebook.pas'; NewNotebook in '..\Components\NewNotebook.pas',
TaskbarProgressFunc in 'TaskbarProgressFunc.pas',
HtmlHelpFunc in 'HtmlHelpFunc.pas';
{$SetPEFlags IMAGE_FILE_RELOCS_STRIPPED} {$SetPEFlags IMAGE_FILE_RELOCS_STRIPPED}
{$SETPEOSVERSION 6.0} {$SETPEOSVERSION 6.1}
{$SETPESUBSYSVERSION 6.0} {$SETPESUBSYSVERSION 6.1}
{$WEAKLINKRTTI ON} {$WEAKLINKRTTI ON}
{$R Compil32.docicon.res} {$R Compil32.docicon.res}
@ -61,9 +63,9 @@ procedure SetAppUserModelID;
var var
Func: function(AppID: PWideChar): HRESULT; stdcall; Func: function(AppID: PWideChar): HRESULT; stdcall;
begin begin
{ On Windows 7, for the IDE to be pinnable and show a Jump List, it is { For the IDE to be pinnable and show a Jump List, it is necessary to
necessary to explicitly assign an AppUserModelID because by default the explicitly assign an AppUserModelID because by default the taskbar excludes
taskbar excludes applications that have "Setup" in their name. } applications that have "Setup" in their name. }
Func := GetProcAddress(GetModuleHandle('shell32.dll'), Func := GetProcAddress(GetModuleHandle('shell32.dll'),
'SetCurrentProcessExplicitAppUserModelID'); 'SetCurrentProcessExplicitAppUserModelID');
if Assigned(Func) then if Assigned(Func) then

View File

@ -78,6 +78,7 @@
<MainSource>MainSource</MainSource> <MainSource>MainSource</MainSource>
</DelphiCompile> </DelphiCompile>
<DCCReference Include="SafeDLLPath.pas"/> <DCCReference Include="SafeDLLPath.pas"/>
<DCCReference Include="..\Components\PathFunc.pas"/>
<DCCReference Include="CompForm.pas"> <DCCReference Include="CompForm.pas">
<Form>CompileForm</Form> <Form>CompileForm</Form>
</DCCReference> </DCCReference>
@ -127,6 +128,8 @@
<DCCReference Include="..\Components\DropListBox.pas"/> <DCCReference Include="..\Components\DropListBox.pas"/>
<DCCReference Include="..\Components\NewCheckListBox.pas"/> <DCCReference Include="..\Components\NewCheckListBox.pas"/>
<DCCReference Include="..\Components\NewNotebook.pas"/> <DCCReference Include="..\Components\NewNotebook.pas"/>
<DCCReference Include="TaskbarProgressFunc.pas"/>
<DCCReference Include="HtmlHelpFunc.pas"/>
<BuildConfiguration Include="Base"> <BuildConfiguration Include="Base">
<Key>Base</Key> <Key>Base</Key>
</BuildConfiguration> </BuildConfiguration>

View File

@ -62,13 +62,11 @@ type
FileLineNumber: Integer; FileLineNumber: Integer;
end; end;
{$IFDEF UNICODE}
TPreLangData = class TPreLangData = class
public public
Name: String; Name: String;
LanguageCodePage: Integer; LanguageCodePage: Integer;
end; end;
{$ENDIF}
TLangData = class TLangData = class
public public
@ -193,7 +191,7 @@ type
PreprocOutput: String; PreprocOutput: String;
DefaultLangData: TLangData; DefaultLangData: TLangData;
{$IFDEF UNICODE} PreLangDataList, {$ENDIF} LangDataList: TList; PreLangDataList, LangDataList: TList;
SignToolList: TList; SignToolList: TList;
SignTools, SignToolsParams: TStringList; SignTools, SignToolsParams: TStringList;
SignToolRetryCount, SignToolRetryDelay, SignToolMinimumTimeBetween: Integer; SignToolRetryCount, SignToolRetryDelay, SignToolMinimumTimeBetween: Integer;
@ -283,13 +281,9 @@ type
procedure EnumDirsProc(const Line: PChar; const Ext: Integer); procedure EnumDirsProc(const Line: PChar; const Ext: Integer);
procedure EnumIconsProc(const Line: PChar; const Ext: Integer); procedure EnumIconsProc(const Line: PChar; const Ext: Integer);
procedure EnumINIProc(const Line: PChar; const Ext: Integer); procedure EnumINIProc(const Line: PChar; const Ext: Integer);
{$IFDEF UNICODE}
procedure EnumLangOptionsPreProc(const Line: PChar; const Ext: Integer); procedure EnumLangOptionsPreProc(const Line: PChar; const Ext: Integer);
{$ENDIF}
procedure EnumLangOptionsProc(const Line: PChar; const Ext: Integer); procedure EnumLangOptionsProc(const Line: PChar; const Ext: Integer);
{$IFDEF UNICODE}
procedure EnumLanguagesPreProc(const Line: PChar; const Ext: Integer); procedure EnumLanguagesPreProc(const Line: PChar; const Ext: Integer);
{$ENDIF}
procedure EnumLanguagesProc(const Line: PChar; const Ext: Integer); procedure EnumLanguagesProc(const Line: PChar; const Ext: Integer);
procedure EnumRegistryProc(const Line: PChar; const Ext: Integer); procedure EnumRegistryProc(const Line: PChar; const Ext: Integer);
procedure EnumDeleteProc(const Line: PChar; const Ext: Integer); procedure EnumDeleteProc(const Line: PChar; const Ext: Integer);
@ -305,9 +299,7 @@ type
function GetLZMAExeFilename(const Allow64Bit: Boolean): String; function GetLZMAExeFilename(const Allow64Bit: Boolean): String;
procedure InitBzipDLL; procedure InitBzipDLL;
procedure InitCryptDLL; procedure InitCryptDLL;
{$IFDEF UNICODE}
procedure InitPreLangData(const APreLangData: TPreLangData); procedure InitPreLangData(const APreLangData: TPreLangData);
{$ENDIF}
procedure InitLanguageEntry(var ALanguageEntry: TSetupLanguageEntry); procedure InitLanguageEntry(var ALanguageEntry: TSetupLanguageEntry);
procedure InitLZMADLL; procedure InitLZMADLL;
procedure InitPreprocessor; procedure InitPreprocessor;
@ -331,13 +323,9 @@ type
procedure ProcessWildcardsParameter(const ParamData: String; procedure ProcessWildcardsParameter(const ParamData: String;
const AWildcards: TStringList; const TooLongMsg: String); const AWildcards: TStringList; const TooLongMsg: String);
procedure ReadDefaultMessages; procedure ReadDefaultMessages;
{$IFDEF UNICODE}
procedure ReadMessagesFromFilesPre(const AFiles: String; const ALangIndex: Integer); procedure ReadMessagesFromFilesPre(const AFiles: String; const ALangIndex: Integer);
{$ENDIF}
procedure ReadMessagesFromFiles(const AFiles: String; const ALangIndex: Integer); procedure ReadMessagesFromFiles(const AFiles: String; const ALangIndex: Integer);
{$IFDEF UNICODE}
procedure ReadMessagesFromScriptPre; procedure ReadMessagesFromScriptPre;
{$ENDIF}
procedure ReadMessagesFromScript; procedure ReadMessagesFromScript;
function ReadScriptFile(const Filename: String; const UseCache: Boolean; function ReadScriptFile(const Filename: String; const UseCache: Boolean;
const AnsiConvertCodePage: Cardinal): TScriptFileLines; const AnsiConvertCodePage: Cardinal): TScriptFileLines;
@ -372,9 +360,6 @@ type
end; end;
var var
{$IFNDEF UNICODE}
CompilerLeadBytes: TLeadByteSet;
{$ENDIF}
ZipInitialized, BzipInitialized, LZMAInitialized, CryptInitialized: Boolean; ZipInitialized, BzipInitialized, LZMAInitialized, CryptInitialized: Boolean;
PreprocessorInitialized: Boolean; PreprocessorInitialized: Boolean;
PreprocessScriptProc: TPreprocessScriptProc; PreprocessScriptProc: TPreprocessScriptProc;
@ -714,41 +699,6 @@ begin
F.Seek(0); F.Seek(0);
end; end;
function Is64BitPEImage(const Filename: String): Boolean;
{ Returns True if the specified file is a non-32-bit PE image, False
otherwise. }
var
F: TFile;
DosHeader: packed record
Sig: array[0..1] of AnsiChar;
Other: array[0..57] of Byte;
PEHeaderOffset: LongWord;
end;
PESigAndHeader: packed record
Sig: DWORD;
Header: TImageFileHeader;
OptHeaderMagic: Word;
end;
begin
Result := False;
F := TFile.Create(Filename, fdOpenExisting, faRead, fsRead);
try
if F.Read(DosHeader, SizeOf(DosHeader)) = SizeOf(DosHeader) then begin
if (DosHeader.Sig[0] = 'M') and (DosHeader.Sig[1] = 'Z') and
(DosHeader.PEHeaderOffset <> 0) then begin
F.Seek(DosHeader.PEHeaderOffset);
if F.Read(PESigAndHeader, SizeOf(PESigAndHeader)) = SizeOf(PESigAndHeader) then begin
if (PESigAndHeader.Sig = IMAGE_NT_SIGNATURE) and
(PESigAndHeader.OptHeaderMagic <> IMAGE_NT_OPTIONAL_HDR32_MAGIC) then
Result := True;
end;
end;
end;
finally
F.Free;
end;
end;
function CountChars(const S: String; C: Char): Integer; function CountChars(const S: String; C: Char): Integer;
var var
I: Integer; I: Integer;
@ -817,13 +767,8 @@ begin
if Result[I] = '{' then if Result[I] = '{' then
Delete(Result, I, 1); Delete(Result, I, 1);
end end
else begin else
{$IFNDEF UNICODE}
if Result[I] in CompilerLeadBytes then
Inc(I);
{$ENDIF}
Inc(I); Inc(I);
end;
end; end;
end; end;
@ -1556,9 +1501,7 @@ begin
UsedUserAreas.Duplicates := dupIgnore; UsedUserAreas.Duplicates := dupIgnore;
PreprocIncludedFilenames := TStringList.Create; PreprocIncludedFilenames := TStringList.Create;
DefaultLangData := TLangData.Create; DefaultLangData := TLangData.Create;
{$IFDEF UNICODE}
PreLangDataList := TLowFragList.Create; PreLangDataList := TLowFragList.Create;
{$ENDIF}
LangDataList := TLowFragList.Create; LangDataList := TLowFragList.Create;
SignToolList := TLowFragList.Create; SignToolList := TLowFragList.Create;
SignTools := TStringList.Create; SignTools := TStringList.Create;
@ -1591,9 +1534,7 @@ begin
SignToolList.Free; SignToolList.Free;
end; end;
LangDataList.Free; LangDataList.Free;
{$IFDEF UNICODE}
PreLangDataList.Free; PreLangDataList.Free;
{$ENDIF}
DefaultLangData.Free; DefaultLangData.Free;
PreprocIncludedFilenames.Free; PreprocIncludedFilenames.Free;
UsedUserAreas.Free; UsedUserAreas.Free;
@ -1622,8 +1563,6 @@ end;
procedure TSetupCompiler.InitPreprocessor; procedure TSetupCompiler.InitPreprocessor;
{$IFNDEF STATICPREPROC} {$IFNDEF STATICPREPROC}
const
FuncNameSuffix = {$IFDEF UNICODE} 'W' {$ELSE} 'A' {$ENDIF};
var var
Filename: String; Filename: String;
Attr: DWORD; Attr: DWORD;
@ -1643,8 +1582,7 @@ begin
if M = 0 then if M = 0 then
AbortCompileFmt('Failed to load preprocessor DLL "%s" (%d)', AbortCompileFmt('Failed to load preprocessor DLL "%s" (%d)',
[Filename, GetLastError]); [Filename, GetLastError]);
PreprocessScriptProc := GetProcAddress(M, PreprocessScriptProc := GetProcAddress(M, 'ISPreprocessScriptW');
PAnsiChar('ISPreprocessScript' + FuncNameSuffix));
if not Assigned(PreprocessScriptProc) then if not Assigned(PreprocessScriptProc) then
AbortCompileFmt('Failed to get address of functions in "%s"', [Filename]); AbortCompileFmt('Failed to get address of functions in "%s"', [Filename]);
end; end;
@ -2203,7 +2141,6 @@ var
UseCache := not (LangSection and LangSectionPre); UseCache := not (LangSection and LangSectionPre);
AnsiConvertCodePage := 0; AnsiConvertCodePage := 0;
{$IFDEF UNICODE}
if LangSection then begin if LangSection then begin
{ During a Pre pass on an .isl file, use code page 1252 for translation. { During a Pre pass on an .isl file, use code page 1252 for translation.
Previously, the system code page was used, but on DBCS that resulted in Previously, the system code page was used, but on DBCS that resulted in
@ -2219,7 +2156,6 @@ var
AnsiConvertCodePage := TPreLangData(PreLangDataList[Ext]).LanguageCodePage; AnsiConvertCodePage := TPreLangData(PreLangDataList[Ext]).LanguageCodePage;
end; end;
end; end;
{$ENDIF}
Lines := ReadScriptFile(Filename, UseCache, AnsiConvertCodePage); Lines := ReadScriptFile(Filename, UseCache, AnsiConvertCodePage);
try try
@ -2822,13 +2758,7 @@ begin
1:{ Constant is OK } 1:{ Constant is OK }
end; end;
{$IFDEF UNICODE}
end; end;
{$ELSE}
end
else if S[I] in CompilerLeadBytes then
Inc(I);
{$ENDIF}
Inc(I); Inc(I);
end; end;
end; end;
@ -2848,7 +2778,7 @@ begin
Decl := '0'; Decl := '0';
for I := Low(Parameters) to High(Parameters) do begin for I := Low(Parameters) to High(Parameters) do begin
if Parameters[I].VType = {$IFDEF UNICODE} vtUnicodeString {$ELSE} vtAnsiString {$ENDIF} then if Parameters[I].VType = vtUnicodeString then
Decl := Decl + ' @String' Decl := Decl + ' @String'
else if Parameters[I].VType = vtInteger then else if Parameters[I].VType = vtInteger then
Decl := Decl + ' @LongInt' Decl := Decl + ' @LongInt'
@ -3251,18 +3181,15 @@ procedure TSetupCompiler.ReadTextFile(const Filename: String; const LangIndex: I
var var
F: TFile; F: TFile;
Size: Cardinal; Size: Cardinal;
{$IFDEF UNICODE}
UnicodeFile, RTFFile: Boolean; UnicodeFile, RTFFile: Boolean;
AnsiConvertCodePage: Integer; AnsiConvertCodePage: Integer;
S: RawByteString; S: RawByteString;
U: String; U: String;
{$ENDIF}
begin begin
try try
F := TFile.Create(Filename, fdOpenExisting, faRead, fsRead); F := TFile.Create(Filename, fdOpenExisting, faRead, fsRead);
try try
Size := F.Size.Lo; Size := F.Size.Lo;
{$IFDEF UNICODE}
SetLength(S, Size); SetLength(S, Size);
F.ReadBuffer(S[1], Size); F.ReadBuffer(S[1], Size);
@ -3291,10 +3218,6 @@ begin
Text := S; Text := S;
end else end else
Text := S; Text := S;
{$ELSE}
SetLength(Text, Size);
F.ReadBuffer(Text[1], Size);
{$ENDIF}
finally finally
F.Free; F.Free;
end; end;
@ -3926,10 +3849,6 @@ begin
CompressProps.WorkerProcessFilename := GetLZMAExeFilename(True) CompressProps.WorkerProcessFilename := GetLZMAExeFilename(True)
else else
CompressProps.WorkerProcessFilename := ''; CompressProps.WorkerProcessFilename := '';
if (CompressProps.WorkerProcessFilename <> '') and
(Byte(GetVersion()) < 5) then
AbortCompileOnLineFmt(SCompilerDirectiveRequiresWindows2000,
['Setup', KeyName]);
end; end;
ssMergeDuplicateFiles: begin ssMergeDuplicateFiles: begin
DontMergeDuplicateFiles := not StrToBool(Value); DontMergeDuplicateFiles := not StrToBool(Value);
@ -3942,8 +3861,8 @@ begin
Invalid; Invalid;
if SetupHeader.MinVersion.WinVersion <> 0 then if SetupHeader.MinVersion.WinVersion <> 0 then
AbortCompileOnLine(SCompilerMinVersionWinMustBeZero); AbortCompileOnLine(SCompilerMinVersionWinMustBeZero);
if SetupHeader.MinVersion.NTVersion < $06000000 then if SetupHeader.MinVersion.NTVersion < $06010000 then
AbortCompileOnLineFmt(SCompilerMinVersionNTTooLow, ['6.0']); AbortCompileOnLineFmt(SCompilerMinVersionNTTooLow, ['6.1']);
end; end;
ssMissingMessagesWarning: begin ssMissingMessagesWarning: begin
MissingMessagesWarning := StrToBool(Value); MissingMessagesWarning := StrToBool(Value);
@ -4005,8 +3924,6 @@ begin
SetSetupHeaderOption(shRestartIfNeededByRun); SetSetupHeaderOption(shRestartIfNeededByRun);
end; end;
ssSetupIconFile: begin ssSetupIconFile: begin
if (Value <> '') and (Win32Platform <> VER_PLATFORM_WIN32_NT) then
AbortCompileOnLineFmt(SCompilerDirectiveIsNTOnly, ['Setup', KeyName]);
SetupIconFilename := Value; SetupIconFilename := Value;
end; end;
ssSetupLogging: begin ssSetupLogging: begin
@ -4030,11 +3947,7 @@ begin
SetSetupHeaderOption(shShowTasksTreeLines); SetSetupHeaderOption(shShowTasksTreeLines);
end; end;
ssShowUndisplayableLanguages: begin ssShowUndisplayableLanguages: begin
{$IFDEF UNICODE}
WarningsList.Add(Format(SCompilerEntryObsolete, ['Setup', KeyName])); WarningsList.Add(Format(SCompilerEntryObsolete, ['Setup', KeyName]));
{$ELSE}
SetSetupHeaderOption(shShowUndisplayableLanguages);
{$ENDIF}
end; end;
ssSignedUninstaller: begin ssSignedUninstaller: begin
SetSetupHeaderOption(shSignedUninstaller); SetSetupHeaderOption(shSignedUninstaller);
@ -4278,7 +4191,6 @@ function TSetupCompiler.FindLangEntryIndexByName(const AName: String;
var var
I: Integer; I: Integer;
begin begin
{$IFDEF UNICODE}
if Pre then begin if Pre then begin
for I := 0 to PreLangDataList.Count-1 do begin for I := 0 to PreLangDataList.Count-1 do begin
if TPreLangData(PreLangDataList[I]).Name = AName then begin if TPreLangData(PreLangDataList[I]).Name = AName then begin
@ -4288,7 +4200,6 @@ begin
end; end;
AbortCompileOnLineFmt(SCompilerUnknownLanguage, [AName]); AbortCompileOnLineFmt(SCompilerUnknownLanguage, [AName]);
end; end;
{$ENDIF}
for I := 0 to LanguageEntries.Count-1 do begin for I := 0 to LanguageEntries.Count-1 do begin
if PSetupLanguageEntry(LanguageEntries[I]).Name = AName then begin if PSetupLanguageEntry(LanguageEntries[I]).Name = AName then begin
@ -4313,7 +4224,6 @@ begin
Result := -1; Result := -1;
end; end;
{$IFDEF UNICODE}
procedure TSetupCompiler.EnumLangOptionsPreProc(const Line: PChar; const Ext: Integer); procedure TSetupCompiler.EnumLangOptionsPreProc(const Line: PChar; const Ext: Integer);
procedure ApplyToLangEntryPre(const KeyName, Value: String; procedure ApplyToLangEntryPre(const KeyName, Value: String;
@ -4366,7 +4276,6 @@ begin
end else end else
ApplyToLangEntryPre(KeyName, Value, TPreLangData(PreLangDataList[LangIndex]), False); ApplyToLangEntryPre(KeyName, Value, TPreLangData(PreLangDataList[LangIndex]), False);
end; end;
{$ENDIF}
procedure TSetupCompiler.EnumLangOptionsProc(const Line: PChar; const Ext: Integer); procedure TSetupCompiler.EnumLangOptionsProc(const Line: PChar; const Ext: Integer);
@ -4445,7 +4354,7 @@ procedure TSetupCompiler.EnumLangOptionsProc(const Line: PChar; const Ext: Integ
lsLanguageCodePage: begin lsLanguageCodePage: begin
if AffectsMultipleLangs then if AffectsMultipleLangs then
AbortCompileOnLineFmt(SCompilerCantSpecifyLangOption, [KeyName]); AbortCompileOnLineFmt(SCompilerCantSpecifyLangOption, [KeyName]);
{$IFNDEF UNICODE}LangOptions.LanguageCodePage := {$ENDIF}StrToIntCheck(Value); StrToIntCheck(Value);
end; end;
lsLanguageID: begin lsLanguageID: begin
if AffectsMultipleLangs then if AffectsMultipleLangs then
@ -4881,35 +4790,14 @@ type
mkcPgDn, mkcEnd, mkcHome, mkcLeft, mkcUp, mkcRight, mkcDown, mkcIns, mkcPgDn, mkcEnd, mkcHome, mkcLeft, mkcUp, mkcRight, mkcDown, mkcIns,
mkcDel, mkcShift, mkcCtrl, mkcAlt); mkcDel, mkcShift, mkcCtrl, mkcAlt);
{$IFDEF Delphi3OrHigher}
var var
MenuKeyCaps: array[TMenuKeyCap] of string = ( MenuKeyCaps: array[TMenuKeyCap] of string = (
SmkcBkSp, SmkcTab, SmkcEsc, SmkcEnter, SmkcSpace, SmkcPgUp, SmkcBkSp, SmkcTab, SmkcEsc, SmkcEnter, SmkcSpace, SmkcPgUp,
SmkcPgDn, SmkcEnd, SmkcHome, SmkcLeft, SmkcUp, SmkcRight, SmkcPgDn, SmkcEnd, SmkcHome, SmkcLeft, SmkcUp, SmkcRight,
SmkcDown, SmkcIns, SmkcDel, SmkcShift, SmkcCtrl, SmkcAlt); SmkcDown, SmkcIns, SmkcDel, SmkcShift, SmkcCtrl, SmkcAlt);
{$ELSE}
var
MenuKeyCaps: array[TMenuKeyCap] of string;
const
MenuKeyCapIDs: array[TMenuKeyCap] of Word = (
SmkcBkSp, SmkcTab, SmkcEsc, SmkcEnter, SmkcSpace, SmkcPgUp,
SmkcPgDn, SmkcEnd, SmkcHome, SmkcLeft, SmkcUp, SmkcRight,
SmkcDown, SmkcIns, SmkcDel, SmkcShift, SmkcCtrl, SmkcAlt);
{$ENDIF}
procedure TSetupCompiler.EnumIconsProc(const Line: PChar; const Ext: Integer); procedure TSetupCompiler.EnumIconsProc(const Line: PChar; const Ext: Integer);
{$IFNDEF Delphi3OrHigher}
procedure LoadStrings;
var
I: TMenuKeyCap;
begin
for I := Low(TMenuKeyCap) to High(TMenuKeyCap) do
MenuKeyCaps[I] := LoadStr(MenuKeyCapIDs[I]);
end;
{$ENDIF}
function HotKeyToText(HotKey: Word): string; function HotKeyToText(HotKey: Word): string;
function GetSpecialName(HotKey: Word): string; function GetSpecialName(HotKey: Word): string;
@ -5028,19 +4916,15 @@ const
(Name: ParamCommonAfterInstall; Flags: []), (Name: ParamCommonAfterInstall; Flags: []),
(Name: ParamCommonMinVersion; Flags: []), (Name: ParamCommonMinVersion; Flags: []),
(Name: ParamCommonOnlyBelowVersion; Flags: [])); (Name: ParamCommonOnlyBelowVersion; Flags: []));
Flags: array[0..9] of PChar = ( Flags: array[0..8] of PChar = (
'uninsneveruninstall', 'runminimized', 'createonlyiffileexists', 'uninsneveruninstall', 'runminimized', 'createonlyiffileexists',
'useapppaths', 'closeonexit', 'dontcloseonexit', 'runmaximized', 'useapppaths', 'closeonexit', 'dontcloseonexit', 'runmaximized',
'foldershortcut', 'excludefromshowinnewinstall', 'preventpinning'); 'excludefromshowinnewinstall', 'preventpinning');
var var
Values: array[TParam] of TParamValue; Values: array[TParam] of TParamValue;
NewIconEntry: PSetupIconEntry; NewIconEntry: PSetupIconEntry;
S: String; S: String;
begin begin
{$IFNDEF Delphi3OrHigher}
LoadStrings;
{$ENDIF}
ExtractParameters(Line, ParamInfo, Values); ExtractParameters(Line, ParamInfo, Values);
NewIconEntry := AllocMem(SizeOf(TSetupIconEntry)); NewIconEntry := AllocMem(SizeOf(TSetupIconEntry));
@ -5061,9 +4945,8 @@ begin
4: CloseOnExit := icYes; 4: CloseOnExit := icYes;
5: CloseOnExit := icNo; 5: CloseOnExit := icNo;
6: ShowCmd := SW_SHOWMAXIMIZED; 6: ShowCmd := SW_SHOWMAXIMIZED;
7: Include(Options, ioFolderShortcut); 7: Include(Options, ioExcludeFromShowInNewInstall);
8: Include(Options, ioExcludeFromShowInNewInstall); 8: Include(Options, ioPreventPinning);
9: Include(Options, ioPreventPinning);
end; end;
{ Name } { Name }
@ -5613,13 +5496,7 @@ procedure TSetupCompiler.EnumFilesProc(const Line: PChar; const Ext: Integer);
if Result[I] = '{' then begin if Result[I] = '{' then begin
Insert('{', Result, I); Insert('{', Result, I);
Inc(I); Inc(I);
{$IFDEF UNICODE}
end; end;
{$ELSE}
end
else if Result[I] in CompilerLeadBytes then
Inc(I);
{$ENDIF}
Inc(I); Inc(I);
end; end;
end; end;
@ -6009,12 +5886,6 @@ type
if not ExternalFile and not(foIgnoreVersion in NewFileEntry^.Options) and if not ExternalFile and not(foIgnoreVersion in NewFileEntry^.Options) and
(NewFileLocationEntry^.Flags * [foVersionInfoValid, foVersionInfoNotValid] = []) then begin (NewFileLocationEntry^.Flags * [foVersionInfoValid, foVersionInfoNotValid] = []) then begin
AddStatus(Format(SCompilerStatusFilesVerInfo, [SourceFile])); AddStatus(Format(SCompilerStatusFilesVerInfo, [SourceFile]));
{ Windows versions prior to 2000 cannot read version info on 64-bit
images. Throw an error rather than silently failing to read the
version info (which could be dangerous). }
if (Win32Platform <> VER_PLATFORM_WIN32_NT) or (Byte(GetVersion) < 5) then
if Is64BitPEImage(SourceFile) then
AbortCompileOnLine(SCompilerFilesCantReadVersionInfoOn64BitImage);
if GetVersionNumbers(SourceFile, VersionNumbers) then begin if GetVersionNumbers(SourceFile, VersionNumbers) then begin
NewFileLocationEntry^.FileVersionMS := VersionNumbers.MS; NewFileLocationEntry^.FileVersionMS := VersionNumbers.MS;
NewFileLocationEntry^.FileVersionLS := VersionNumbers.LS; NewFileLocationEntry^.FileVersionLS := VersionNumbers.LS;
@ -6078,32 +5949,20 @@ type
function ComparePathStr(P1, P2: PChar): Integer; function ComparePathStr(P1, P2: PChar): Integer;
{ Like CompareStr, but sorts backslashes correctly ('A\B' < 'AB\B') } { Like CompareStr, but sorts backslashes correctly ('A\B' < 'AB\B') }
var var
{$IFNDEF UNICODE}
LastWasLeadByte: BOOL;
{$ENDIF}
C1, C2: Char; C1, C2: Char;
begin begin
{$IFNDEF UNICODE}
LastWasLeadByte := False;
{$ENDIF}
repeat repeat
C1 := P1^; C1 := P1^;
if (C1 = '\') {$IFNDEF UNICODE} and not LastWasLeadByte {$ENDIF} then if C1 = '\' then
C1 := #1; C1 := #1;
C2 := P2^; C2 := P2^;
if (C2 = '\') {$IFNDEF UNICODE} and not LastWasLeadByte {$ENDIF} then if C2 = '\' then
C2 := #1; C2 := #1;
Result := Ord(C1) - Ord(C2); Result := Ord(C1) - Ord(C2);
if Result <> 0 then if Result <> 0 then
Break; Break;
if C1 = #0 then if C1 = #0 then
Break; Break;
{$IFNDEF UNICODE}
if LastWasLeadByte then
LastWasLeadByte := False
else
LastWasLeadByte := IsDBCSLeadByte(Ord(C1));
{$ENDIF}
Inc(P1); Inc(P1);
Inc(P2); Inc(P2);
until False; until False;
@ -6755,7 +6614,6 @@ const
(Name: ParamLanguagesInfoBeforeFile; Flags: [piNoEmpty]), (Name: ParamLanguagesInfoBeforeFile; Flags: [piNoEmpty]),
(Name: ParamLanguagesInfoAfterFile; Flags: [piNoEmpty])); (Name: ParamLanguagesInfoAfterFile; Flags: [piNoEmpty]));
{$IFDEF UNICODE}
procedure TSetupCompiler.EnumLanguagesPreProc(const Line: PChar; const Ext: Integer); procedure TSetupCompiler.EnumLanguagesPreProc(const Line: PChar; const Ext: Integer);
var var
Values: array[TLanguagesParam] of TParamValue; Values: array[TLanguagesParam] of TParamValue;
@ -6786,7 +6644,6 @@ begin
ReadMessagesFromFilesPre(Filename, PreLangDataList.Count-1); ReadMessagesFromFilesPre(Filename, PreLangDataList.Count-1);
end; end;
{$ENDIF}
procedure TSetupCompiler.EnumLanguagesProc(const Line: PChar; const Ext: Integer); procedure TSetupCompiler.EnumLanguagesProc(const Line: PChar; const Ext: Integer);
var var
@ -7032,7 +6889,6 @@ begin
end; end;
end; end;
{$IFDEF UNICODE}
procedure TSetupCompiler.InitPreLangData(const APreLangData: TPreLangData); procedure TSetupCompiler.InitPreLangData(const APreLangData: TPreLangData);
{ Initializes a TPreLangData object with the default settings } { Initializes a TPreLangData object with the default settings }
begin begin
@ -7041,7 +6897,6 @@ begin
LanguageCodePage := 0; LanguageCodePage := 0;
end; end;
end; end;
{$ENDIF}
procedure TSetupCompiler.InitLanguageEntry(var ALanguageEntry: TSetupLanguageEntry); procedure TSetupCompiler.InitLanguageEntry(var ALanguageEntry: TSetupLanguageEntry);
{ Initializes a TSetupLanguageEntry record with the default settings } { Initializes a TSetupLanguageEntry record with the default settings }
@ -7050,9 +6905,6 @@ begin
Name := 'default'; Name := 'default';
LanguageName := 'English'; LanguageName := 'English';
LanguageID := $0409; { U.S. English } LanguageID := $0409; { U.S. English }
{$IFNDEF UNICODE}
LanguageCodePage := 0;
{$ENDIF}
DialogFontName := DefaultDialogFontName; DialogFontName := DefaultDialogFontName;
DialogFontSize := 8; DialogFontSize := 8;
TitleFontName := 'Arial'; TitleFontName := 'Arial';
@ -7067,7 +6919,6 @@ begin
end; end;
end; end;
{$IFDEF UNICODE}
procedure TSetupCompiler.ReadMessagesFromFilesPre(const AFiles: String; procedure TSetupCompiler.ReadMessagesFromFilesPre(const AFiles: String;
const ALangIndex: Integer); const ALangIndex: Integer);
var var
@ -7084,7 +6935,6 @@ begin
CallIdleProc; CallIdleProc;
end; end;
end; end;
{$ENDIF}
procedure TSetupCompiler.ReadMessagesFromFiles(const AFiles: String; procedure TSetupCompiler.ReadMessagesFromFiles(const AFiles: String;
const ALangIndex: Integer); const ALangIndex: Integer);
@ -7123,7 +6973,6 @@ begin
{ ^ Copy(..., 4, Maxint) is to skip past "msg" } { ^ Copy(..., 4, Maxint) is to skip past "msg" }
end; end;
{$IFDEF UNICODE}
procedure TSetupCompiler.ReadMessagesFromScriptPre; procedure TSetupCompiler.ReadMessagesFromScriptPre;
procedure CreateDefaultLanguageEntryPre; procedure CreateDefaultLanguageEntryPre;
@ -7157,7 +7006,6 @@ begin
EnumIniSection(EnumLangOptionsPreProc, 'LangOptions', -1, False, True, '', True, False); EnumIniSection(EnumLangOptionsPreProc, 'LangOptions', -1, False, True, '', True, False);
CallIdleProc; CallIdleProc;
end; end;
{$ENDIF}
procedure TSetupCompiler.ReadMessagesFromScript; procedure TSetupCompiler.ReadMessagesFromScript;
@ -7645,7 +7493,6 @@ procedure TSetupCompiler.Compile;
end; end;
end; end;
{$IFDEF UNICODE}
procedure FreePreLangData; procedure FreePreLangData;
var var
I: Integer; I: Integer;
@ -7655,7 +7502,6 @@ procedure TSetupCompiler.Compile;
PreLangDataList.Delete(I); PreLangDataList.Delete(I);
end; end;
end; end;
{$ENDIF}
procedure FreeLangData; procedure FreeLangData;
var var
@ -7724,9 +7570,6 @@ var
F.WriteBuffer(SetupID, SizeOf(SetupID)); F.WriteBuffer(SetupID, SizeOf(SetupID));
{$IFNDEF UNICODE}
SetupHeader.LeadBytes := CompilerLeadBytes;
{$ENDIF}
SetupHeader.NumLanguageEntries := LanguageEntries.Count; SetupHeader.NumLanguageEntries := LanguageEntries.Count;
SetupHeader.NumCustomMessageEntries := CustomMessageEntries.Count; SetupHeader.NumCustomMessageEntries := CustomMessageEntries.Count;
SetupHeader.NumPermissionEntries := PermissionEntries.Count; SetupHeader.NumPermissionEntries := PermissionEntries.Count;
@ -8232,7 +8075,7 @@ var
end; end;
end; end;
procedure PrepareSetupE32(var M: TMemoryFile; const RemoveManifestDllHijackProtection: Boolean); procedure PrepareSetupE32(var M: TMemoryFile);
var var
TempFilename, E32Filename, ConvertFilename: String; TempFilename, E32Filename, ConvertFilename: String;
ConvertFile: TFile; ConvertFile: TFile;
@ -8258,21 +8101,11 @@ var
UpdateVersionInfo(ConvertFile, TFileVersionNumbers(nil^), VersionInfoProductVersion, VersionInfoCompany, UpdateVersionInfo(ConvertFile, TFileVersionNumbers(nil^), VersionInfoProductVersion, VersionInfoCompany,
'', '', VersionInfoCopyright, VersionInfoProductName, VersionInfoProductTextVersion, VersionInfoOriginalFileName, '', '', VersionInfoCopyright, VersionInfoProductName, VersionInfoProductTextVersion, VersionInfoOriginalFileName,
False); False);
if RemoveManifestDllHijackProtection then begin
AddStatus(Format(SCompilerStatusUpdatingManifest, ['SETUP.E32']));
CompExeUpdate.RemoveManifestDllHijackProtection(ConvertFile, False);
end else begin
{ Use the opportunity to check that the manifest is correctly prepared for removing the
protection, without actually removing it. Doing this only once per compile since there's
only one source manifest. }
CompExeUpdate.RemoveManifestDllHijackProtection(ConvertFile, True);
end;
finally finally
ConvertFile.Free; ConvertFile.Free;
end; end;
M := TMemoryFile.Create(ConvertFilename); M := TMemoryFile.Create(ConvertFilename);
UpdateSetupPEHeaderFields(M, RemoveManifestDllHijackProtection, TerminalServicesAware, UpdateSetupPEHeaderFields(M, TerminalServicesAware, DEPCompatible, ASLRCompatible);
DEPCompatible, ASLRCompatible);
if shSignedUninstaller in SetupHeader.Options then if shSignedUninstaller in SetupHeader.Options then
SignSetupE32(M); SignSetupE32(M);
finally finally
@ -8408,10 +8241,8 @@ var
SetupE32: TMemoryFile; SetupE32: TMemoryFile;
I: Integer; I: Integer;
AppNameHasConsts, AppVersionHasConsts, AppPublisherHasConsts, AppNameHasConsts, AppVersionHasConsts, AppPublisherHasConsts,
AppCopyrightHasConsts, AppIdHasConsts, Uninstallable, RemoveManifestDllHijackProtection: Boolean; AppCopyrightHasConsts, AppIdHasConsts, Uninstallable: Boolean;
PrivilegesRequiredValue: String; PrivilegesRequiredValue: String;
OSVersionInfo: TOSVersionInfo;
WindowsVersion: Cardinal;
begin begin
{ Sanity check: A single TSetupCompiler instance cannot be used to do { Sanity check: A single TSetupCompiler instance cannot be used to do
multiple compiles. A separate instance must be used for each compile, multiple compiles. A separate instance must be used for each compile,
@ -8758,28 +8589,28 @@ begin
{ Prepare Setup executable & signed uninstaller data } { Prepare Setup executable & signed uninstaller data }
if Output then begin if Output then begin
AddStatus(SCompilerStatusPreparingSetupExe); AddStatus(SCompilerStatusPreparingSetupExe);
{ The manifest block protecting special DLLs breaks Vista compatibility } PrepareSetupE32(SetupE32);
RemoveManifestDllHijackProtection := SetupHeader.MinVersion.NTVersion < $06010000; end else
if RemoveManifestDllHijackProtection then
WarningsList.Add(Format(SCompilerRemoveManifestDllHijackProtection, ['6.1']))
else begin
OSVersionInfo.dwOSVersionInfoSize := SizeOf(OSVersionInfo);
if GetVersionEx(OSVersionInfo) then begin
WindowsVersion := (Byte(OSVersionInfo.dwMajorVersion) shl 24) or
(Byte(OSVersionInfo.dwMinorVersion) shl 16) or Word(OSVersionInfo.dwBuildNumber);
if WindowsVersion < Cardinal($06010000) then
WarningsList.Add(Format(SCompilerDidntRemoveManifestDllHijackProtection, ['6.1']))
end;
end;
PrepareSetupE32(SetupE32, RemoveManifestDllHijackProtection);
end else begin
AddStatus(SCompilerStatusSkippingPreparingSetupExe); AddStatus(SCompilerStatusSkippingPreparingSetupExe);
RemoveManifestDllHijackProtection := False; { silence compiler }
end;
{ Read languages: { Read languages:
Non Unicode: 0. Determine final code pages:
Unicode Setup uses Unicode text and does not depend on the system code page. To
provide Setup with Unicode text without requiring Unicode .isl files (but still
supporting Unicode .iss, license and info files), the compiler converts the .isl
files to Unicode during compilation. It also does this if it finds ANSI plain text
license and info files. To be able to do this it needs to know the language's code
page but as seen above it can't simply take this from the current .isl. And license
and info files do not even have a language code page setting.
This means the Unicode compiler has to do an extra phase: following the logic above
it first determines the final language code page for each language, storing these
into an extra list called PreDataList, and then it continues as normal while using
the final language code page for any conversions needed.
Note: it must avoid caching the .isl files while determining the code pages, since
the conversion is done *before* the caching.
1. Read Default.isl messages: 1. Read Default.isl messages:
@ -8835,35 +8666,8 @@ begin
4. Check 'language completeness' of custom message constants: 4. Check 'language completeness' of custom message constants:
CheckCustomMessageDefinitions is used to check for missing custom messages and CheckCustomMessageDefinitions is used to check for missing custom messages and
where necessary it 'promotes' a custom message by resetting its LangIndex property where necessary it 'promotes' a custom message by resetting its LangIndex property
to -1. to -1. }
5. Display the language at run time:
Setup checks if the system code page matches the language code page, and only shows
the language if it does. The system code page is then used to display all text, this
does not only include messages and custom messages, but also any readme and info files.
Unicode:
Unicode works exactly like above with one exception:
0. Determine final code pages:
Unicode Setup uses Unicode text and does not depend on the system code page. To
provide Setup with Unicode text without requiring Unicode .isl files (but still
supporting Unicode .iss, license and info files), the compiler converts the .isl
files to Unicode during compilation. It also does this if it finds ANSI plain text
license and info files. To be able to do this it needs to know the language's code
page but as seen above it can't simply take this from the current .isl. And license
and info files do not even have a language code page setting.
This means the Unicode compiler has to do an extra phase: following the logic above
it first determines the final language code page for each language, storing these
into an extra list called PreDataList, and then it continues as normal while using
the final language code page for any conversions needed.
Note: it must avoid caching the .isl files while determining the code pages, since
the conversion is done *before* the caching. }
{$IFDEF UNICODE}
{ 0. Determine final language code pages } { 0. Determine final language code pages }
AddStatus(SCompilerStatusDeterminingCodePages); AddStatus(SCompilerStatusDeterminingCodePages);
@ -8874,7 +8678,6 @@ begin
{ 0.2. Read [LangOptions] in the script } { 0.2. Read [LangOptions] in the script }
ReadMessagesFromScriptPre; ReadMessagesFromScriptPre;
{$ENDIF}
{ 1. Read Default.isl messages } { 1. Read Default.isl messages }
AddStatus(SCompilerStatusReadingDefaultMessages); AddStatus(SCompilerStatusReadingDefaultMessages);
@ -9046,8 +8849,7 @@ begin
end; end;
SetupFile := TFile.Create(ExeFilename, fdOpenExisting, faReadWrite, fsNone); SetupFile := TFile.Create(ExeFilename, fdOpenExisting, faReadWrite, fsNone);
try try
UpdateSetupPEHeaderFields(SetupFile, RemoveManifestDllHijackProtection, UpdateSetupPEHeaderFields(SetupFile, TerminalServicesAware, DEPCompatible, ASLRCompatible);
TerminalServicesAware, DEPCompatible, ASLRCompatible);
SizeOfExe := SetupFile.Size.Lo; SizeOfExe := SetupFile.Size.Lo;
finally finally
SetupFile.Free; SetupFile.Free;
@ -9107,10 +8909,7 @@ begin
True); True);
{ Update manifest if needed } { Update manifest if needed }
if RemoveManifestDllHijackProtection then begin if UseSetupLdr then begin
AddStatus(Format(SCompilerStatusUpdatingManifest, ['SETUP.EXE']));
CompExeUpdate.RemoveManifestDllHijackProtection(ExeFile, False);
end else if UseSetupLdr then begin
AddStatus(Format(SCompilerStatusUpdatingManifest, ['SETUP.EXE'])); AddStatus(Format(SCompilerStatusUpdatingManifest, ['SETUP.EXE']));
CompExeUpdate.PreventCOMCTL32Sideloading(ExeFile); CompExeUpdate.PreventCOMCTL32Sideloading(ExeFile);
end; end;
@ -9186,9 +8985,7 @@ begin
FileLocationEntryFilenames.Clear; FileLocationEntryFilenames.Clear;
FreeLineInfoList(ExpectedCustomMessageNames); FreeLineInfoList(ExpectedCustomMessageNames);
FreeLangData; FreeLangData;
{$IFDEF UNICODE}
FreePreLangData; FreePreLangData;
{$ENDIF}
FreeScriptFiles; FreeScriptFiles;
FreeLineInfoList(CodeText); FreeLineInfoList(CodeText);
FreeAndNil(CompressProps); FreeAndNil(CompressProps);
@ -9360,10 +9157,6 @@ begin
end; end;
initialization initialization
{$IFNDEF UNICODE}
GetLeadBytes(CompilerLeadBytes);
ConstLeadBytes := @CompilerLeadBytes;
{$ENDIF}
finalization finalization
if CryptProv <> 0 then begin if CryptProv <> 0 then begin
CryptReleaseContext(CryptProv, 0); CryptReleaseContext(CryptProv, 0);

View File

@ -2,7 +2,7 @@ unit DebugClient;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2019 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -71,9 +71,8 @@ begin
if DebugClientWnd = 0 then if DebugClientWnd = 0 then
InternalError('Failed to create DebugClientWnd'); InternalError('Failed to create DebugClientWnd');
{ On Vista, unprivileged processes can't send messages to elevated processes { Unprivileged processes can't send messages to elevated processes by default.
by default. Allow the debugger (which normally runs unprivileged) to send Allow the debugger (which normally runs unprivileged) to send messages to us. }
messages to us. }
for I := Low(DebugClientMessages) to High(DebugClientMessages) do for I := Low(DebugClientMessages) to High(DebugClientMessages) do
AddToWindowMessageFilterEx(DebugClientWnd, DebugClientMessages[I]); AddToWindowMessageFilterEx(DebugClientWnd, DebugClientMessages[I]);

View File

@ -2,7 +2,7 @@ unit DebugStruct;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2020 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -101,11 +101,9 @@ function GetThreadTopWindow: HWND;
function SendCopyDataMessage(DestWnd, SourceWnd: HWND; CopyDataMsg: DWORD; function SendCopyDataMessage(DestWnd, SourceWnd: HWND; CopyDataMsg: DWORD;
Data: Pointer; Size: Cardinal): LRESULT; Data: Pointer; Size: Cardinal): LRESULT;
function SendCopyDataMessageStr(DestWnd, SourceWnd: HWND; CopyDataMsg: DWORD; function SendCopyDataMessageStr(DestWnd, SourceWnd: HWND; CopyDataMsg: DWORD;
Data: AnsiString): LRESULT;{$IFDEF UNICODE} overload;{$ENDIF} Data: AnsiString): LRESULT; overload;
{$IFDEF UNICODE}
function SendCopyDataMessageStr(DestWnd, SourceWnd: HWND; CopyDataMsg: DWORD; function SendCopyDataMessageStr(DestWnd, SourceWnd: HWND; CopyDataMsg: DWORD;
Data: UnicodeString): LRESULT; overload; Data: UnicodeString): LRESULT; overload;
{$ENDIF}
implementation implementation
@ -140,29 +138,15 @@ end;
function SendCopyDataMessageStr(DestWnd, SourceWnd: HWND; CopyDataMsg: DWORD; function SendCopyDataMessageStr(DestWnd, SourceWnd: HWND; CopyDataMsg: DWORD;
Data: AnsiString): LRESULT; Data: AnsiString): LRESULT;
begin begin
{ Windows 95/98/Me bug workaround: Call UniqueString to ensure the string is
in writable memory. Amazingly enough, sending a WM_COPYDATA message with a
read-only buffer causes a fatal page fault error. }
if (Win32Platform = VER_PLATFORM_WIN32_WINDOWS) and
IsBadWritePtr(Pointer(Data), Length(Data)*SizeOf(Data[1])) then
UniqueString(Data);
Result := SendCopyDataMessage(DestWnd, SourceWnd, CopyDataMsg, Result := SendCopyDataMessage(DestWnd, SourceWnd, CopyDataMsg,
Pointer(Data), Length(Data)*SizeOf(Data[1])); Pointer(Data), Length(Data)*SizeOf(Data[1]));
end; end;
{$IFDEF UNICODE}
function SendCopyDataMessageStr(DestWnd, SourceWnd: HWND; CopyDataMsg: DWORD; function SendCopyDataMessageStr(DestWnd, SourceWnd: HWND; CopyDataMsg: DWORD;
Data: UnicodeString): LRESULT; Data: UnicodeString): LRESULT;
begin begin
{ Windows 95/98/Me bug workaround: Call UniqueString to ensure the string is
in writable memory. Amazingly enough, sending a WM_COPYDATA message with a
read-only buffer causes a fatal page fault error. }
if (Win32Platform = VER_PLATFORM_WIN32_WINDOWS) and
IsBadWritePtr(Pointer(Data), Length(Data)*SizeOf(Data[1])) then
UniqueString(Data);
Result := SendCopyDataMessage(DestWnd, SourceWnd, CopyDataMsg, Result := SendCopyDataMessage(DestWnd, SourceWnd, CopyDataMsg,
Pointer(Data), Length(Data)*SizeOf(Data[1])); Pointer(Data), Length(Data)*SizeOf(Data[1]));
end; end;
{$ENDIF}
end. end.

View File

@ -96,18 +96,14 @@ type
FBufferOffset, FBufferSize: Cardinal; FBufferOffset, FBufferSize: Cardinal;
FEof: Boolean; FEof: Boolean;
FBuffer: array[0..4095] of AnsiChar; FBuffer: array[0..4095] of AnsiChar;
{$IFDEF UNICODE}
FSawFirstLine: Boolean; FSawFirstLine: Boolean;
FCodePage: Cardinal; FCodePage: Cardinal;
{$ENDIF} function DoReadLine(const UTF8: Boolean): AnsiString;
function DoReadLine{$IFDEF UNICODE}(const UTF8: Boolean){$ENDIF}: AnsiString;
function GetEof: Boolean; function GetEof: Boolean;
procedure FillBuffer; procedure FillBuffer;
public public
function ReadLine: String; function ReadLine: String;
{$IFDEF UNICODE}
function ReadAnsiLine: AnsiString; function ReadAnsiLine: AnsiString;
{$ENDIF}
property CodePage: Cardinal write FCodePage; property CodePage: Cardinal write FCodePage;
property Eof: Boolean read GetEof; property Eof: Boolean read GetEof;
end; end;
@ -116,7 +112,7 @@ type
private private
FSeekedToEnd: Boolean; FSeekedToEnd: Boolean;
FUTF8NoPreamble: Boolean; FUTF8NoPreamble: Boolean;
procedure DoWrite(const S: AnsiString{$IFDEF UNICODE}; const UTF8: Boolean{$ENDIF}); procedure DoWrite(const S: AnsiString; const UTF8: Boolean);
protected protected
function CreateHandle(const AFilename: String; function CreateHandle(const AFilename: String;
ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess; ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
@ -125,10 +121,8 @@ type
property UTF8NoPreamble: Boolean read FUTF8NoPreamble write FUTF8NoPreamble; property UTF8NoPreamble: Boolean read FUTF8NoPreamble write FUTF8NoPreamble;
procedure Write(const S: String); procedure Write(const S: String);
procedure WriteLine(const S: String); procedure WriteLine(const S: String);
{$IFDEF UNICODE}
procedure WriteAnsi(const S: AnsiString); procedure WriteAnsi(const S: AnsiString);
procedure WriteAnsiLine(const S: AnsiString); procedure WriteAnsiLine(const S: AnsiString);
{$ENDIF}
end; end;
TFileMapping = class TFileMapping = class
@ -438,29 +432,21 @@ begin
end; end;
function TTextFileReader.ReadLine: String; function TTextFileReader.ReadLine: String;
{$IFDEF UNICODE}
var var
S: RawByteString; S: RawByteString;
{$ENDIF}
begin begin
{$IFDEF UNICODE}
S := DoReadLine(True); S := DoReadLine(True);
if FCodePage <> 0 then if FCodePage <> 0 then
SetCodePage(S, FCodePage, False); SetCodePage(S, FCodePage, False);
Result := String(S); Result := String(S);
{$ELSE}
Result := DoReadLine;
{$ENDIF}
end; end;
{$IFDEF UNICODE}
function TTextFileReader.ReadAnsiLine: AnsiString; function TTextFileReader.ReadAnsiLine: AnsiString;
begin begin
Result := DoReadLine(False); Result := DoReadLine(False);
end; end;
{$ENDIF}
function TTextFileReader.DoReadLine{$IFDEF UNICODE}(const UTF8: Boolean){$ENDIF}: AnsiString; function TTextFileReader.DoReadLine(const UTF8: Boolean): AnsiString;
var var
I, L: Cardinal; I, L: Cardinal;
S: AnsiString; S: AnsiString;
@ -502,7 +488,7 @@ begin
Break; Break;
end; end;
end; end;
{$IFDEF UNICODE}
if not FSawFirstLine then begin if not FSawFirstLine then begin
if UTF8 then begin if UTF8 then begin
{ Handle UTF8 as requested: check for a BOM at the start and if not found then check entire file } { Handle UTF8 as requested: check for a BOM at the start and if not found then check entire file }
@ -526,7 +512,7 @@ begin
end; end;
FSawFirstLine := True; FSawFirstLine := True;
end; end;
{$ENDIF}
Result := S; Result := S;
end; end;
@ -545,17 +531,11 @@ begin
ASharing); ASharing);
end; end;
{$IFDEF UNICODE}
procedure TTextFileWriter.DoWrite(const S: AnsiString; const UTF8: Boolean); procedure TTextFileWriter.DoWrite(const S: AnsiString; const UTF8: Boolean);
{$ELSE}
procedure TTextFileWriter.DoWrite(const S: String);
{$ENDIF}
{ Writes a string to the file, seeking to the end first if necessary } { Writes a string to the file, seeking to the end first if necessary }
const const
CRLF: array[0..1] of AnsiChar = (#13, #10); CRLF: array[0..1] of AnsiChar = (#13, #10);
{$IFDEF UNICODE}
UTF8Preamble: array[0..2] of AnsiChar = (#$EF, #$BB, #$BF); UTF8Preamble: array[0..2] of AnsiChar = (#$EF, #$BB, #$BF);
{$ENDIF}
var var
I: Integer64; I: Integer64;
C: AnsiChar; C: AnsiChar;
@ -578,12 +558,8 @@ begin
{ Otherwise, append CRLF } { Otherwise, append CRLF }
WriteBuffer(CRLF, SizeOf(CRLF)); WriteBuffer(CRLF, SizeOf(CRLF));
end; end;
{$IFDEF UNICODE}
end else if UTF8 and not FUTF8NoPreamble then end else if UTF8 and not FUTF8NoPreamble then
WriteBuffer(UTF8Preamble, SizeOf(UTF8Preamble)); WriteBuffer(UTF8Preamble, SizeOf(UTF8Preamble));
{$ELSE}
end;
{$ENDIF}
FSeekedToEnd := True; FSeekedToEnd := True;
end; end;
WriteBuffer(Pointer(S)^, Length(S)); WriteBuffer(Pointer(S)^, Length(S));
@ -591,11 +567,7 @@ end;
procedure TTextFileWriter.Write(const S: String); procedure TTextFileWriter.Write(const S: String);
begin begin
{$IFDEF UNICODE}
DoWrite(UTF8Encode(S), True); DoWrite(UTF8Encode(S), True);
{$ELSE}
DoWrite(S);
{$ENDIF}
end; end;
procedure TTextFileWriter.WriteLine(const S: String); procedure TTextFileWriter.WriteLine(const S: String);
@ -603,7 +575,6 @@ begin
Write(S + #13#10); Write(S + #13#10);
end; end;
{$IFDEF UNICODE}
procedure TTextFileWriter.WriteAnsi(const S: AnsiString); procedure TTextFileWriter.WriteAnsi(const S: AnsiString);
begin begin
DoWrite(S, False); DoWrite(S, False);
@ -613,7 +584,6 @@ procedure TTextFileWriter.WriteAnsiLine(const S: AnsiString);
begin begin
WriteAnsi(S + #13#10); WriteAnsi(S + #13#10);
end; end;
{$ENDIF}
{ TFileMapping } { TFileMapping }
@ -629,9 +599,7 @@ const
begin begin
inherited Create; inherited Create;
{ Dynamically import RtlNtStatusToDosError since Windows 95 doesn't have it } if not Assigned(_RtlNtStatusToDosError) then
if not Assigned(_RtlNtStatusToDosError) and
(Win32Platform = VER_PLATFORM_WIN32_NT) then
_RtlNtStatusToDosError := GetProcAddress(GetModuleHandle('ntdll.dll'), _RtlNtStatusToDosError := GetProcAddress(GetModuleHandle('ntdll.dll'),
'RtlNtStatusToDosError'); 'RtlNtStatusToDosError');
@ -684,16 +652,14 @@ begin
(Cardinal(EExternalException(E).ExceptionRecord.NumberParameters) >= Cardinal(2)) and (Cardinal(EExternalException(E).ExceptionRecord.NumberParameters) >= Cardinal(2)) and
(Cardinal(EExternalException(E).ExceptionRecord.ExceptionInformation[1]) >= Cardinal(FMemory)) and (Cardinal(EExternalException(E).ExceptionRecord.ExceptionInformation[1]) >= Cardinal(FMemory)) and
(Cardinal(EExternalException(E).ExceptionRecord.ExceptionInformation[1]) < Cardinal(Cardinal(FMemory) + FMapSize)) then begin (Cardinal(EExternalException(E).ExceptionRecord.ExceptionInformation[1]) < Cardinal(Cardinal(FMemory) + FMapSize)) then begin
{ NT has a third parameter containing the NT status code of the error { There should be a third parameter containing the NT status code of the error
condition that caused the exception. Convert that into a Win32 error code condition that caused the exception. Convert that into a Win32 error code
and use it to generate our error message. } and use it to generate our error message. }
if (Cardinal(EExternalException(E).ExceptionRecord.NumberParameters) >= Cardinal(3)) and if (Cardinal(EExternalException(E).ExceptionRecord.NumberParameters) >= Cardinal(3)) and
Assigned(_RtlNtStatusToDosError) then Assigned(_RtlNtStatusToDosError) then
TFile.RaiseError(_RtlNtStatusToDosError(EExternalException(E).ExceptionRecord.ExceptionInformation[2])) TFile.RaiseError(_RtlNtStatusToDosError(EExternalException(E).ExceptionRecord.ExceptionInformation[2]))
else begin else begin
{ Windows 9x/Me doesn't have a third parameter, and 95 doesn't have { Use generic "The system cannot [read|write] to the specified device" errors }
RtlNtStatusToDosError, so use generic "The system cannot [read|write]
to the specified device" errors }
if EExternalException(E).ExceptionRecord.ExceptionInformation[0] = 0 then if EExternalException(E).ExceptionRecord.ExceptionInformation[0] = 0 then
TFile.RaiseError(ERROR_READ_FAULT) TFile.RaiseError(ERROR_READ_FAULT)
else else

View File

@ -2,7 +2,7 @@ unit Helper;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2010 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -10,8 +10,6 @@ unit Helper;
NOTE: These functions are NOT thread-safe. Do not call them from multiple NOTE: These functions are NOT thread-safe. Do not call them from multiple
threads simultaneously. threads simultaneously.
$jrsoftware: issrc/Projects/Helper.pas,v 1.14 2010/10/20 02:43:26 jr Exp $
} }
interface interface
@ -146,7 +144,6 @@ begin
end; end;
procedure FillWideCharBuffer(var Buf: array of WideChar; const S: String); procedure FillWideCharBuffer(var Buf: array of WideChar; const S: String);
{$IFDEF UNICODE}
begin begin
if High(Buf) <= 0 then if High(Buf) <= 0 then
InternalError('FillWideCharBuffer: Invalid Buf'); InternalError('FillWideCharBuffer: Invalid Buf');
@ -154,23 +151,6 @@ begin
InternalError('FillWideCharBuffer: String too long'); InternalError('FillWideCharBuffer: String too long');
StrPLCopy(Buf, S, High(Buf)); StrPLCopy(Buf, S, High(Buf));
end; end;
{$ELSE}
var
SourceLen, DestLen: Integer;
begin
if High(Buf) <= 0 then
InternalError('FillWideCharBuffer: Invalid Buf');
SourceLen := Length(S);
if SourceLen = 0 then
DestLen := 0
else begin
DestLen := MultiByteToWideChar(CP_ACP, 0, PChar(S), SourceLen, Buf, High(Buf));
if DestLen <= 0 then
InternalError('FillWideCharBuffer: MultiByteToWideChar failed');
end;
Buf[DestLen] := #0;
end;
{$ENDIF}
{ THelper } { THelper }

View File

@ -2,13 +2,11 @@ unit HtmlHelpFunc;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2006 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
Functions for HTML Help Functions for HTML Help
$jrsoftware: issrc/Projects/HtmlHelpFunc.pas,v 1.6 2009/03/23 23:16:44 mlaan Exp $
} }
interface interface
@ -56,7 +54,7 @@ begin
if HHCtrl = 0 then begin if HHCtrl = 0 then begin
HHCtrl := LoadLibrary(PChar(AddBackslash(GetSystemDir) + 'hhctrl.ocx')); HHCtrl := LoadLibrary(PChar(AddBackslash(GetSystemDir) + 'hhctrl.ocx'));
if HHCtrl <> 0 then if HHCtrl <> 0 then
HtmlHelp := GetProcAddress(HHCtrl, {$IFDEF UNICODE}'HtmlHelpW'{$ELSE}'HtmlHelpA'{$ENDIF}) HtmlHelp := GetProcAddress(HHCtrl, 'HtmlHelpW')
else else
HtmlHelp := nil; HtmlHelp := nil;
end; end;

View File

@ -27,8 +27,8 @@ uses
CompTypes in 'CompTypes.pas'; CompTypes in 'CompTypes.pas';
{$SetPEFlags IMAGE_FILE_RELOCS_STRIPPED} {$SetPEFlags IMAGE_FILE_RELOCS_STRIPPED}
{$SETPEOSVERSION 6.0} {$SETPEOSVERSION 6.1}
{$SETPESUBSYSVERSION 6.0} {$SETPESUBSYSVERSION 6.1}
{$WEAKLINKRTTI ON} {$WEAKLINKRTTI ON}
{$R ISCC.manifest.res} {$R ISCC.manifest.res}

View File

@ -33,8 +33,8 @@ uses
PathFunc in '..\Components\PathFunc.pas'; PathFunc in '..\Components\PathFunc.pas';
{$IMAGEBASE $00800000} {$IMAGEBASE $00800000}
{$SETPEOSVERSION 6.0} {$SETPEOSVERSION 6.1}
{$SETPESUBSYSVERSION 6.0} {$SETPESUBSYSVERSION 6.1}
{$WEAKLINKRTTI ON} {$WEAKLINKRTTI ON}
{$R ISCmplr.images.res} {$R ISCmplr.images.res}

View File

@ -3,7 +3,7 @@
Copyright (C) 2001-2002 Alex Yackimoff Copyright (C) 2001-2002 Alex Yackimoff
Inno Setup Inno Setup
Copyright (C) 1997-2020 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
} }
@ -36,8 +36,8 @@ uses
Struct in '..\Struct.pas'; Struct in '..\Struct.pas';
{$IMAGEBASE $01800000} {$IMAGEBASE $01800000}
{$SETPEOSVERSION 6.0} {$SETPEOSVERSION 6.1}
{$SETPESUBSYSVERSION 6.0} {$SETPESUBSYSVERSION 6.1}
{$WEAKLINKRTTI ON} {$WEAKLINKRTTI ON}
{$R ISPP.version.res} {$R ISPP.version.res}

View File

@ -3,7 +3,7 @@
Copyright (C) 2001-2002 Alex Yackimoff Copyright (C) 2001-2002 Alex Yackimoff
Inno Setup Inno Setup
Copyright (C) 1997-2020 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
} }
@ -1500,19 +1500,19 @@ begin
try try
with IInternalFuncParams(Params) do with IInternalFuncParams(Params) do
begin begin
OldDateSeparator := {$IFDEF IS_DXE}FormatSettings.{$ENDIF}DateSeparator; OldDateSeparator := FormatSettings.DateSeparator;
OldTimeSeparator := {$IFDEF IS_DXE}FormatSettings.{$ENDIF}TimeSeparator; OldTimeSeparator := FormatSettings.TimeSeparator;
try try
NewDateSeparatorString := Get(1).AsStr; NewDateSeparatorString := Get(1).AsStr;
NewTimeSeparatorString := Get(2).AsStr; NewTimeSeparatorString := Get(2).AsStr;
if NewDateSeparatorString <> '' then if NewDateSeparatorString <> '' then
{$IFDEF IS_DXE}FormatSettings.{$ENDIF}DateSeparator := NewDateSeparatorString[1]; FormatSettings.DateSeparator := NewDateSeparatorString[1];
if NewTimeSeparatorString <> '' then if NewTimeSeparatorString <> '' then
{$IFDEF IS_DXE}FormatSettings.{$ENDIF}TimeSeparator := NewTimeSeparatorString[1]; FormatSettings.TimeSeparator := NewTimeSeparatorString[1];
MakeStr(ResPtr^, FormatDateTime(Get(0).AsStr, Now())); MakeStr(ResPtr^, FormatDateTime(Get(0).AsStr, Now()));
finally finally
{$IFDEF IS_DXE}FormatSettings.{$ENDIF}TimeSeparator := OldTimeSeparator; FormatSettings.TimeSeparator := OldTimeSeparator;
{$IFDEF IS_DXE}FormatSettings.{$ENDIF}DateSeparator := OldDateSeparator; FormatSettings.DateSeparator := OldDateSeparator;
end; end;
end; end;
except except
@ -1535,23 +1535,23 @@ begin
try try
with IInternalFuncParams(Params) do with IInternalFuncParams(Params) do
begin begin
OldDateSeparator := {$IFDEF IS_DXE}FormatSettings.{$ENDIF}DateSeparator; OldDateSeparator := FormatSettings.DateSeparator;
OldTimeSeparator := {$IFDEF IS_DXE}FormatSettings.{$ENDIF}TimeSeparator; OldTimeSeparator := FormatSettings.TimeSeparator;
try try
NewDateSeparatorString := Get(2).AsStr; NewDateSeparatorString := Get(2).AsStr;
NewTimeSeparatorString := Get(3).AsStr; NewTimeSeparatorString := Get(3).AsStr;
if NewDateSeparatorString <> '' then if NewDateSeparatorString <> '' then
{$IFDEF IS_DXE}FormatSettings.{$ENDIF}DateSeparator := NewDateSeparatorString[1]; FormatSettings.DateSeparator := NewDateSeparatorString[1];
if NewTimeSeparatorString <> '' then if NewTimeSeparatorString <> '' then
{$IFDEF IS_DXE}FormatSettings.{$ENDIF}TimeSeparator := NewTimeSeparatorString[1]; FormatSettings.TimeSeparator := NewTimeSeparatorString[1];
if not FileAge(PrependPath(Ext, Get(0).AsStr), Age) then begin if not FileAge(PrependPath(Ext, Get(0).AsStr), Age) then begin
FuncResult.Error('Invalid file name'); FuncResult.Error('Invalid file name');
Result.Error := ISPPFUNC_FAIL Result.Error := ISPPFUNC_FAIL
end else end else
MakeStr(ResPtr^, FormatDateTime(Get(1).AsStr, Age)); MakeStr(ResPtr^, FormatDateTime(Get(1).AsStr, Age));
finally finally
{$IFDEF IS_DXE}FormatSettings.{$ENDIF}TimeSeparator := OldTimeSeparator; FormatSettings.TimeSeparator := OldTimeSeparator;
{$IFDEF IS_DXE}FormatSettings.{$ENDIF}DateSeparator := OldDateSeparator; FormatSettings.DateSeparator := OldDateSeparator;
end; end;
end; end;
except except
@ -1620,7 +1620,6 @@ end;
function GetMD5OfUnicodeString(Ext: Longint; const Params: IIsppFuncParams; function GetMD5OfUnicodeString(Ext: Longint; const Params: IIsppFuncParams;
const FuncResult: IIsppFuncResult): TIsppFuncResult; stdcall; const FuncResult: IIsppFuncResult): TIsppFuncResult; stdcall;
{$IFDEF UNICODE}
var var
S: UnicodeString; S: UnicodeString;
begin begin
@ -1639,12 +1638,6 @@ begin
end; end;
end; end;
end; end;
{$ELSE}
begin
FuncResult.Error('Cannot call "GetMD5OfUnicodeString" function during non Unicode compilation');
Result.Error := ISPPFUNC_FAIL
end;
{$ENDIF}
function GetSHA1OfFile(Ext: Longint; const Params: IIsppFuncParams; function GetSHA1OfFile(Ext: Longint; const Params: IIsppFuncParams;
const FuncResult: IIsppFuncResult): TIsppFuncResult; stdcall; const FuncResult: IIsppFuncResult): TIsppFuncResult; stdcall;
@ -1703,7 +1696,6 @@ end;
function GetSHA1OfUnicodeString(Ext: Longint; const Params: IIsppFuncParams; function GetSHA1OfUnicodeString(Ext: Longint; const Params: IIsppFuncParams;
const FuncResult: IIsppFuncResult): TIsppFuncResult; stdcall; const FuncResult: IIsppFuncResult): TIsppFuncResult; stdcall;
{$IFDEF UNICODE}
var var
S: UnicodeString; S: UnicodeString;
begin begin
@ -1722,12 +1714,6 @@ begin
end; end;
end; end;
end; end;
{$ELSE}
begin
FuncResult.Error('Cannot call "GetSHA1OfUnicodeString" function during non Unicode compilation');
Result.Error := ISPPFUNC_FAIL
end;
{$ENDIF}
function TrimFunc(Ext: Longint; const Params: IIsppFuncParams; function TrimFunc(Ext: Longint; const Params: IIsppFuncParams;
const FuncResult: IIsppFuncResult): TIsppFuncResult; stdcall; const FuncResult: IIsppFuncResult): TIsppFuncResult; stdcall;

View File

@ -3,7 +3,7 @@
Copyright (C) 2001-2002 Alex Yackimoff Copyright (C) 2001-2002 Alex Yackimoff
Inno Setup Inno Setup
Copyright (C) 1997-2020 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
} }
@ -859,11 +859,7 @@ function TPreprocessor.ProcessPreprocCommand(Command: TPreprocessorCommand;
if Windows.GetTempFileName(PChar(Path), PChar(UpperCase(Original)), 0, PChar(Result)) <> 0 then if Windows.GetTempFileName(PChar(Path), PChar(UpperCase(Original)), 0, PChar(Result)) <> 0 then
SetLength(Result, StrLen(PChar(Result))) SetLength(Result, StrLen(PChar(Result)))
else else
{$IFDEF IS_D7} RaiseLastOSError;
RaiseLastOSError
{$ELSE}
RaiseLastWin32Error;
{$ENDIF}
end; end;
var var
@ -1079,20 +1075,14 @@ begin
end; end;
procedure TPreprocessor.SaveToFile(const FileName: string); procedure TPreprocessor.SaveToFile(const FileName: string);
{$IFDEF UNICODE}
var var
S: String; S: String;
{$ENDIF}
begin begin
{$IFDEF UNICODE}
S := FOutput.Text; S := FOutput.Text;
if SameText(S, String(AnsiString(S))) then if SameText(S, String(AnsiString(S))) then
FOutput.SaveToFile(FileName) FOutput.SaveToFile(FileName)
else else
FOutput.SaveToFile(FileName, TEncoding.UTF8); FOutput.SaveToFile(FileName, TEncoding.UTF8);
{$ELSE}
FOutput.SaveToFile(FileName)
{$ENDIF}
end; end;
function TPreprocessor.CheckFile(const FileName: string): Boolean; function TPreprocessor.CheckFile(const FileName: string): Boolean;
@ -1408,13 +1398,8 @@ end;
function LookupAlwaysDefined(const Name: string): Boolean; function LookupAlwaysDefined(const Name: string): Boolean;
const const
{$IFDEF UNICODE}
AlwaysDefined: array[0..3] of string = AlwaysDefined: array[0..3] of string =
('ISPP_INVOKED', 'WINDOWS', '__WIN32__', 'UNICODE'); ('ISPP_INVOKED', 'WINDOWS', '__WIN32__', 'UNICODE');
{$ELSE}
AlwaysDefined: array[0..2] of string =
('ISPP_INVOKED', 'WINDOWS', '__WIN32__');
{$ENDIF}
var var
I: Integer; I: Integer;
begin begin

View File

@ -3,7 +3,7 @@
Copyright (C) 2001-2002 Alex Yackimoff Copyright (C) 2001-2002 Alex Yackimoff
Inno Setup Inno Setup
Copyright (C) 1997-2020 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
} }
@ -25,7 +25,7 @@ implementation
{$I ..\Version.inc} {$I ..\Version.inc}
uses SysUtils, Classes, IsppStack {$IFDEF IS_D12}, Windows{$ENDIF}; uses SysUtils, Classes, IsppStack, Windows;
procedure WarningMsg(const Msg: string; const Args: array of const); procedure WarningMsg(const Msg: string; const Args: array of const);
var var

View File

@ -2,7 +2,7 @@ unit InstFnc2;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2010 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -15,7 +15,7 @@ interface
function CreateShellLink(const Filename, Description, ShortcutTo, Parameters, function CreateShellLink(const Filename, Description, ShortcutTo, Parameters,
WorkingDir: String; IconFilename: String; const IconIndex, ShowCmd: Integer; WorkingDir: String; IconFilename: String; const IconIndex, ShowCmd: Integer;
const HotKey: Word; FolderShortcut: Boolean; const AppUserModelID: String; const HotKey: Word; const AppUserModelID: String;
const AppUserModelToastActivatorCLSID: PGUID; const AppUserModelToastActivatorCLSID: PGUID;
const ExcludeFromShowInNewInstall, PreventPinning: Boolean): String; const ExcludeFromShowInNewInstall, PreventPinning: Boolean): String;
procedure RegisterTypeLibrary(const Filename: String); procedure RegisterTypeLibrary(const Filename: String);
@ -26,27 +26,7 @@ implementation
uses uses
Windows, SysUtils, PathFunc, CmnFunc2, InstFunc, Main, Msgs, MsgIDs, Windows, SysUtils, PathFunc, CmnFunc2, InstFunc, Main, Msgs, MsgIDs,
{$IFNDEF Delphi3orHigher} OLE2, {$ELSE} ActiveX, ComObj, {$ENDIF} ActiveX, ComObj, PropSys, ShellAPI, ShlObj;
{$IFDEF IS_D14} PropSys, {$ENDIF}
ShellAPI, ShlObj;
function IsWindowsXP: Boolean;
{ Returns True if running Windows XP or later }
begin
Result := (WindowsVersion >= Cardinal($05010000));
end;
function IsWindowsVista: Boolean;
{ Returns True if running Windows Vista or later }
begin
Result := (WindowsVersion >= Cardinal($06000000));
end;
function IsWindows7: Boolean;
{ Returns True if running Windows 7 or later }
begin
Result := (WindowsVersion >= Cardinal($06010000));
end;
function IsWindows8: Boolean; function IsWindows8: Boolean;
{ Returns True if running Windows 8 or later } { Returns True if running Windows 8 or later }
@ -100,15 +80,12 @@ begin
Result := ''; Result := '';
CurFilename := nil; CurFilename := nil;
OleResult := PF.GetCurFile(CurFilename); OleResult := PF.GetCurFile(CurFilename);
{ Note: Prior to Windows 2000/Me, GetCurFile succeeds but returns a NULL
pointer }
if SUCCEEDED(OleResult) and Assigned(CurFilename) then begin if SUCCEEDED(OleResult) and Assigned(CurFilename) then begin
if OleResult = S_OK then if OleResult = S_OK then
Result := WideCharToString(CurFilename); Result := WideCharToString(CurFilename);
CoTaskMemFree(CurFilename); CoTaskMemFree(CurFilename);
end; end;
{ If GetCurFile didn't work (e.g. not running Windows 2000/Me or later), we { If GetCurFile didn't work, we have no choice but to try to guess the filename }
have no choice but to try to guess the filename }
if Result = '' then begin if Result = '' then begin
if NewFileExists(OriginalFilename) then if NewFileExists(OriginalFilename) then
Result := OriginalFilename Result := OriginalFilename
@ -121,48 +98,9 @@ begin
end; end;
end; end;
{$IFNDEF UNICODE}
type
TPropertyKey = packed record
fmtid: TGUID;
pid: DWORD;
end;
{$IFNDEF IS_D4}
TPropVariant = TVariantArg;
{$ENDIF}
{$IFNDEF Delphi3orHigher}
const
IID_IPropertyStore: TGUID = (
D1:$886d8eeb; D2:$8cf2; D3:$4446; D4:($8d,$02,$cd,$ba,$1d,$bd,$cf,$99));
type
IPropertyStore = class(IUnknown)
function GetCount(var cProps: DWORD): HResult; virtual; stdcall; abstract;
function GetAt(iProp: DWORD; var pkey: TPropertyKey): HResult; virtual; stdcall; abstract;
function GetValue(const key: TPropertyKey; var pv: TPropVariant): HResult; virtual; stdcall; abstract;
function SetValue(const key: TPropertyKey; const propvar: TPropVariant): HResult; virtual; stdcall; abstract;
function Commit: HResult; virtual; stdcall; abstract;
end;
{$ELSE}
{$IFNDEF IS_D14}
type
IPropertyStore = interface(IUnknown)
['{886d8eeb-8cf2-4446-8d02-cdba1dbdcf99}']
function GetCount(var cProps: DWORD): HResult; stdcall;
function GetAt(iProp: DWORD; var pkey: TPropertyKey): HResult; stdcall;
function GetValue(const key: TPropertyKey; var pv: TPropVariant): HResult; stdcall;
function SetValue(const key: TPropertyKey; const propvar: TPropVariant): HResult; stdcall;
function Commit: HResult; stdcall;
end;
{$ENDIF}
{$ENDIF}
{$ENDIF}
function CreateShellLink(const Filename, Description, ShortcutTo, Parameters, function CreateShellLink(const Filename, Description, ShortcutTo, Parameters,
WorkingDir: String; IconFilename: String; const IconIndex, ShowCmd: Integer; WorkingDir: String; IconFilename: String; const IconIndex, ShowCmd: Integer;
const HotKey: Word; FolderShortcut: Boolean; const AppUserModelID: String; const HotKey: Word; const AppUserModelID: String;
const AppUserModelToastActivatorCLSID: PGUID; const AppUserModelToastActivatorCLSID: PGUID;
const ExcludeFromShowInNewInstall, PreventPinning: Boolean): String; const ExcludeFromShowInNewInstall, PreventPinning: Boolean): String;
{ Creates a lnk file named Filename, with a description of Description, with a { Creates a lnk file named Filename, with a description of Description, with a
@ -173,8 +111,6 @@ function CreateShellLink(const Filename, Description, ShortcutTo, Parameters,
is not necessary if you are using Delphi 3 and your project already 'uses' is not necessary if you are using Delphi 3 and your project already 'uses'
the ComObj RTL unit. } the ComObj RTL unit. }
const const
CLSID_FolderShortcut: TGUID = (
D1:$0AFACED1; D2:$E828; D3:$11D1; D4:($91,$87,$B5,$32,$F1,$E9,$57,$5D));
PKEY_AppUserModel_ID: TPropertyKey = ( PKEY_AppUserModel_ID: TPropertyKey = (
fmtid: (D1:$9F4C2855; D2:$9F79; D3:$4B39; D4:($A8,$D0,$E1,$D4,$2D,$E1,$D5,$F3)); fmtid: (D1:$9F4C2855; D2:$9F79; D3:$4B39; D4:($A8,$D0,$E1,$D4,$2D,$E1,$D5,$F3));
pid: 5); pid: 5);
@ -192,163 +128,20 @@ const
pid: 26); pid: 26);
APPUSERMODEL_STARTPINOPTION_NOPINONINSTALL = 1; APPUSERMODEL_STARTPINOPTION_NOPINONINSTALL = 1;
{$IFNDEF Delphi3OrHigher}
var
OleResult: HRESULT;
SL: IShellLink;
PS: IPropertyStore;
PV: TPropVariant;
PF: IPersistFile;
WideFilename: PWideChar;
begin
if FolderShortcut then
OleResult := CoCreateInstance(CLSID_FolderShortcut, nil, CLSCTX_INPROC_SERVER,
IID_IShellLink, SL)
else
OleResult := E_FAIL;
{ If a folder shortcut wasn't requested, or if CoCreateInstance failed
because the user isn't running Windows 2000/Me or later, create a normal
shell link instead }
if OleResult <> S_OK then begin
FolderShortcut := False;
OleResult := CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER,
IID_IShellLink, SL);
if OleResult <> S_OK then
RaiseOleError('CoCreateInstance', OleResult);
end;
PF := nil;
PS := nil;
WideFilename := nil;
try
SL.SetPath(PChar(ShortcutTo));
SL.SetArguments(PChar(Parameters));
if not FolderShortcut then
AssignWorkingDir(SL, WorkingDir);
if IconFilename <> '' then begin
{ Work around a 64-bit Windows bug. It replaces pf32 with %ProgramFiles%
which is wrong. This causes an error when the user tries to change the
icon of the installed shortcut. Note that the icon does actually display
fine because it *also* stores the original 'non replaced' path in the
shortcut. }
if IsWin64 then
StringChangeEx(IconFileName, ExpandConst('{commonpf32}\'), '%ProgramFiles(x86)%\', True);
SL.SetIconLocation(PChar(IconFilename), IconIndex);
end;
SL.SetShowCmd(ShowCmd);
if Description <> '' then
SL.SetDescription(PChar(Description));
if HotKey <> 0 then
SL.SetHotKey(HotKey);
{ Note: Vista and newer support IPropertyStore but Vista errors if you try to
commit a PKEY_AppUserModel_ID, so avoid setting the property on Vista. }
if IsWindows7 and ((AppUserModelID <> '') or (AppUserModelToastActivatorCLSID <> nil) or ExcludeFromShowInNewInstall or PreventPinning) then begin
OleResult := SL.QueryInterface(IID_IPropertyStore, PS);
if OleResult <> S_OK then
RaiseOleError('IShellLink::QueryInterface(IID_IPropertyStore)', OleResult);
{ According to MSDN the PreventPinning property should be set before the ID property. In practice
this doesn't seem to matter - at least not for shortcuts - but do it first anyway. }
if PreventPinning then begin
PV.vt := VT_BOOL;
Smallint(PV.vbool) := -1;
OleResult := PS.SetValue(PKEY_AppUserModel_PreventPinning, PV);
if OleResult <> S_OK then
RaiseOleError('IPropertyStore::SetValue(PKEY_AppUserModel_PreventPinning)', OleResult);
end;
if AppUserModelID <> '' then begin
PV.vt := VT_BSTR;
PV.bstrVal := StringToOleStr(AppUserModelID);
if PV.bstrVal = nil then
OutOfMemoryError;
try
OleResult := PS.SetValue(PKEY_AppUserModel_ID, PV);
if OleResult <> S_OK then
RaiseOleError('IPropertyStore::SetValue(PKEY_AppUserModel_ID)', OleResult);
finally
SysFreeString(PV.bstrVal);
end;
end;
if IsWindows10 and (AppUserModelToastActivatorCLSID <> nil) then begin
PV.vt := VT_CLSID;
PV.puuid := AppUserModelToastActivatorCLSID;
OleResult := PS.SetValue(PKEY_AppUserModel_ToastActivatorCLSID, PV);
if OleResult <> S_OK then
RaiseOleError('IPropertyStore::SetValue(PKEY_AppUserModel_ToastActivatorCLSID)', OleResult);
end;
if ExcludeFromShowInNewInstall then begin
PV.vt := VT_BOOL;
Smallint(PV.vbool) := -1;
OleResult := PS.SetValue(PKEY_AppUserModel_ExcludeFromShowInNewInstall, PV);
if OleResult <> S_OK then
RaiseOleError('IPropertyStore::SetValue(PKEY_AppUserModel_ExcludeFromShowInNewInstall)', OleResult);
if IsWindows8 then begin
PV.vt := VT_UI4;
PV.lVal := APPUSERMODEL_STARTPINOPTION_NOPINONINSTALL;
OleResult := PS.SetValue(PKEY_AppUserModel_StartPinOption, PV);
if OleResult <> S_OK then
RaiseOleError('IPropertyStore::SetValue(PKEY_AppUserModel_StartPinOption)', OleResult);
end;
end;
OleResult := PS.Commit;
if OleResult <> S_OK then
RaiseOleError('IPropertyStore::Commit', OleResult);
end;
OleResult := SL.QueryInterface(IID_IPersistFile, PF);
if OleResult <> S_OK then
RaiseOleError('IShellLink::QueryInterface(IID_IPersistFile)', OleResult);
{ When creating a folder shortcut on 2000/Me, IPersistFile::Save will strip
off everything past the last '.' in the filename, so we keep the .lnk
extension on to give it something harmless to strip off. XP doesn't do
that, so we must remove the .lnk extension ourself. }
if FolderShortcut and IsWindowsXP then
WideFilename := StringToOleStr(PathChangeExt(Filename, ''))
else
WideFilename := StringToOleStr(Filename);
if WideFilename = nil then
OutOfMemoryError;
OleResult := PF.Save(WideFilename, True);
if OleResult <> S_OK then
RaiseOleError('IPersistFile::Save', OleResult);
Result := GetResultingFilename(PF, Filename);
finally
if Assigned(WideFilename) then
SysFreeString(WideFilename);
if Assigned(PS) then
PS.Release;
if Assigned(PF) then
PF.Release;
SL.Release;
end;
{$ELSE}
var var
OleResult: HRESULT; OleResult: HRESULT;
Obj: IUnknown; Obj: IUnknown;
SL: IShellLink; SL: IShellLink;
PS: {$IFDEF IS_D14}PropSys.{$ENDIF}IPropertyStore; PS: PropSys.IPropertyStore;
PV: TPropVariant; PV: TPropVariant;
PF: IPersistFile; PF: IPersistFile;
WideAppUserModelID, WideFilename: WideString; WideAppUserModelID, WideFilename: WideString;
begin begin
if FolderShortcut then begin Obj := CreateComObject(CLSID_ShellLink);
try
Obj := CreateComObject(CLSID_FolderShortcut);
except
{ Folder shortcuts aren't supported prior to Windows 2000/Me. Fall back
to creating a normal shell link. }
Obj := nil;
end;
end;
if Obj = nil then begin
FolderShortcut := False;
Obj := CreateComObject(CLSID_ShellLink);
end;
SL := Obj as IShellLink; SL := Obj as IShellLink;
SL.SetPath(PChar(ShortcutTo)); SL.SetPath(PChar(ShortcutTo));
SL.SetArguments(PChar(Parameters)); SL.SetArguments(PChar(Parameters));
if not FolderShortcut then AssignWorkingDir(SL, WorkingDir);
AssignWorkingDir(SL, WorkingDir);
if IconFilename <> '' then begin if IconFilename <> '' then begin
{ Work around a 64-bit Windows bug. It replaces pf32 with %ProgramFiles% { Work around a 64-bit Windows bug. It replaces pf32 with %ProgramFiles%
which is wrong. This causes an error when the user tries to change the which is wrong. This causes an error when the user tries to change the
@ -365,10 +158,8 @@ begin
if HotKey <> 0 then if HotKey <> 0 then
SL.SetHotKey(HotKey); SL.SetHotKey(HotKey);
{ Note: Vista and newer support IPropertyStore but Vista errors if you try to if (AppUserModelID <> '') or (AppUserModelToastActivatorCLSID <> nil) or ExcludeFromShowInNewInstall or PreventPinning then begin
commit a PKEY_AppUserModel_ID, so avoid setting the property on Vista. } PS := Obj as PropSys.IPropertyStore;
if IsWindows7 and ((AppUserModelID <> '') or (AppUserModelToastActivatorCLSID <> nil) or ExcludeFromShowInNewInstall or PreventPinning) then begin
PS := Obj as {$IFDEF IS_D14}PropSys.{$ENDIF}IPropertyStore;
{ According to MSDN the PreventPinning property should be set before the ID property. In practice { According to MSDN the PreventPinning property should be set before the ID property. In practice
this doesn't seem to matter - at least not for shortcuts - but do it first anyway. } this doesn't seem to matter - at least not for shortcuts - but do it first anyway. }
if PreventPinning then begin if PreventPinning then begin
@ -413,49 +204,15 @@ begin
end; end;
PF := SL as IPersistFile; PF := SL as IPersistFile;
{ When creating a folder shortcut on 2000/Me, IPersistFile::Save will strip WideFilename := Filename;
off everything past the last '.' in the filename, so we keep the .lnk
extension on to give it something harmless to strip off. XP doesn't do
that, so we must remove the .lnk extension ourself. }
if FolderShortcut and IsWindowsXP then
WideFilename := PathChangeExt(Filename, '')
else
WideFilename := Filename;
OleResult := PF.Save(PWideChar(WideFilename), True); OleResult := PF.Save(PWideChar(WideFilename), True);
if OleResult <> S_OK then if OleResult <> S_OK then
RaiseOleError('IPersistFile::Save', OleResult); RaiseOleError('IPersistFile::Save', OleResult);
Result := GetResultingFilename(PF, Filename); Result := GetResultingFilename(PF, Filename);
{ Delphi 3 automatically releases COM objects when they go out of scope }
{$ENDIF}
end; end;
procedure RegisterTypeLibrary(const Filename: String); procedure RegisterTypeLibrary(const Filename: String);
{$IFNDEF Delphi3OrHigher}
var
WideFilename: PWideChar;
OleResult: HRESULT;
TypeLib: ITypeLib;
begin
WideFilename := StringToOleStr(PathExpand(Filename));
if WideFilename = nil then
OutOfMemoryError;
try
OleResult := LoadTypeLib(WideFilename, TypeLib);
if OleResult <> S_OK then
RaiseOleError('LoadTypeLib', OleResult);
try
OleResult := RegisterTypeLib(TypeLib, WideFilename, nil);
if OleResult <> S_OK then
RaiseOleError('RegisterTypeLib', OleResult);
finally
TypeLib.Release;
end;
finally
SysFreeString(WideFilename);
end;
end;
{$ELSE}
var var
WideFilename: WideString; WideFilename: WideString;
OleResult: HRESULT; OleResult: HRESULT;
@ -469,53 +226,11 @@ begin
if OleResult <> S_OK then if OleResult <> S_OK then
RaiseOleError('RegisterTypeLib', OleResult); RaiseOleError('RegisterTypeLib', OleResult);
end; end;
{$ENDIF}
procedure UnregisterTypeLibrary(const Filename: String); procedure UnregisterTypeLibrary(const Filename: String);
type type
TUnRegTlbProc = function(const libID: TGUID; wVerMajor, wVerMinor: Word; TUnRegTlbProc = function(const libID: TGUID; wVerMajor, wVerMinor: Word;
lcid: TLCID; syskind: TSysKind): HResult; stdcall; lcid: TLCID; syskind: TSysKind): HResult; stdcall;
{$IFNDEF Delphi3OrHigher}
var
UnRegTlbProc: TUnRegTlbProc;
WideFilename: PWideChar;
OleResult: HRESULT;
TypeLib: ITypeLib;
LibAttr: PTLibAttr;
begin
{ Dynamically import UnRegisterTypeLib since older OLEAUT32.DLL versions
don't have this function }
@UnRegTlbProc := GetProcAddress(GetModuleHandle('OLEAUT32.DLL'),
'UnRegisterTypeLib');
if @UnRegTlbProc = nil then
Win32ErrorMsg('GetProcAddress');
WideFilename := StringToOleStr(PathExpand(Filename));
if WideFilename = nil then
OutOfMemoryError;
try
OleResult := LoadTypeLib(WideFilename, TypeLib);
if OleResult <> S_OK then
RaiseOleError('LoadTypeLib', OleResult);
try
OleResult := TypeLib.GetLibAttr(LibAttr);
if OleResult <> S_OK then
RaiseOleError('ITypeLib::GetLibAttr', OleResult);
try
with LibAttr^ do
OleResult := UnRegTlbProc(Guid, wMajorVerNum, wMinorVerNum, LCID, SysKind);
if OleResult <> S_OK then
RaiseOleError('UnRegisterTypeLib', OleResult);
finally
TypeLib.ReleaseTLibAttr(LibAttr);
end;
finally
TypeLib.Release;
end;
finally
SysFreeString(WideFilename);
end;
end;
{$ELSE}
var var
UnRegTlbProc: TUnRegTlbProc; UnRegTlbProc: TUnRegTlbProc;
WideFilename: WideString; WideFilename: WideString;
@ -545,7 +260,6 @@ begin
TypeLib.ReleaseTLibAttr(LibAttr); TypeLib.ReleaseTLibAttr(LibAttr);
end; end;
end; end;
{$ENDIF}
const const
CLSID_StartMenuPin: TGUID = ( CLSID_StartMenuPin: TGUID = (
@ -557,28 +271,11 @@ const
IID_ShellItem: TGUID = ( IID_ShellItem: TGUID = (
D1:$43826D1E; D2:$E718; D3:$42EE; D4:($BC,$55,$A1,$E2,$61,$C3,$7B,$FE)); D1:$43826D1E; D2:$E718; D3:$42EE; D4:($BC,$55,$A1,$E2,$61,$C3,$7B,$FE));
{$IFNDEF Delphi3OrHigher}
type
IShellItem = class(IUnknown)
function BindToHandler(const pbc: IBindCtx; const bhid: TGUID;
const riid: TIID; var ppv): HResult; virtual; stdcall; abstract;
function GetParent(var ppsi: IShellItem): HResult; virtual; stdcall; abstract;
function GetDisplayName(sigdnName: DWORD; var ppszName: LPWSTR): HResult; virtual; stdcall; abstract;
function GetAttributes(sfgaoMask: DWORD; var psfgaoAttribs: DWORD): HResult; virtual; stdcall; abstract;
function Compare(const psi: IShellItem; hint: DWORD;
var piOrder: Integer): HResult; virtual; stdcall; abstract;
end;
IStartMenuPinnedList = class(IUnknown)
function RemoveFromList(const pitem: IShellItem): HRESULT; virtual; stdcall; abstract;
end;
{$ELSE}
type type
IStartMenuPinnedList = interface(IUnknown) IStartMenuPinnedList = interface(IUnknown)
['{4CD19ADA-25A5-4A32-B3B7-347BEE5BE36B}'] ['{4CD19ADA-25A5-4A32-B3B7-347BEE5BE36B}']
function RemoveFromList(const pitem: IShellItem): HRESULT; stdcall; function RemoveFromList(const pitem: IShellItem): HRESULT; stdcall;
end; end;
{$ENDIF}
var var
SHCreateItemFromParsingNameFunc: function(pszPath: LPCWSTR; const pbc: IBindCtx; SHCreateItemFromParsingNameFunc: function(pszPath: LPCWSTR; const pbc: IBindCtx;
@ -589,40 +286,17 @@ var
was not pinned at all. http://msdn.microsoft.com/en-us/library/bb774817.aspx } was not pinned at all. http://msdn.microsoft.com/en-us/library/bb774817.aspx }
function UnpinShellLink(const Filename: String): Boolean; function UnpinShellLink(const Filename: String): Boolean;
var var
{$IFNDEF Delphi3OrHigher}
WideFileName: PWideChar;
{$ELSE}
WideFileName: WideString; WideFileName: WideString;
{$ENDIF}
ShellItem: IShellItem; ShellItem: IShellItem;
StartMenuPinnedList: IStartMenuPinnedList; StartMenuPinnedList: IStartMenuPinnedList;
begin begin
{$IFNDEF Delphi3OrHigher}
ShellItem := nil;
StartMenuPinnedList := nil;
WideFilename := StringToOleStr(PathExpand(Filename));
if WideFilename = nil then
OutOfMemoryError;
try
{$ELSE}
WideFilename := PathExpand(Filename); WideFilename := PathExpand(Filename);
{$ENDIF} if Assigned(SHCreateItemFromParsingNameFunc) and
if IsWindowsVista and //only attempt on Windows Vista and newer just to be sure
Assigned(SHCreateItemFromParsingNameFunc) and
SUCCEEDED(SHCreateItemFromParsingNameFunc(PWideChar(WideFilename), nil, IID_ShellItem, ShellItem)) and SUCCEEDED(SHCreateItemFromParsingNameFunc(PWideChar(WideFilename), nil, IID_ShellItem, ShellItem)) and
SUCCEEDED(CoCreateInstance(CLSID_StartMenuPin, nil, CLSCTX_INPROC_SERVER, IID_StartMenuPinnedList, StartMenuPinnedList)) then SUCCEEDED(CoCreateInstance(CLSID_StartMenuPin, nil, CLSCTX_INPROC_SERVER, IID_StartMenuPinnedList, StartMenuPinnedList)) then
Result := StartMenuPinnedList.RemoveFromList(ShellItem) = S_OK Result := StartMenuPinnedList.RemoveFromList(ShellItem) = S_OK
else else
Result := True; Result := True;
{$IFNDEF Delphi3OrHigher}
finally
SysFreeString(WideFilename);
if StartMenuPinnedList <> nil then
StartMenuPinnedList.Release;
if ShellItem <> nil then
ShellItem.Release;
end;
{$ENDIF}
end; end;
procedure InitOle; procedure InitOle;

View File

@ -2,7 +2,7 @@ unit InstFunc;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2020 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -72,19 +72,13 @@ function GetFileDateTime(const DisableFsRedir: Boolean; const Filename: String;
var DateTime: TFileTime): Boolean; var DateTime: TFileTime): Boolean;
function GetMD5OfFile(const DisableFsRedir: Boolean; const Filename: String): TMD5Digest; function GetMD5OfFile(const DisableFsRedir: Boolean; const Filename: String): TMD5Digest;
function GetMD5OfAnsiString(const S: AnsiString): TMD5Digest; function GetMD5OfAnsiString(const S: AnsiString): TMD5Digest;
{$IFDEF UNICODE}
function GetMD5OfUnicodeString(const S: UnicodeString): TMD5Digest; function GetMD5OfUnicodeString(const S: UnicodeString): TMD5Digest;
{$ENDIF}
function GetSHA1OfFile(const DisableFsRedir: Boolean; const Filename: String): TSHA1Digest; function GetSHA1OfFile(const DisableFsRedir: Boolean; const Filename: String): TSHA1Digest;
function GetSHA1OfAnsiString(const S: AnsiString): TSHA1Digest; function GetSHA1OfAnsiString(const S: AnsiString): TSHA1Digest;
{$IFDEF UNICODE}
function GetSHA1OfUnicodeString(const S: UnicodeString): TSHA1Digest; function GetSHA1OfUnicodeString(const S: UnicodeString): TSHA1Digest;
{$ENDIF}
function GetSHA256OfFile(const DisableFsRedir: Boolean; const Filename: String): String; function GetSHA256OfFile(const DisableFsRedir: Boolean; const Filename: String): String;
function GetSHA256OfAnsiString(const S: AnsiString): String; function GetSHA256OfAnsiString(const S: AnsiString): String;
{$IFDEF UNICODE}
function GetSHA256OfUnicodeString(const S: UnicodeString): String; function GetSHA256OfUnicodeString(const S: UnicodeString): String;
{$ENDIF}
function GetRegRootKeyName(const RootKey: HKEY): String; function GetRegRootKeyName(const RootKey: HKEY): String;
function GetSpaceOnDisk(const DisableFsRedir: Boolean; const DriveRoot: String; function GetSpaceOnDisk(const DisableFsRedir: Boolean; const DriveRoot: String;
var FreeBytes, TotalBytes: Integer64): Boolean; var FreeBytes, TotalBytes: Integer64): Boolean;
@ -122,7 +116,8 @@ function ForceDirectories(const DisableFsRedir: Boolean; Dir: String): Boolean;
implementation implementation
uses uses
Messages, ShellApi, PathFunc, Msgs, MsgIDs, FileClass, RedirFunc, SetupTypes, Hash, Classes; Messages, ShellApi, PathFunc, Msgs, MsgIDs, FileClass, RedirFunc, SetupTypes,
Hash, Classes, RegStr;
procedure InternalError(const Id: String); procedure InternalError(const Id: String);
begin begin
@ -347,8 +342,7 @@ begin
end; end;
function ReplaceSystemDirWithSysNative(Path: String; const IsWin64: Boolean): String; function ReplaceSystemDirWithSysNative(Path: String; const IsWin64: Boolean): String;
{ If the user is running 64-bit Windows Vista or newer and Path { If Path begins with 'x:\windows\system32\' it replaces it with
begins with 'x:\windows\system32\' it replaces it with
'x:\windows\sysnative\' and if Path equals 'x:\windows\system32' 'x:\windows\sysnative\' and if Path equals 'x:\windows\system32'
it replaces it with 'x:\windows\sysnative'. Otherwise, Path is it replaces it with 'x:\windows\sysnative'. Otherwise, Path is
returned unchanged. } returned unchanged. }
@ -384,93 +378,23 @@ end;
procedure RestartReplace(const DisableFsRedir: Boolean; TempFile, DestFile: String); procedure RestartReplace(const DisableFsRedir: Boolean; TempFile, DestFile: String);
{ Renames TempFile to DestFile the next time Windows is started. If DestFile { Renames TempFile to DestFile the next time Windows is started. If DestFile
already existed, it will be overwritten. If DestFile is '' then TempFile already existed, it will be overwritten. If DestFile is '' then TempFile
will be deleted, however this is only supported by 95/98 and NT, not will be deleted.. }
Windows 3.1x. }
var
WinDir, WinInitFile, TempWinInitFile: String;
OldF: TTextFileReader;
NewF: TTextFileWriter;
L, L2: String;
RenameSectionFound, WriteLastLine: Boolean;
begin begin
TempFile := PathExpand(TempFile); TempFile := PathExpand(TempFile);
if DestFile <> '' then if DestFile <> '' then
DestFile := PathExpand(DestFile); DestFile := PathExpand(DestFile);
if not UsingWinNT then begin if not DisableFsRedir then begin
{ Because WININIT.INI allows multiple entries with the same name, { Work around WOW64 bug present in the IA64 and x64 editions of Windows
it must manually parse the file instead of using XP (3790) and Server 2003 prior to SP1 RC2: MoveFileEx writes filenames
WritePrivateProfileString } to the registry verbatim without mapping system32->syswow64. }
WinDir := GetWinDir; TempFile := ReplaceSystemDirWithSysWow64(TempFile);
WinInitFile := AddBackslash(WinDir) + 'WININIT.INI'; if DestFile <> '' then
TempWinInitFile := GenerateUniqueName(False, WinDir, '.tmp'); DestFile := ReplaceSystemDirWithSysWow64(DestFile);
try
OldF := nil;
NewF := nil;
try
{ Flush Windows' cache for the file first }
WritePrivateProfileString(nil, nil, nil, PChar(WinInitFile));
OldF := TTextFileReader.Create(WinInitFile, fdOpenAlways, faRead,
fsRead);
NewF := TTextFileWriter.Create(TempWinInitFile, fdCreateAlways,
faWrite, fsNone);
RenameSectionFound := False;
WriteLastLine := False;
while not OldF.Eof do begin
L := OldF.ReadLine;
WriteLastLine := True;
L2 := Trim(L);
if (L2 <> '') and (L2[1] = '[') then begin
if CompareText(L2, '[rename]') = 0 then
RenameSectionFound := True
else
if RenameSectionFound then
Break;
end;
NewF.WriteLine(L);
WriteLastLine := False;
end;
if not RenameSectionFound then
NewF.WriteLine('[rename]');
if DestFile <> '' then
L2 := GetShortName(DestFile)
else
L2 := 'NUL';
NewF.WriteLine(L2 + '=' + GetShortName(TempFile));
if WriteLastLine then
NewF.WriteLine(L);
while not OldF.Eof do begin
L := OldF.ReadLine;
NewF.WriteLine(L);
end;
finally
NewF.Free;
OldF.Free;
end;
{ Strip any read-only attribute }
SetFileAttributes(PChar(WinInitFile), FILE_ATTRIBUTE_ARCHIVE);
if not DeleteFile(WinInitFile) then
Win32ErrorMsg('DeleteFile');
if not MoveFile(PChar(TempWinInitFile), PChar(WinInitFile)) then
Win32ErrorMsg('MoveFile');
except
DeleteFile(TempWinInitFile);
raise;
end;
end
else begin
if not DisableFsRedir then begin
{ Work around WOW64 bug present in the IA64 and x64 editions of Windows
XP (3790) and Server 2003 prior to SP1 RC2: MoveFileEx writes filenames
to the registry verbatim without mapping system32->syswow64. }
TempFile := ReplaceSystemDirWithSysWow64(TempFile);
if DestFile <> '' then
DestFile := ReplaceSystemDirWithSysWow64(DestFile);
end;
if not MoveFileExRedir(DisableFsRedir, TempFile, DestFile,
MOVEFILE_DELAY_UNTIL_REBOOT or MOVEFILE_REPLACE_EXISTING) then
Win32ErrorMsg('MoveFileEx');
end; end;
if not MoveFileExRedir(DisableFsRedir, TempFile, DestFile,
MOVEFILE_DELAY_UNTIL_REBOOT or MOVEFILE_REPLACE_EXISTING) then
Win32ErrorMsg('MoveFileEx');
end; end;
function DelTree(const DisableFsRedir: Boolean; const Path: String; function DelTree(const DisableFsRedir: Boolean; const Path: String;
@ -593,7 +517,7 @@ end;
procedure IncrementSharedCount(const RegView: TRegView; const Filename: String; procedure IncrementSharedCount(const RegView: TRegView; const Filename: String;
const AlreadyExisted: Boolean); const AlreadyExisted: Boolean);
const const
SharedDLLsKey = NEWREGSTR_PATH_SETUP + '\SharedDLLs'; {don't localize} SharedDLLsKey = REGSTR_PATH_SETUP + '\SharedDLLs'; {don't localize}
var var
ErrorCode: Longint; ErrorCode: Longint;
K: HKEY; K: HKEY;
@ -656,7 +580,7 @@ function DecrementSharedCount(const RegView: TRegView;
{ Attempts to decrement the shared file reference count of Filename. Returns { Attempts to decrement the shared file reference count of Filename. Returns
True if the count reached zero (meaning it's OK to delete the file). } True if the count reached zero (meaning it's OK to delete the file). }
const const
SharedDLLsKey = NEWREGSTR_PATH_SETUP + '\SharedDLLs'; {don't localize} SharedDLLsKey = REGSTR_PATH_SETUP + '\SharedDLLs'; {don't localize}
var var
ErrorCode: Longint; ErrorCode: Longint;
K: HKEY; K: HKEY;
@ -815,24 +739,20 @@ begin
Result := MD5Buf(Pointer(S)^, Length(S)*SizeOf(S[1])); Result := MD5Buf(Pointer(S)^, Length(S)*SizeOf(S[1]));
end; end;
{$IFDEF UNICODE}
function GetMD5OfUnicodeString(const S: UnicodeString): TMD5Digest; function GetMD5OfUnicodeString(const S: UnicodeString): TMD5Digest;
begin begin
Result := MD5Buf(Pointer(S)^, Length(S)*SizeOf(S[1])); Result := MD5Buf(Pointer(S)^, Length(S)*SizeOf(S[1]));
end; end;
{$ENDIF}
function GetSHA1OfAnsiString(const S: AnsiString): TSHA1Digest; function GetSHA1OfAnsiString(const S: AnsiString): TSHA1Digest;
begin begin
Result := SHA1Buf(Pointer(S)^, Length(S)*SizeOf(S[1])); Result := SHA1Buf(Pointer(S)^, Length(S)*SizeOf(S[1]));
end; end;
{$IFDEF UNICODE}
function GetSHA1OfUnicodeString(const S: UnicodeString): TSHA1Digest; function GetSHA1OfUnicodeString(const S: UnicodeString): TSHA1Digest;
begin begin
Result := SHA1Buf(Pointer(S)^, Length(S)*SizeOf(S[1])); Result := SHA1Buf(Pointer(S)^, Length(S)*SizeOf(S[1]));
end; end;
{$ENDIF}
function GetSHA256OfAnsiString(const S: AnsiString): String; function GetSHA256OfAnsiString(const S: AnsiString): String;
var var
@ -848,7 +768,6 @@ begin
end; end;
end; end;
{$IFDEF UNICODE}
function GetSHA256OfUnicodeString(const S: UnicodeString): String; function GetSHA256OfUnicodeString(const S: UnicodeString): String;
var var
M: TMemoryStream; M: TMemoryStream;
@ -862,7 +781,6 @@ begin
M.Free; M.Free;
end; end;
end; end;
{$ENDIF}
var var
SFCInitialized: Boolean; SFCInitialized: Boolean;
@ -875,9 +793,6 @@ function IsProtectedSystemFile(const DisableFsRedir: Boolean;
var var
M: HMODULE; M: HMODULE;
FN: String; FN: String;
{$IFNDEF UNICODE}
Buf: array[0..4095] of WideChar;
{$ENDIF}
begin begin
if not SFCInitialized then begin if not SFCInitialized then begin
M := SafeLoadLibrary(PChar(AddBackslash(GetSystemDir) + 'sfc.dll'), M := SafeLoadLibrary(PChar(AddBackslash(GetSystemDir) + 'sfc.dll'),
@ -893,18 +808,10 @@ begin
FN := PathExpand(Filename); FN := PathExpand(Filename);
if not DisableFsRedir then if not DisableFsRedir then
FN := ReplaceSystemDirWithSysWow64(FN); FN := ReplaceSystemDirWithSysWow64(FN);
{$IFDEF UNICODE}
Result := SfcIsFileProtectedFunc(0, PChar(FN)); Result := SfcIsFileProtectedFunc(0, PChar(FN));
{$ELSE}
Buf[MultiByteToWideChar(CP_ACP, 0, PChar(FN), Length(FN), Buf,
(SizeOf(Buf) div SizeOf(Buf[0])) - 1)] := #0;
Result := (Buf[0] <> #0) and SfcIsFileProtectedFunc(0, Buf);
{$ENDIF}
end end
else begin else
{ Windows File Protection doesn't exist on Windows 95/98/NT4 } Result := False; { Should never happen }
Result := False;
end;
end; end;
procedure HandleProcessWait(ProcessHandle: THandle; const Wait: TExecWait; procedure HandleProcessWait(ProcessHandle: THandle; const Wait: TExecWait;
@ -960,16 +867,13 @@ begin
Filename: "c:\batch.bat"; Parameters: """abc""" Filename: "c:\batch.bat"; Parameters: """abc"""
And other Windows versions might have unknown quirks too, since And other Windows versions might have unknown quirks too, since
CreateProcess isn't documented to accept .bat files in the first place. } CreateProcess isn't documented to accept .bat files in the first place. }
if UsingWinNT then { With cmd.exe, the whole command line must be quoted for quoted
{ With cmd.exe, the whole command line must be quoted for quoted parameters to work. For example, this fails:
parameters to work. For example, this fails: cmd.exe /c "z:\blah.bat" "test"
cmd.exe /c "z:\blah.bat" "test" But this works:
But this works: cmd.exe /c ""z:\blah.bat" "test""
cmd.exe /c ""z:\blah.bat" "test"" }
} CmdLine := '"' + AddBackslash(GetSystemDir) + 'cmd.exe" /C "' + CmdLine + '"'
CmdLine := '"' + AddBackslash(GetSystemDir) + 'cmd.exe" /C "' + CmdLine + '"'
else
CmdLine := '"' + AddBackslash(GetWinDir) + 'COMMAND.COM" /C ' + CmdLine;
end; end;
if WorkingDir = '' then if WorkingDir = '' then
WorkingDir := PathExtractDir(Filename); WorkingDir := PathExtractDir(Filename);
@ -1141,44 +1045,35 @@ function NewAdjustTokenPrivileges(TokenHandle: THandle; DisableAllPrivileges: BO
external advapi32 name 'AdjustTokenPrivileges'; external advapi32 name 'AdjustTokenPrivileges';
function RestartComputer: Boolean; function RestartComputer: Boolean;
{ Restarts the computer. On Windows 9x/Me, the function will NOT return if it { Restarts the computer. }
is successful. }
var var
Token: THandle; Token: THandle;
TokenPriv: TTokenPrivileges; TokenPriv: TTokenPrivileges;
const const
SE_SHUTDOWN_NAME = 'SeShutdownPrivilege'; { don't localize } SE_SHUTDOWN_NAME = 'SeShutdownPrivilege'; { don't localize }
begin begin
if Win32Platform = VER_PLATFORM_WIN32_NT then begin if not OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,
if not OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, Token) then begin
{$IFNDEF Delphi3orHigher} @Token {$ELSE} Token {$ENDIF}) then begin Result := False;
Result := False; Exit;
Exit; end;
end;
LookupPrivilegeValue(nil, SE_SHUTDOWN_NAME, TokenPriv.Privileges[0].Luid); LookupPrivilegeValue(nil, SE_SHUTDOWN_NAME, TokenPriv.Privileges[0].Luid);
TokenPriv.PrivilegeCount := 1; TokenPriv.PrivilegeCount := 1;
TokenPriv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED; TokenPriv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
NewAdjustTokenPrivileges(Token, False, TokenPriv, 0, nil, nil); NewAdjustTokenPrivileges(Token, False, TokenPriv, 0, nil, nil);
{ Cannot test the return value of AdjustTokenPrivileges. } { Cannot test the return value of AdjustTokenPrivileges. }
if GetLastError <> ERROR_SUCCESS then begin if GetLastError <> ERROR_SUCCESS then begin
Result := False; Result := False;
Exit; Exit;
end;
end; end;
Result := ExitWindowsEx(EWX_REBOOT, 0); Result := ExitWindowsEx(EWX_REBOOT, 0);
{ On Windows 9x/Me: { ExitWindowsEx returns True immediately. The system then asynchronously
ExitWindowsEx synchronously sends WM_QUERYENDSESSION messages to all
processes except the current process. If any WM_QUERYENDSESSION handler
blocks the shutdown, it returns False. Otherwise, it kills the current
process and does not return.
On NT platforms:
ExitWindowsEx returns True immediately. The system then asynchronously
sends WM_QUERYENDSESSION messages to all processes, including the current sends WM_QUERYENDSESSION messages to all processes, including the current
process. The current process is not killed until it has received process. The current process is not killed until it has received
WM_QUERYENDSESSION and WM_ENDSESSION messages. } WM_QUERYENDSESSION and WM_ENDSESSION messages. }
@ -1206,48 +1101,24 @@ end;
function MakePendingFileRenameOperationsChecksum: TMD5Digest; function MakePendingFileRenameOperationsChecksum: TMD5Digest;
{ Calculates a checksum of the current PendingFileRenameOperations registry { Calculates a checksum of the current PendingFileRenameOperations registry
value (on NT 4+ platforms) or of the current WININIT.INI file (on non-NT value The caller can use this checksum to determine if
platforms). The caller can use this checksum to determine if PendingFileRenameOperations was changed (perhaps by another program). }
PendingFileRenameOperations or WININIT.INI was changed (perhaps by another
program). }
var var
Context: TMD5Context; Context: TMD5Context;
K: HKEY; K: HKEY;
S: String; S: String;
WinInitFile: String;
F: TFile;
Buf: array[0..4095] of Byte;
BytesRead: Cardinal;
begin begin
MD5Init(Context); MD5Init(Context);
try try
if UsingWinNT then begin if RegOpenKeyExView(rvDefault, HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\Session Manager',
if RegOpenKeyExView(rvDefault, HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\Session Manager', 0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin
0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin if RegQueryMultiStringValue(K, 'PendingFileRenameOperations', S) then
if RegQueryMultiStringValue(K, 'PendingFileRenameOperations', S) then MD5Update(Context, S[1], Length(S)*SizeOf(S[1]));
MD5Update(Context, S[1], Length(S)*SizeOf(S[1])); { When "PendingFileRenameOperations" is full, it spills over into
{ When "PendingFileRenameOperations" is full, it spills over into "PendingFileRenameOperations2" }
"PendingFileRenameOperations2" } if RegQueryMultiStringValue(K, 'PendingFileRenameOperations2', S) then
if RegQueryMultiStringValue(K, 'PendingFileRenameOperations2', S) then MD5Update(Context, S[1], Length(S)*SizeOf(S[1]));
MD5Update(Context, S[1], Length(S)*SizeOf(S[1])); RegCloseKey(K);
RegCloseKey(K);
end;
end
else begin
WinInitFile := AddBackslash(GetWinDir) + 'WININIT.INI';
if NewFileExists(WinInitFile) then begin
F := TFile.Create(WinInitFile, fdOpenExisting, faRead, fsRead);
try
while True do begin
BytesRead := F.Read(Buf, SizeOf(Buf));
if BytesRead = 0 then
Break;
MD5Update(Context, Buf, BytesRead);
end;
finally
F.Free;
end;
end;
end; end;
except except
{ don't propagate exceptions } { don't propagate exceptions }
@ -1261,101 +1132,46 @@ procedure EnumFileReplaceOperationsFilenames(const EnumFunc: TEnumFROFilenamesPr
registry value or WININIT.INI file. The function does not distinguish between registry value or WININIT.INI file. The function does not distinguish between
source and destination filenames; it enumerates both. } source and destination filenames; it enumerates both. }
procedure DoNT; procedure DoValue(const K: HKEY; const ValueName: PChar);
procedure DoValue(const K: HKEY; const ValueName: PChar);
var
S: String;
P, PEnd: PChar;
begin
if not RegQueryMultiStringValue(K, ValueName, S) then
Exit;
P := PChar(S);
PEnd := P + Length(S);
while P < PEnd do begin
if P[0] = '!' then
{ Note: '!' means that MoveFileEx was called with the
MOVEFILE_REPLACE_EXISTING flag }
Inc(P);
if StrLComp(P, '\??\', 4) = 0 then begin
Inc(P, 4);
if P[0] <> #0 then
EnumFunc(P, Param);
end;
Inc(P, StrLen(P) + 1);
end;
end;
var var
K: HKEY; S: String;
P, PEnd: PChar;
begin begin
if RegOpenKeyExView(rvDefault, HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\Session Manager', if not RegQueryMultiStringValue(K, ValueName, S) then
0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin
try
DoValue(K, 'PendingFileRenameOperations');
{ When "PendingFileRenameOperations" is full, it spills over into
"PendingFileRenameOperations2" }
DoValue(K, 'PendingFileRenameOperations2');
finally
RegCloseKey(K);
end;
end;
end;
procedure DoNonNT;
var
WinInitFile: String;
F: TTextFileReader;
Line, Filename: String;
InRenameSection: Boolean;
P: Integer;
begin
WinInitFile := AddBackslash(GetWinDir) + 'WININIT.INI';
if not NewFileExists(WinInitFile) then
Exit; Exit;
try P := PChar(S);
F := TTextFileReader.Create(WinInitFile, fdOpenExisting, faRead, fsRead); PEnd := P + Length(S);
try while P < PEnd do begin
InRenameSection := False; if P[0] = '!' then
while not F.Eof do begin { Note: '!' means that MoveFileEx was called with the
Line := Trim(F.ReadLine); MOVEFILE_REPLACE_EXISTING flag }
if (Line = '') or (Line[1] = ';') then Inc(P);
Continue; if StrLComp(P, '\??\', 4) = 0 then begin
if Line[1] = '[' then begin Inc(P, 4);
InRenameSection := (CompareText(Line, '[rename]') = 0); if P[0] <> #0 then
end EnumFunc(P, Param);
else if InRenameSection then begin
P := Pos('=', Line);
if P > 0 then begin
Filename := Copy(Line, 1, P-1);
if (Filename <> '') and (CompareText(Filename, 'NUL') <> 0) then
EnumFunc(Filename, Param);
Filename := Copy(Line, P+1, Maxint);
if (Filename <> '') and (CompareText(Filename, 'NUL') <> 0) then
EnumFunc(Filename, Param);
end;
end;
end;
finally
F.Free;
end; end;
except Inc(P, StrLen(P) + 1);
{ ignore exceptions }
end; end;
end; end;
var
K: HKEY;
begin begin
if UsingWinNT then if RegOpenKeyExView(rvDefault, HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\Session Manager',
DoNT 0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin
else try
DoNonNT; DoValue(K, 'PendingFileRenameOperations');
{ When "PendingFileRenameOperations" is full, it spills over into
"PendingFileRenameOperations2" }
DoValue(K, 'PendingFileRenameOperations2');
finally
RegCloseKey(K);
end;
end;
end; end;
procedure UnregisterFont(const FontName, FontFilename: String; const PerUserFont: Boolean); procedure UnregisterFont(const FontName, FontFilename: String; const PerUserFont: Boolean);
const
FontsKeys: array[Boolean] of PChar =
(NEWREGSTR_PATH_SETUP + '\Fonts',
'Software\Microsoft\Windows NT\CurrentVersion\Fonts');
var var
RootKey, K: HKEY; RootKey, K: HKEY;
begin begin
@ -1364,7 +1180,7 @@ begin
else else
RootKey := HKEY_LOCAL_MACHINE; RootKey := HKEY_LOCAL_MACHINE;
if RegOpenKeyExView(rvDefault, RootKey, FontsKeys[UsingWinNT], if RegOpenKeyExView(rvDefault, RootKey, 'Software\Microsoft\Windows NT\CurrentVersion\Fonts',
0, KEY_SET_VALUE, K) = ERROR_SUCCESS then begin 0, KEY_SET_VALUE, K) = ERROR_SUCCESS then begin
RegDeleteValue(K, PChar(FontName)); RegDeleteValue(K, PChar(FontName));
RegCloseKey(K); RegCloseKey(K);
@ -1388,7 +1204,7 @@ begin
GetDiskFreeSpaceEx, however, *does* succeed with UNC paths, so use it GetDiskFreeSpaceEx, however, *does* succeed with UNC paths, so use it
if available. } if available. }
GetDiskFreeSpaceExFunc := GetProcAddress(GetModuleHandle(kernel32), GetDiskFreeSpaceExFunc := GetProcAddress(GetModuleHandle(kernel32),
{$IFDEF UNICODE}'GetDiskFreeSpaceExW'{$ELSE}'GetDiskFreeSpaceExA'{$ENDIF}); 'GetDiskFreeSpaceExW');
if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
Result := False; Result := False;
Exit; Exit;
@ -1403,9 +1219,8 @@ begin
DWORD(SectorsPerCluster), DWORD(BytesPerSector), DWORD(FreeClusters), DWORD(SectorsPerCluster), DWORD(BytesPerSector), DWORD(FreeClusters),
DWORD(TotalClusters)); DWORD(TotalClusters));
if Result then begin if Result then begin
{ Windows 95/98 cap the result of GetDiskFreeSpace at 2GB, but NT 4.0 { The result of GetDiskFreeSpace does not cap at 2GB, so we must use a
does not, so we must use a 64-bit multiply operation to avoid an 64-bit multiply operation to avoid an overflow. }
overflow. }
Multiply32x32to64(BytesPerSector * SectorsPerCluster, FreeClusters, Multiply32x32to64(BytesPerSector * SectorsPerCluster, FreeClusters,
FreeBytes); FreeBytes);
Multiply32x32to64(BytesPerSector * SectorsPerCluster, TotalClusters, Multiply32x32to64(BytesPerSector * SectorsPerCluster, TotalClusters,
@ -1442,8 +1257,7 @@ end;
procedure RefreshEnvironment; procedure RefreshEnvironment;
{ Notifies other applications (Explorer) that environment variables have { Notifies other applications (Explorer) that environment variables have
changed. Based on code from KB article 104011. changed. Based on code from KB article 104011. }
Note: Win9x's Explorer ignores this message. }
var var
MsgResult: DWORD_PTR; MsgResult: DWORD_PTR;
begin begin
@ -1484,7 +1298,6 @@ function DetermineDefaultLanguage(const GetLanguageEntryProc: TGetLanguageEntryP
{ Finds the index of the language entry that most closely matches the user's { Finds the index of the language entry that most closely matches the user's
UI language / locale. If no match is found, ResultIndex is set to 0. } UI language / locale. If no match is found, ResultIndex is set to 0. }
{$IFDEF UNICODE}
function GetCodePageFromLangID(const ALangID: LANGID): Integer; function GetCodePageFromLangID(const ALangID: LANGID): Integer;
const const
LOCALE_RETURN_NUMBER = $20000000; LOCALE_RETURN_NUMBER = $20000000;
@ -1497,7 +1310,6 @@ function DetermineDefaultLanguage(const GetLanguageEntryProc: TGetLanguageEntryP
else else
Result := -1; Result := -1;
end; end;
{$ENDIF}
var var
I: Integer; I: Integer;
@ -1532,14 +1344,9 @@ begin
I := 0; I := 0;
while GetLanguageEntryProc(I, LangEntry) do begin while GetLanguageEntryProc(I, LangEntry) do begin
if LangEntry.LanguageID = UILang then begin if LangEntry.LanguageID = UILang then begin
{$IFNDEF UNICODE} ResultIndex := I;
if (LangEntry.LanguageCodePage = 0) or (LangEntry.LanguageCodePage = GetACP) then Result := ddMatch;
{$ENDIF} Exit;
begin
ResultIndex := I;
Result := ddMatch;
Exit;
end;
end; end;
Inc(I); Inc(I);
end; end;
@ -1547,9 +1354,6 @@ begin
I := 0; I := 0;
while GetLanguageEntryProc(I, LangEntry) do begin while GetLanguageEntryProc(I, LangEntry) do begin
if (LangEntry.LanguageID and $3FF) = (UILang and $3FF) then begin if (LangEntry.LanguageID and $3FF) = (UILang and $3FF) then begin
{$IFNDEF UNICODE}
if (LangEntry.LanguageCodePage = 0) or (LangEntry.LanguageCodePage = GetACP) then
{$ELSE}
{ On Unicode, there is no LanguageCodePage filter, so we have to check { On Unicode, there is no LanguageCodePage filter, so we have to check
the language IDs to ensure we don't return Simplified Chinese on a the language IDs to ensure we don't return Simplified Chinese on a
Traditional Chinese system, or vice versa. Traditional Chinese system, or vice versa.
@ -1559,7 +1363,6 @@ begin
Traditional Chinese LANGIDs ($0404, $0C04, $1404) use CP 950 } Traditional Chinese LANGIDs ($0404, $0C04, $1404) use CP 950 }
if ((UILang and $3FF) <> LANG_CHINESE) or if ((UILang and $3FF) <> LANG_CHINESE) or
(GetCodePageFromLangID(LangEntry.LanguageID) = GetCodePageFromLangID(UILang)) then (GetCodePageFromLangID(LangEntry.LanguageID) = GetCodePageFromLangID(UILang)) then
{$ENDIF}
begin begin
ResultIndex := I; ResultIndex := I;
Result := ddMatch; Result := ddMatch;

View File

@ -2,7 +2,7 @@ unit Install;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2020 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -35,7 +35,7 @@ uses
Compress, SHA1, PathFunc, CmnFunc, CmnFunc2, RedirFunc, Int64Em, MsgIDs, Compress, SHA1, PathFunc, CmnFunc, CmnFunc2, RedirFunc, Int64Em, MsgIDs,
Wizard, DebugStruct, DebugClient, VerInfo, ScriptRunner, RegDLL, Helper, Wizard, DebugStruct, DebugClient, VerInfo, ScriptRunner, RegDLL, Helper,
ResUpdate, DotNet, TaskbarProgressFunc, NewProgressBar, RestartManager, ResUpdate, DotNet, TaskbarProgressFunc, NewProgressBar, RestartManager,
Net.HTTPClient, Net.URLClient, NetEncoding; Net.HTTPClient, Net.URLClient, NetEncoding, RegStr;
type type
TSetupUninstallLog = class(TUninstallLog) TSetupUninstallLog = class(TUninstallLog)
@ -395,7 +395,6 @@ var
end; end;
function PackCompiledCodeTextIntoString(const CompiledCodeText: AnsiString): String; function PackCompiledCodeTextIntoString(const CompiledCodeText: AnsiString): String;
{$IFDEF UNICODE}
var var
N: Integer; N: Integer;
begin begin
@ -404,21 +403,12 @@ var
Inc(N); { This will lead to 1 extra byte being moved but that's ok since it is the #0 } Inc(N); { This will lead to 1 extra byte being moved but that's ok since it is the #0 }
N := N div 2; N := N div 2;
SetString(Result, PChar(Pointer(CompiledCodeText)), N); SetString(Result, PChar(Pointer(CompiledCodeText)), N);
{$ELSE}
begin
Result := CompiledCodeText;
{$ENDIF}
end; end;
procedure RecordCompiledCode; procedure RecordCompiledCode;
var var
LeadBytesStr, ExpandedApp, ExpandedGroup, CustomMessagesStr: String; LeadBytesStr, ExpandedApp, ExpandedGroup, CustomMessagesStr: String;
begin begin
{$IFNDEF UNICODE}
SetString(LeadBytesStr, PChar(@SetupHeader.LeadBytes),
SizeOf(SetupHeader.LeadBytes));
{$ENDIF}
{ Only use app if Setup creates one } { Only use app if Setup creates one }
if shCreateAppDir in SetupHeader.Options then if shCreateAppDir in SetupHeader.Options then
ExpandedApp := ExpandConst('{app}') ExpandedApp := ExpandConst('{app}')
@ -438,7 +428,7 @@ var
{ Record [Code] even if empty to 'overwrite' old versions } { Record [Code] even if empty to 'overwrite' old versions }
UninstLog.Add(utCompiledCode, [PackCompiledCodeTextIntoString(SetupHeader.CompiledCodeText), UninstLog.Add(utCompiledCode, [PackCompiledCodeTextIntoString(SetupHeader.CompiledCodeText),
LeadBytesStr, ExpandedApp, ExpandedGroup, WizardGroupValue, LeadBytesStr, ExpandedApp, ExpandedGroup, WizardGroupValue,
ExpandConst('{language}'), CustomMessagesStr], SetupBinVersion {$IFDEF UNICODE} or Longint($80000000) {$ENDIF}); ExpandConst('{language}'), CustomMessagesStr], SetupBinVersion or Longint($80000000));
end; end;
type type
@ -683,13 +673,9 @@ var
else else
Z := ExpandedAppVerName; Z := ExpandedAppVerName;
HandleDuplicateDisplayNames(Z); HandleDuplicateDisplayNames(Z);
{ For the entry to appear in ARP, DisplayName cannot exceed 63 characters { For the entry to appear in ARP, DisplayName cannot exceed 259 characters
on Windows 9x/NT 4.0, or 259 characters on Windows 2000 and later. } on Windows 2000 and later. }
if WindowsVersionAtLeast(5, 0) then SetStringValue(H2, 'DisplayName', Copy(Z, 1, 259));
I := 259
else
I := 63;
SetStringValue(H2, 'DisplayName', Copy(Z, 1, I));
SetStringValueUnlessEmpty(H2, 'DisplayIcon', ExpandConst(SetupHeader.UninstallDisplayIcon)); SetStringValueUnlessEmpty(H2, 'DisplayIcon', ExpandConst(SetupHeader.UninstallDisplayIcon));
var ExtraUninstallString: String; var ExtraUninstallString: String;
if shUninstallLogging in SetupHeader.Options then if shUninstallLogging in SetupHeader.Options then
@ -721,29 +707,25 @@ var
SetDWordValue(H2, 'VersionMajor', MajorVersion); SetDWordValue(H2, 'VersionMajor', MajorVersion);
SetDWordValue(H2, 'VersionMinor', MinorVersion); SetDWordValue(H2, 'VersionMinor', MinorVersion);
end; end;
{ Note: Windows 7 doesn't automatically calculate sizes so set EstimatedSize ourselves. Do not set it { Note: Windows 7 (and later?) doesn't automatically calculate sizes so set EstimatedSize ourselves. }
on earlier Windows versions since calculated sizes are cached and clearing the cache would require if (SetupHeader.UninstallDisplaySize.Hi = 0) and (SetupHeader.UninstallDisplaySize.Lo = 0) then begin
updating an undocumented key at HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Management\ARPCache\<id>. } { Estimate the size by taking the size of all files and adding any ExtraDiskSpaceRequired. }
if WindowsVersion shr 16 >= $0601 then begin EstimatedSize := AfterInstallFilesSize;
if (SetupHeader.UninstallDisplaySize.Hi = 0) and (SetupHeader.UninstallDisplaySize.Lo = 0) then begin Inc6464(EstimatedSize, SetupHeader.ExtraDiskSpaceRequired);
{ Estimate the size by taking the size of all files and adding any ExtraDiskSpaceRequired. } for I := 0 to Entries[seComponent].Count-1 do begin
EstimatedSize := AfterInstallFilesSize; with PSetupComponentEntry(Entries[seComponent][I])^ do begin
Inc6464(EstimatedSize, SetupHeader.ExtraDiskSpaceRequired); if ShouldProcessEntry(WizardComponents, nil, Name, '', Languages, '') then
for I := 0 to Entries[seComponent].Count-1 do begin Inc6464(EstimatedSize, ExtraDiskSpaceRequired);
with PSetupComponentEntry(Entries[seComponent][I])^ do begin
if ShouldProcessEntry(WizardComponents, nil, Name, '', Languages, '') then
Inc6464(EstimatedSize, ExtraDiskSpaceRequired);
end;
end; end;
end else
EstimatedSize := SetupHeader.UninstallDisplaySize;
{ ARP on Windows 7 without SP1 only pays attention to the lower 6 bytes of EstimatedSize and
throws away the rest. For example putting in $4000001 (=4GB + 1KB) displays as 1 KB.
So we need to check for this. Already checked this is Windows 7 or newer above. }
if (Hi(NTServicePackLevel) > 0) or (WindowsVersion shr 16 > $0601) or (EstimatedSize.Hi = 0) then begin
Div64(EstimatedSize, 1024);
SetDWordValue(H2, 'EstimatedSize', EstimatedSize.Lo)
end; end;
end else
EstimatedSize := SetupHeader.UninstallDisplaySize;
{ ARP on Windows 7 without SP1 only pays attention to the lower 6 bytes of EstimatedSize and
throws away the rest. For example putting in $4000001 (=4GB + 1KB) displays as 1 KB.
So we need to check for this. }
if (Hi(NTServicePackLevel) > 0) or (WindowsVersion shr 16 > $0601) or (EstimatedSize.Hi = 0) then begin
Div64(EstimatedSize, 1024);
SetDWordValue(H2, 'EstimatedSize', EstimatedSize.Lo)
end; end;
{ Also see SetPreviousData in ScriptFunc.pas } { Also see SetPreviousData in ScriptFunc.pas }
@ -906,11 +888,7 @@ var
anti-spyware programs that catch all unins*.exe files with certain MD5 anti-spyware programs that catch all unins*.exe files with certain MD5
sums just because some piece of spyware was deployed with Inno Setup and sums just because some piece of spyware was deployed with Inno Setup and
had the unins*.exe file in its directory. } had the unins*.exe file in its directory. }
{$IFDEF UNICODE}
UniqueValue := GetSHA1OfUnicodeString(ExpandedAppId); UniqueValue := GetSHA1OfUnicodeString(ExpandedAppId);
{$ELSE}
UniqueValue := GetSHA1OfAnsiString(ExpandedAppId);
{$ENDIF}
F.WriteBuffer(UniqueValue, SizeOf(UniqueValue)); F.WriteBuffer(UniqueValue, SizeOf(UniqueValue));
UninstallerMsgTail.ID := UninstallerMsgTailID; UninstallerMsgTail.ID := UninstallerMsgTailID;
@ -930,10 +908,6 @@ var
procedure InstallFont(const Filename, FontName: String; procedure InstallFont(const Filename, FontName: String;
const PerUserFont, AddToFontTableNow: Boolean; var WarnedPerUserFonts: Boolean); const PerUserFont, AddToFontTableNow: Boolean; var WarnedPerUserFonts: Boolean);
const
FontsKeys: array[Boolean] of PChar =
(NEWREGSTR_PATH_SETUP + '\Fonts',
'Software\Microsoft\Windows NT\CurrentVersion\Fonts');
var var
RootKey, K: HKEY; RootKey, K: HKEY;
begin begin
@ -956,7 +930,7 @@ var
RootKey := HKEY_CURRENT_USER RootKey := HKEY_CURRENT_USER
else else
RootKey := HKEY_LOCAL_MACHINE; RootKey := HKEY_LOCAL_MACHINE;
if RegOpenKeyExView(rvDefault, RootKey, FontsKeys[IsNT], 0, if RegOpenKeyExView(rvDefault, RootKey, 'Software\Microsoft\Windows NT\CurrentVersion\Fonts', 0,
KEY_SET_VALUE, K) = ERROR_SUCCESS then begin KEY_SET_VALUE, K) = ERROR_SUCCESS then begin
if RegSetValueEx(K, PChar(FontName), 0, REG_SZ, PChar(Filename), if RegSetValueEx(K, PChar(FontName), 0, REG_SZ, PChar(Filename),
(Length(Filename)+1)*SizeOf(Filename[1])) <> ERROR_SUCCESS then (Length(Filename)+1)*SizeOf(Filename[1])) <> ERROR_SUCCESS then
@ -1183,19 +1157,12 @@ var
Log('Non-default bitness: 32-bit'); Log('Non-default bitness: 32-bit');
end; end;
{ See if it's a protected system file. { See if it's a protected system file. }
Note: We don't call IsProtectedSystemFile anymore on Windows Me if IsProtectedSystemFile(DisableFsRedir, DestFile) then begin
even though it supports WFP. Two users reported that installs ran Log('Dest file is protected by Windows File Protection.');
very slowly on 4.2.1, and with the help of one of the users, the IsProtectedFile := (CurFile^.FileType = ftUserFile);
cause was narrowed down to this call. For him, it was taking 6 end else
seconds per call. I have no idea what would cause it to be so IsProtectedFile := False;
slow; it only took a few milliseconds in my tests on Windows Me. }
IsProtectedFile := False;
if IsNT and (WindowsVersion >= Cardinal($05000000)) then
if IsProtectedSystemFile(DisableFsRedir, DestFile) then begin
Log('Dest file is protected by Windows File Protection.');
IsProtectedFile := (CurFile^.FileType = ftUserFile);
end;
DestFileExists := NewFileExistsRedir(DisableFsRedir, DestFile); DestFileExists := NewFileExistsRedir(DisableFsRedir, DestFile);
if not CheckedDestFileExistedBefore then begin if not CheckedDestFileExistedBefore then begin
@ -1972,14 +1939,10 @@ var
'IconIndex=' + IntToStr(IconIndex) + SNewLine; 'IconIndex=' + IntToStr(IconIndex) + SNewLine;
F := TTextFileWriter.Create(Filename, fdCreateAlways, faWrite, fsNone); F := TTextFileWriter.Create(Filename, fdCreateAlways, faWrite, fsNone);
try try
{$IFDEF UNICODE}
if SameText(S, String(AnsiString(S))) then if SameText(S, String(AnsiString(S))) then
F.WriteAnsi(AnsiString(S)) F.WriteAnsi(AnsiString(S))
else else
F.Write(S); F.Write(S);
{$ELSE}
F.Write(S);
{$ENDIF}
finally finally
F.Free; F.Free;
end; end;
@ -2008,15 +1971,15 @@ var
procedure CreateAnIcon(Name: String; const Description, Path, Parameters, procedure CreateAnIcon(Name: String; const Description, Path, Parameters,
WorkingDir, IconFilename: String; const IconIndex, ShowCmd: Integer; WorkingDir, IconFilename: String; const IconIndex, ShowCmd: Integer;
const NeverUninstall: Boolean; const CloseOnExit: TSetupIconCloseOnExit; const NeverUninstall: Boolean; const CloseOnExit: TSetupIconCloseOnExit;
const HotKey: Word; FolderShortcut: Boolean; const HotKey: Word; const AppUserModelID: String;
const AppUserModelID: String; const AppUserModelToastActivatorCLSID: PGUID; const AppUserModelToastActivatorCLSID: PGUID;
const ExcludeFromShowInNewInstall, PreventPinning: Boolean); const ExcludeFromShowInNewInstall, PreventPinning: Boolean);
var var
BeginsWithGroup: Boolean; BeginsWithGroup: Boolean;
LinkFilename, PifFilename, UrlFilename, DirFilename, ProbableFilename, LinkFilename, PifFilename, UrlFilename, DirFilename, ProbableFilename,
ResultingFilename: String; ResultingFilename: String;
Flags: TMakeDirFlags; Flags: TMakeDirFlags;
URLShortcut, FolderShortcutCreated: Boolean; URLShortcut: Boolean;
begin begin
BeginsWithGroup := Copy(Name, 1, 8) = '{group}\'; BeginsWithGroup := Copy(Name, 1, 8) = '{group}\';
{ Note: PathExpand removes trailing spaces, so it can't be called on { Note: PathExpand removes trailing spaces, so it can't be called on
@ -2033,12 +1996,6 @@ var
else if BeginsWithGroup then else if BeginsWithGroup then
Include(Flags, mdAlwaysUninstall); Include(Flags, mdAlwaysUninstall);
{ On Windows 7, folder shortcuts don't expand properly on the Start Menu
(they just show "target"), so ignore the foldershortcut flag.
(Windows Vista works fine.) }
if FolderShortcut and WindowsVersionAtLeast(6, 1) then
FolderShortcut := False;
URLShortcut := IsPathURL(Path); URLShortcut := IsPathURL(Path);
if URLShortcut then if URLShortcut then
ProbableFilename := UrlFilename ProbableFilename := UrlFilename
@ -2066,12 +2023,11 @@ var
environment-variable strings (e.g. %SystemRoot%\...) } environment-variable strings (e.g. %SystemRoot%\...) }
ResultingFilename := CreateShellLink(LinkFilename, Description, Path, ResultingFilename := CreateShellLink(LinkFilename, Description, Path,
Parameters, WorkingDir, IconFilename, IconIndex, ShowCmd, HotKey, Parameters, WorkingDir, IconFilename, IconIndex, ShowCmd, HotKey,
FolderShortcut, AppUserModelID, AppUserModelToastActivatorCLSID, AppUserModelID, AppUserModelToastActivatorCLSID,
ExcludeFromShowInNewInstall, PreventPinning); ExcludeFromShowInNewInstall, PreventPinning);
FolderShortcutCreated := FolderShortcut and DirExists(ResultingFilename);
{ If a .pif file was created, apply the "Close on exit" setting } { If a .pif file was created, apply the "Close on exit" setting }
if (CloseOnExit <> icNoSetting) and not FolderShortcutCreated and if (CloseOnExit <> icNoSetting) and
(CompareText(PathExtractExt(ResultingFilename), '.pif') = 0) then begin (CompareText(PathExtractExt(ResultingFilename), '.pif') = 0) then begin
try try
ModifyPifFile(ResultingFilename, CloseOnExit = icYes); ModifyPifFile(ResultingFilename, CloseOnExit = icYes);
@ -2084,7 +2040,6 @@ var
{ Create an Internet Shortcut (.url) file } { Create an Internet Shortcut (.url) file }
CreateURLFile(UrlFilename, Path, IconFilename, IconIndex); CreateURLFile(UrlFilename, Path, IconFilename, IconIndex);
ResultingFilename := UrlFilename; ResultingFilename := UrlFilename;
FolderShortcutCreated := False;
end; end;
Log('Successfully created the icon.'); Log('Successfully created the icon.');
@ -2093,24 +2048,14 @@ var
CreatedIcon := True; CreatedIcon := True;
{ Notify shell of the change } { Notify shell of the change }
if FolderShortcutCreated then SHChangeNotify(SHCNE_CREATE, SHCNF_PATH, PChar(ResultingFilename), nil);
SHChangeNotify(SHCNE_MKDIR, SHCNF_PATH, PChar(ResultingFilename), nil)
else
SHChangeNotify(SHCNE_CREATE, SHCNF_PATH, PChar(ResultingFilename), nil);
SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_PATH or SHCNF_FLUSH, SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_PATH or SHCNF_FLUSH,
PChar(PathExtractDir(ResultingFilename)), nil); PChar(PathExtractDir(ResultingFilename)), nil);
{ Add uninstall log entries } { Add uninstall log entries }
if not NeverUninstall then begin if not NeverUninstall then begin
if FolderShortcutCreated then begin if URLShortcut then
UninstLog.Add(utDeleteDirOrFiles, [ResultingFilename], UninstLog.Add(utDeleteFile, [ResultingFilename], utDeleteFile_CallChangeNotify)
utDeleteDirOrFiles_IsDir or utDeleteDirOrFiles_CallChangeNotify);
UninstLog.Add(utDeleteFile, [AddBackslash(ResultingFilename) + 'target.lnk'], 0);
UninstLog.Add(utDeleteFile, [AddBackslash(ResultingFilename) + 'Desktop.ini'], 0);
end
else if URLShortcut then begin
UninstLog.Add(utDeleteFile, [ResultingFilename], utDeleteFile_CallChangeNotify);
end
else begin else begin
{ Even though we only created one file, go ahead and try deleting { Even though we only created one file, go ahead and try deleting
both a .lnk and .pif file at uninstall time, in case the user both a .lnk and .pif file at uninstall time, in case the user
@ -2122,14 +2067,12 @@ var
end; end;
function ExpandAppPath(const Filename: String): String; function ExpandAppPath(const Filename: String): String;
const
AppPathsBaseKey = NEWREGSTR_PATH_SETUP + '\App Paths\';
var var
K: HKEY; K: HKEY;
Found: Boolean; Found: Boolean;
begin begin
if RegOpenKeyExView(InstallDefaultRegView, HKEY_LOCAL_MACHINE, if RegOpenKeyExView(InstallDefaultRegView, HKEY_LOCAL_MACHINE,
PChar(AppPathsBaseKey + Filename), 0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin PChar(REGSTR_PATH_APPPATHS + '\' + Filename), 0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin
Found := RegQueryStringValue(K, '', Result); Found := RegQueryStringValue(K, '', Result);
RegCloseKey(K); RegCloseKey(K);
if Found then if Found then
@ -2164,7 +2107,7 @@ var
ExpandConst(Parameters), ExpandConst(WorkingDir), ExpandConst(Parameters), ExpandConst(WorkingDir),
ExpandConst(IconFilename), IconIndex, ShowCmd, ExpandConst(IconFilename), IconIndex, ShowCmd,
ioUninsNeverUninstall in Options, CloseOnExit, HotKey, ioUninsNeverUninstall in Options, CloseOnExit, HotKey,
ioFolderShortcut in Options, ExpandConst(AppUserModelID), TACLSID, ExpandConst(AppUserModelID), TACLSID,
ioExcludeFromShowInNewInstall in Options, ioExcludeFromShowInNewInstall in Options,
ioPreventPinning in Options) ioPreventPinning in Options)
end else end else
@ -2320,10 +2263,8 @@ var
NeedToRetry, DidDeleteKey: Boolean; NeedToRetry, DidDeleteKey: Boolean;
ErrorCode: Longint; ErrorCode: Longint;
QV: Integer64; QV: Integer64;
{$IFDEF UNICODE}
I: Integer; I: Integer;
AnsiS: AnsiString; AnsiS: AnsiString;
{$ENDIF}
begin begin
for CurRegNumber := 0 to Entries[seRegistry].Count-1 do begin for CurRegNumber := 0 to Entries[seRegistry].Count-1 do begin
with PSetupRegistryEntry(Entries[seRegistry][CurRegNumber])^ do begin with PSetupRegistryEntry(Entries[seRegistry][CurRegNumber])^ do begin
@ -2495,16 +2436,11 @@ var
RegError(reRegSetValueEx, RK, S, ErrorCode); RegError(reRegSetValueEx, RK, S, ErrorCode);
end; end;
rtBinary: begin rtBinary: begin
{$IFDEF UNICODE}
AnsiS := ''; AnsiS := '';
for I := 1 to Length(ValueData) do for I := 1 to Length(ValueData) do
AnsiS := AnsiS + AnsiChar(Ord(ValueData[I])); AnsiS := AnsiS + AnsiChar(Ord(ValueData[I]));
ErrorCode := RegSetValueEx(K, PChar(N), 0, REG_BINARY, ErrorCode := RegSetValueEx(K, PChar(N), 0, REG_BINARY,
PAnsiChar(AnsiS), Length(AnsiS)); PAnsiChar(AnsiS), Length(AnsiS));
{$ELSE}
ErrorCode := RegSetValueEx(K, PChar(N), 0, REG_BINARY,
PChar(ValueData), Length(ValueData));
{$ENDIF}
if (ErrorCode <> ERROR_SUCCESS) and if (ErrorCode <> ERROR_SUCCESS) and
not(roNoError in Options) then not(roNoError in Options) then
RegError(reRegSetValueEx, RK, S, ErrorCode); RegError(reRegSetValueEx, RK, S, ErrorCode);
@ -2607,7 +2543,6 @@ var
const const
Chars: array[Boolean, Boolean] of Char = (('s', 't'), ('S', 'T')); Chars: array[Boolean, Boolean] of Char = (('s', 't'), ('S', 'T'));
RunOnceKey = NEWREGSTR_PATH_SETUP + '\RunOnce';
var var
RegSvrExeFilename: String; RegSvrExeFilename: String;
F: TTextFileWriter; F: TTextFileWriter;
@ -2627,8 +2562,8 @@ var
{ In case Windows directory is write protected, try the Temp directory. { In case Windows directory is write protected, try the Temp directory.
Windows directory is our first choice since some people (ignorantly) Windows directory is our first choice since some people (ignorantly)
put things like "DELTREE C:\WINDOWS\TEMP\*.*" in their AUTOEXEC.BAT. put things like "DELTREE C:\WINDOWS\TEMP\*.*" in their AUTOEXEC.BAT.
Also on Windows 2000 and later, each user has his own personal Temp Also, each user has his own personal Temp directory which may not
directory which may not be accessible by other users. } be accessible by other users. }
RegSvrExeFilename := CreateRegSvrExe(GetTempDir); RegSvrExeFilename := CreateRegSvrExe(GetTempDir);
end; end;
end end
@ -2666,11 +2601,11 @@ var
RootKey := HKEY_LOCAL_MACHINE RootKey := HKEY_LOCAL_MACHINE
else else
RootKey := HKEY_CURRENT_USER; RootKey := HKEY_CURRENT_USER;
ErrorCode := RegCreateKeyExView(rvDefault, RootKey, RunOnceKey, 0, nil, ErrorCode := RegCreateKeyExView(rvDefault, RootKey, REGSTR_PATH_RUNONCE, 0, nil,
REG_OPTION_NON_VOLATILE, KEY_SET_VALUE or KEY_QUERY_VALUE, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE or KEY_QUERY_VALUE,
nil, H, @Disp); nil, H, @Disp);
if ErrorCode <> ERROR_SUCCESS then if ErrorCode <> ERROR_SUCCESS then
RegError(reRegCreateKeyEx, RootKey, RunOnceKey, ErrorCode); RegError(reRegCreateKeyEx, RootKey, REGSTR_PATH_RUNONCE, ErrorCode);
try try
J := 0; J := 0;
while True do begin while True do begin
@ -2688,7 +2623,7 @@ var
ErrorCode := RegSetValueEx(H, PChar(ValueName), 0, REG_SZ, PChar(Data), ErrorCode := RegSetValueEx(H, PChar(ValueName), 0, REG_SZ, PChar(Data),
(Length(Data)+1)*SizeOf(Data[1])); (Length(Data)+1)*SizeOf(Data[1]));
if ErrorCode <> ERROR_SUCCESS then if ErrorCode <> ERROR_SUCCESS then
RegError(reRegSetValueEx, RootKey, RunOnceKey, ErrorCode); RegError(reRegSetValueEx, RootKey, REGSTR_PATH_RUNONCE, ErrorCode);
Break; Break;
end; end;
end; end;
@ -3391,13 +3326,7 @@ procedure ExtractTemporaryFile(const BaseName: String);
if Result[I] = '{' then begin if Result[I] = '{' then begin
Insert('{', Result, I); Insert('{', Result, I);
Inc(I); Inc(I);
{$IFDEF UNICODE}
end; end;
{$ELSE}
end
else if Result[I] in ConstLeadBytes^ then
Inc(I);
{$ENDIF}
Inc(I); Inc(I);
end; end;
end; end;

View File

@ -2,7 +2,7 @@ unit Int64Em;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2008 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -10,8 +10,6 @@ unit Int64Em;
integer value - and functions for manipulating Integer64's. integer value - and functions for manipulating Integer64's.
(We can't use the Int64 type since it's only available in Delphi 4 and (We can't use the Int64 type since it's only available in Delphi 4 and
later.) later.)
$jrsoftware: issrc/Projects/Int64Em.pas,v 1.14 2008/10/03 19:53:57 jr Exp $
} }
interface interface
@ -19,10 +17,6 @@ interface
{$I VERSION.INC} {$I VERSION.INC}
type type
{$IFNDEF IS_D4}
LongWord = Cardinal;
{$ENDIF}
Integer64 = record Integer64 = record
Lo, Hi: LongWord; Lo, Hi: LongWord;
end; end;

View File

@ -2,7 +2,7 @@ unit LZMA;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2010 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -15,12 +15,8 @@ interface
{$I VERSION.INC} {$I VERSION.INC}
uses uses
Windows, SysUtils, {$IFNDEF Delphi3orHigher} Ole2, {$ENDIF} Windows, SysUtils,
Compress, Int64Em; Compress, Int64Em;
{ Note: Ole2 must be included in the 'uses' clause on D2, and after Windows,
because it redefines E_* constants in Windows that are incorrect.
E_OUTOFMEMORY, for example, is defined as $80000002 in Windows, instead
of $8007000E. }
function LZMAInitCompressFunctions(Module: HMODULE): Boolean; function LZMAInitCompressFunctions(Module: HMODULE): Boolean;
function LZMAGetLevel(const Value: String; var Level: Integer): Boolean; function LZMAGetLevel(const Value: String; var Level: Integer): Boolean;

View File

@ -3,9 +3,6 @@ unit MD5;
{ {
MD5.pas: Translated from C to Delphi by Jordan Russell on 2004-03-16. MD5.pas: Translated from C to Delphi by Jordan Russell on 2004-03-16.
Still in the public domain. The original C code was taken from dpkg. Still in the public domain. The original C code was taken from dpkg.
$jrsoftware: issrc/Projects/MD5.pas,v 1.2 2004/03/16 17:58:14 jr Exp $
(based on revision 1.15 from local 'md5' repository)
} }
(* (*
@ -32,20 +29,8 @@ unit MD5;
interface interface
{$IFNDEF VER80}
{$IFNDEF VER90}
{$IFNDEF VER93}
{$IFNDEF VER100}
{$IFNDEF VER110}
{$DEFINE MD5_D4PLUS}
{$ENDIF}
{$ENDIF}
{$ENDIF}
{$ENDIF}
{$ENDIF}
type type
TMD5Word = {$IFDEF MD5_D4PLUS} LongWord {$ELSE} Cardinal {$ENDIF}; TMD5Word = LongWord;
TMD5Buf = array[0..3] of TMD5Word; TMD5Buf = array[0..3] of TMD5Word;
TMD5In = array[0..15] of TMD5Word; TMD5In = array[0..15] of TMD5Word;
TMD5Context = record TMD5Context = record

View File

@ -167,7 +167,7 @@ var
{ Other } { Other }
ShowLanguageDialog, MatchedLangParameter: Boolean; ShowLanguageDialog, MatchedLangParameter: Boolean;
InstallMode: (imNormal, imSilent, imVerySilent); InstallMode: (imNormal, imSilent, imVerySilent);
HasIcons, IsNT, IsWin64, Is64BitInstallMode, IsAdmin, IsPowerUserOrAdmin, IsAdminInstallMode, HasIcons, IsWin64, Is64BitInstallMode, IsAdmin, IsPowerUserOrAdmin, IsAdminInstallMode,
NeedPassword, NeedSerial, NeedsRestart, RestartSystem, NeedPassword, NeedSerial, NeedsRestart, RestartSystem,
IsUninstaller, AllowUninstallerShutdown, AcceptedQueryEndSessionInProgress: Boolean; IsUninstaller, AllowUninstallerShutdown, AcceptedQueryEndSessionInProgress: Boolean;
InstallDefaultDisableFsRedir, ScriptFuncDisableFsRedir: Boolean; InstallDefaultDisableFsRedir, ScriptFuncDisableFsRedir: Boolean;
@ -185,9 +185,7 @@ var
SetupExitCode: Integer; SetupExitCode: Integer;
CreatedIcon: Boolean; CreatedIcon: Boolean;
RestartInitiatedByThisProcess, DownloadTemporaryFileProcessMessages: Boolean; RestartInitiatedByThisProcess, DownloadTemporaryFileProcessMessages: Boolean;
{$IFDEF IS_D12}
TaskbarButtonHidden: Boolean; TaskbarButtonHidden: Boolean;
{$ENDIF}
InstallModeRootKey: HKEY; InstallModeRootKey: HKEY;
CodeRunner: TScriptRunner; CodeRunner: TScriptRunner;
@ -268,10 +266,9 @@ uses
ShellAPI, ShlObj, ShellAPI, ShlObj,
Msgs, MsgIDs, Install, InstFunc, InstFnc2, RedirFunc, PathFunc, Msgs, MsgIDs, Install, InstFunc, InstFnc2, RedirFunc, PathFunc,
Compress, CompressZlib, bzlib, LZMADecomp, ArcFour, SetupEnt, SelLangForm, Compress, CompressZlib, bzlib, LZMADecomp, ArcFour, SetupEnt, SelLangForm,
Wizard, DebugClient, VerInfo, Extract, FileClass, Logging, MD5, SHA1, Wizard, DebugClient, VerInfo, Extract, FileClass, Logging, MD5, SHA1, ActiveX,
{$IFNDEF Delphi3orHigher} OLE2, {$ELSE} ActiveX, {$ENDIF}
SimpleExpression, Helper, SpawnClient, SpawnServer, DotNet, BitmapImage, SimpleExpression, Helper, SpawnClient, SpawnServer, DotNet, BitmapImage,
TaskDialog; TaskDialog, RegStr;
{$R *.DFM} {$R *.DFM}
@ -310,12 +307,10 @@ begin
end; end;
function GetUninstallRegKeyBaseName(const ExpandedAppId: String): String; function GetUninstallRegKeyBaseName(const ExpandedAppId: String): String;
{$IFDEF UNICODE}
var var
UseAnsiCRC32: Boolean; UseAnsiCRC32: Boolean;
S: AnsiString; S: AnsiString;
I: Integer; I: Integer;
{$ENDIF}
begin begin
{ Set uninstall registry key base name } { Set uninstall registry key base name }
Result := ExpandedAppId; Result := ExpandedAppId;
@ -327,7 +322,6 @@ begin
resulting string is 57 characters long. On Unicode, only do this if we resulting string is 57 characters long. On Unicode, only do this if we
can get a CRC32 compatible with ANSI versions, else there's no point can get a CRC32 compatible with ANSI versions, else there's no point
in shortening since Unicode doesn't run on Win95. } in shortening since Unicode doesn't run on Win95. }
{$IFDEF UNICODE}
UseAnsiCRC32 := True; UseAnsiCRC32 := True;
for I := 1 to Length(Result) do begin for I := 1 to Length(Result) do begin
if Ord(Result[I]) > 126 then begin if Ord(Result[I]) > 126 then begin
@ -339,15 +333,12 @@ begin
S := AnsiString(Result); S := AnsiString(Result);
FmtStr(Result, '%.48s~%.8x', [Result, GetCRC32(S[1], Length(S)*SizeOf(S[1]))]); FmtStr(Result, '%.48s~%.8x', [Result, GetCRC32(S[1], Length(S)*SizeOf(S[1]))]);
end; end;
{$ELSE}
FmtStr(Result, '%.48s~%.8x', [Result, GetCRC32(Result[1], Length(Result)*SizeOf(Result[1]))]);
{$ENDIF}
end; end;
end; end;
function GetUninstallRegSubkeyName(const UninstallRegKeyBaseName: String): String; function GetUninstallRegSubkeyName(const UninstallRegKeyBaseName: String): String;
begin begin
Result := Format('%s\%s_is1', [NEWREGSTR_PATH_UNINSTALL, UninstallRegKeyBaseName]); Result := Format('%s\%s_is1', [REGSTR_PATH_UNINSTALL, UninstallRegKeyBaseName]);
end; end;
{ Based on FindPreviousData in Wizard.pas } { Based on FindPreviousData in Wizard.pas }
@ -1267,13 +1258,8 @@ begin
Inc(I); { Skip closing brace } Inc(I); { Skip closing brace }
end; end;
end end
else begin else
{$IFNDEF UNICODE}
if Result[I] in ConstLeadBytes^ then
Inc(I);
{$ENDIF}
Inc(I); Inc(I);
end;
end; end;
end; end;
@ -1299,7 +1285,7 @@ procedure InitMainNonSHFolderConsts;
var var
H: HKEY; H: HKEY;
begin begin
if RegOpenKeyExView(RegView, HKEY_LOCAL_MACHINE, NEWREGSTR_PATH_SETUP, 0, if RegOpenKeyExView(RegView, HKEY_LOCAL_MACHINE, REGSTR_PATH_SETUP, 0,
KEY_QUERY_VALUE, H) = ERROR_SUCCESS then begin KEY_QUERY_VALUE, H) = ERROR_SUCCESS then begin
if not RegQueryStringValue(H, Name, Result) then if not RegQueryStringValue(H, Name, Result) then
Result := ''; Result := '';
@ -1310,14 +1296,11 @@ procedure InitMainNonSHFolderConsts;
end; end;
procedure ReadSysUserInfo; procedure ReadSysUserInfo;
const
Paths: array[Boolean] of PChar = (NEWREGSTR_PATH_SETUP,
'SOFTWARE\Microsoft\Windows NT\CurrentVersion');
var var
RegView: TRegView; RegView: TRegView;
K: HKEY; K: HKEY;
begin begin
{ Windows Vista and Server 2008 x64 are bugged: the owner and organization { Windows 7 x64 (and later?) is bugged: the owner and organization
are set to "Microsoft" on the 32-bit key. So on 64-bit Windows, read are set to "Microsoft" on the 32-bit key. So on 64-bit Windows, read
from the 64-bit key. (The bug doesn't exist on 64-bit XP or Server 2003, from the 64-bit key. (The bug doesn't exist on 64-bit XP or Server 2003,
but it's safe to read the 64-bit key on those versions too.) } but it's safe to read the 64-bit key on those versions too.) }
@ -1325,8 +1308,8 @@ procedure InitMainNonSHFolderConsts;
RegView := rv64Bit RegView := rv64Bit
else else
RegView := rvDefault; RegView := rvDefault;
if RegOpenKeyExView(RegView, HKEY_LOCAL_MACHINE, Paths[IsNT], 0, KEY_QUERY_VALUE, if RegOpenKeyExView(RegView, HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion',
K) = ERROR_SUCCESS then begin 0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin
RegQueryStringValue(K, 'RegisteredOwner', SysUserInfoName); RegQueryStringValue(K, 'RegisteredOwner', SysUserInfoName);
RegQueryStringValue(K, 'RegisteredOrganization', SysUserInfoOrg); RegQueryStringValue(K, 'RegisteredOrganization', SysUserInfoOrg);
RegCloseKey(K); RegCloseKey(K);
@ -1341,10 +1324,7 @@ begin
WinSysNativeDir := GetSysNativeDir(IsWin64); WinSysNativeDir := GetSysNativeDir(IsWin64);
{ Get system drive } { Get system drive }
if Win32Platform = VER_PLATFORM_WIN32_NT then SystemDrive := GetEnv('SystemDrive'); {don't localize}
SystemDrive := GetEnv('SystemDrive') {don't localize}
else
SystemDrive := '';
if SystemDrive = '' then begin if SystemDrive = '' then begin
SystemDrive := PathExtractDrive(WinDir); SystemDrive := PathExtractDrive(WinDir);
if SystemDrive = '' then if SystemDrive = '' then
@ -1371,10 +1351,7 @@ begin
end; end;
{ Get path of command interpreter } { Get path of command interpreter }
if IsNT then CmdFilename := AddBackslash(WinSystemDir) + 'cmd.exe';
CmdFilename := AddBackslash(WinSystemDir) + 'cmd.exe'
else
CmdFilename := AddBackslash(WinDir) + 'COMMAND.COM';
{ Get user info from system } { Get user info from system }
ReadSysUserInfo; ReadSysUserInfo;
@ -1501,7 +1478,7 @@ begin
SHFolderDLLHandle := SafeLoadLibrary(Filename, SEM_NOOPENFILEERRORBOX); SHFolderDLLHandle := SafeLoadLibrary(Filename, SEM_NOOPENFILEERRORBOX);
if SHFolderDLLHandle = 0 then if SHFolderDLLHandle = 0 then
InternalError(Format('Failed to load DLL "%s"', [Filename])); InternalError(Format('Failed to load DLL "%s"', [Filename]));
@SHGetFolderPathFunc := GetProcAddress(SHFolderDLLHandle, {$IFDEF UNICODE}'SHGetFolderPathW'{$ELSE}'SHGetFolderPathA'{$ENDIF}); @SHGetFolderPathFunc := GetProcAddress(SHFolderDLLHandle, 'SHGetFolderPathW');
if @SHGetFolderPathFunc = nil then if @SHGetFolderPathFunc = nil then
InternalError('Failed to get address of SHGetFolderPath function'); InternalError('Failed to get address of SHGetFolderPath function');
end; end;
@ -1528,17 +1505,16 @@ begin
if Create then if Create then
Folder := Folder or CSIDL_FLAG_CREATE; Folder := Folder or CSIDL_FLAG_CREATE;
{ Work around a nasty bug in Windows Vista (still present in SP1) and { Work around a nasty bug in Windows Vista and Windows Server 2008 and maybe
Windows Server 2008: When a folder ID resolves to the root directory of a later versions also: When a folder ID resolves to the root directory of a
drive ('X:\') and the CSIDL_FLAG_CREATE flag is passed, SHGetFolderPath drive ('X:\') and the CSIDL_FLAG_CREATE flag is passed, SHGetFolderPath
fails with code 0x80070005. fails with code 0x80070005.
So on Vista only, first try calling the function without CSIDL_FLAG_CREATE. So, first try calling the function without CSIDL_FLAG_CREATE.
If and only if that fails, call it again with the flag. If and only if that fails, call it again with the flag.
Note: The calls *must* be issued in this order; if it's called with the Note: The calls *must* be issued in this order; if it's called with the
flag first, it seems to permanently cache the failure code, causing future flag first, it seems to permanently cache the failure code, causing future
calls that don't include the flag to fail as well. } calls that don't include the flag to fail as well. }
if (WindowsVersion shr 16 >= $0600) and if Folder and CSIDL_FLAG_CREATE <> 0 then
(Folder and CSIDL_FLAG_CREATE <> 0) then
Res := SHGetFolderPathFunc(0, Folder and not CSIDL_FLAG_CREATE, 0, Res := SHGetFolderPathFunc(0, Folder and not CSIDL_FLAG_CREATE, 0,
SHGFP_TYPE_CURRENT, Buf) SHGFP_TYPE_CURRENT, Buf)
else else
@ -1557,7 +1533,7 @@ end;
function GetShellFolderByGUID(Folder: TGUID; const Create: Boolean): String; function GetShellFolderByGUID(Folder: TGUID; const Create: Boolean): String;
begin begin
if Assigned(SHGetKnownFolderPathFunc) and (WindowsVersion shr 16 >= $0600) then begin if Assigned(SHGetKnownFolderPathFunc) then begin
var dwFlags: DWORD := 0; var dwFlags: DWORD := 0;
if Create then if Create then
dwFlags := dwFlags or KF_FLAG_CREATE; dwFlags := dwFlags or KF_FLAG_CREATE;
@ -1605,16 +1581,12 @@ var
ShellFolder: String; ShellFolder: String;
begin begin
if not ShellFoldersRead[Common, ID] then begin if not ShellFoldersRead[Common, ID] then begin
if ID = sfUserProgramFiles then begin if ID = sfUserProgramFiles then
ShellFolder := GetShellFolderByGUID(FOLDERID_UserProgramFiles {Windows 7+}, True); ShellFolder := GetShellFolderByGUID(FOLDERID_UserProgramFiles, True)
if ShellFolder = '' then else if ID = sfUserCommonFiles then
ShellFolder := ExpandConst('{localappdata}\Programs'); { supply default, same as Window 7 and newer } ShellFolder := GetShellFolderByGUID(FOLDERID_UserProgramFilesCommon, True)
end else if ID = sfUserCommonFiles then begin else if ID = sfUserSavedGames then
ShellFolder := GetShellFolderByGUID(FOLDERID_UserProgramFilesCommon {Windows 7+}, True); ShellFolder := GetShellFolderByGUID(FOLDERID_SavedGames, True)
if ShellFolder = '' then
ShellFolder := ExpandConst('{localappdata}\Programs\Common'); { supply default, same as Window 7 and newer }
end else if ID = sfUserSavedGames then
ShellFolder := GetShellFolderByGUID(FOLDERID_SavedGames {Vista+}, True)
else else
ShellFolder := GetShellFolderByCSIDL(FolderIDs[Common, ID], True); ShellFolder := GetShellFolderByCSIDL(FolderIDs[Common, ID], True);
ShellFolders[Common, ID] := ShellFolder; ShellFolders[Common, ID] := ShellFolder;
@ -1629,22 +1601,16 @@ var
Ver, Ver2, MinVer, OnlyBelowVer: Cardinal; Ver, Ver2, MinVer, OnlyBelowVer: Cardinal;
begin begin
Ver := WindowsVersion; Ver := WindowsVersion;
if IsNT then begin MinVer := MinVersion.NTVersion;
MinVer := MinVersion.NTVersion; OnlyBelowVer := OnlyBelowVersion.NTVersion;
OnlyBelowVer := OnlyBelowVersion.NTVersion;
end
else begin
MinVer := 0;
OnlyBelowVer := 0;
end;
Result := irInstall; Result := irInstall;
if MinVer = 0 then if MinVer = 0 then
Result := irNotOnThisPlatform Result := irNotOnThisPlatform
else begin else begin
if Ver < MinVer then if Ver < MinVer then
Result := irVersionTooLow Result := irVersionTooLow
else if (IsNT and (LongRec(Ver).Hi = LongRec(MinVer).Hi) and else if (LongRec(Ver).Hi = LongRec(MinVer).Hi) and
(NTServicePackLevel < MinVersion.NTServicePack)) then (NTServicePackLevel < MinVersion.NTServicePack) then
Result := irServicePackTooLow Result := irServicePackTooLow
else begin else begin
if OnlyBelowVer <> 0 then begin if OnlyBelowVer <> 0 then begin
@ -1652,23 +1618,17 @@ begin
{ A build number of 0 on OnlyBelowVersion means 'match any build' } { A build number of 0 on OnlyBelowVersion means 'match any build' }
if LongRec(OnlyBelowVer).Lo = 0 then if LongRec(OnlyBelowVer).Lo = 0 then
Ver2 := Ver2 and $FFFF0000; { set build number to zero on Ver2 also } Ver2 := Ver2 and $FFFF0000; { set build number to zero on Ver2 also }
if not IsNT then begin { Note: When OnlyBelowVersion includes a service pack level, the
if Ver2 >= OnlyBelowVer then version number test changes from a "<" to "<=" operation. Thus,
Result := irVerTooHigh; on Windows 2000 SP4, 5.0 and 5.0.2195 will fail, but 5.0sp5 and
end 5.0.2195sp5 will pass. }
else begin if (Ver2 > OnlyBelowVer) or
{ Note: When OnlyBelowVersion includes a service pack level, the ((Ver2 = OnlyBelowVer) and
version number test changes from a "<" to "<=" operation. Thus, (OnlyBelowVersion.NTServicePack = 0)) or
on Windows 2000 SP4, 5.0 and 5.0.2195 will fail, but 5.0sp5 and ((LongRec(Ver).Hi = LongRec(OnlyBelowVer).Hi) and
5.0.2195sp5 will pass. } (OnlyBelowVersion.NTServicePack <> 0) and
if (Ver2 > OnlyBelowVer) or (NTServicePackLevel >= OnlyBelowVersion.NTServicePack)) then
((Ver2 = OnlyBelowVer) and Result := irVerTooHigh;
(OnlyBelowVersion.NTServicePack = 0)) or
((LongRec(Ver).Hi = LongRec(OnlyBelowVer).Hi) and
(OnlyBelowVersion.NTServicePack <> 0) and
(NTServicePackLevel >= OnlyBelowVersion.NTServicePack)) then
Result := irVerTooHigh;
end;
end; end;
end; end;
end; end;
@ -1884,12 +1844,8 @@ var
J: Integer; J: Integer;
begin begin
Filename := AFilename; Filename := AFilename;
if IsNT then begin if not DisableFsRedir then
if not DisableFsRedir then Filename := ReplaceSystemDirWithSysWow64(Filename);
Filename := ReplaceSystemDirWithSysWow64(Filename);
end
else
Filename := GetShortName(Filename);
Filename := PathLowercase(Filename); Filename := PathLowercase(Filename);
for J := 0 to CheckForFileSL.Count-1 do begin for J := 0 to CheckForFileSL.Count-1 do begin
if CheckForFileSL[J] = Filename then begin if CheckForFileSL[J] = Filename then begin
@ -1979,8 +1935,7 @@ begin
{ From MSDN: "Installers should not disable file system redirection before calling { From MSDN: "Installers should not disable file system redirection before calling
the Restart Manager API. This means that a 32-bit installer run on 64-bit Windows the Restart Manager API. This means that a 32-bit installer run on 64-bit Windows
is unable register a file in the %windir%\system32 directory." This is incorrect, is unable register a file in the %windir%\system32 directory." This is incorrect,
we can register such files by using the Sysnative alias. Note: the Sysnative alias we can register such files by using the Sysnative alias. }
is only available on Windows Vista and newer, but so is Restart Manager. }
if DisableFsRedir then if DisableFsRedir then
Filename := ReplaceSystemDirWithSysNative(Filename, IsWin64); Filename := ReplaceSystemDirWithSysNative(Filename, IsWin64);
@ -1989,11 +1944,7 @@ begin
Len := Length(Filename); Len := Length(Filename);
GetMem(RegisterFileBatchFilenames[RegisterFileFilenamesBatchCount], (Len + 1) * SizeOf(RegisterFileBatchFilenames[RegisterFileFilenamesBatchCount][0])); GetMem(RegisterFileBatchFilenames[RegisterFileFilenamesBatchCount], (Len + 1) * SizeOf(RegisterFileBatchFilenames[RegisterFileFilenamesBatchCount][0]));
{$IFNDEF UNICODE} StrPCopy(RegisterFileBatchFilenames[RegisterFileFilenamesBatchCount], Filename);
RegisterFileFilenames[RegisterFileFilenamesCount][MultiByteToWideChar(CP_ACP, 0, PChar(Filename), Len, RegisterFileFilenames[RegisterFileFilenamesCount], Len)] := #0;
{$ELSE}
StrPCopy(RegisterFileBatchFilenames[RegisterFileFilenamesBatchCount], Filename);
{$ENDIF}
Inc(RegisterFileFilenamesBatchCount); Inc(RegisterFileFilenamesBatchCount);
Inc(RmRegisteredFilesCount); Inc(RmRegisteredFilesCount);
@ -2164,14 +2115,6 @@ end;
procedure SetActiveLanguage(const I: Integer); procedure SetActiveLanguage(const I: Integer);
{ Activates the specified language } { Activates the specified language }
const
{$IFDEF UNICODE}
{ UNICODE requires 2000+, so we can just use the English name }
SMSPGothic = 'MS PGothic';
{$ELSE}
{ "MS PGothic" in Japanese (CP 932) }
SMSPGothic = #$82'l'#$82'r '#$82'o'#$83'S'#$83'V'#$83'b'#$83'N';
{$ENDIF}
var var
LangEntry: PSetupLanguageEntry; LangEntry: PSetupLanguageEntry;
J: Integer; J: Integer;
@ -2191,30 +2134,6 @@ begin
Finalize(LangOptions); { prevent leak on D2 } Finalize(LangOptions); { prevent leak on D2 }
LangOptions := LangEntry^; LangOptions := LangEntry^;
{ Hack for Japanese: Override the default fonts on older versions of Windows
that don't (fully) support font linking }
if (LangOptions.LanguageID = $0411) and
{$IFNDEF UNICODE}
(GetACP = 932) and
{$ENDIF}
(WindowsVersion < Cardinal($05010000)) and
FontExists(SMSPGothic) then begin
{ Windows <= 2000: Verdana can't display Japanese }
LangOptions.WelcomeFontName := SMSPGothic;
LangOptions.WelcomeFontSize := 12;
{$IFNDEF UNICODE}
if WindowsVersion < Cardinal($05000000) then begin
{ Windows 9x/Me/NT 4.0: MS Sans Serif can't display Japanese }
LangOptions.DialogFontName := SMSPGothic;
LangOptions.DialogFontSize := 9;
LangOptions.TitleFontName := SMSPGothic;
LangOptions.TitleFontSize := 29;
LangOptions.CopyrightFontName := SMSPGothic;
LangOptions.CopyrightFontSize := 9;
end;
{$ENDIF}
end;
if LangEntry.LicenseText <> '' then if LangEntry.LicenseText <> '' then
ActiveLicenseText := LangEntry.LicenseText ActiveLicenseText := LangEntry.LicenseText
else else
@ -2293,9 +2212,7 @@ begin
application window. We can't simply hide the window because on D3+ the VCL application window. We can't simply hide the window because on D3+ the VCL
would just show it again in TApplication.UpdateVisible when the first form would just show it again in TApplication.UpdateVisible when the first form
is shown. } is shown. }
{$IFDEF IS_D12}
TaskbarButtonHidden := not AVisible; { see WM_STYLECHANGING hook in Setup.dpr } TaskbarButtonHidden := not AVisible; { see WM_STYLECHANGING hook in Setup.dpr }
{$ENDIF}
if (GetWindowLong(Application.Handle, GWL_EXSTYLE) and WS_EX_TOOLWINDOW = 0) <> AVisible then begin if (GetWindowLong(Application.Handle, GWL_EXSTYLE) and WS_EX_TOOLWINDOW = 0) <> AVisible then begin
SetWindowPos(Application.Handle, 0, 0, 0, 0, 0, SWP_NOSIZE or SetWindowPos(Application.Handle, 0, 0, 0, 0, 0, SWP_NOSIZE or
SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_HIDEWINDOW); SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_HIDEWINDOW);
@ -2333,18 +2250,16 @@ begin
SP := SP + '.' + IntToStr(Lo(NTServicePackLevel)); SP := SP + '.' + IntToStr(Lo(NTServicePackLevel));
end; end;
LogFmt('Windows version: %u.%u.%u%s (NT platform: %s)', [WindowsVersion shr 24, LogFmt('Windows version: %u.%u.%u%s (NT platform: %s)', [WindowsVersion shr 24,
(WindowsVersion shr 16) and $FF, WindowsVersion and $FFFF, SP, SYesNo[IsNT]]); (WindowsVersion shr 16) and $FF, WindowsVersion and $FFFF, SP, SYesNo[True]]);
LogFmt('64-bit Windows: %s', [SYesNo[IsWin64]]); LogFmt('64-bit Windows: %s', [SYesNo[IsWin64]]);
LogFmt('Processor architecture: %s', [SetupProcessorArchitectureNames[ProcessorArchitecture]]); LogFmt('Processor architecture: %s', [SetupProcessorArchitectureNames[ProcessorArchitecture]]);
if IsNT then begin if IsAdmin then
if IsAdmin then Log('User privileges: Administrative')
Log('User privileges: Administrative') else if IsPowerUserOrAdmin then
else if IsPowerUserOrAdmin then Log('User privileges: Power User')
Log('User privileges: Power User') else
else Log('User privileges: None');
Log('User privileges: None');
end;
end; end;
function GetMessageBoxResultText(const AResult: Integer): String; function GetMessageBoxResultText(const AResult: Integer): String;
@ -3658,8 +3573,8 @@ begin
BorderStyle := bsSingle; BorderStyle := bsSingle;
{ Make the main window full-screen. If the window is resizable, limit it { Make the main window full-screen. If the window is resizable, limit it
to just the work area because on recent versions of Windows (e.g. 2000) to just the work area because full-screen resizable windows don't cover
full-screen resizable windows don't cover over the taskbar. } over the taskbar. }
BoundsRect := GetRectOfPrimaryMonitor(BorderStyle = bsSizeable); BoundsRect := GetRectOfPrimaryMonitor(BorderStyle = bsSizeable);
{ Before maximizing the window, ensure Handle is created now so the correct { Before maximizing the window, ensure Handle is created now so the correct
'restored' position is saved properly } 'restored' position is saved properly }
@ -3816,9 +3731,7 @@ begin
S := S + SNewLine2 + SetupMessages[msgAboutSetupNote]; S := S + SNewLine2 + SetupMessages[msgAboutSetupNote];
if SetupMessages[msgTranslatorNote] <> '' then if SetupMessages[msgTranslatorNote] <> '' then
S := S + SNewLine2 + SetupMessages[msgTranslatorNote]; S := S + SNewLine2 + SetupMessages[msgTranslatorNote];
{$IFDEF UNICODE}
StringChangeEx(S, '(C)', #$00A9, True); StringChangeEx(S, '(C)', #$00A9, True);
{$ENDIF}
LoggedMsgBox(S, SetupMessages[msgAboutSetupTitle], mbInformation, MB_OK, False, 0); LoggedMsgBox(S, SetupMessages[msgAboutSetupTitle], mbInformation, MB_OK, False, 0);
end; end;
@ -4478,45 +4391,6 @@ end;
procedure InitWindowsVersion; procedure InitWindowsVersion;
procedure ReadServicePackFromRegistry;
var
K: HKEY;
Size, Typ, SP: DWORD;
begin
if RegOpenKeyExView(rvDefault, HKEY_LOCAL_MACHINE, 'System\CurrentControlSet\Control\Windows',
0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin
Size := SizeOf(SP);
if (RegQueryValueEx(K, 'CSDVersion', nil, @Typ, @SP, @Size) = ERROR_SUCCESS) and
(Typ = REG_DWORD) and (Size = SizeOf(SP)) then
NTServicePackLevel := Word(SP);
RegCloseKey(K);
end;
end;
procedure ReadProductTypeFromRegistry;
const
VER_NT_WORKSTATION = 1;
VER_NT_DOMAIN_CONTROLLER = 2;
VER_NT_SERVER = 3;
var
K: HKEY;
S: String;
begin
if RegOpenKeyExView(rvDefault, HKEY_LOCAL_MACHINE, 'System\CurrentControlSet\Control\ProductOptions',
0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin
{ See MS KB article 152078 for details on this key }
if RegQueryStringValue(K, 'ProductType', S) then begin
if CompareText(S, 'WinNT') = 0 then
WindowsProductType := VER_NT_WORKSTATION
else if CompareText(S, 'LanmanNT') = 0 then
WindowsProductType := VER_NT_DOMAIN_CONTROLLER
else if CompareText(S, 'ServerNT') = 0 then
WindowsProductType := VER_NT_SERVER;
end;
RegCloseKey(K);
end;
end;
type type
TOSVersionInfoEx = packed record TOSVersionInfoEx = packed record
dwOSVersionInfoSize: DWORD; dwOSVersionInfoSize: DWORD;
@ -4541,22 +4415,12 @@ begin
(Byte(OSVersionInfo.dwMinorVersion) shl 16) or (Byte(OSVersionInfo.dwMinorVersion) shl 16) or
Word(OSVersionInfo.dwBuildNumber); Word(OSVersionInfo.dwBuildNumber);
{ ^ Note: We MUST clip dwBuildNumber to 16 bits for Win9x compatibility } { ^ Note: We MUST clip dwBuildNumber to 16 bits for Win9x compatibility }
if IsNT then begin OSVersionInfoEx.dwOSVersionInfoSize := SizeOf(OSVersionInfoEx);
if OSVersionInfo.dwMajorVersion >= 5 then begin if GetVersionEx(POSVersionInfo(@OSVersionInfoEx)^) then begin
{ OSVERSIONINFOEX is only available starting in Windows 2000 } NTServicePackLevel := (Byte(OSVersionInfoEx.wServicePackMajor) shl 8) or
OSVersionInfoEx.dwOSVersionInfoSize := SizeOf(OSVersionInfoEx); Byte(OSVersionInfoEx.wServicePackMinor);
if GetVersionEx(POSVersionInfo(@OSVersionInfoEx)^) then begin WindowsProductType := OSVersionInfoEx.wProductType;
NTServicePackLevel := (Byte(OSVersionInfoEx.wServicePackMajor) shl 8) or WindowsSuiteMask := OSVersionInfoEx.wSuiteMask;
Byte(OSVersionInfoEx.wServicePackMinor);
WindowsProductType := OSVersionInfoEx.wProductType;
WindowsSuiteMask := OSVersionInfoEx.wSuiteMask;
end;
end
else if OSVersionInfo.dwMajorVersion = 4 then begin
{ Read from the registry on NT 4 }
ReadServicePackFromRegistry;
ReadProductTypeFromRegistry;
end;
end; end;
end; end;
end; end;
@ -4606,12 +4470,8 @@ begin
end; end;
initialization initialization
IsNT := UsingWinNT;
InitIsWin64AndProcessorArchitecture; InitIsWin64AndProcessorArchitecture;
InitWindowsVersion; InitWindowsVersion;
{$IFNDEF UNICODE}
ConstLeadBytes := @SetupHeader.LeadBytes;
{$ENDIF}
InitComponents := TStringList.Create(); InitComponents := TStringList.Create();
InitTasks := TStringList.Create(); InitTasks := TStringList.Create();
NewParamsForCode := TStringList.Create(); NewParamsForCode := TStringList.Create();

View File

@ -2,7 +2,7 @@ unit RedirFunc;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2007 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -123,10 +123,8 @@ function DisableFsRedirectionIf(const Disable: Boolean;
If Disable is True, the function attempts to disable WOW64 file system If Disable is True, the function attempts to disable WOW64 file system
redirection, so that c:\windows\system32 goes to the 64-bit System directory redirection, so that c:\windows\system32 goes to the 64-bit System directory
instead of the 32-bit one. instead of the 32-bit one.
Returns True if successful, False if not (which normally indicates that Returns True if successful, False if not. For extended error information when
either the user is running 32-bit Windows, or a 64-bit version prior to False is returned, call GetLastError. }
Windows Server 2003 SP1). For extended error information when False is
returned, call GetLastError. }
begin begin
PreviousState.DidDisable := False; PreviousState.DidDisable := False;
if not Disable then if not Disable then
@ -142,7 +140,7 @@ begin
PreviousState.DidDisable := True; PreviousState.DidDisable := True;
end end
else begin else begin
{ The functions do not exist prior to Windows Server 2003 SP1 } { Should never happen }
SetLastError(ERROR_INVALID_FUNCTION); SetLastError(ERROR_INVALID_FUNCTION);
Result := False; Result := False;
end; end;

View File

@ -2,7 +2,7 @@ unit RegDLL;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2012 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -86,11 +86,8 @@ begin
is running } is running }
WindowDisabler := TWindowDisabler.Create; WindowDisabler := TWindowDisabler.Create;
try try
{ On Windows Vista, to get the "WRP Mitigation" compatibility hack which { To get the "WRP Mitigation" compatibility hack which a lot of DLLs
a lot of DLLs a require, we must use regsvr32.exe to handle the require, we must use regsvr32.exe to handle the (un)registration. }
(un)registration.
On Windows 2000/XP/2003, use regsvr32.exe as well for behavioral &
error message consistency. }
RegisterServerUsingRegSvr32(AUnregister, AIs64Bit, Filename); RegisterServerUsingRegSvr32(AUnregister, AIs64Bit, Filename);
finally finally
WindowDisabler.Free; WindowDisabler.Free;

View File

@ -2,7 +2,7 @@ unit RegSvr;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2012 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -53,8 +53,7 @@ end;
function RenameToNonRandomTempName(const Filename: String): String; function RenameToNonRandomTempName(const Filename: String): String;
{ Renames Filename to a name in the format: isRS-nnn.tmp. Returns the new { Renames Filename to a name in the format: isRS-nnn.tmp. Returns the new
filename if successful, or '' if not. filename if successful, or '' if not. Calls MoveFileEx. }
Note: This is an NT-only function, as it calls MoveFileEx. }
var var
Path, NewFilename: String; Path, NewFilename: String;
Attribs: DWORD; Attribs: DWORD;
@ -91,18 +90,14 @@ var
SelfFilename, NewFilename: String; SelfFilename, NewFilename: String;
begin begin
SelfFilename := NewParamStr(0); SelfFilename := NewParamStr(0);
if Win32Platform = VER_PLATFORM_WIN32_NT then begin { RestartReplace will fail if the user doesn't have admin
{ On NT, RestartReplace will fail if the user doesn't have admin privileges. We don't want to leak temporary files, so try to rename
privileges. We don't want to leak temporary files, so try to rename ourself to a non-random name. This way, future runs should just keep
ourself to a non-random name. This way, future runs should just keep overwriting the same temp file. }
overwriting the same temp file. } DeleteOldTempFiles(PathExtractPath(SelfFilename));
DeleteOldTempFiles(PathExtractPath(SelfFilename)); NewFilename := RenameToNonRandomTempName(SelfFilename);
NewFilename := RenameToNonRandomTempName(SelfFilename); if NewFilename <> '' then
if NewFilename <> '' then RestartReplace(False, NewFilename, '')
RestartReplace(False, NewFilename, '')
else
RestartReplace(False, SelfFilename, '');
end
else else
RestartReplace(False, SelfFilename, ''); RestartReplace(False, SelfFilename, '');
end; end;

View File

@ -4,26 +4,12 @@ unit SHA1;
SHA1.pas: SHA-1 hash implementation, based on RFC 3174 and MD5.pas SHA1.pas: SHA-1 hash implementation, based on RFC 3174 and MD5.pas
Author: Jordan Russell, 2010-02-24 Author: Jordan Russell, 2010-02-24
License for SHA1.pas: Public domain, no copyright claimed License for SHA1.pas: Public domain, no copyright claimed
$jrsoftware: issrc/Projects/SHA1.pas,v 1.1 2010/02/25 04:57:34 jr Exp $
} }
interface interface
{$IFNDEF VER80}
{$IFNDEF VER90}
{$IFNDEF VER93}
{$IFNDEF VER100}
{$IFNDEF VER110}
{$DEFINE SHA1_D4PLUS}
{$ENDIF}
{$ENDIF}
{$ENDIF}
{$ENDIF}
{$ENDIF}
type type
TSHA1Word = {$IFDEF SHA1_D4PLUS} LongWord {$ELSE} Cardinal {$ENDIF}; TSHA1Word = LongWord;
TSHA1Buf = array[0..4] of TSHA1Word; TSHA1Buf = array[0..4] of TSHA1Word;
TSHA1In = array[0..15] of TSHA1Word; TSHA1In = array[0..15] of TSHA1Word;
TSHA1WArray = array[0..79] of TSHA1Word; TSHA1WArray = array[0..79] of TSHA1Word;

View File

@ -2,7 +2,7 @@ unit SafeDLLPath;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2016 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -12,7 +12,7 @@ unit SafeDLLPath;
If SetDefaultDllDirectories is not available: If SetDefaultDllDirectories is not available:
-It calls SetDllDirectory('') to prevent LoadLibrary from searching the current -It calls SetDllDirectory('') to prevent LoadLibrary from searching the current
directory for DLLs. (Has no effect on Windows versions prior to XP SP1.) directory for DLLs.
-It then preloads a list of system DLLs which are known to be loaded unsafely -It then preloads a list of system DLLs which are known to be loaded unsafely
by older or unpatched versions of Windows. by older or unpatched versions of Windows.
@ -25,8 +25,6 @@ unit SafeDLLPath;
It also calls SetSearchPathMode to enable "safe search mode", which causes It also calls SetSearchPathMode to enable "safe search mode", which causes
SearchPath, and callers of SearchPath such as CreateProcess, to search the SearchPath, and callers of SearchPath such as CreateProcess, to search the
current directory after the system directories (rather than before). current directory after the system directories (rather than before).
SetSearchPathMode is available in Windows 7 and newer, and on previous
versions that have the KB959426 update installed.
Finally, it calls SetProcessDEPPolicy (where available) to enable DEP for Finally, it calls SetProcessDEPPolicy (where available) to enable DEP for
the lifetime of the process. (This has nothing to do with search paths; the lifetime of the process. (This has nothing to do with search paths;
@ -55,7 +53,6 @@ const
var var
KernelModule: HMODULE; KernelModule: HMODULE;
WinVer: WORD;
SystemDir: String; SystemDir: String;
SetDefaultDllDirectoriesFunc: function(DirectoryFlags: DWORD): BOOL; stdcall; SetDefaultDllDirectoriesFunc: function(DirectoryFlags: DWORD): BOOL; stdcall;
DidSetDefaultDllDirectories: Boolean; DidSetDefaultDllDirectories: Boolean;
@ -96,15 +93,12 @@ end;
initialization initialization
KernelModule := GetModuleHandle(kernel32); KernelModule := GetModuleHandle(kernel32);
WinVer := Swap(Word(GetVersion()));
DidSetDefaultDllDirectories := False; DidSetDefaultDllDirectories := False;
if WinVer <> $0600 then begin //see NSIS link above: CoCreateInstance(CLSID_ShellLink, ...) fails on Vista if SetDefaultDllDirectories is called SetDefaultDllDirectoriesFunc := GetProcAddress(KernelModule, PAnsiChar('SetDefaultDllDirectories'));
SetDefaultDllDirectoriesFunc := GetProcAddress(KernelModule, PAnsiChar('SetDefaultDllDirectories')); if Assigned(SetDefaultDllDirectoriesFunc) then
if Assigned(SetDefaultDllDirectoriesFunc) then DidSetDefaultDllDirectories := SetDefaultDllDirectoriesFunc(LOAD_LIBRARY_SEARCH_SYSTEM32);
DidSetDefaultDllDirectories := SetDefaultDllDirectoriesFunc(LOAD_LIBRARY_SEARCH_SYSTEM32);
end;
if not DidSetDefaultDllDirectories then begin if not DidSetDefaultDllDirectories then begin
SetDllDirectoryFunc := GetProcAddress(KernelModule, PAnsiChar('SetDllDirectoryW')); SetDllDirectoryFunc := GetProcAddress(KernelModule, PAnsiChar('SetDllDirectoryW'));
if Assigned(SetDllDirectoryFunc) then if Assigned(SetDllDirectoryFunc) then

View File

@ -571,15 +571,9 @@ end;
procedure ScriptClassesLibraryRegister_C(Cl: TPSPascalCompiler); procedure ScriptClassesLibraryRegister_C(Cl: TPSPascalCompiler);
const const
clSystemColor = {$IFDEF IS_D7} $FF000000 {$ELSE} $80000000 {$ENDIF}; clSystemColor = $FF000000;
COLOR_HOTLIGHT = 26; COLOR_HOTLIGHT = 26;
begin begin
{$IFNDEF UNICODE}
{ Temporary: Currently used non Unicode ROPS version doesn't define the AnsiString/PAnsiChar types }
Cl.AddTypeS('AnsiString', 'String');
Cl.AddTypeS('PAnsiChar', 'PChar');
{$ENDIF}
{ Std } { Std }
SIRegister_Std_TypesAndConsts(Cl); SIRegister_Std_TypesAndConsts(Cl);
SIRegisterTObject(Cl); SIRegisterTObject(Cl);
@ -593,9 +587,7 @@ begin
SIRegisterTStringList(Cl); SIRegisterTStringList(Cl);
SIRegisterTHandleStream(Cl); SIRegisterTHandleStream(Cl);
SIRegisterTFileStream(Cl); SIRegisterTFileStream(Cl);
{$IFDEF UNICODE}
SIRegisterTStringStream(Cl); SIRegisterTStringStream(Cl);
{$ENDIF}
{ Graphics } { Graphics }
SIRegister_Graphics_TypesAndConsts(Cl); SIRegister_Graphics_TypesAndConsts(Cl);

View File

@ -2,7 +2,7 @@ unit ScriptClasses_R;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2020 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -24,7 +24,7 @@ implementation
uses uses
Windows, Controls, Forms, StdCtrls, Graphics, Windows, Controls, Forms, StdCtrls, Graphics,
uPSR_std, uPSR_classes, uPSR_graphics, uPSR_controls, uPSR_forms, uPSR_std, uPSR_classes, uPSR_graphics, uPSR_controls, uPSR_forms,
uPSR_stdctrls, uPSR_extctrls, uPSR_comobj, {$IFNDEF UNICODE} uPSUtils, {$ENDIF} uPSR_stdctrls, uPSR_extctrls, uPSR_comobj,
NewStaticText, NewCheckListBox, NewProgressBar, RichEditViewer, NewStaticText, NewCheckListBox, NewProgressBar, RichEditViewer,
ExtCtrls, UIStateForm, SetupForm, Main, Wizard, SetupTypes, PasswordEdit, ExtCtrls, UIStateForm, SetupForm, Main, Wizard, SetupTypes, PasswordEdit,
FolderTreeView, BitmapImage, NewNotebook, ScriptDlg, BidiCtrls, FolderTreeView, BitmapImage, NewNotebook, ScriptDlg, BidiCtrls,
@ -33,8 +33,8 @@ uses
type type
TWinControlAccess = class(TWinControl); TWinControlAccess = class(TWinControl);
procedure TWinControlParentBackground_R(Self: TWinControl; var T: Boolean); begin {$IFDEF IS_D7} T := TWinControlAccess(Self).ParentBackground {$ELSE} T := False {$ENDIF}; end; procedure TWinControlParentBackground_R(Self: TWinControl; var T: Boolean); begin T := TWinControlAccess(Self).ParentBackground; end;
procedure TWinControlParentBackground_W(Self: TWinControl; const T: Boolean); begin {$IFDEF IS_D7} TWinControlAccess(Self).ParentBackground := T; {$ENDIF} end; procedure TWinControlParentBackground_W(Self: TWinControl; const T: Boolean); begin TWinControlAccess(Self).ParentBackground := T; end;
procedure RegisterWinControl_R(Cl: TPSRuntimeClassImporter); procedure RegisterWinControl_R(Cl: TPSRuntimeClassImporter);
begin begin
@ -370,9 +370,7 @@ begin
RIRegisterTStringList(Cl); RIRegisterTStringList(Cl);
RIRegisterTHandleStream(Cl); RIRegisterTHandleStream(Cl);
RIRegisterTFileStream(Cl); RIRegisterTFileStream(Cl);
{$IFDEF UNICODE}
RIRegisterTStringStream(Cl); RIRegisterTStringStream(Cl);
{$ENDIF}
{ Graphics } { Graphics }
RIRegisterTGraphicsObject(Cl); RIRegisterTGraphicsObject(Cl);

View File

@ -2,7 +2,7 @@ unit ScriptCompiler;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2018 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -363,10 +363,8 @@ begin
LineLength := FindNewLine(FScriptText, LineStartPosition); LineLength := FindNewLine(FScriptText, LineStartPosition);
end; end;
{$IFDEF UNICODE}
{ Convert Position from the UTF8 encoded ANSI string index to a UTF-16 string index } { Convert Position from the UTF8 encoded ANSI string index to a UTF-16 string index }
Position := Length(UTF8ToString(Copy(FScriptText, LineStartPosition, Position - 1))) + 1; Position := Length(UTF8ToString(Copy(FScriptText, LineStartPosition, Position - 1))) + 1;
{$ENDIF}
Col := Position; Col := Position;
end; end;
@ -465,11 +463,7 @@ var
begin begin
Result := False; Result := False;
{$IFDEF UNICODE}
FScriptText := UTF8Encode(ScriptText); FScriptText := UTF8Encode(ScriptText);
{$ELSE}
FScriptText := ScriptText;
{$ENDIF}
for I := 0 to FExports.Count-1 do for I := 0 to FExports.Count-1 do
TScriptExport(FExports[I]).Exported := False; TScriptExport(FExports[I]).Exported := False;
@ -482,10 +476,8 @@ begin
PSPascalCompiler.AllowNoBegin := True; PSPascalCompiler.AllowNoBegin := True;
PSPascalCompiler.AllowNoEnd := True; PSPascalCompiler.AllowNoEnd := True;
PSPascalCompiler.BooleanShortCircuit := True; PSPascalCompiler.BooleanShortCircuit := True;
{$IFDEF UNICODE}
PSPascalCompiler.AllowDuplicateRegister := False; PSPascalCompiler.AllowDuplicateRegister := False;
PSPascalCompiler.UTF8Decode := True; PSPascalCompiler.UTF8Decode := True;
{$ENDIF}
PSPascalCompiler.AttributesOpenTokenID := CSTI_Less; PSPascalCompiler.AttributesOpenTokenID := CSTI_Less;
PSPascalCompiler.AttributesCloseTokenID := CSTI_Greater; PSPascalCompiler.AttributesCloseTokenID := CSTI_Greater;

View File

@ -2,7 +2,7 @@ unit ScriptFunc_R;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2020 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -22,8 +22,7 @@ implementation
uses uses
Windows, ScriptFunc, Windows, ScriptFunc,
Forms, uPSUtils, SysUtils, Classes, Graphics, Controls, TypInfo, Forms, uPSUtils, SysUtils, Classes, Graphics, Controls, TypInfo, ActiveX,
{$IFNDEF Delphi3orHigher} Ole2, {$ELSE} ActiveX, {$ENDIF}
Struct, ScriptDlg, Main, PathFunc, CmnFunc, CmnFunc2, FileClass, RedirFunc, Struct, ScriptDlg, Main, PathFunc, CmnFunc, CmnFunc2, FileClass, RedirFunc,
Install, InstFunc, InstFnc2, Msgs, MsgIDs, NewDisk, BrowseFunc, Wizard, VerInfo, Install, InstFunc, InstFnc2, Msgs, MsgIDs, NewDisk, BrowseFunc, Wizard, VerInfo,
SetupTypes, Int64Em, MD5, SHA1, Logging, SetupForm, RegDLL, Helper, SetupTypes, Int64Em, MD5, SHA1, Logging, SetupForm, RegDLL, Helper,
@ -33,17 +32,16 @@ var
ScaleBaseUnitsInitialized: Boolean; ScaleBaseUnitsInitialized: Boolean;
ScaleBaseUnitX, ScaleBaseUnitY: Integer; ScaleBaseUnitX, ScaleBaseUnitY: Integer;
procedure NoSetupFuncError(const C: AnsiString);{$IFDEF UNICODE} overload;{$ENDIF} procedure NoSetupFuncError(const C: AnsiString); overload;
begin begin
InternalError(Format('Cannot call "%s" function during Setup', [C])); InternalError(Format('Cannot call "%s" function during Setup', [C]));
end; end;
procedure NoUninstallFuncError(const C: AnsiString);{$IFDEF UNICODE} overload;{$ENDIF} procedure NoUninstallFuncError(const C: AnsiString); overload;
begin begin
InternalError(Format('Cannot call "%s" function during Uninstall', [C])); InternalError(Format('Cannot call "%s" function during Uninstall', [C]));
end; end;
{$IFDEF UNICODE}
procedure NoSetupFuncError(const C: UnicodeString); overload; procedure NoSetupFuncError(const C: UnicodeString); overload;
begin begin
InternalError(Format('Cannot call "%s" function during Setup', [C])); InternalError(Format('Cannot call "%s" function during Setup', [C]));
@ -53,31 +51,15 @@ procedure NoUninstallFuncError(const C: UnicodeString); overload;
begin begin
InternalError(Format('Cannot call "%s" function during Uninstall', [C])); InternalError(Format('Cannot call "%s" function during Uninstall', [C]));
end; end;
{$ENDIF}
{$IFNDEF UNICODE}
procedure NoNonUnicodeFuncError(const C: String);
begin
InternalError(Format('Cannot call "%s" function during non Unicode Setup or Uninstall', [C]));
end;
{$ENDIF}
function StackGetAnsiString(Stack: TPSStack; ItemNo: LongInt): AnsiString; function StackGetAnsiString(Stack: TPSStack; ItemNo: LongInt): AnsiString;
begin begin
{$IFDEF UNICODE}
Result := Stack.GetAnsiString(ItemNo); Result := Stack.GetAnsiString(ItemNo);
{$ELSE}
Result := Stack.GetString(ItemNo);
{$ENDIF}
end; end;
procedure StackSetAnsiString(Stack: TPSStack; ItemNo: LongInt; const Data: AnsiString); procedure StackSetAnsiString(Stack: TPSStack; ItemNo: LongInt; const Data: AnsiString);
begin begin
{$IFDEF UNICODE}
Stack.SetAnsiString(ItemNo, Data); Stack.SetAnsiString(ItemNo, Data);
{$ELSE}
Stack.SetString(ItemNo, Data);
{$ENDIF}
end; end;
function GetMainForm: TMainForm; function GetMainForm: TMainForm;
@ -575,7 +557,7 @@ begin
Stack.SetInt(PStart, StringChangeEx(S, Stack.GetString(PStart-2), Stack.GetString(PStart-3), Stack.GetBool(PStart-4))); Stack.SetInt(PStart, StringChangeEx(S, Stack.GetString(PStart-2), Stack.GetString(PStart-3), Stack.GetBool(PStart-4)));
Stack.SetString(PStart-1, S); Stack.SetString(PStart-1, S);
end else if Proc.Name = 'USINGWINNT' then begin end else if Proc.Name = 'USINGWINNT' then begin
Stack.SetBool(PStart, UsingWinNT()); Stack.SetBool(PStart, True);
end else if Proc.Name = 'FILECOPY' then begin end else if Proc.Name = 'FILECOPY' then begin
ExistingFilename := Stack.GetString(PStart-1); ExistingFilename := Stack.GetString(PStart-1);
if PathCompare(ExistingFilename, SetupLdrOriginalFilename) <> 0 then if PathCompare(ExistingFilename, SetupLdrOriginalFilename) <> 0 then
@ -862,31 +844,19 @@ begin
end else if Proc.Name = 'GETMD5OFSTRING' then begin end else if Proc.Name = 'GETMD5OFSTRING' then begin
Stack.SetString(PStart, MD5DigestToString(GetMD5OfAnsiString(StackGetAnsiString(Stack, PStart-1)))); Stack.SetString(PStart, MD5DigestToString(GetMD5OfAnsiString(StackGetAnsiString(Stack, PStart-1))));
end else if Proc.Name = 'GETMD5OFUNICODESTRING' then begin end else if Proc.Name = 'GETMD5OFUNICODESTRING' then begin
{$IFDEF UNICODE}
Stack.SetString(PStart, MD5DigestToString(GetMD5OfUnicodeString(Stack.GetString(PStart-1)))); Stack.SetString(PStart, MD5DigestToString(GetMD5OfUnicodeString(Stack.GetString(PStart-1))));
{$ELSE}
NoNonUnicodeFuncError(Proc.Name);
{$ENDIF}
end else if Proc.Name = 'GETSHA1OFFILE' then begin end else if Proc.Name = 'GETSHA1OFFILE' then begin
Stack.SetString(PStart, SHA1DigestToString(GetSHA1OfFile(ScriptFuncDisableFsRedir, Stack.GetString(PStart-1)))); Stack.SetString(PStart, SHA1DigestToString(GetSHA1OfFile(ScriptFuncDisableFsRedir, Stack.GetString(PStart-1))));
end else if Proc.Name = 'GETSHA1OFSTRING' then begin end else if Proc.Name = 'GETSHA1OFSTRING' then begin
Stack.SetString(PStart, SHA1DigestToString(GetSHA1OfAnsiString(StackGetAnsiString(Stack, PStart-1)))); Stack.SetString(PStart, SHA1DigestToString(GetSHA1OfAnsiString(StackGetAnsiString(Stack, PStart-1))));
end else if Proc.Name = 'GETSHA1OFUNICODESTRING' then begin end else if Proc.Name = 'GETSHA1OFUNICODESTRING' then begin
{$IFDEF UNICODE}
Stack.SetString(PStart, SHA1DigestToString(GetSHA1OfUnicodeString(Stack.GetString(PStart-1)))); Stack.SetString(PStart, SHA1DigestToString(GetSHA1OfUnicodeString(Stack.GetString(PStart-1))));
{$ELSE}
NoNonUnicodeFuncError(Proc.Name);
{$ENDIF}
end else if Proc.Name = 'GETSHA256OFFILE' then begin end else if Proc.Name = 'GETSHA256OFFILE' then begin
Stack.SetString(PStart, GetSHA256OfFile(ScriptFuncDisableFsRedir, Stack.GetString(PStart-1))); Stack.SetString(PStart, GetSHA256OfFile(ScriptFuncDisableFsRedir, Stack.GetString(PStart-1)));
end else if Proc.Name = 'GETSHA256OFSTRING' then begin end else if Proc.Name = 'GETSHA256OFSTRING' then begin
Stack.SetString(PStart, GetSHA256OfAnsiString(StackGetAnsiString(Stack, PStart-1))); Stack.SetString(PStart, GetSHA256OfAnsiString(StackGetAnsiString(Stack, PStart-1)));
end else if Proc.Name = 'GETSHA256OFUNICODESTRING' then begin end else if Proc.Name = 'GETSHA256OFUNICODESTRING' then begin
{$IFDEF UNICODE}
Stack.SetString(PStart, GetSHA256OfUnicodeString(Stack.GetString(PStart-1))); Stack.SetString(PStart, GetSHA256OfUnicodeString(Stack.GetString(PStart-1)));
{$ELSE}
NoNonUnicodeFuncError(Proc.Name);
{$ENDIF}
end else if Proc.Name = 'GETSPACEONDISK' then begin end else if Proc.Name = 'GETSPACEONDISK' then begin
if GetSpaceOnDisk(ScriptFuncDisableFsRedir, Stack.GetString(PStart-1), FreeBytes, TotalBytes) then begin if GetSpaceOnDisk(ScriptFuncDisableFsRedir, Stack.GetString(PStart-1), FreeBytes, TotalBytes) then begin
if Stack.GetBool(PStart-2) then begin if Stack.GetBool(PStart-2) then begin
@ -1006,7 +976,7 @@ begin
Stack.GetString(PStart-2), Stack.GetString(PStart-3), Stack.GetString(PStart-2), Stack.GetString(PStart-3),
Stack.GetString(PStart-4), Stack.GetString(PStart-5), Stack.GetString(PStart-4), Stack.GetString(PStart-5),
Stack.GetString(PStart-6), Stack.GetInt(PStart-7), Stack.GetString(PStart-6), Stack.GetInt(PStart-7),
Stack.GetInt(PStart-8), 0, False, '', nil, False, False)); Stack.GetInt(PStart-8), 0, '', nil, False, False));
end else if Proc.Name = 'REGISTERTYPELIBRARY' then begin end else if Proc.Name = 'REGISTERTYPELIBRARY' then begin
if Stack.GetBool(PStart) then if Stack.GetBool(PStart) then
HelperRegisterTypeLibrary(False, Stack.GetString(PStart-1)) HelperRegisterTypeLibrary(False, Stack.GetString(PStart-1))
@ -1164,7 +1134,7 @@ begin
Version.Build := WindowsVersion and $FFFF; Version.Build := WindowsVersion and $FFFF;
Version.ServicePackMajor := Hi(NTServicePackLevel); Version.ServicePackMajor := Hi(NTServicePackLevel);
Version.ServicePackMinor := Lo(NTServicePackLevel); Version.ServicePackMinor := Lo(NTServicePackLevel);
Version.NTPlatform := IsNT; Version.NTPlatform := True;
Version.ProductType := WindowsProductType; Version.ProductType := WindowsProductType;
Version.SuiteMask := WindowsSuiteMask; Version.SuiteMask := WindowsSuiteMask;
end; end;
@ -1413,19 +1383,19 @@ begin
end else if Proc.Name = 'SAMETEXT' then begin end else if Proc.Name = 'SAMETEXT' then begin
Stack.SetBool(PStart, CompareText(Stack.GetString(PStart-1), Stack.GetString(PStart-2)) = 0); Stack.SetBool(PStart, CompareText(Stack.GetString(PStart-1), Stack.GetString(PStart-2)) = 0);
end else if Proc.Name = 'GETDATETIMESTRING' then begin end else if Proc.Name = 'GETDATETIMESTRING' then begin
OldDateSeparator := {$IFDEF IS_DXE}FormatSettings.{$ENDIF}DateSeparator; OldDateSeparator := FormatSettings.DateSeparator;
OldTimeSeparator := {$IFDEF IS_DXE}FormatSettings.{$ENDIF}TimeSeparator; OldTimeSeparator := FormatSettings.TimeSeparator;
try try
NewDateSeparator := Stack.GetString(PStart-2)[1]; NewDateSeparator := Stack.GetString(PStart-2)[1];
NewTimeSeparator := Stack.GetString(PStart-3)[1]; NewTimeSeparator := Stack.GetString(PStart-3)[1];
if NewDateSeparator <> #0 then if NewDateSeparator <> #0 then
{$IFDEF IS_DXE}FormatSettings.{$ENDIF}DateSeparator := NewDateSeparator; FormatSettings.DateSeparator := NewDateSeparator;
if NewTimeSeparator <> #0 then if NewTimeSeparator <> #0 then
{$IFDEF IS_DXE}FormatSettings.{$ENDIF}TimeSeparator := NewTimeSeparator; FormatSettings.TimeSeparator := NewTimeSeparator;
Stack.SetString(PStart, FormatDateTime(Stack.GetString(PStart-1), Now())); Stack.SetString(PStart, FormatDateTime(Stack.GetString(PStart-1), Now()));
finally finally
{$IFDEF IS_DXE}FormatSettings.{$ENDIF}TimeSeparator := OldTimeSeparator; FormatSettings.TimeSeparator := OldTimeSeparator;
{$IFDEF IS_DXE}FormatSettings.{$ENDIF}DateSeparator := OldDateSeparator; FormatSettings.DateSeparator := OldDateSeparator;
end; end;
end else if Proc.Name = 'SYSERRORMESSAGE' then begin end else if Proc.Name = 'SYSERRORMESSAGE' then begin
Stack.SetString(PStart, Win32ErrorString(Stack.GetInt(PStart-1))); Stack.SetString(PStart, Win32ErrorString(Stack.GetInt(PStart-1)));
@ -1480,45 +1450,6 @@ begin
end; end;
end; end;
{$IFNDEF IS_D7}
procedure _FmtStr(var Result: string; const Format: string;
const Args: array of const);
var
Len, BufLen: Integer;
Buffer: array[0..4095] of Char;
begin
BufLen := SizeOf(Buffer);
if Length(Format) < (sizeof(Buffer) - (sizeof(Buffer) div 4)) then
Len := FormatBuf(Buffer, sizeof(Buffer) - 1, Pointer(Format)^, Length(Format), Args)
else
begin
BufLen := Length(Format);
Len := BufLen;
end;
if Len >= BufLen - 1 then
begin
while Len >= BufLen - 1 do
begin
Inc(BufLen, BufLen);
Result := ''; // prevent copying of existing data, for speed
SetLength(Result, BufLen);
Len := FormatBuf(Pointer(Result)^, BufLen - 1, Pointer(Format)^,
Length(Format), Args);
end;
SetLength(Result, Len);
end
else
SetString(Result, Buffer, Len);
end;
{ We use the Format/FmtStr functions from Delphi 7 because Delphi 2's Format
raises an exception if the result is more than 4096 characters. }
function _Format(const Format: string; const Args: array of const): string;
begin
_FmtStr(Result, Format, Args);
end;
{$ENDIF}
{ VerInfo } { VerInfo }
function VerInfoProc(Caller: TPSExec; Proc: TPSExternalProcRec; Global, Stack: TPSStack): Boolean; function VerInfoProc(Caller: TPSExec; Proc: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
var var
@ -1694,16 +1625,15 @@ function OtherProc(Caller: TPSExec; Proc: TPSExternalProcRec; Global, Stack: TPS
Code: TPSError; Code: TPSError;
E: TObject; E: TObject;
begin begin
Code := Caller.{$IFDEF UNICODE} LastEx {$ELSE} ExceptionCode {$ENDIF}; Code := Caller.LastEx;
if Code = erNoError then if Code = erNoError then
Result := '(There is no current exception)' Result := '(There is no current exception)'
else begin else begin
E := Caller.{$IFDEF UNICODE} LastExObject {$ELSE} ExceptionObject {$ENDIF}; E := Caller.LastExObject;
if Assigned(E) and (E is Exception) then if Assigned(E) and (E is Exception) then
Result := Exception(E).Message Result := Exception(E).Message
else else
Result := String(PSErrorToString(Code, Caller. Result := String(PSErrorToString(Code, Caller.LastExParam));
{$IFDEF UNICODE} LastExParam {$ELSE} ExceptionString {$ENDIF}));
end; end;
end; end;
@ -1799,10 +1729,6 @@ function OtherProc(Caller: TPSExec; Proc: TPSExternalProcRec; Global, Stack: TPS
I, N: Integer; I, N: Integer;
S: String; S: String;
begin begin
{$IFNDEF UNICODE}
if UTF8 then
NoNonUnicodeFuncError('SAVESTRINGSTOUTF8FILE');
{$ENDIF}
try try
if Append then if Append then
F := TTextFileWriterRedir.Create(ScriptFuncDisableFsRedir, FileName, fdOpenAlways, faWrite, fsNone) F := TTextFileWriterRedir.Create(ScriptFuncDisableFsRedir, FileName, fdOpenAlways, faWrite, fsNone)
@ -1814,14 +1740,10 @@ function OtherProc(Caller: TPSExec; Proc: TPSExternalProcRec; Global, Stack: TPS
N := PSDynArrayGetLength(Pointer(Arr.Dta^), Arr.aType); N := PSDynArrayGetLength(Pointer(Arr.Dta^), Arr.aType);
for I := 0 to N-1 do begin for I := 0 to N-1 do begin
S := VNGetString(PSGetArrayField(Arr^, I)); S := VNGetString(PSGetArrayField(Arr^, I));
{$IFDEF UNICODE}
if not UTF8 then if not UTF8 then
F.WriteAnsiLine(AnsiString(S)) F.WriteAnsiLine(AnsiString(S))
else else
F.WriteLine(S); F.WriteLine(S);
{$ELSE}
F.WriteLine(S);
{$ENDIF}
end; end;
finally finally
F.Free; F.Free;
@ -2124,7 +2046,7 @@ begin
ScriptInterpreter.RegisterDelphiFunction(@_FindNext, 'FindNext', cdRegister); ScriptInterpreter.RegisterDelphiFunction(@_FindNext, 'FindNext', cdRegister);
ScriptInterpreter.RegisterDelphiFunction(@_FindClose, 'FindClose', cdRegister); ScriptInterpreter.RegisterDelphiFunction(@_FindClose, 'FindClose', cdRegister);
ScriptInterpreter.RegisterDelphiFunction(@_FmtMessage, 'FmtMessage', cdRegister); ScriptInterpreter.RegisterDelphiFunction(@_FmtMessage, 'FmtMessage', cdRegister);
ScriptInterpreter.RegisterDelphiFunction({$IFNDEF IS_D7} @_Format {$ELSE} @Format {$ENDIF}, 'Format', cdRegister); ScriptInterpreter.RegisterDelphiFunction(@Format, 'Format', cdRegister);
ScriptInterpreter.RegisterDelphiFunction(@_GetWindowsVersionEx, 'GetWindowsVersionEx', cdRegister); ScriptInterpreter.RegisterDelphiFunction(@_GetWindowsVersionEx, 'GetWindowsVersionEx', cdRegister);
end; end;

View File

@ -2,7 +2,7 @@ unit ScriptRunner;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2019 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -147,7 +147,6 @@ begin
Param := CreateHeapVariant(FPSExec.FindType2(btString)); Param := CreateHeapVariant(FPSExec.FindType2(btString));
PPSVariantAString(Param).Data := AnsiString(Parameters[I].vAnsiString); PPSVariantAString(Param).Data := AnsiString(Parameters[I].vAnsiString);
end; end;
{$IFDEF UNICODE}
vtWideString: vtWideString:
begin begin
Param := CreateHeapVariant(FPSExec.FindType2(btWideString)); Param := CreateHeapVariant(FPSExec.FindType2(btWideString));
@ -158,7 +157,6 @@ begin
Param := CreateHeapVariant(FPSExec.FindType2(btUnicodeString)); Param := CreateHeapVariant(FPSExec.FindType2(btUnicodeString));
PPSVariantUString(Param).Data := UnicodeString(Parameters[I].VUnicodeString); PPSVariantUString(Param).Data := UnicodeString(Parameters[I].VUnicodeString);
end; end;
{$ENDIF}
vtInteger: vtInteger:
begin begin
Param := CreateHeapVariant(FPSExec.FindType2(btS32)); Param := CreateHeapVariant(FPSExec.FindType2(btS32));
@ -190,7 +188,6 @@ end;
{---} {---}
{$IFDEF UNICODE}
function EncodeDLLFilenameForROPS(const Filename: String): AnsiString; function EncodeDLLFilenameForROPS(const Filename: String): AnsiString;
begin begin
Result := ''; Result := '';
@ -203,7 +200,6 @@ begin
UnloadDLL(Caller, EncodeDLLFilenameForROPS(Stack.GetString(-1))); UnloadDLL(Caller, EncodeDLLFilenameForROPS(Stack.GetString(-1)));
Result := True; Result := True;
end; end;
{$ENDIF}
function PSExecOnSpecialProcImport(Sender: TPSExec; p: TPSExternalProcRec; Tag: Pointer): Boolean; function PSExecOnSpecialProcImport(Sender: TPSExec; p: TPSExternalProcRec; Tag: Pointer): Boolean;
const const
@ -211,9 +207,7 @@ const
var var
ScriptRunner: TScriptRunner; ScriptRunner: TScriptRunner;
S, DllName, FunctionName: AnsiString; S, DllName, FunctionName: AnsiString;
{$IFDEF UNICODE}
UnicodeDllName: String; UnicodeDllName: String;
{$ENDIF}
I: Integer; I: Integer;
ForceDelayLoad, DelayLoad: Boolean; ForceDelayLoad, DelayLoad: Boolean;
ErrorCode: LongInt; ErrorCode: LongInt;
@ -248,30 +242,17 @@ begin
FunctionName := Copy(S, 1, I-1); FunctionName := Copy(S, 1, I-1);
ScriptRunner.LogFmt('Function name: %s', [FunctionName]); ScriptRunner.LogFmt('Function name: %s', [FunctionName]);
{$IFDEF UNICODE}
UnicodeDllName := UTF8ToString(DllName); UnicodeDllName := UTF8ToString(DllName);
ScriptRunner.LogFmt('DLL name: %s', [UnicodeDllname]); ScriptRunner.LogFmt('DLL name: %s', [UnicodeDllname]);
{$ELSE}
ScriptRunner.LogFmt('DLL name: %s', [DllName]);
{$ENDIF}
if Assigned(ScriptRunner.FOnDllImport) then begin if Assigned(ScriptRunner.FOnDllImport) then begin
{$IFDEF UNICODE}
ScriptRunner.FOnDllImport(UnicodeDllName, ForceDelayLoad); ScriptRunner.FOnDllImport(UnicodeDllName, ForceDelayLoad);
DllName := EncodeDLLFilenameForROPS(UnicodeDllName); DllName := EncodeDLLFilenameForROPS(UnicodeDllName);
{$ELSE}
ScriptRunner.FOnDllImport(DllName, ForceDelayLoad);
{$ENDIF}
p.Decl := AnsiString('dll:') + DllName + Copy(p.Decl, Pos(AnsiString(#0), p.Decl), MaxInt); p.Decl := AnsiString('dll:') + DllName + Copy(p.Decl, Pos(AnsiString(#0), p.Decl), MaxInt);
end; end;
if DllName <> '' then begin if DllName <> '' then begin
{$IFDEF UNICODE}
ScriptRunner.LogFmt('Dest DLL name: %s', [UnicodeDllName]); ScriptRunner.LogFmt('Dest DLL name: %s', [UnicodeDllName]);
{$ELSE}
ScriptRunner.LogFmt('Dest DLL name: %s', [DllName]);
{$ENDIF}
ScriptRunner.Log('Importing the DLL function.'); ScriptRunner.Log('Importing the DLL function.');
end else end else
ScriptRunner.Log('Skipping.'); { We're actually still going to call ProcessDllImport but this doesn't matter to the user. } ScriptRunner.Log('Skipping.'); { We're actually still going to call ProcessDllImport but this doesn't matter to the user. }
@ -341,12 +322,8 @@ begin
FPSExec.OnSourceLine := PSExecOnSourceLine; FPSExec.OnSourceLine := PSExecOnSourceLine;
FPSExec.OnException := PSExecOnException; FPSExec.OnException := PSExecOnException;
{$IFNDEF UNICODE}
RegisterDLLRuntimeEx(FPSExec, False);
{$ELSE}
RegisterDLLRuntimeEx(FPSExec, False, False); RegisterDLLRuntimeEx(FPSExec, False, False);
FPSExec.RegisterFunctionName('UNLOADDLL', NewUnloadDLLProc, nil, nil); FPSExec.RegisterFunctionName('UNLOADDLL', NewUnloadDLLProc, nil, nil);
{$ENDIF}
FClassImporter := ScriptClassesLibraryRegister_R(FPSExec); FClassImporter := ScriptClassesLibraryRegister_R(FPSExec);
ScriptFuncLibraryRegister_R(FPSExec); ScriptFuncLibraryRegister_R(FPSExec);
end; end;
@ -391,7 +368,7 @@ begin
if Proc.Attributes.Count > 0 then begin if Proc.Attributes.Count > 0 then begin
Attr := Proc.Attributes.FindAttribute(AnsiString(FNamingAttribute)); Attr := Proc.Attributes.FindAttribute(AnsiString(FNamingAttribute));
if (Attr <> nil) and (Attr.ValueCount = 1) and if (Attr <> nil) and (Attr.ValueCount = 1) and
({$IFDEF UNICODE} ((Attr.Value[0].FType.BaseType = btUnicodeString) and (CompareText(PPSVariantUString(Attr.Value[0]).Data, Name) = 0)) or {$ENDIF} (((Attr.Value[0].FType.BaseType = btUnicodeString) and (CompareText(PPSVariantUString(Attr.Value[0]).Data, Name) = 0)) or
((Attr.Value[0].FType.BaseType = btString) and (CompareText(PPSVariantAString(Attr.Value[0]).Data, Name) = 0))) then begin ((Attr.Value[0].FType.BaseType = btString) and (CompareText(PPSVariantAString(Attr.Value[0]).Data, Name) = 0))) then begin
if ProcNos <> nil then if ProcNos <> nil then
ProcNos.Add(Pointer(ProcNo)); ProcNos.Add(Pointer(ProcNo));
@ -584,20 +561,12 @@ begin
Params := TPSList.Create(); Params := TPSList.Create();
try try
SetPSExecParameters(Parameters, Params); SetPSExecParameters(Parameters, Params);
{$IFDEF UNICODE}
SetPSExecReturnValue(Params, btUnicodeString, Res); SetPSExecReturnValue(Params, btUnicodeString, Res);
{$ELSE}
SetPSExecReturnValue(Params, btString, Res);
{$ENDIF}
FPSExec.RunProc(Params, Cardinal(ProcNos[I])); FPSExec.RunProc(Params, Cardinal(ProcNos[I]));
WriteBackParameters(Parameters, Params); WriteBackParameters(Parameters, Params);
RaisePSExecException; RaisePSExecException;
{$IFDEF UNICODE}
Result := PPSVariantUString(Res).Data; Result := PPSVariantUString(Res).Data;
{$ELSE}
Result := PPSVariantAString(Res).Data;
{$ENDIF}
if (Result <> '') and (BreakCondition = bcNonEmpty) then if (Result <> '') and (BreakCondition = bcNonEmpty) then
Exit; Exit;
finally finally
@ -628,7 +597,6 @@ function TScriptRunner.EvaluateUsedVariable(const Param1, Param2, Param3: LongIn
function VariantToString(const p: TPSVariantIFC; const ClassProperties: AnsiString): String; function VariantToString(const p: TPSVariantIFC; const ClassProperties: AnsiString): String;
begin begin
{$IFDEF UNICODE}
//PSVariantToString isn't Unicode enabled, handle strings ourselves //PSVariantToString isn't Unicode enabled, handle strings ourselves
//doesn't handle more complex types as records, arrays and objects //doesn't handle more complex types as records, arrays and objects
if p.Dta <> nil then begin if p.Dta <> nil then begin
@ -640,7 +608,6 @@ function TScriptRunner.EvaluateUsedVariable(const Param1, Param2, Param3: LongIn
Result := PSVariantToString(p, ClassProperties); Result := PSVariantToString(p, ClassProperties);
end; end;
end else end else
{$ENDIF}
Result := PSVariantToString(p, ClassProperties); Result := PSVariantToString(p, ClassProperties);
end; end;

View File

@ -2,13 +2,11 @@ unit SecurityFunc;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2008 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
Functions for altering ACLs on files & registry keys Functions for altering ACLs on files & registry keys
$jrsoftware: issrc/Projects/SecurityFunc.pas,v 1.6 2008/10/17 22:18:14 jr Exp $
} }
interface interface
@ -27,39 +25,11 @@ implementation
uses uses
PathFunc, Msgs, InstFunc, Logging, RedirFunc, Helper; PathFunc, Msgs, InstFunc, Logging, RedirFunc, Helper;
{$IFNDEF UNICODE}
function AllocWideCharStr(const S: String): PWideChar;
{ Allocates a null-terminated Unicode copy of S on the heap. Use FreeMem to
free the returned pointer. }
var
SourceLen, DestLen: Integer;
begin
SourceLen := Length(S);
if SourceLen = 0 then
DestLen := 0
else begin
DestLen := MultiByteToWideChar(CP_ACP, 0, PChar(S), SourceLen, nil, 0);
if (DestLen <= 0) or (DestLen >= High(Integer) div SizeOf(WideChar)) then
InternalError('AllocWideCharStr: MultiByteToWideChar failed');
end;
GetMem(Result, (DestLen + 1) * SizeOf(WideChar));
try
if DestLen <> 0 then
if MultiByteToWideChar(CP_ACP, 0, PChar(S), SourceLen, Result, DestLen) <> DestLen then
InternalError('AllocWideCharStr: MultiByteToWideChar failed');
Result[DestLen] := #0;
except
FreeMem(Result);
raise;
end;
end;
{$ENDIF}
function InternalGrantPermission(const ObjectType: DWORD; const ObjectName: String; function InternalGrantPermission(const ObjectType: DWORD; const ObjectName: String;
const Entries: TGrantPermissionEntry; const EntryCount: Integer; const Entries: TGrantPermissionEntry; const EntryCount: Integer;
const Inheritance: DWORD): DWORD; const Inheritance: DWORD): DWORD;
{ Grants the specified access to the specified object. Returns ERROR_SUCCESS if { Grants the specified access to the specified object. Returns ERROR_SUCCESS if
successful. Always fails on Windows 9x/Me and NT 4.0. } successful. }
type type
PPSID = ^PSID; PPSID = ^PSID;
PPACL = ^PACL; PPACL = ^PACL;
@ -95,9 +65,6 @@ var
SetEntriesInAclW: function(cCountOfExplicitEntries: ULONG; SetEntriesInAclW: function(cCountOfExplicitEntries: ULONG;
const pListOfExplicitEntries: TExplicitAccessW; OldAcl: PACL; const pListOfExplicitEntries: TExplicitAccessW; OldAcl: PACL;
var NewAcl: PACL): DWORD; stdcall; var NewAcl: PACL): DWORD; stdcall;
{$IFNDEF UNICODE}
WideObjectName: PWideChar;
{$ENDIF}
SD: PSECURITY_DESCRIPTOR; SD: PSECURITY_DESCRIPTOR;
Dacl, NewDacl: PACL; Dacl, NewDacl: PACL;
ExplicitAccess: PArrayOfExplicitAccessW; ExplicitAccess: PArrayOfExplicitAccessW;
@ -105,13 +72,6 @@ var
I: Integer; I: Integer;
Sid: PSID; Sid: PSID;
begin begin
{ Windows 9x/Me don't support ACLs, and GetNamedSecurityInfo and
SetEntriesInACL are buggy on NT 4 }
if (Win32Platform <> VER_PLATFORM_WIN32_NT) or (Lo(GetVersion) < 5) then begin
Result := ERROR_INVALID_FUNCTION;
Exit;
end;
AdvApiHandle := GetModuleHandle(advapi32); AdvApiHandle := GetModuleHandle(advapi32);
GetNamedSecurityInfoW := GetProcAddress(AdvApiHandle, PAnsiChar('GetNamedSecurityInfoW')); GetNamedSecurityInfoW := GetProcAddress(AdvApiHandle, PAnsiChar('GetNamedSecurityInfoW'));
SetNamedSecurityInfoW := GetProcAddress(AdvApiHandle, PAnsiChar('SetNamedSecurityInfoW')); SetNamedSecurityInfoW := GetProcAddress(AdvApiHandle, PAnsiChar('SetNamedSecurityInfoW'));
@ -122,63 +82,52 @@ begin
Exit; Exit;
end; end;
{$IFNDEF UNICODE} ExplicitAccess := nil;
WideObjectName := AllocWideCharStr(ObjectName); Result := GetNamedSecurityInfoW(PChar(ObjectName), ObjectType,
DACL_SECURITY_INFORMATION, nil, nil, @Dacl, nil, SD);
if Result <> ERROR_SUCCESS then
Exit;
try try
{$ENDIF} { Note: Dacl will be nil if GetNamedSecurityInfo is called on a FAT partition.
ExplicitAccess := nil; Be careful not to dereference a nil pointer. }
Result := GetNamedSecurityInfoW( ExplicitAccess := AllocMem(EntryCount * SizeOf(ExplicitAccess[0]));
{$IFDEF UNICODE} PChar(ObjectName) {$ELSE} WideObjectName {$ENDIF}, E := @Entries;
ObjectType, DACL_SECURITY_INFORMATION, nil, nil, @Dacl, nil, SD); for I := 0 to EntryCount-1 do begin
if not AllocateAndInitializeSid(E.Sid.Authority, E.Sid.SubAuthCount,
E.Sid.SubAuth[0], E.Sid.SubAuth[1], 0, 0, 0, 0, 0, 0, Sid) then begin
Result := GetLastError;
if Result = ERROR_SUCCESS then { just in case... }
Result := ERROR_INVALID_PARAMETER;
Exit;
end;
ExplicitAccess[I].grfAccessPermissions := E.AccessMask;
ExplicitAccess[I].grfAccessMode := GRANT_ACCESS;
ExplicitAccess[I].grfInheritance := Inheritance;
ExplicitAccess[I].Trustee.TrusteeForm := TRUSTEE_IS_SID;
ExplicitAccess[I].Trustee.TrusteeType := TRUSTEE_IS_UNKNOWN;
PSID(ExplicitAccess[I].Trustee.ptstrName) := Sid;
Inc(E);
end;
Result := SetEntriesInAclW(EntryCount, ExplicitAccess[0], Dacl, NewDacl);
if Result <> ERROR_SUCCESS then if Result <> ERROR_SUCCESS then
Exit; Exit;
try try
{ Note: Dacl will be nil if GetNamedSecurityInfo is called on a FAT partition. Result := SetNamedSecurityInfoW(PChar(ObjectName), ObjectType,
Be careful not to dereference a nil pointer. } DACL_SECURITY_INFORMATION, nil, nil, NewDacl, nil);
ExplicitAccess := AllocMem(EntryCount * SizeOf(ExplicitAccess[0]));
E := @Entries;
for I := 0 to EntryCount-1 do begin
if not AllocateAndInitializeSid(E.Sid.Authority, E.Sid.SubAuthCount,
E.Sid.SubAuth[0], E.Sid.SubAuth[1], 0, 0, 0, 0, 0, 0, Sid) then begin
Result := GetLastError;
if Result = ERROR_SUCCESS then { just in case... }
Result := ERROR_INVALID_PARAMETER;
Exit;
end;
ExplicitAccess[I].grfAccessPermissions := E.AccessMask;
ExplicitAccess[I].grfAccessMode := GRANT_ACCESS;
ExplicitAccess[I].grfInheritance := Inheritance;
ExplicitAccess[I].Trustee.TrusteeForm := TRUSTEE_IS_SID;
ExplicitAccess[I].Trustee.TrusteeType := TRUSTEE_IS_UNKNOWN;
PSID(ExplicitAccess[I].Trustee.ptstrName) := Sid;
Inc(E);
end;
Result := SetEntriesInAclW(EntryCount, ExplicitAccess[0], Dacl, NewDacl);
if Result <> ERROR_SUCCESS then
Exit;
try
Result := SetNamedSecurityInfoW(
{$IFDEF UNICODE} PChar(ObjectName) {$ELSE} WideObjectName {$ENDIF},
ObjectType, DACL_SECURITY_INFORMATION, nil, nil, NewDacl, nil);
finally
LocalFree(HLOCAL(NewDacl));
end;
finally finally
if Assigned(ExplicitAccess) then begin LocalFree(HLOCAL(NewDacl));
for I := EntryCount-1 downto 0 do begin
Sid := PSID(ExplicitAccess[I].Trustee.ptstrName);
if Assigned(Sid) then
FreeSid(Sid);
end;
FreeMem(ExplicitAccess);
end;
LocalFree(HLOCAL(SD));
end; end;
{$IFNDEF UNICODE}
finally finally
FreeMem(WideObjectName); if Assigned(ExplicitAccess) then begin
for I := EntryCount-1 downto 0 do begin
Sid := PSID(ExplicitAccess[I].Trustee.ptstrName);
if Assigned(Sid) then
FreeSid(Sid);
end;
FreeMem(ExplicitAccess);
end;
LocalFree(HLOCAL(SD));
end; end;
{$ENDIF}
end; end;
function GrantPermission(const Use64BitHelper: Boolean; const ObjectType: DWORD; function GrantPermission(const Use64BitHelper: Boolean; const ObjectType: DWORD;
@ -210,8 +159,7 @@ const
function GrantPermissionOnFile(const DisableFsRedir: Boolean; Filename: String; function GrantPermissionOnFile(const DisableFsRedir: Boolean; Filename: String;
const Entries: TGrantPermissionEntry; const EntryCount: Integer): Boolean; const Entries: TGrantPermissionEntry; const EntryCount: Integer): Boolean;
{ Grants the specified access to the specified file/directory. Returns True if { Grants the specified access to the specified file/directory. Returns True if
successful. On failure, the thread's last error code is set. Always fails on successful. On failure, the thread's last error code is set. }
Windows 9x/Me and NT 4.0. }
const const
SE_FILE_OBJECT = 1; SE_FILE_OBJECT = 1;
var var
@ -239,8 +187,7 @@ function GrantPermissionOnKey(const RegView: TRegView; const RootKey: HKEY;
const Subkey: String; const Entries: TGrantPermissionEntry; const Subkey: String; const Entries: TGrantPermissionEntry;
const EntryCount: Integer): Boolean; const EntryCount: Integer): Boolean;
{ Grants the specified access to the specified registry key. Returns True if { Grants the specified access to the specified registry key. Returns True if
successful. On failure, the thread's last error code is set. Always fails on successful. On failure, the thread's last error code is set. }
Windows 9x/Me and NT 4.0. }
const const
SE_REGISTRY_KEY = 4; SE_REGISTRY_KEY = 4;
var var

View File

@ -2,13 +2,11 @@ unit SelFolderForm;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2004 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
"Select Folder" form "Select Folder" form
$jrsoftware: issrc/Projects/SelFolderForm.pas,v 1.15 2010/10/22 10:33:26 mlaan Exp $
} }
interface interface
@ -60,14 +58,10 @@ begin
Form.NewFolderButton.Visible := not AppendDir and (NewFolderName <> ''); Form.NewFolderButton.Visible := not AppendDir and (NewFolderName <> '');
if StartMenu then begin if StartMenu then begin
with Form.FFolderTreeView as TStartMenuFolderTreeView do with Form.FFolderTreeView as TStartMenuFolderTreeView do
if IsNT then SetPaths(GetShellFolder(False, sfPrograms),
SetPaths(GetShellFolder(False, sfPrograms), GetShellFolder(True, sfPrograms),
GetShellFolder(True, sfPrograms), GetShellFolder(False, sfStartup),
GetShellFolder(False, sfStartup), GetShellFolder(True, sfStartup));
GetShellFolder(True, sfStartup))
else
SetPaths(GetShellFolder(False, sfPrograms),
'', GetShellFolder(False, sfStartup), '');
TidyUpGroupName(Path); TidyUpGroupName(Path);
end end
else else

View File

@ -42,24 +42,6 @@ uses
{$R *.DFM} {$R *.DFM}
var
DefComboWndProcW, PrevComboWndProc: Pointer;
function NewComboWndProc(Wnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT;
stdcall;
begin
case Msg of
{ CB_ADDSTRING must pass to the default Unicode combo box window procedure
since PrevWndProc is an ANSI window procedure and calling it would result
in Unicode->ANSI conversion. Do the same for CB_GETLBTEXT(LEN) so that
MSAA sees Unicode strings. }
CB_ADDSTRING, CB_GETLBTEXT, CB_GETLBTEXTLEN:
Result := CallWindowProcW(DefComboWndProcW, Wnd, Msg, wParam, lParam)
else
Result := CallWindowProcW(PrevComboWndProc, Wnd, Msg, wParam, lParam);
end;
end;
function AskForLanguage: Boolean; function AskForLanguage: Boolean;
{ Creates and shows the "Select Language" dialog. Returns True and activates { Creates and shows the "Select Language" dialog. Returns True and activates
the selected language if the user clicks OK, or False otherwise. } the selected language if the user clicks OK, or False otherwise. }
@ -67,47 +49,13 @@ var
LangForm: TSelectLanguageForm; LangForm: TSelectLanguageForm;
I, J: Integer; I, J: Integer;
LangEntry: PSetupLanguageEntry; LangEntry: PSetupLanguageEntry;
{$IFNDEF UNICODE}
ClassInfo: TWndClassW;
N: String;
{$ENDIF}
begin begin
LangForm := TSelectLanguageForm.Create(Application); LangForm := TSelectLanguageForm.Create(Application);
try try
{$IFNDEF UNICODE}
{ On NT, make it possible to add Unicode strings to our ANSI combo box by
installing a window procedure with special CB_ADDSTRING handling.
Yeah, this is a hack; it's too hard to create a native Unicode control
in Delphi. }
if Win32Platform = VER_PLATFORM_WIN32_NT then begin
if GetClassInfoW(0, 'COMBOBOX', ClassInfo) then begin
DefComboWndProcW := ClassInfo.lpfnWndProc;
Longint(PrevComboWndProc) := SetWindowLongW(LangForm.LangCombo.Handle,
GWL_WNDPROC, Longint(@NewComboWndProc));
end;
end;
{$ENDIF}
for I := 0 to Entries[seLanguage].Count-1 do begin for I := 0 to Entries[seLanguage].Count-1 do begin
LangEntry := Entries[seLanguage][I]; LangEntry := Entries[seLanguage][I];
{$IFDEF UNICODE}
J := LangForm.LangCombo.Items.Add(LangEntry.LanguageName); J := LangForm.LangCombo.Items.Add(LangEntry.LanguageName);
LangForm.LangCombo.Items.Objects[J] := TObject(I); LangForm.LangCombo.Items.Objects[J] := TObject(I);
{$ELSE}
if (I = ActiveLanguage) or (LangEntry.LanguageCodePage = 0) or
(LangEntry.LanguageCodePage = GetACP) or
(shShowUndisplayableLanguages in SetupHeader.Options) then begin
{ Note: LanguageName is Unicode }
N := LangEntry.LanguageName + #0#0; { need wide null! }
if Win32Platform = VER_PLATFORM_WIN32_NT then
J := SendMessageW(LangForm.LangCombo.Handle, CB_ADDSTRING, 0,
Longint(PWideChar(Pointer(N))))
else
J := LangForm.LangCombo.Items.Add(WideCharToString(PWideChar(Pointer(N))));
if J >= 0 then
LangForm.LangCombo.Items.Objects[J] := TObject(I);
end;
{$ENDIF}
end; end;
{ If there's multiple languages, select the previous language, if available } { If there's multiple languages, select the previous language, if available }
@ -150,9 +98,7 @@ constructor TSelectLanguageForm.Create(AOwner: TComponent);
begin begin
inherited; inherited;
{$IFDEF IS_D7}
MainPanel.ParentBackground := False; MainPanel.ParentBackground := False;
{$ENDIF}
InitializeFont; InitializeFont;

View File

@ -2,7 +2,7 @@ program Setup;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2020 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -82,7 +82,8 @@ uses
RestartManager in '..\Components\RestartManager.pas', RestartManager in '..\Components\RestartManager.pas',
Resample in '..\Components\Resample.pas', Resample in '..\Components\Resample.pas',
dwTaskbarList in '..\Components\dwTaskbarList.pas', dwTaskbarList in '..\Components\dwTaskbarList.pas',
ASMInline in '..\Components\ASMInline.pas'; ASMInline in '..\Components\ASMInline.pas',
TaskbarProgressFunc in 'TaskbarProgressFunc.pas';
{$SetPEFlags IMAGE_FILE_RELOCS_STRIPPED} {$SetPEFlags IMAGE_FILE_RELOCS_STRIPPED}
{$SETPEOSVERSION 6.1} {$SETPEOSVERSION 6.1}
@ -148,8 +149,7 @@ begin
end; end;
WM_ENDSESSION: begin WM_ENDSESSION: begin
{ Should only get here if RestartInitiatedByThisProcess is set or an { Should only get here if RestartInitiatedByThisProcess is set or an
Uninstaller shutdown was allowed, or if the user forced a shutdown Uninstaller shutdown was allowed, or if the user forced a shutdown.
on Vista or newer.
Skip the default handling which calls Halt. No code of ours depends Skip the default handling which calls Halt. No code of ours depends
on the Halt call to clean up, and it could theoretically result in on the Halt call to clean up, and it could theoretically result in
obscure reentrancy bugs. obscure reentrancy bugs.
@ -170,7 +170,6 @@ begin
AcceptedQueryEndSessionInProgress := False; AcceptedQueryEndSessionInProgress := False;
Result := True; Result := True;
end; end;
{$IFDEF IS_D12}
WM_STYLECHANGING: begin WM_STYLECHANGING: begin
{ On Delphi 2009, we must suppress some of the VCL's manipulation of { On Delphi 2009, we must suppress some of the VCL's manipulation of
the application window styles in order to prevent the taskbar button the application window styles in order to prevent the taskbar button
@ -194,7 +193,6 @@ begin
PStyleStruct(Message.LParam).styleNew and not WS_EX_APPWINDOW; PStyleStruct(Message.LParam).styleNew and not WS_EX_APPWINDOW;
end; end;
end; end;
{$ENDIF}
end; end;
end; end;
@ -202,8 +200,6 @@ procedure DisableWindowGhosting;
var var
Proc: procedure; stdcall; Proc: procedure; stdcall;
begin begin
{ Note: The documentation claims this function is only available in XP SP1,
but it's actually available on stock XP too. }
Proc := GetProcAddress(GetModuleHandle(user32), 'DisableProcessWindowsGhosting'); Proc := GetProcAddress(GetModuleHandle(user32), 'DisableProcessWindowsGhosting');
if Assigned(Proc) then if Assigned(Proc) then
Proc; Proc;
@ -272,13 +268,11 @@ begin
end; end;
begin begin
{$IFDEF IS_D12}
{ Delphi 2009 initially sets WS_EX_TOOLWINDOW on the application window. { Delphi 2009 initially sets WS_EX_TOOLWINDOW on the application window.
That will prevent our ShowWindow(Application.Handle, SW_SHOW) calls from That will prevent our ShowWindow(Application.Handle, SW_SHOW) calls from
actually displaying the taskbar button as intended, so clear it. } actually displaying the taskbar button as intended, so clear it. }
SetWindowLong(Application.Handle, GWL_EXSTYLE, SetWindowLong(Application.Handle, GWL_EXSTYLE,
GetWindowLong(Application.Handle, GWL_EXSTYLE) and not WS_EX_TOOLWINDOW); GetWindowLong(Application.Handle, GWL_EXSTYLE) and not WS_EX_TOOLWINDOW);
{$ENDIF}
try try
SetErrorMode(SEM_FAILCRITICALERRORS); SetErrorMode(SEM_FAILCRITICALERRORS);

View File

@ -157,6 +157,7 @@
<DCCReference Include="..\Components\Resample.pas"/> <DCCReference Include="..\Components\Resample.pas"/>
<DCCReference Include="..\Components\dwTaskbarList.pas"/> <DCCReference Include="..\Components\dwTaskbarList.pas"/>
<DCCReference Include="..\Components\ASMInline.pas"/> <DCCReference Include="..\Components\ASMInline.pas"/>
<DCCReference Include="TaskbarProgressFunc.pas"/>
<BuildConfiguration Include="Base"> <BuildConfiguration Include="Base">
<Key>Base</Key> <Key>Base</Key>
</BuildConfiguration> </BuildConfiguration>

View File

@ -2,7 +2,7 @@ unit SetupForm;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2019 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -42,11 +42,7 @@ type
procedure WndProc(var Message: TMessage); override; procedure WndProc(var Message: TMessage); override;
public public
constructor Create(AOwner: TComponent); override; constructor Create(AOwner: TComponent); override;
{$IFNDEF IS_D4}
constructor CreateNew(AOwner: TComponent);
{$ELSE}
constructor CreateNew(AOwner: TComponent; Dummy: Integer = 0); override; constructor CreateNew(AOwner: TComponent; Dummy: Integer = 0); override;
{$ENDIF}
function CalculateButtonWidth(const ButtonCaptions: array of String): Integer; function CalculateButtonWidth(const ButtonCaptions: array of String): Integer;
procedure InitializeFont; procedure InitializeFont;
function ScalePixelsX(const N: Integer): Integer; function ScalePixelsX(const N: Integer): Integer;
@ -302,11 +298,7 @@ begin
Position := poDesigned; Position := poDesigned;
end; end;
{$IFNDEF IS_D4}
constructor TSetupForm.CreateNew(AOwner: TComponent);
{$ELSE}
constructor TSetupForm.CreateNew(AOwner: TComponent; Dummy: Integer = 0); constructor TSetupForm.CreateNew(AOwner: TComponent; Dummy: Integer = 0);
{$ENDIF}
begin begin
{ Note: On Delphi 2 and 3, CreateNew isn't virtual, so this is only reached { Note: On Delphi 2 and 3, CreateNew isn't virtual, so this is only reached
when TSetupForm.CreateNew is called explicitly } when TSetupForm.CreateNew is called explicitly }

View File

@ -2,7 +2,7 @@ unit SimpleExpression;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2013 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -68,24 +68,10 @@ implementation
uses uses
SysUtils; SysUtils;
{$IFNDEF UNICODE}
type
TSysCharSet = set of AnsiChar;
function CharInSet(C: AnsiChar; const CharSet: TSysCharSet): Boolean;
begin
Result := C in CharSet;
end;
{$ENDIF}
procedure AssignStringToVarRec(var VarRec: TVarRec; const S: String); procedure AssignStringToVarRec(var VarRec: TVarRec; const S: String);
begin begin
{$IFDEF UNICODE}
VarRec.VType := vtUnicodeString; VarRec.VType := vtUnicodeString;
UnicodeString(VarRec.VUnicodeString) := S; UnicodeString(VarRec.VUnicodeString) := S;
{$ELSE}
VarRec.VType := vtAnsiString;
AnsiString(VarRec.VAnsiString) := S;
{$ENDIF}
end; end;
{---} {---}
@ -252,7 +238,7 @@ begin
Result := True; { Lazy and in lazy branch, just return something } Result := True; { Lazy and in lazy branch, just return something }
finally finally
for I := High(Parameters) downto Low(Parameters) do for I := High(Parameters) downto Low(Parameters) do
if Parameters[I].VType = {$IFDEF UNICODE} vtUnicodeString {$ELSE} vtAnsiString {$ENDIF} then if Parameters[I].VType = vtUnicodeString then
AssignStringToVarRec(Parameters[I], ''); AssignStringToVarRec(Parameters[I], '');
end end
end; end;

View File

@ -2,7 +2,7 @@ unit SpawnClient;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2007 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -10,8 +10,6 @@ unit SpawnClient;
NOTE: These functions are NOT thread-safe. Do not call them from multiple NOTE: These functions are NOT thread-safe. Do not call them from multiple
threads simultaneously. threads simultaneously.
$jrsoftware: issrc/Projects/SpawnClient.pas,v 1.5 2007/09/05 02:07:35 jr Exp $
} }
interface interface
@ -60,10 +58,10 @@ procedure AllowSpawnServerToSetForegroundWindow;
normally lasts until new input is generated (a keystroke or click, not normally lasts until new input is generated (a keystroke or click, not
simply mouse movement). simply mouse movement).
Note: If the spawn server process has no visible windows, it seems this Note: If the spawn server process has no visible windows, it seems this
isn't needed (on 2000 & Vista); the process can set the foreground window isn't needed; the process can set the foreground window as it pleases.
as it pleases. If it does have a visible window, though, it definitely is If it does have a visible window, though, it definitely is needed (e.g. in
needed (e.g. in the /DebugSpawnServer case). Let's not rely on any the /DebugSpawnServer case). Let's not rely on any undocumented behavior and
undocumented behavior and call AllowSetForegroundWindow unconditionally. } call AllowSetForegroundWindow unconditionally. }
var var
PID: DWORD; PID: DWORD;
AllowSetForegroundWindowFunc: function(dwProcessId: DWORD): BOOL; stdcall; AllowSetForegroundWindowFunc: function(dwProcessId: DWORD): BOOL; stdcall;

View File

@ -2,13 +2,11 @@ unit SpawnServer;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2010 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
Spawn server Spawn server
$jrsoftware: issrc/Projects/SpawnServer.pas,v 1.13 2010/04/17 19:30:25 jr Exp $
} }
interface interface
@ -102,89 +100,6 @@ begin
end; end;
end; end;
type
TOSVersionInfoExW = record
dwOSVersionInfoSize: DWORD;
dwMajorVersion: DWORD;
dwMinorVersion: DWORD;
dwBuildNumber: DWORD;
dwPlatformId: DWORD;
szCSDVersion: array[0..127] of WideChar;
wServicePackMajor: Word;
wServicePackMinor: Word;
wSuiteMask: Word;
wProductType: Byte;
wReserved: Byte;
end;
const
VER_MINORVERSION = $0000001;
VER_MAJORVERSION = $0000002;
VER_SERVICEPACKMINOR = $0000010;
VER_SERVICEPACKMAJOR = $0000020;
VER_GREATER_EQUAL = 3;
var
VerSetConditionMaskFunc, VerifyVersionInfoWFunc: Pointer;
{ These are implemented in asm because Delphi 2 doesn't support functions that
take 64-bit parameters or return a 64-bit result (in EDX:EAX) }
procedure CallVerSetConditionMask(var dwlConditionMask: Integer64;
dwTypeBitMask: DWORD; dwConditionMask: DWORD);
asm
push esi
mov esi, eax // ESI = @dwlConditionMask
push ecx // dwConditionMask
push edx // dwTypeBitMask
push dword ptr [esi+4] // dwlConditionMask.Hi
push dword ptr [esi] // dwlConditionMask.Lo
call VerSetConditionMaskFunc
mov dword ptr [esi], eax // write dwlConditionMask.Lo
mov dword ptr [esi+4], edx // write dwlConditionMask.Hi
pop esi
end;
function CallVerifyVersionInfoW(const lpVersionInfo: TOSVersionInfoExW;
dwTypeMask: DWORD; const dwlConditionMask: Integer64): BOOL;
asm
push dword ptr [ecx+4] // dwlConditionMask.Hi
push dword ptr [ecx] // dwlConditionMask.Lo
push edx // dwTypeMask
push eax // lpVersionInfo
call VerifyVersionInfoWFunc
end;
function IsReallyVista: Boolean;
{ Returns True if the OS is *really* Vista or later. VerifyVersionInfo is used
because it appears to always check the true OS version number, whereas
GetVersion(Ex) can return a fake version number (e.g. 5.x) if the program is
set to run in compatibility mode, or if it is started by a program running
in compatibility mode. }
var
ConditionMask: Integer64;
VerInfo: TOSVersionInfoExW;
begin
Result := False;
{ These functions are present on Windows 2000 and later.
NT 4.0 SP6 has VerifyVersionInfoW, but not VerSetConditionMask.
Windows 9x/Me and early versions of NT 4.0 have neither. }
if Assigned(VerSetConditionMaskFunc) and Assigned(VerifyVersionInfoWFunc) then begin
ConditionMask.Lo := 0;
ConditionMask.Hi := 0;
{ Docs say: "If you are testing the major version, you must also test the
minor version and the service pack major and minor versions." }
CallVerSetConditionMask(ConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
CallVerSetConditionMask(ConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
CallVerSetConditionMask(ConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
CallVerSetConditionMask(ConditionMask, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL);
FillChar(VerInfo, SizeOf(VerInfo), 0);
VerInfo.dwOSVersionInfoSize := SizeOf(VerInfo);
VerInfo.dwMajorVersion := 6;
Result := CallVerifyVersionInfoW(VerInfo, VER_MAJORVERSION or
VER_MINORVERSION or VER_SERVICEPACKMAJOR or VER_SERVICEPACKMINOR,
ConditionMask);
end;
end;
const const
TokenElevationTypeDefault = 1; { User does not have a split token (they're TokenElevationTypeDefault = 1; { User does not have a split token (they're
not an admin, or UAC is turned off) } not an admin, or UAC is turned off) }
@ -194,7 +109,7 @@ const
function GetTokenElevationType: DWORD; function GetTokenElevationType: DWORD;
{ Returns token elevation type (TokenElevationType* constant). In case of { Returns token elevation type (TokenElevationType* constant). In case of
failure (e.g. not running Vista), 0 is returned. } failure, 0 is returned. }
const const
TokenElevationType = 18; TokenElevationType = 18;
var var
@ -203,11 +118,9 @@ var
ReturnLength: DWORD; ReturnLength: DWORD;
begin begin
Result := 0; Result := 0;
if OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, if OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, Token) then begin
{$IFNDEF Delphi3orHigher} @ {$ENDIF} Token) then begin
ElevationType := 0; ElevationType := 0;
if GetTokenInformation(Token, if GetTokenInformation(Token, TTokenInformationClass(TokenElevationType),
{$IFDEF Delphi3orHigher} TTokenInformationClass {$ENDIF} (TokenElevationType),
@ElevationType, SizeOf(ElevationType), ReturnLength) then @ElevationType, SizeOf(ElevationType), ReturnLength) then
Result := ElevationType; Result := ElevationType;
CloseHandle(Token); CloseHandle(Token);
@ -221,7 +134,7 @@ var
ElevationType: DWORD; ElevationType: DWORD;
begin begin
Result := False; Result := False;
if IsReallyVista and not IsAdminLoggedOn then begin if not IsAdminLoggedOn then begin
if ARequireAdministrator then if ARequireAdministrator then
Result := True Result := True
else if AEmulateHighestAvailable then begin else if AEmulateHighestAvailable then begin
@ -240,15 +153,14 @@ end;
{$ELSE} {$ELSE}
begin begin
{ For debugging/testing only: } { For debugging/testing only: }
Result := (Lo(GetVersion) >= 5); Result := True;
end; end;
{$ENDIF} {$ENDIF}
function GetFinalFileName(const Filename: String): String; function GetFinalFileName(const Filename: String): String;
{ Calls GetFinalPathNameByHandle (new API in Vista) to expand any SUBST'ed { Calls GetFinalPathNameByHandle to expand any SUBST'ed drives, network drives,
drives, network drives, and symbolic links in Filename. and symbolic links in Filename. This is needed for elevation to succeed when
This is needed for elevation to succeed on Windows Vista/7 when Setup is Setup is started from a SUBST'ed drive letter. }
started from a SUBST'ed drive letter. }
function ConvertToNormalPath(P: PChar): String; function ConvertToNormalPath(P: PChar): String;
begin begin
@ -267,8 +179,7 @@ function GetFinalFileName(const Filename: String): String;
const const
FILE_SHARE_DELETE = $00000004; FILE_SHARE_DELETE = $00000004;
var var
GetFinalPathNameByHandleFunc: function(hFile: THandle; GetFinalPathNameByHandleFunc: function(hFile: THandle; lpszFilePath: PWideChar;
lpszFilePath: {$IFDEF UNICODE} PWideChar {$ELSE} PAnsiChar {$ENDIF};
cchFilePath: DWORD; dwFlags: DWORD): DWORD; stdcall; cchFilePath: DWORD; dwFlags: DWORD): DWORD; stdcall;
Attr, FlagsAndAttributes: DWORD; Attr, FlagsAndAttributes: DWORD;
H: THandle; H: THandle;
@ -276,11 +187,7 @@ var
Buf: array[0..4095] of Char; Buf: array[0..4095] of Char;
begin begin
GetFinalPathNameByHandleFunc := GetProcAddress(GetModuleHandle(kernel32), GetFinalPathNameByHandleFunc := GetProcAddress(GetModuleHandle(kernel32),
{$IFDEF UNICODE} 'GetFinalPathNameByHandleW');
'GetFinalPathNameByHandleW'
{$ELSE}
'GetFinalPathNameByHandleA'
{$ENDIF} );
if Assigned(GetFinalPathNameByHandleFunc) then begin if Assigned(GetFinalPathNameByHandleFunc) then begin
Attr := GetFileAttributes(PChar(Filename)); Attr := GetFileAttributes(PChar(Filename));
if Attr <> $FFFFFFFF then begin if Attr <> $FFFFFFFF then begin
@ -326,15 +233,13 @@ procedure RespawnSelfElevated(const AExeFilename, AParams: String;
{ Spawns a new process using the "runas" verb. { Spawns a new process using the "runas" verb.
Notes: Notes:
1. Despite the function's name, the spawned process may not actually be 1. Despite the function's name, the spawned process may not actually be
elevated / running as administrator on Vista. If UAC is disabled, "runas" elevated / running as administrator. If UAC is disabled, "runas"
behaves like "open". Also, if a non-admin user is a member of a special behaves like "open". Also, if a non-admin user is a member of a special
system group like Backup Operators, they can select their own user account system group like Backup Operators, they can select their own user account
at a UAC dialog. Therefore, it is critical that the caller include some at a UAC dialog. Therefore, it is critical that the caller include some
kind of protection against respawning more than once. kind of protection against respawning more than once.
2. If AExeFilename is on a network drive, Vista's ShellExecuteEx function is 2. If AExeFilename is on a network drive, the ShellExecuteEx function is
smart enough to substitute it with a UNC path. XP does not do this, which smart enough to substitute it with a UNC path. }
causes the function to fail with ERROR_PATH_NOT_FOUND because the new
user doesn't retain the original user's drive mappings. }
const const
SEE_MASK_NOZONECHECKS = $00800000; SEE_MASK_NOZONECHECKS = $00800000;
var var
@ -547,10 +452,4 @@ begin
end; end;
end; end;
var
Kernel32Handle: HMODULE;
initialization
Kernel32Handle := GetModuleHandle(kernel32);
VerSetConditionMaskFunc := GetProcAddress(Kernel32Handle, 'VerSetConditionMask');
VerifyVersionInfoWFunc := GetProcAddress(Kernel32Handle, 'VerifyVersionInfoW');
end. end.

View File

@ -2,7 +2,7 @@ unit Struct;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2020 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -33,10 +33,10 @@ const
this file it's recommended you change SetupID. Any change will do (like this file it's recommended you change SetupID. Any change will do (like
changing the letters or numbers), as long as your format is changing the letters or numbers), as long as your format is
unrecognizable by the standard Inno Setup. } unrecognizable by the standard Inno Setup. }
SetupID: TSetupID = 'Inno Setup Setup Data (6.1.0)'{$IFDEF UNICODE}+' (u)'{$ENDIF}; SetupID: TSetupID = 'Inno Setup Setup Data (6.3.0)';
UninstallLogID: array[Boolean] of TUninstallLogID = UninstallLogID: array[Boolean] of TUninstallLogID =
('Inno Setup Uninstall Log (b)', 'Inno Setup Uninstall Log (b) 64-bit'); ('Inno Setup Uninstall Log (b)', 'Inno Setup Uninstall Log (b) 64-bit');
MessagesHdrID: TMessagesHdrID = 'Inno Setup Messages (6.0.0)'{$IFDEF UNICODE}+' (u)'{$ENDIF}; MessagesHdrID: TMessagesHdrID = 'Inno Setup Messages (6.0.0) (u)';
MessagesLangOptionsID: TMessagesLangOptionsID = '!mlo!001'; MessagesLangOptionsID: TMessagesLangOptionsID = '!mlo!001';
ZLIBID: TCompID = 'zlb'#26; ZLIBID: TCompID = 'zlb'#26;
DiskSliceID: TDiskSliceID = 'idska32'#26; DiskSliceID: TDiskSliceID = 'idska32'#26;
@ -61,8 +61,7 @@ type
shAllowUNCPath, shUserInfoPage, shUsePreviousUserInfo, shAllowUNCPath, shUserInfoPage, shUsePreviousUserInfo,
shUninstallRestartComputer, shRestartIfNeededByRun, shShowTasksTreeLines, shUninstallRestartComputer, shRestartIfNeededByRun, shShowTasksTreeLines,
shAllowCancelDuringInstall, shWizardImageStretch, shAppendDefaultDirName, shAllowCancelDuringInstall, shWizardImageStretch, shAppendDefaultDirName,
shAppendDefaultGroupName, shEncryptionUsed, shAppendDefaultGroupName, shEncryptionUsed, shSetupLogging,
{$IFNDEF UNICODE}shShowUndisplayableLanguages, {$ENDIF}shSetupLogging,
shSignedUninstaller, shUsePreviousLanguage, shDisableWelcomePage, shSignedUninstaller, shUsePreviousLanguage, shDisableWelcomePage,
shCloseApplications, shRestartApplications, shAllowNetworkDrive, shCloseApplications, shRestartApplications, shAllowNetworkDrive,
shForceCloseApplications, shAppNameHasConsts, shUsePreviousPrivileges, shForceCloseApplications, shAppNameHasConsts, shUsePreviousPrivileges,
@ -94,9 +93,6 @@ type
AppModifyPath, CreateUninstallRegKey, Uninstallable, CloseApplicationsFilter, AppModifyPath, CreateUninstallRegKey, Uninstallable, CloseApplicationsFilter,
SetupMutex, ChangesEnvironment, ChangesAssociations: String; SetupMutex, ChangesEnvironment, ChangesAssociations: String;
LicenseText, InfoBeforeText, InfoAfterText, CompiledCodeText: AnsiString; LicenseText, InfoBeforeText, InfoAfterText, CompiledCodeText: AnsiString;
{$IFNDEF UNICODE}
LeadBytes: set of AnsiChar;
{$ENDIF}
NumLanguageEntries, NumCustomMessageEntries, NumPermissionEntries, NumLanguageEntries, NumCustomMessageEntries, NumPermissionEntries,
NumTypeEntries, NumComponentEntries, NumTaskEntries, NumDirEntries, NumTypeEntries, NumComponentEntries, NumTaskEntries, NumDirEntries,
NumFileEntries, NumFileLocationEntries, NumIconEntries, NumIniEntries, NumFileEntries, NumFileLocationEntries, NumIconEntries, NumIniEntries,
@ -137,13 +133,10 @@ const
type type
PSetupLanguageEntry = ^TSetupLanguageEntry; PSetupLanguageEntry = ^TSetupLanguageEntry;
TSetupLanguageEntry = packed record TSetupLanguageEntry = packed record
{$IFNDEF UNICODE}
{ Note: LanguageName is Unicode }
{$ENDIF}
Name, LanguageName, DialogFontName, TitleFontName, WelcomeFontName, Name, LanguageName, DialogFontName, TitleFontName, WelcomeFontName,
CopyrightFontName: String; CopyrightFontName: String;
Data, LicenseText, InfoBeforeText, InfoAfterText: AnsiString; Data, LicenseText, InfoBeforeText, InfoAfterText: AnsiString;
LanguageID{$IFNDEF UNICODE}, LanguageCodePage{$ENDIF}: Cardinal; LanguageID: Cardinal;
DialogFontSize: Integer; DialogFontSize: Integer;
TitleFontSize: Integer; TitleFontSize: Integer;
WelcomeFontSize: Integer; WelcomeFontSize: Integer;
@ -278,7 +271,7 @@ type
CloseOnExit: TSetupIconCloseOnExit; CloseOnExit: TSetupIconCloseOnExit;
HotKey: Word; HotKey: Word;
Options: set of (ioUninsNeverUninstall, ioCreateOnlyIfFileExists, Options: set of (ioUninsNeverUninstall, ioCreateOnlyIfFileExists,
ioUseAppPaths, ioFolderShortcut, ioExcludeFromShowInNewInstall, ioUseAppPaths, ioExcludeFromShowInNewInstall,
ioPreventPinning, ioHasAppUserModelToastActivatorCLSID); ioPreventPinning, ioHasAppUserModelToastActivatorCLSID);
end; end;
const const

View File

@ -2,13 +2,11 @@ unit TaskbarProgressFunc;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2010 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
Wrappers for ITaskbarList3.SetProgressState & SetProgressValue Wrappers for ITaskbarList3.SetProgressState & SetProgressValue
$jrsoftware: issrc/Projects/TaskbarProgressFunc.pas,v 1.1 2010/10/29 01:48:45 jr Exp $
} }
interface interface
@ -23,7 +21,7 @@ procedure SetAppTaskbarProgressValue(const Completed, Total: Cardinal);
implementation implementation
uses uses
Windows, {$IFDEF VER90} OLE2 {$ELSE} ActiveX {$ENDIF}, Forms, dwTaskbarList; Windows, ActiveX, Forms, dwTaskbarList;
var var
TaskbarListInitialized: Boolean; TaskbarListInitialized: Boolean;
@ -31,20 +29,15 @@ var
function InitializeTaskbarList: Boolean; function InitializeTaskbarList: Boolean;
var var
WinVer: Word;
Intf: ITaskbarList3; Intf: ITaskbarList3;
begin begin
if not TaskbarListInitialized then begin if not TaskbarListInitialized then begin
WinVer := Swap(Word(GetVersion())); if CoCreateInstance(CLSID_TaskbarList, nil, CLSCTX_INPROC_SERVER, IID_TaskbarList3, Intf) = S_OK then
if WinVer >= $0601 then if Intf.HrInit = S_OK then begin
if CoCreateInstance(CLSID_TaskbarList, nil, CLSCTX_INPROC_SERVER, IID_TaskbarList3, Intf) = S_OK then { Safety: don't allow the instance to be destroyed at shutdown }
if Intf.HrInit = S_OK then begin Intf._AddRef;
{$IFNDEF VER90} TaskbarListInterface := Intf;
{ Safety: don't allow the instance to be destroyed at shutdown } end;
Intf._AddRef;
{$ENDIF}
TaskbarListInterface := Intf;
end;
TaskbarListInitialized := True; TaskbarListInitialized := True;
end; end;
Result := Assigned(TaskbarListInterface); Result := Assigned(TaskbarListInterface);

View File

@ -2,15 +2,13 @@ unit UIStateForm;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2004 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
TUIStateForm, a TForm descendant which correctly handles the hiding of TUIStateForm, a TForm descendant which correctly handles the hiding of
accelerator key characters and focus rectangles on Windows 2000 and later accelerator key characters and focus rectangles when the
when the "Hide keyboard navigation indicators" option is enabled. "Hide keyboard navigation indicators" option is enabled.
$jrsoftware: issrc/Projects/UIStateForm.pas,v 1.2 2004/06/26 04:36:08 jr Exp $
} }
interface interface

View File

@ -2,7 +2,7 @@ unit Undo;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2020 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -19,16 +19,13 @@ uses
Windows, SysUtils, Int64Em, FileClass, CmnFunc2; Windows, SysUtils, Int64Em, FileClass, CmnFunc2;
const const
HighestSupportedVersion = 48 {$IFDEF UNICODE} + 1000{$ENDIF}; HighestSupportedVersion = 1048;
{ Each time the format of the uninstall log changes (usually a new entry type { Each time the format of the uninstall log changes (usually a new entry type
is added), HighestSupportedVersion and the file version number of Setup is added), HighestSupportedVersion and the file version number of Setup
are incremented to match (51.x). Do NOT do this yourself; doing so could cause are incremented to match (51.x). Do NOT do this yourself; doing so could cause
incompatibilities with future Inno Setup releases. It's recommended that you incompatibilities with future Inno Setup releases. It's recommended that you
use the "utUserDefined" log entry type if you wish to implement your own use the "utUserDefined" log entry type if you wish to implement your own
custom uninstall log entries; see below for more information. custom uninstall log entries; see below for more information. }
Note: the non Unicode HighestSupportedVersion may never become greater than
or equal to 1000. }
type type
TUninstallRecTyp = type Word; TUninstallRecTyp = type Word;
@ -301,10 +298,7 @@ begin
DirsNotRemoved.AddIfDoesntExist(DirsNotRemovedPrefix[DisableFsRedir] + DirName); DirsNotRemoved.AddIfDoesntExist(DirsNotRemovedPrefix[DisableFsRedir] + DirName);
end end
else if Assigned(RestartDeleteDirList) and else if Assigned(RestartDeleteDirList) and
ListContainsPathOrSubdir(RestartDeleteDirList, DirName) and ListContainsPathOrSubdir(RestartDeleteDirList, DirName) then begin
(Win32Platform = VER_PLATFORM_WIN32_NT) then begin
{ Note: This code is NT-only; I don't think it's possible to
restart-delete directories on Windows 9x. }
LogFmt('Failed to delete directory (%d). Will delete on restart (if empty).', LogFmt('Failed to delete directory (%d). Will delete on restart (if empty).',
[LastError]); [LastError]);
LoggedRestartDeleteDir(DisableFsRedir, DirName); LoggedRestartDeleteDir(DisableFsRedir, DirName);
@ -378,39 +372,19 @@ procedure TUninstallLog.Add(const Typ: TUninstallRecTyp; const Data: array of St
var var
I, L: Integer; I, L: Integer;
S, X: AnsiString; S, X: AnsiString;
{$IFDEF UNICODE}
AData: AnsiString; AData: AnsiString;
{$ENDIF}
NewRec: PUninstallRec; NewRec: PUninstallRec;
begin begin
for I := 0 to High(Data) do begin for I := 0 to High(Data) do begin
L := Length(Data[I])*SizeOf(Data[I][1]); L := Length(Data[I])*SizeOf(Data[I][1]);
{$IFNDEF UNICODE} SetLength(X, SizeOf(Byte) + SizeOf(Integer));
if L < $FD then X[1] := AnsiChar($FE);
S := S + AnsiChar(L) Integer((@X[2])^) := Integer(-L);
else if L <= $FFFF then begin S := S + X;
SetLength(X, SizeOf(Byte) + SizeOf(Word));
X[1] := AnsiChar($FD);
Word((@X[2])^) := Word(L);
S := S + X;
end
else begin
{$ENDIF}
SetLength(X, SizeOf(Byte) + SizeOf(Integer));
X[1] := AnsiChar($FE);
Integer((@X[2])^) := Integer({$IFDEF UNICODE}-{$ENDIF}L);
S := S + X;
{$IFNDEF UNICODE}
end;
{$ENDIF}
{$IFDEF UNICODE}
SetString(AData, PAnsiChar(Pointer(Data[I])), L); SetString(AData, PAnsiChar(Pointer(Data[I])), L);
S := S + AData; S := S + AData;
{$ELSE}
S := S + Data[I];
{$ENDIF}
end; end;
S := S + AnsiChar($FF); S := S + AnsiChar($FF);
@ -422,12 +396,6 @@ begin
if Version < HighestSupportedVersion then if Version < HighestSupportedVersion then
Version := HighestSupportedVersion; Version := HighestSupportedVersion;
{$IFNDEF UNICODE}
{ If the version is in Unicode range, bump it there too if needed. }
if (Version >= 1000) and
(Version < 1000 + HighestSupportedVersion) then
Version := 1000 + HighestSupportedVersion;
{$ENDIF}
end; end;
procedure TUninstallLog.AddReg(const Typ: TUninstallRecTyp; procedure TUninstallLog.AddReg(const Typ: TUninstallRecTyp;
@ -537,13 +505,8 @@ begin
$FF: Break; $FF: Break;
end; end;
if L < 0 then begin if L < 0 then begin
{$IFDEF UNICODE}
L := -L; L := -L;
SetString(Data[I], PChar(X), L div SizeOf(Char)); SetString(Data[I], PChar(X), L div SizeOf(Char));
{$ELSE}
{ Should not be possible to get here, but check anyway for safety. }
InternalError('ExtractRecData: Unicode data unsupported by this build');
{$ENDIF}
end else end else
SetString(Data[I], PAnsiChar(X), L); SetString(Data[I], PAnsiChar(X), L);
Inc(X, L); Inc(X, L);
@ -1161,12 +1124,9 @@ class function TUninstallLog.WriteSafeHeaderString(Dest: PAnsiChar;
#1 marker. If MaxDestBytes = 0 it returns the amount of bytes needed. } #1 marker. If MaxDestBytes = 0 it returns the amount of bytes needed. }
var var
N: Integer; N: Integer;
{$IFDEF UNICODE}
I: Integer; I: Integer;
{$ENDIF}
begin begin
N := Length(Source); N := Length(Source);
{$IFDEF UNICODE}
{ Only UTF-8-encode when non-ASCII characters are present } { Only UTF-8-encode when non-ASCII characters are present }
for I := 1 to N do begin for I := 1 to N do begin
if Ord(Source[I]) > 126 then begin if Ord(Source[I]) > 126 then begin
@ -1179,7 +1139,6 @@ begin
Exit; Exit;
end; end;
end; end;
{$ENDIF}
if MaxDestBytes <> 0 then if MaxDestBytes <> 0 then
AnsiStrings.StrPLCopy(Dest, AnsiString(Source), MaxDestBytes - 1); AnsiStrings.StrPLCopy(Dest, AnsiString(Source), MaxDestBytes - 1);
Result := (N + 1) * SizeOf(Dest^); Result := (N + 1) * SizeOf(Dest^);
@ -1187,14 +1146,10 @@ end;
class function TUninstallLog.ReadSafeHeaderString(const Source: AnsiString): String; class function TUninstallLog.ReadSafeHeaderString(const Source: AnsiString): String;
begin begin
{$IFDEF UNICODE}
if (Source <> '') and (Source[1] = #1) then if (Source <> '') and (Source[1] = #1) then
Result := UTF8ToString(Copy(Source, 2, Maxint)) Result := UTF8ToString(Copy(Source, 2, Maxint))
else else
Result := String(Source); Result := String(Source);
{$ELSE}
Result := Source;
{$ENDIF}
end; end;
procedure TUninstallLog.Save(const Filename: String; procedure TUninstallLog.Save(const Filename: String;

View File

@ -2,7 +2,7 @@ unit UninstProgressForm;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2019 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -106,9 +106,7 @@ begin
InitializeFont; InitializeFont;
{$IFDEF IS_D7}
MainPanel.ParentBackGround := False; MainPanel.ParentBackGround := False;
{$ENDIF}
PageNameLabel.Font.Style := [fsBold]; PageNameLabel.Font.Style := [fsBold];
PageNameLabel.Caption := SetupMessages[msgWizardUninstalling]; PageNameLabel.Caption := SetupMessages[msgWizardUninstalling];

View File

@ -2,7 +2,7 @@ unit Uninstall;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2020 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -48,9 +48,6 @@ var
LogFilename: String; LogFilename: String;
InitialProcessWnd, FirstPhaseWnd, DebugWnd: HWND; InitialProcessWnd, FirstPhaseWnd, DebugWnd: HWND;
OldWindowProc: Pointer; OldWindowProc: Pointer;
{$IFNDEF UNICODE}
UninstLeadBytes: set of Char;
{$ENDIF}
procedure ShowExceptionMsg; procedure ShowExceptionMsg;
var var
@ -472,11 +469,7 @@ end;
function ExtractCompiledCodeText(S: String): AnsiString; function ExtractCompiledCodeText(S: String): AnsiString;
begin begin
{$IFDEF UNICODE}
SetString(Result, PAnsiChar(Pointer(S)), Length(S)*SizeOf(S[1])); SetString(Result, PAnsiChar(Pointer(S)), Length(S)*SizeOf(S[1]));
{$ELSE}
Result := S;
{$ENDIF}
end; end;
procedure RunSecondPhase; procedure RunSecondPhase;
@ -494,7 +487,7 @@ begin
SetTaskbarButtonVisibility(False); SetTaskbarButtonVisibility(False);
RestartSystem := False; RestartSystem := False;
AllowUninstallerShutdown := (WindowsVersion shr 16 >= $0600); AllowUninstallerShutdown := True;
try try
if DebugWnd <> 0 then if DebugWnd <> 0 then
@ -552,21 +545,13 @@ begin
UninstDataFile := OpenUninstDataFile(faReadWrite); UninstDataFile := OpenUninstDataFile(faReadWrite);
if not UninstLog.ExtractLatestRecData(utCompiledCode, if not UninstLog.ExtractLatestRecData(utCompiledCode,
SetupBinVersion {$IFDEF UNICODE} or Longint($80000000) {$ENDIF}, CompiledCodeData) then SetupBinVersion or Longint($80000000), CompiledCodeData) then
InternalError('Cannot find utCompiledCode record for this version of the uninstaller'); InternalError('Cannot find utCompiledCode record for this version of the uninstaller');
if DebugWnd <> 0 then if DebugWnd <> 0 then
CompiledCodeText := DebugClientCompiledCodeText CompiledCodeText := DebugClientCompiledCodeText
else else
CompiledCodeText := ExtractCompiledCodeText(CompiledCodeData[0]); CompiledCodeText := ExtractCompiledCodeText(CompiledCodeData[0]);
{$IFNDEF UNICODE}
{ Initialize ConstLeadBytes }
if Length(CompiledCodeData[1]) <> SizeOf(UninstLeadBytes) then
InternalError('utCompiledCode[1] is invalid');
Move(Pointer(CompiledCodeData[1])^, UninstLeadBytes, SizeOf(UninstLeadBytes));
ConstLeadBytes := @UninstLeadBytes;
{$ENDIF}
InitializeAdminInstallMode(ufAdminInstallMode in UninstLog.Flags); InitializeAdminInstallMode(ufAdminInstallMode in UninstLog.Flags);
{ Initialize install mode } { Initialize install mode }

110
Projects/VerInfo.pas Normal file
View File

@ -0,0 +1,110 @@
unit VerInfo;
{
Inno Setup
Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT.
Version info functions
}
interface
uses
Windows, SysUtils, Int64Em;
{$I VERSION.INC}
type
TFileVersionNumbers = record
MS, LS: LongWord;
end;
function GetVersionInfo(const Filename: String;
var VersionInfo: TVSFixedFileInfo): Boolean;
function GetVersionNumbers(const Filename: String;
var VersionNumbers: TFileVersionNumbers): Boolean;
function StrToVersionNumbers(const S: String;
var Version: TFileVersionNumbers): Boolean;
implementation
uses
CmnFunc2, FileClass;
function GetVersionInfo(const Filename: String;
var VersionInfo: TVSFixedFileInfo): Boolean;
var
VersionSize: Integer;
VersionHandle: DWORD;
VersionBuf: PChar;
VerInfo: PVSFixedFileInfo;
VerInfoSize: UINT;
begin
Result := False;
VersionSize := GetFileVersionInfoSize(PChar(Filename), VersionHandle);
if VersionSize > 0 then begin
GetMem(VersionBuf, VersionSize);
try
if GetFileVersionInfo(PChar(Filename), VersionHandle, VersionSize, VersionBuf) then begin
if VerQueryValue(VersionBuf, '\', Pointer(VerInfo), VerInfoSize) then begin
VersionInfo := VerInfo^;
Result := True;
end;
end;
finally
FreeMem(VersionBuf);
end;
end;
end;
function GetVersionNumbers(const Filename: String;
var VersionNumbers: TFileVersionNumbers): Boolean;
var
VerInfo: TVSFixedFileInfo;
begin
Result := GetVersionInfo(Filename, VerInfo);
if Result then begin
VersionNumbers.MS := VerInfo.dwFileVersionMS;
VersionNumbers.LS := VerInfo.dwFileVersionLS;
end;
end;
function StrToVersionNumbers(const S: String; var Version: TFileVersionNumbers): Boolean;
function SplitNextNumber(var Z: String): Word;
var
I, N: Integer;
begin
if Trim(Z) <> '' then begin
I := Pos('.', Z);
if I = 0 then
I := Length(Z)+1;
N := StrToInt(Trim(Copy(Z, 1, I-1)));
if (N < Low(Word)) or (N > High(Word)) then
Abort;
Result := N;
Z := Copy(Z, I+1, Maxint);
end else
Result := 0;
end;
var
Z: String;
W: Word;
begin
try
Z := S;
W := SplitNextNumber(Z);
Version.MS := (DWord(W) shl 16) or SplitNextNumber(Z);
W := SplitNextNumber(Z);
Version.LS := (DWord(W) shl 16) or SplitNextNumber(Z);
Result := True;
except
Result := False;
end;
end;
end.

View File

@ -1,250 +0,0 @@
unit VerInfo;
{
Inno Setup
Copyright (C) 1997-2020 Jordan Russell
Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT.
Version info functions
}
interface
uses
Windows, SysUtils, Int64Em;
{$I VERSION.INC}
type
TFileVersionNumbers = record
MS, LS: LongWord;
end;
function GetVersionInfo(const Filename: String;
var VersionInfo: TVSFixedFileInfo): Boolean;
function GetVersionNumbers(const Filename: String;
var VersionNumbers: TFileVersionNumbers): Boolean;
function StrToVersionNumbers(const S: String;
var Version: TFileVersionNumbers): Boolean;
implementation
uses
CmnFunc2, FileClass;
function GetVXDVersionInfo(const Filename: String;
var VersionInfo: TVSFixedFileInfo): Boolean;
{ Gets the version info from a VXD file. Returns True if successful.
Note: The code in this function is based on the code in the MS KB article
Q201685.
Known issue: This function fails if the version resource has a name
(TVXDVersionResource.cName <> $FF). It's rare, but such VXDs do exist --
see Windows 98's MSGAME.VXD for example. Given that as of 2007 Windows 9x
is mostly obsolete, I don't plan on fixing this. }
const
IMAGE_DOS_SIGNATURE = $5A4D; { MZ }
IMAGE_VXD_SIGNATURE = $454C; { LE }
type
PImageVXDHeader = ^TImageVXDHeader;
TImageVXDHeader = packed record
e32_magic: Word; // Magic number
e32_border: Byte; // The byte ordering for the VXD
e32_worder: Byte; // The word ordering for the VXD
e32_level: DWORD; // The EXE format level for now = 0
e32_cpu: Word; // The CPU type
e32_os: Word; // The OS type
e32_ver: DWORD; // Module version
e32_mflags: DWORD; // Module flags
e32_mpages: DWORD; // Module # pages
e32_startobj: DWORD; // Object # for instruction pointer
e32_eip: DWORD; // Extended instruction pointer
e32_stackobj: DWORD; // Object # for stack pointer
e32_esp: DWORD; // Extended stack pointer
e32_pagesize: DWORD; // VXD page size
e32_lastpagesize: DWORD; // Last page size in VXD
e32_fixupsize: DWORD; // Fixup section size
e32_fixupsum: DWORD; // Fixup section checksum
e32_ldrsize: DWORD; // Loader section size
e32_ldrsum: DWORD; // Loader section checksum
e32_objtab: DWORD; // Object table offset
e32_objcnt: DWORD; // Number of objects in module
e32_objmap: DWORD; // Object page map offset
e32_itermap: DWORD; // Object iterated data map offset
e32_rsrctab: DWORD; // Offset of Resource Table
e32_rsrccnt: DWORD; // Number of resource entries
e32_restab: DWORD; // Offset of resident name table
e32_enttab: DWORD; // Offset of Entry Table
e32_dirtab: DWORD; // Offset of Module Directive Table
e32_dircnt: DWORD; // Number of module directives
e32_fpagetab: DWORD; // Offset of Fixup Page Table
e32_frectab: DWORD; // Offset of Fixup Record Table
e32_impmod: DWORD; // Offset of Import Module Name Table
e32_impmodcnt: DWORD; // Number of entries in Import Module Name Table
e32_impproc: DWORD; // Offset of Import Procedure Name Table
e32_pagesum: DWORD; // Offset of Per-Page Checksum Table
e32_datapage: DWORD; // Offset of Enumerated Data Pages
e32_preload: DWORD; // Number of preload pages
e32_nrestab: DWORD; // Offset of Non-resident Names Table
e32_cbnrestab: DWORD; // Size of Non-resident Name Table
e32_nressum: DWORD; // Non-resident Name Table Checksum
e32_autodata: DWORD; // Object # for automatic data object
e32_debuginfo: DWORD; // Offset of the debugging information
e32_debuglen: DWORD; // The length of the debugging info. in bytes
e32_instpreload: DWORD; // Number of instance pages in preload section of VXD file
e32_instdemand: DWORD; // Number of instance pages in demand load section of VXD file
e32_heapsize: DWORD; // Size of heap - for 16-bit apps
e32_res3: array[0..11] of Byte; // Reserved words
e32_winresoff: DWORD;
e32_winreslen: DWORD;
e32_devid: Word; // Device ID for VxD
e32_ddkver: Word; // DDK version for VxD
end;
PVXDVersionResource = ^TVXDVersionResource;
TVXDVersionResource = packed record
cType: Byte;
wID: Word;
cName: Byte;
wOrdinal: Word;
wFlags: Word;
dwResSize: DWORD;
end;
var
F: TFile;
DosHeader: packed record
Sig: Word;
Other: array[0..57] of Byte;
VXDHeaderOffset: DWORD;
end;
VXDHeader: TImageVXDHeader;
VXDVersionRes: TVXDVersionResource;
RootNode: packed record
cbNode: Word;
cbData: Word;
szKey: array[0..15] of AnsiChar; { should always be 'VS_VERSION_INFO'#0 }
Value: TVSFixedFileInfo;
end;
begin
Result := False;
try
if not NewFileExists(Filename) then
Exit;
F := TFile.Create(Filename, fdOpenExisting, faRead, fsRead);
try
{ DOS header }
if (F.Read(DosHeader, SizeOf(DosHeader)) <> SizeOf(DosHeader)) or
(DosHeader.Sig <> IMAGE_DOS_SIGNATURE) or
(DosHeader.VXDHeaderOffset = 0) then
Exit;
{ VXD header }
F.Seek(DosHeader.VXDHeaderOffset);
if (F.Read(VXDHeader, SizeOf(VXDHeader)) <> SizeOf(VXDHeader)) or
(DWORD(Pointer(@VXDHeader)^) <> IMAGE_VXD_SIGNATURE) then
Exit;
if Cardinal(VXDHeader.e32_winreslen) <= Cardinal(SizeOf(VXDVersionRes)) then
Exit; { sanity check }
{ Resource }
F.Seek(VXDHeader.e32_winresoff);
F.ReadBuffer(VXDVersionRes, SizeOf(VXDVersionRes));
if (VXDVersionRes.cType <> $FF) or
(VXDVersionRes.wID <> 16) or { RT_VERSION? }
(VXDVersionRes.cName <> $FF) then
Exit; { we don't support non-ordinal types/names (see "Known issue") }
if Cardinal(VXDVersionRes.dwResSize) < Cardinal(SizeOf(RootNode)) then
Exit; { sanity check }
F.ReadBuffer(RootNode, SizeOf(RootNode));
if (RootNode.cbNode >= SizeOf(RootNode)) and
(RootNode.cbData >= SizeOf(RootNode.Value)) and
(RootNode.Value.dwSignature = VS_FFI_SIGNATURE) then begin
VersionInfo := RootNode.Value;
Result := True;
end;
finally
F.Free;
end;
except
{ don't propagate exceptions }
end;
end;
function GetVersionInfo(const Filename: String;
var VersionInfo: TVSFixedFileInfo): Boolean;
var
VersionSize: Integer;
VersionHandle: DWORD;
VersionBuf: PChar;
VerInfo: PVSFixedFileInfo;
VerInfoSize: UINT;
begin
Result := False;
VersionSize := GetFileVersionInfoSize(PChar(Filename), VersionHandle);
if VersionSize > 0 then begin
GetMem(VersionBuf, VersionSize);
try
if GetFileVersionInfo(PChar(Filename), VersionHandle, VersionSize, VersionBuf) then begin
if VerQueryValue(VersionBuf, '\', Pointer(VerInfo), VerInfoSize) then begin
VersionInfo := VerInfo^;
Result := True;
end;
end;
finally
FreeMem(VersionBuf);
end;
end
else if Win32Platform <> VER_PLATFORM_WIN32_WINDOWS then begin
{ NT's version APIs don't support VXDs, so use our own code to handle them }
Result := GetVXDVersionInfo(Filename, VersionInfo);
end;
end;
function GetVersionNumbers(const Filename: String;
var VersionNumbers: TFileVersionNumbers): Boolean;
var
VerInfo: TVSFixedFileInfo;
begin
Result := GetVersionInfo(Filename, VerInfo);
if Result then begin
VersionNumbers.MS := VerInfo.dwFileVersionMS;
VersionNumbers.LS := VerInfo.dwFileVersionLS;
end;
end;
function StrToVersionNumbers(const S: String; var Version: TFileVersionNumbers): Boolean;
function SplitNextNumber(var Z: String): Word;
var
I, N: Integer;
begin
if Trim(Z) <> '' then begin
I := Pos('.', Z);
if I = 0 then
I := Length(Z)+1;
N := StrToInt(Trim(Copy(Z, 1, I-1)));
if (N < Low(Word)) or (N > High(Word)) then
Abort;
Result := N;
Z := Copy(Z, I+1, Maxint);
end else
Result := 0;
end;
var
Z: String;
W: Word;
begin
try
Z := S;
W := SplitNextNumber(Z);
Version.MS := (DWord(W) shl 16) or SplitNextNumber(Z);
W := SplitNextNumber(Z);
Version.LS := (DWord(W) shl 16) or SplitNextNumber(Z);
Result := True;
except
Result := False;
end;
end;
end.

View File

@ -2,7 +2,7 @@ unit Wizard;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2019 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
@ -767,9 +767,8 @@ begin
PrevSelectedTasks := TStringList.Create(); PrevSelectedTasks := TStringList.Create();
PrevDeselectedTasks := TStringList.Create(); PrevDeselectedTasks := TStringList.Create();
{$IFDEF IS_D7}
MainPanel.ParentBackground := False; MainPanel.ParentBackground := False;
{$ENDIF}
{ Prior to scaling the form, shrink WizardSmallBitmapImage if it's currently { Prior to scaling the form, shrink WizardSmallBitmapImage if it's currently
larger than WizardSmallImage. This way, stretching will not occur if the larger than WizardSmallImage. This way, stretching will not occur if the
user specifies a smaller-than-default image and WizardImageStretch=yes, user specifies a smaller-than-default image and WizardImageStretch=yes,
@ -2703,26 +2702,18 @@ var
pszPath: PChar; dwFlags: DWORD): HRESULT; stdcall; pszPath: PChar; dwFlags: DWORD): HRESULT; stdcall;
procedure ReconnectPath(const Path: String); procedure ReconnectPath(const Path: String);
{ Attempts to re-establish the connection to Path if it's on a network drive. { Attempts to re-establish the connection to Path if it's on a network drive
It is particularly important to call this on Windows Vista, where mapped since mapped network drives are initially disconnected in elevated processes. }
network drives are initially disconnected in elevated processes.
Only has an effect on Windows XP and later. }
var var
WindowList: Pointer; WindowList: Pointer;
begin begin
{ If this fails, we shouldn't display any message boxes since the install { If this fails, we shouldn't display any message boxes since the install
might be running silently with /SUPPRESSMSGBOXES. might be running silently with /SUPPRESSMSGBOXES and this is indeed so:
Because of that requirement, we must limit this code to Windows XP and The SHPathPrepareForWrite documentation claims that "user interface
later: The SHPathPrepareForWrite documentation claims that "user interface windows will not be created" when hwnd is NULL. }
windows will not be created" when hwnd is NULL, however I found that on if Assigned(SHPathPrepareForWriteFunc) then begin
Windows 2000, it can still display unowned "An error occurred while { "Just in case" it tries to display UI anyway (it never did in tests),
reconnecting" message boxes (e.g. if you log in with persistently mapped disable our windows }
drives while your Local Area Connection is disabled).
Windows XP/2003/Vista suppress these message boxes when NULL is passed. }
if (WindowsVersion >= Cardinal($05010000)) and
Assigned(SHPathPrepareForWriteFunc) then begin
{ "Just in case" XP and later tries to display UI (it never did in my
tests), disable our windows }
WindowList := DisableTaskWindows(0); WindowList := DisableTaskWindows(0);
try try
SHPathPrepareForWriteFunc(0, nil, PChar(Path), SHPPFW_NONE); SHPathPrepareForWriteFunc(0, nil, PChar(Path), SHPPFW_NONE);
@ -3008,5 +2999,5 @@ end;
initialization initialization
SHPathPrepareForWriteFunc := GetProcAddress(SafeLoadLibrary(AddBackslash(GetSystemDir) + shell32, SHPathPrepareForWriteFunc := GetProcAddress(SafeLoadLibrary(AddBackslash(GetSystemDir) + shell32,
SEM_NOOPENFILEERRORBOX), {$IFDEF UNICODE}'SHPathPrepareForWriteW'{$ELSE}'SHPathPrepareForWriteA'{$ENDIF}); SEM_NOOPENFILEERRORBOX), 'SHPathPrepareForWriteW');
end. end.

View File

@ -2,12 +2,11 @@ unit XPTheme;
{ {
Inno Setup Inno Setup
Copyright (C) 1997-2007 Jordan Russell Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT. For conditions of distribution and use, see LICENSE.TXT.
Enables themes on Windows XP/Vista, and disables DPI scaling on Vista. Enables themes. Used only by the Setup and SetupLdr projects.
Used only by the Setup and SetupLdr projects.
Note: XPTheme must be included as the first unit in the program's "uses" Note: XPTheme must be included as the first unit in the program's "uses"
clause so that its code runs before any VCL initialization code. clause so that its code runs before any VCL initialization code.
@ -26,14 +25,5 @@ uses
procedure InitCommonControls; external comctl32 name 'InitCommonControls'; procedure InitCommonControls; external comctl32 name 'InitCommonControls';
initialization initialization
{ Work around bug in Windows XP Gold & SP1: If the application manifest
specifies COMCTL32.DLL version 6.0 (to enable visual styles), we must
call InitCommonControls() to ensure that we actually link to
COMCTL32.DLL, otherwise calls to MessageBox() fail. (XP SP2 appears
to fix this.)
Programs that don't statically link to COMCTL32, like SetupLdr, need this.
(Actually, that's not completely true -- SetupLdr uses RedirFunc, which
loads SHELL32.DLL, which in turn loads COMCTL32.DLL. But let's not rely on
that undocumented behavior.) }
InitCommonControls; InitCommonControls;
end. end.

View File

@ -52,6 +52,11 @@ For conditions of distribution and use, see <a href="https://jrsoftware.org/file
<li>The tab for the selected #include file now shows a close button.</li> <li>The tab for the selected #include file now shows a close button.</li>
<li>Added a clickable panel to the Status Bar showing the amount of closed tabs if there are any.</li> <li>Added a clickable panel to the Status Bar showing the amount of closed tabs if there are any.</li>
</ul> </ul>
<p><span class="head2">Support for Windows Vista and Windows Server 2008 removed</span></p>
<ul>
<li><b>OS requirements change:</b> Windows Vista and Windows Server 2008 are no longer supported. Windows 7 and Windows Server 2008 R2 are now the minimum supported operating systems. [Setup] section directive <tt>MinVersion</tt> still defaults to <tt>6.1sp1</tt>, so by default Setup will still not run versions of Windows 7 and Windows Server 2008 R2 which have not been updated.</li>
<li>Removed [Icons] section flag <tt>foldershortcut</tt> which was already ignored except when running on Windows Vista or Windows Server 2008, as folder shortcuts do not expand properly on the Start Menu anymore.</li>
</ul>
<p><span class="head2">Other changes</span></p> <p><span class="head2">Other changes</span></p>
<ul> <ul>
<li>Compiler IDE change: Added new <i>[Files] Entries Designer</i> menu item to the <i>Tools</i> menu to design and insert extra entries to the [Files] section.</li> <li>Compiler IDE change: Added new <i>[Files] Entries Designer</i> menu item to the <i>Tools</i> menu to design and insert extra entries to the [Files] section.</li>