📄 setupldr.dpr
字号:
xor edx, edx
lock or [eax], edx
end;
var
SysInfo: TSystemInfo;
CurAddr: Pointer;
MemInfo: TMemoryBasicInformation;
ChangedProtection: Boolean;
OrigProtect: DWORD;
Offset: Cardinal;
begin
{ Get system's page size }
GetSystemInfo(SysInfo);
CurAddr := Pointer(Module);
if VirtualQuery(CurAddr, MemInfo, SizeOf(MemInfo)) = 0 then
Exit;
{ Perform this loop until we find a region beyond the end of the file }
while MemInfo.AllocationBase = Pointer(Module) do begin
{ We can only force committed pages into RAM.
We do not want to trigger guard pages and confuse the application. }
if (MemInfo.State = MEM_COMMIT) and (MemInfo.Protect and PAGE_GUARD = 0) then begin
ChangedProtection := False;
{ Determine if the pages in this region are nonwriteable }
if (MemInfo.Protect = PAGE_NOACCESS) or
(MemInfo.Protect = PAGE_READONLY) or
(MemInfo.Protect = PAGE_EXECUTE) or
(MemInfo.Protect = PAGE_EXECUTE_READ) then begin
{ Nonwriteable region, make it writeable (with the least protection) }
if VirtualProtect(MemInfo.BaseAddress, MemInfo.RegionSize,
PAGE_EXECUTE_READWRITE, @OrigProtect) then
ChangedProtection := True;
end;
{ Write to every page in the region.
This forces the page to be in RAM and swapped to the paging file. }
Offset := 0;
while Offset < MemInfo.RegionSize do begin
Touch(PDWORD(Cardinal(MemInfo.BaseAddress) + Offset)^);
Inc(Offset, SysInfo.dwPageSize);
end;
{ If we changed the protection, change it back }
if ChangedProtection then
VirtualProtect(MemInfo.BaseAddress, MemInfo.RegionSize, OrigProtect,
@OrigProtect);
end;
{ Get next region }
Cardinal(CurAddr) := Cardinal(MemInfo.BaseAddress) + MemInfo.RegionSize;
if VirtualQuery(CurAddr, MemInfo, SizeOf(MemInfo)) = 0 then
Break;
end;
end;
const
{ Exit codes that are returned by SetupLdr.
Note: Setup also returns exit codes with the same numbers. }
ecInitializationError = 1; { Setup failed to initialize. }
ecCancelledBeforeInstall = 2; { User clicked Cancel before the actual
installation started. }
var
SelfFilename: String;
SourceF, DestF: TFile;
SizeOfFile: Longint;
ExeHeader: TSetupLdrExeHeader;
OffsetTable: TSetupLdrOffsetTable;
TempDir: String;
TempFile: String;
TestID: TSetupID;
P: Pointer;
Reader: TCompressedBlockReader;
I: Integer;
begin
try
{ Ensure all of SetupLdr is paged in so that in the case of a disk spanning
install Windows will never complain when the disk/CD containing SetupLdr
is ejected. }
RunImageLocally(HInstance);
ProcessCommandLine;
SelfFilename := NewParamStr(0);
SourceF := TFile.Create(SelfFilename, fdOpenExisting, faRead, fsRead);
try
SizeOfFile := SourceF.Size.Lo;
SourceF.Seek(SetupLdrExeHeaderOffset);
SourceF.ReadBuffer(ExeHeader, SizeOf(ExeHeader));
if (ExeHeader.ID <> SetupLdrExeHeaderID) or
(ExeHeader.OffsetTableOffset <> not ExeHeader.NotOffsetTableOffset) or
(ExeHeader.OffsetTableOffset + SizeOf(OffsetTable) > SizeOfFile) then
SetupCorruptError;
SourceF.Seek(ExeHeader.OffsetTableOffset);
SourceF.ReadBuffer(OffsetTable, SizeOf(OffsetTable));
if (OffsetTable.ID <> SetupLdrOffsetTableID) or
(GetCRC32(OffsetTable, SizeOf(OffsetTable) - SizeOf(OffsetTable.TableCRC)) <> OffsetTable.TableCRC) or
(SizeOfFile < OffsetTable.TotalSize) then
SetupCorruptError;
SourceF.Seek(OffsetTable.Offset0);
SourceF.ReadBuffer(TestID, SizeOf(TestID));
if TestID <> SetupID then
SetupCorruptError;
try
Reader := TCompressedBlockReader.Create(SourceF, TLZMADecompressor);
try
SECompressedBlockRead(Reader, SetupHeader, SizeOf(SetupHeader),
SetupHeaderStrings);
LanguageEntryCount := SetupHeader.NumLanguageEntries;
LanguageEntries := AllocMem(LanguageEntryCount * SizeOf(TSetupLanguageEntry));
for I := 0 to LanguageEntryCount-1 do
SECompressedBlockRead(Reader, LanguageEntries[I], SizeOf(LanguageEntries[I]),
SetupLanguageEntryStrings);
finally
Reader.Free;
end;
except
on ECompressDataError do
SetupCorruptError;
end;
ActivateDefaultLanguage;
if Win32Platform = VER_PLATFORM_WIN32s then begin
MessageBox(0, PChar(FmtSetupMessage1(msgNotOnThisPlatform, 'Win32s')),
PChar(SetupMessages[msgErrorTitle]), MB_OK or MB_ICONSTOP);
Abort;
end;
{ Show the startup prompt. If this is enabled, SetupHeader.AppName won't
have constants. }
if not(shDisableStartupPrompt in SetupHeader.Options) and
not InitDisableStartupPrompt and
(MessageBox(0, PChar(FmtSetupMessage1(msgSetupLdrStartupMessage, SetupHeader.AppName)),
PChar(SetupMessages[msgSetupAppTitle]), MB_YESNO or MB_ICONQUESTION) <> IDYES) then begin
SetupLdrExitCode := ecCancelledBeforeInstall;
Abort;
end;
{ Create a temporary directory, and extract the embedded setup program
there }
Randomize;
GenerateTempDir(TempDir);
TempFile := GenerateUniqueName(TempDir, '.tmp');
SourceF.Seek(OffsetTable.OffsetEXE);
try
P := nil;
DestF := TFile.Create(TempFile, fdCreateAlways, faWrite, fsNone);
try
GetMem(P, OffsetTable.UncompressedSizeEXE);
FillChar(P^, OffsetTable.UncompressedSizeEXE, 0);
try
Reader := TCompressedBlockReader.Create(SourceF, TLZMADecompressor);
try
Reader.Read(P^, OffsetTable.UncompressedSizeEXE);
finally
Reader.Free;
end;
except
on ECompressDataError do
SetupCorruptError;
end;
TransformCallInstructions(P^, OffsetTable.UncompressedSizeEXE, False);
if GetCRC32(P^, OffsetTable.UncompressedSizeEXE) <> OffsetTable.CRCEXE then
SetupCorruptError;
{ Preallocate the bytes to avoid file system fragmentation }
DestF.Seek(OffsetTable.UncompressedSizeEXE);
DestF.Truncate;
DestF.Seek(0);
DestF.WriteBuffer(P^, OffsetTable.UncompressedSizeEXE);
finally
FreeMem(P);
DestF.Free;
end;
except
on E: EFileError do begin
SetLastError(E.ErrorCode);
RaiseLastError(msgLdrCannotCreateTemp);
end;
end;
FreeAndNil(SourceF);
{ Create SetupLdrWnd, which is used by Setup to communicate with
SetupLdr }
SetupLdrWnd := CreateWindowEx(0, 'STATIC', 'InnoSetupLdrWindow', 0,
0, 0, 0, 0, HWND_DESKTOP, 0, HInstance, nil);
Longint(OrigWndProc) := SetWindowLong(SetupLdrWnd, GWL_WNDPROC,
Longint(@SetupLdrWndProc));
{ Now execute Setup. Use the exit code it returns as our exit code. }
ExecAndWait(TempFile, Format('/SL4 $%x %s %d %d %s',
[SetupLdrWnd, AddQuotes(SelfFilename), OffsetTable.Offset0,
OffsetTable.Offset1, GetCmdTail]),
SetupLdrExitCode);
finally
SourceF.Free;
if TempFile <> '' then
{ Even though Setup has terminated by now, the system may still have
the file locked for a short period of time (esp. on multiprocessor
systems), so use DelayDeleteFile to delete it. }
DelayDeleteFile(TempFile, 12);
if TempDir <> '' then
RemoveDirectory(PChar(TempDir));
if SetupLdrWnd <> 0 then
{ SetupLdrWnd must be destroyed before RestartComputer is called,
otherwise SetupLdrWndProc would deny the shutdown request }
DestroyWindow(SetupLdrWnd);
if Assigned(LanguageEntries) then begin
Finalize(LanguageEntries[0], LanguageEntryCount);
FreeMem(LanguageEntries);
LanguageEntries := nil;
end;
end;
if RestartSystem then
RestartComputer;
except
ShowExceptionMsg;
{ If SetupLdrExitCode wasn't explicitly set earlier, default to
ecInitializationError }
if SetupLdrExitCode = 0 then
SetupLdrExitCode := ecInitializationError;
end;
Halt(SetupLdrExitCode);
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -