Setup.RegDLL.pas 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. unit Setup.RegDLL;
  2. {
  3. Inno Setup
  4. Copyright (C) 1997-2024 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, PathFunc, Shared.CommonFunc.Vcl, Shared.CommonFunc, Setup.InstFunc, SetupLdrAndSetup.Messages, Shared.SetupMessageIDs,
  17. Setup.LoggingFunc, SetupLdrAndSetup.RedirFunc, Setup.MainFunc;
  18. function WaitForAndCloseProcessHandle(var AProcessHandle: THandle): DWORD;
  19. var
  20. WaitResult: DWORD;
  21. begin
  22. try
  23. repeat
  24. { Process any pending messages first because MsgWaitForMultipleObjects
  25. (called below) only returns when *new* messages arrive }
  26. Application.ProcessMessages;
  27. WaitResult := MsgWaitForMultipleObjects(1, AProcessHandle, False, INFINITE, QS_ALLINPUT);
  28. until WaitResult <> WAIT_OBJECT_0+1;
  29. if WaitResult = WAIT_FAILED then
  30. Win32ErrorMsg('MsgWaitForMultipleObjects');
  31. if not GetExitCodeProcess(AProcessHandle, Result) then
  32. Win32ErrorMsg('GetExitCodeProcess');
  33. finally
  34. CloseHandle(AProcessHandle);
  35. end;
  36. end;
  37. procedure RegisterServerUsingRegSvr32(const AUnregister: Boolean;
  38. const AIs64Bit: Boolean; const Filename: String);
  39. var
  40. SysDir, CmdLine: String;
  41. StartupInfo: TStartupInfo;
  42. ProcessInfo: TProcessInformation;
  43. ExitCode: DWORD;
  44. begin
  45. SysDir := GetSystemDir;
  46. CmdLine := '"' + AddBackslash(SysDir) + 'regsvr32.exe"';
  47. if AUnregister then
  48. CmdLine := CmdLine + ' /u';
  49. CmdLine := CmdLine + ' /s "' + Filename + '"';
  50. if AIs64Bit then
  51. Log('Spawning 64-bit RegSvr32: ' + CmdLine)
  52. else
  53. Log('Spawning 32-bit RegSvr32: ' + CmdLine);
  54. FillChar(StartupInfo, SizeOf(StartupInfo), 0);
  55. StartupInfo.cb := SizeOf(StartupInfo);
  56. if not CreateProcessRedir(AIs64Bit, nil, PChar(CmdLine), nil, nil, False,
  57. CREATE_DEFAULT_ERROR_MODE, nil, PChar(SysDir), StartupInfo,
  58. ProcessInfo) then
  59. Win32ErrorMsg('CreateProcess');
  60. CloseHandle(ProcessInfo.hThread);
  61. ExitCode := WaitForAndCloseProcessHandle(ProcessInfo.hProcess);
  62. if ExitCode <> 0 then
  63. raise Exception.Create(FmtSetupMessage1(msgErrorRegSvr32Failed,
  64. Format('0x%x', [ExitCode])));
  65. end;
  66. procedure RegisterServer(const AUnregister: Boolean; const AIs64Bit: Boolean;
  67. const Filename: String; const AFailCriticalErrors: Boolean);
  68. var
  69. WindowDisabler: TWindowDisabler;
  70. begin
  71. if AIs64Bit and not IsWin64 then
  72. InternalError('Cannot register 64-bit DLLs on this version of Windows');
  73. { Disable windows so the user can't utilize our UI while the child process
  74. is running }
  75. WindowDisabler := TWindowDisabler.Create;
  76. try
  77. { To get the "WRP Mitigation" compatibility hack which a lot of DLLs
  78. require, we must use regsvr32.exe to handle the (un)registration. }
  79. RegisterServerUsingRegSvr32(AUnregister, AIs64Bit, Filename);
  80. finally
  81. WindowDisabler.Free;
  82. end;
  83. end;
  84. end.