Setup.RegDLL.pas 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. unit Setup.RegDLL;
  2. {
  3. Inno Setup
  4. Copyright (C) 1997-2026 Jordan Russell
  5. Portions by Martijn Laan
  6. For conditions of distribution and use, see LICENSE.TXT.
  7. Registers 32-bit/64-bit DLL-based OLE servers in a child process (regsvr32.exe)
  8. }
  9. interface
  10. uses
  11. Windows;
  12. procedure RegisterServer(const AUnregister: Boolean; const AIs64Bit: Boolean;
  13. const Filename: String; const AFailCriticalErrors: Boolean);
  14. implementation
  15. uses
  16. SysUtils, Forms,
  17. PathFunc,
  18. Shared.CommonFunc.Vcl, Shared.CommonFunc, Shared.SetupMessageIDs,
  19. SetupLdrAndSetup.Messages,
  20. Setup.InstFunc, Setup.LoggingFunc, Setup.MainFunc, Setup.PathRedir,
  21. Setup.RedirFunc;
  22. function WaitForAndCloseProcessHandle(var AProcessHandle: THandle): DWORD;
  23. var
  24. WaitResult: DWORD;
  25. begin
  26. try
  27. repeat
  28. { Process any pending messages first because MsgWaitForMultipleObjects
  29. (called below) only returns when *new* messages arrive }
  30. Application.ProcessMessages;
  31. WaitResult := MsgWaitForMultipleObjects(1, AProcessHandle, False, INFINITE, QS_ALLINPUT);
  32. until WaitResult <> WAIT_OBJECT_0+1;
  33. if WaitResult = WAIT_FAILED then
  34. Win32ErrorMsg('MsgWaitForMultipleObjects');
  35. if not GetExitCodeProcess(AProcessHandle, Result) then
  36. Win32ErrorMsg('GetExitCodeProcess');
  37. finally
  38. CloseHandle(AProcessHandle);
  39. end;
  40. end;
  41. procedure RegisterServerUsingRegSvr32(const AUnregister: Boolean;
  42. const AIs64Bit: Boolean; const Filename: String);
  43. var
  44. SysDir, CmdLine: String;
  45. StartupInfo: TStartupInfo;
  46. ProcessInfo: TProcessInformation;
  47. ExitCode: DWORD;
  48. begin
  49. { For the path to regsvr32.exe, choose between SysWOW64 and System32
  50. depending on AIs64Bit.
  51. On 32-bit Setup, we disable WOW64 file system redirection instead of using
  52. Sysnative due to the problems described in ProcessRunEntry's comments. }
  53. SysDir := ApplyPathRedirRules(AIs64Bit, GetSystemDir, tpNativeBit,
  54. [rfNormalPath]);
  55. const RedirFilename = ApplyRedirForRegistrationOperation(AIs64Bit, Filename);
  56. CmdLine := '"' + AddBackslash(SysDir) + 'regsvr32.exe"';
  57. if AUnregister then
  58. CmdLine := CmdLine + ' /u';
  59. CmdLine := CmdLine + ' /s "' + RedirFilename + '"';
  60. if AIs64Bit then
  61. Log('Spawning 64-bit RegSvr32: ' + CmdLine)
  62. else
  63. Log('Spawning 32-bit RegSvr32: ' + CmdLine);
  64. FillChar(StartupInfo, SizeOf(StartupInfo), 0);
  65. StartupInfo.cb := SizeOf(StartupInfo);
  66. if not CreateProcessRedir(IsWin64, nil, PChar(CmdLine), nil, nil, False,
  67. CREATE_DEFAULT_ERROR_MODE, nil, PChar(SysDir), StartupInfo,
  68. ProcessInfo) then
  69. Win32ErrorMsg('CreateProcess');
  70. CloseHandle(ProcessInfo.hThread);
  71. ExitCode := WaitForAndCloseProcessHandle(ProcessInfo.hProcess);
  72. if ExitCode <> 0 then
  73. raise Exception.Create(FmtSetupMessage1(msgErrorRegSvr32Failed,
  74. Format('0x%x', [ExitCode])));
  75. end;
  76. procedure RegisterServer(const AUnregister: Boolean; const AIs64Bit: Boolean;
  77. const Filename: String; const AFailCriticalErrors: Boolean);
  78. var
  79. WindowDisabler: TWindowDisabler;
  80. begin
  81. if AIs64Bit and not IsWin64 then
  82. InternalError('Cannot register 64-bit DLLs on this version of Windows');
  83. { Disable windows so the user can't utilize our UI while the child process
  84. is running }
  85. WindowDisabler := TWindowDisabler.Create;
  86. try
  87. { To get the "WRP Mitigation" compatibility hack which a lot of DLLs
  88. require, we must use regsvr32.exe to handle the (un)registration. }
  89. RegisterServerUsingRegSvr32(AUnregister, AIs64Bit, Filename);
  90. finally
  91. WindowDisabler.Free;
  92. end;
  93. end;
  94. end.