library ShutdownHooks;
{$IMAGEBASE $42800000}
uses
  Windows,
  madCodeHook,
  sysutils;
// ***************************************************************
var
  ExitWindowsExNext             : function (flags, reserved: dword) : bool; stdcall;
  InitiateSystemShutdownWNext   : function (pc, msg: pwideChar; timeOut: dword; force, reboot: bool) : bool; stdcall;
  InitiateSystemShutdownExWNext : function (pc, msg: pwideChar; timeOut: dword; force, reboot, reason: bool) : bool; stdcall;
procedure log(s:string);
var f:textfile;
begin
  assignfile(f,'c:\hooking.log');
  try
    append(f);
  except
    rewrite(f);
  end;
  writeln(f,s);
  closefile(f);
end;
function IsShutdownAllowed(flags: dword) : boolean;
var b1 : boolean;
begin
  log('IsShutdownAllowed');
  b1 := false;
  if SendIpcMessage('ShutdownIpcQueue', @flags, 4, @b1, 1, 5000, false) and (not b1) then begin
    result := false;
    SetLastError(ERROR_ACCESS_DENIED);
  end else
    result := true;
end;
function ExitWindowsExCallback(flags, reserved: dword) : bool; stdcall;
begin
  log('ExitWindowsExCallback');
  result := IsShutdownAllowed(flags) and
            ExitWindowsExNext(flags, reserved);
end;
function GetShutdownFlags(force, reboot: boolean) : dword;
begin
  log('GetShutdownFlags');
  if reboot then
       result := EWX_REBOOT
  else result := EWX_SHUTDOWN;
  if force then
    result := result or EWX_FORCE;
end;
function InitiateSystemShutdownWCallback(pc, msg: pwideChar; timeOut: dword; force, reboot: bool) : bool; stdcall;
begin
  log('InitiateSystemShutdownWCallback');
  result := IsShutdownAllowed(GetShutdownFlags(force, reboot)) and
            InitiateSystemShutdownWNext(pc, msg, timeOut, force, reboot);
end;
function InitiateSystemShutdownExWCallback(pc, msg: pwideChar; timeOut: dword; force, reboot, reason: bool) : bool; stdcall;
begin
  log('InitiateSystemShutdownExWCallback');
  result := IsShutdownAllowed(GetShutdownFlags(force, reboot)) and
            InitiateSystemShutdownExWNext(pc, msg, timeOut, force, reboot, reason);
end;
// ***************************************************************
begin
  log('hook1 ok? '+booltostr(HookAPI(  user32,             'ExitWindowsEx',             @ExitWindowsExCallback,             @ExitWindowsExNext),true));
  log('hook2 ok? '+booltostr(HookAPI(advapi32,   'InitiateSystemShutdownW',   @InitiateSystemShutdownWCallback,   @InitiateSystemShutdownWNext),true));
  log('hook3 ok? '+booltostr(HookAPI(advapi32, 'InitiateSystemShutdownExW', @InitiateSystemShutdownExWCallback, @InitiateSystemShutdownExWNext),true));
end.
---------end lib
--------------program:
program prog;
uses windows, madcodehook, sysutils;
var MayShutdown:boolean=false;
procedure log(s:string);
var f:textfile;
begin
  assignfile(f,'c:\hooking.log');
  try
    append(f);
  except
    rewrite(f);
  end;
  writeln(f,s);
  closefile(f);
end;
procedure ShutdownIpcQueue(name       : pchar;
                           messageBuf : pointer;
                           messageLen : dword;
                           answerBuf  : pointer;
                           answerLen  : dword); stdcall;
var s1 : string;
begin
  boolean(answerBuf^) := MayShutdown;
  if not MayShutdown then begin
    if      dword(messageBuf^) and EWX_LOGOFF <> 0 then s1 := 'You''re not allowed to log off.'
    else if dword(messageBuf^) and EWX_REBOOT <> 0 then s1 := 'You''re not allowed to restart Windows.'
    else                                                s1 := 'You''re not allowed to shutdown Windows.';
    log('ShutdownIpcQueue: '+s1);
  end;
end;
begin
  CreateIpcQueue('ShutdownIpcQueue', ShutdownIpcQueue);
  log('inject ok? ' + booltostr(InjectLibrary(ALL_SESSIONS or SYSTEM_PROCESSES, 'ShutdownHooks.dll'),true));
end.