프로그래밍 초보 탈출

Libraries/Delphi Library

[System] System Power Control Library

째즈토끼 2022. 6. 23. 23:48
unit LibPowerSystem;

interface

uses
  Windows, SysUtils, TlHelp32, Forms, WinBase, Messages,
  LibProcessInfo;

procedure SYSTEM_Reboot(Force : Boolean);
procedure SYSTEM_PowerOff(Force : Boolean);
procedure SYSTEM_LogOff;

// 2010.11.25 JAZZ 추가
// Deny 횟수만큼 Allow 해야 실제로 Allow된다. 단 AllowForce인 경우 무조건 Allow.
procedure SYSTEM_DenySuspendMode;
procedure SYSTEM_AllowSuspendMode(const AllowForce: Boolean = FALSE);
function  SYSTEM_ON_WM_POWERBROADCAST(var M: TMessage) : Boolean;	// 메인 폼에서 메세지 Dispatcher에 이 함수 연결할것

// 2014.11.28 JAZZ 추가
function SYSTEM_Suspend(DisableWakeEvent: Boolean = FALSE): Boolean;	// 절전 모드
function SYSTEM_Hibernate(DisableWakeEvent: Boolean = FALSE): Boolean;	// 최대 절정 모드

{
=============================================================
Samples
=============================================================
type TForm1 = Class(TForm)
  ...
  procedure ON_WM_POWERBROADCAST(var M:TMessage); message WM_POWERBROADCAST;
  ...
  end;

...

procedure TForm1.ON_WM_POWERBROADCAST(var M: TMessage);
begin
  if not SYSTEM_ON_WM_POWERBROADCAST(M) then begin
     inherited;
     end;
end;
=============================================================
}

{$EXTERNALSYM SetSuspendState}
function SetSuspendState(Hibernate, ForceCritical, DisableWakeEvent: BOOLEAN): BOOLEAN; stdcall;
 

[System] Process Information Library

unit LibProcessInfo; interface uses Windows, WinBase, SysUtils, TlHelp32, PSAPI; type TProcessFindProc = function (ProcessInfo : PProcessEntry32; UserPara : Pointer) : BOOL; stdcall; TModuleFindProc..

jazz16.tistory.com

const
  powrprof_lib = 'powrprof.dll';

function SetSuspendState; external powrprof_lib name 'SetSuspendState';

const
   SystemProcessList_NT : Array[0..5] of String =
   (	'EXPLORER.EXE',	'SVCHOST.EXE',	'CISVC.EXE',	'CIDAEMON.EXE',
   	'SERVICES.EXE',	'WINLOGON.EXE'
   );

   SystemProcessList_98 : Array[0..10] of String =
   (	'EXPLORER.EXE',	'MPREXE.EXE',	'WMIEXE.EXE',	'MSTASK.EXE',
        'SYSTRAY.EXE',	'INTERNAT.EXE',	'TASKMON.EXE',	'IMEJP98M.EXE',
        'USER.EXE',	'MSGSRV32.EXE',	'KB891711.EXE'
   );


function SYSTEM_ActiveDesktopEnabled : Boolean;
begin
  Result := FindWindowEx(
            FindWindowEx(
            FindWindowEx(GetDesktopWindow, 0, 'Progman', nil),
            				   0, 'SHELLDLL_DefView', nil),
            				   0, 'Internet Explorer_Server', nil) <> 0;
end;

const
  DEBUG_MSG_BOX	= FALSE;

procedure SYSTEM_KillProcessByFilter(ExcludeFileList : Array of String;
		const ExcludeNonExeImage : Boolean = TRUE;
		const UserProcessOnlyOnNT : Boolean = TRUE);
var
  Process32	: TProcessEntry32;
  SHandle	: THandle;  // the handle of the Windows object
  RT		: BOOL;
  Ln, I		: Integer;
  EX		: Array of String;
  FileName	: String;
  CPID		: DWORD;
{$IF DEBUG_MSG_BOX}
  DL		: String;
{$IFEND}
begin
{$IF DEBUG_MSG_BOX}
  DL := '';
{$IFEND}
  Ln := Length(ExcludeFileList);
  SetLength(EX, Ln);
  if Ln > 0 then for I:=0 to Ln-1 do EX[I] := UpperCase(ExtractFileName(ExcludeFileList[I]));

  CPID			:= GetCurrentProcessID;
  Process32.dwSize	:= SizeOf(TProcessEntry32);
  SHandle		:= CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  RT			:= Process32First(SHandle, Process32);
  while RT do begin
    RT := Process32.th32ProcessID <> CPID;
    if RT then FileName := UpperCase(ExtractFileName(Process32.szExeFile));
    if RT and ExcludeNonExeImage then RT := ExtractFileExt(FileName) = '.EXE';
    if RT and (Ln > 0) then for I:=0 to Ln-1 do if EX[I] = FileName then RT := FALSE;

{$IF DEBUG_MSG_BOX}
    if RT then begin
       if KillProcess(Process32.th32ProcessID, UserProcessOnlyOnNT)
          then DL := DL + #13 + 'SUCC : ' + Process32.szExeFile
          else DL := DL + #13 + 'FAIL : ' + Process32.szExeFile;
       end;
{$ELSE}
    if RT then KillProcess(Process32.th32ProcessID, UserProcessOnlyOnNT);
{$IFEND}

    RT := Process32Next(SHandle, Process32);
    end;
  CloseHandle(SHandle);

{$IF DEBUG_MSG_BOX}
  MessageBox(0, PChar(DL), 'KillProcess Report', MB_OK);
{$IFEND}

end;
function SYSTEM_AccessNTPrivilege(Prvlg : PChar; ModeEnable : Boolean) : Boolean;
var
  Token : THandle;
  PRV, nPRV   : TTokenPrivileges;
begin
  PRV.PrivilegeCount := 1;
  if ModeEnable
     then PRV.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
     else PRV.Privileges[0].Attributes := 0;

  Result :=	OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, Token)
         and	LookupPrivilegeValue('', Prvlg, PRV.Privileges[0].LUID)
         and	Windows.AdjustTokenPrivileges(Token, False, PRV, SizeOf(TOKEN_PRIVILEGES), @nPRV, nPRV.PrivilegeCount);
end;

function SYSTEM_GetShutdownPrivilegeNT(ModeEnable : Boolean) : Boolean;
const
  SE_SHUTDOWN_NAME = 'SeShutdownPrivilege';
begin
  Result := SYSTEM_AccessNTPrivilege(SE_SHUTDOWN_NAME, ModeEnable);
end;
procedure SYSTEM_RebootNT(Force : Boolean);
var
  FLAG : DWORD;
begin
  if not SYSTEM_GetShutdownPrivilegeNT(TRUE) then Exit;

  FLAG := EWX_SHUTDOWN or EWX_REBOOT;
  if Force then begin
     if SYSTEM_ActiveDesktopEnabled
        then SYSTEM_KillProcessByFilter(SystemProcessList_NT, TRUE, TRUE)
        else FLAG := FLAG or EWX_FORCE;
     end;
  ExitWindowsEx(FLAG, 0);
end;

procedure SYSTEM_Reboot98(Force : Boolean);
var
  FLAG : DWORD;
begin
  FLAG := EW_REBOOTSYSTEM;
  if Force then SYSTEM_KillProcessByFilter(SystemProcessList_98, TRUE, TRUE);
  Application.ProcessMessages;
  Sleep(100);
  Application.ProcessMessages;
  ExitWindowsEx(FLAG, 0);
  Application.ProcessMessages;
  Sleep(100);
  Application.ProcessMessages;
//  Halt(0);
end;

procedure SYSTEM_Reboot(Force : Boolean);
begin
  if (Win32Platform = VER_PLATFORM_WIN32_NT)
     then SYSTEM_RebootNT(Force)
     else SYSTEM_Reboot98(Force);
end;
procedure SYSTEM_PowerOffNT(Force : Boolean);
var
  FLAG : DWORD;
begin
  if not SYSTEM_GetShutdownPrivilegeNT(TRUE) then Exit;

  FLAG := EWX_SHUTDOWN or EWX_POWEROFF;
  if Force then begin
     if SYSTEM_ActiveDesktopEnabled
        then SYSTEM_KillProcessByFilter(SystemProcessList_NT, TRUE, TRUE)
        else FLAG := FLAG or EWX_FORCE;
     end;
  ExitWindowsEx(FLAG, 0);
end;

procedure SYSTEM_PowerOff98(Force : Boolean);
var
  FLAG : DWORD;
begin
  FLAG := $0040 or EWX_SHUTDOWN;
  if Force then SYSTEM_KillProcessByFilter(SystemProcessList_98, TRUE, TRUE);
  Application.ProcessMessages;
  Sleep(100);
  Application.ProcessMessages;
  ExitWindowsEx(FLAG, 0);
  Application.ProcessMessages;
  Sleep(100);
  Application.ProcessMessages;
//  Halt(0);
end;

procedure SYSTEM_PowerOff(Force : Boolean);
begin
  if (Win32Platform = VER_PLATFORM_WIN32_NT)
     then SYSTEM_PowerOffNT(Force)
     else SYSTEM_PowerOff98(Force);
end;
procedure SYSTEM_LogOffNT;
begin
  ExitWindowsEx(EWX_LOGOFF, 0);
end;

procedure SYSTEM_LogOff98;
begin
  ExitWindowsEx($0040 or EWX_LOGOFF, 0);
end;

procedure SYSTEM_LogOff;
begin
  if (Win32Platform = VER_PLATFORM_WIN32_NT)
     then SYSTEM_LogOffNT()
     else SYSTEM_LogOff98();
end;
// 2010.11.25 JAZZ 추가
// Deny 횟수만큼 Allow 해야 실제로 Allow된다.
var
  __DenySuspendTag : Integer;

procedure __LockPowerSuspend;
begin
  // 대기모드/최대절전모드 진입금지
  try SetThreadExecutionState(ES_CONTINUOUS or ES_SYSTEM_REQUIRED or ES_AWAYMODE_REQUIRED { or ES_DISPLAY_REQUIRED });
      except
      end;
end;

procedure __ReleasePowerSuspend;
begin
  // 대기모드/최대절전모드 진입허용
  try SetThreadExecutionState(ES_CONTINUOUS);
      except
      end;
end;

procedure SYSTEM_DenySuspendMode;
begin
  // 굳이 크리티컬 처리를 할 필요는 없을듯... 쓰레드내에서 호출하지 마라!!!
  Inc(__DenySuspendTag);
  if __DenySuspendTag = 1 then begin
     __LockPowerSuspend();
     end;
end;

procedure SYSTEM_AllowSuspendMode(const AllowForce: Boolean = FALSE);
begin
  if __DenySuspendTag < 1 then Exit;
  if AllowForce
     then __DenySuspendTag := 0
     else Dec(__DenySuspendTag);
     
  if __DenySuspendTag = 0 then begin
     __ReleasePowerSuspend();
     end;
end;
function  SYSTEM_ON_WM_POWERBROADCAST(var M: TMessage) : Boolean;	// 메인 폼에서 메세지 Dispatcher에 이 함수 연결할것
const
  PBT_APMQUERYSUSPEND = $00000000;
begin
  RESULT := FALSE;
  case M.WParam of
     // Vista 이상에서는 들어오지 않는다. ( SetThreadExecutionState 사용 )
     PBT_APMQUERYSUSPEND : begin
	 if __DenySuspendTag > 0
	    then M.Result := BROADCAST_QUERY_DENY
	    else M.Result := Integer(TRUE);
	 RESULT := TRUE;
	 end;
     end;
end;

// 2014.11.28 JAZZ 추가
function SYSTEM_Suspend(DisableWakeEvent: Boolean = FALSE): Boolean;	// 절전 모드
begin
  RESULT := FALSE;
  if (Win32Platform <> VER_PLATFORM_WIN32_NT) then Exit;
  if not SYSTEM_GetShutdownPrivilegeNT(TRUE) then Exit;
  RESULT := SetSuspendState(FALSE, TRUE, DisableWakeEvent);
end;

// 2014.11.28 JAZZ 추가
function SYSTEM_Hibernate(DisableWakeEvent: Boolean = FALSE): Boolean;	// 최대 절정 모드
begin
  RESULT := FALSE;
  if (Win32Platform <> VER_PLATFORM_WIN32_NT) then Exit;
  if not SYSTEM_GetShutdownPrivilegeNT(TRUE) then Exit;
  RESULT := SetSuspendState(TRUE, TRUE, DisableWakeEvent);
end;

end.

'Libraries > Delphi Library' 카테고리의 다른 글

[String] Wide String Library  (0) 2022.06.24
[String] String Library  (0) 2022.06.24
[System] OS Version Library  (0) 2022.06.23
[OLE] OLE Command Library  (0) 2022.06.23
[IPC] Mutex Library  (0) 2022.06.22