{$A+,Z4}
const
PROCESS_QUERY_LIMITED_INFORMATION =
$1000
;
RstrtMgr =
'Rstrtmgr.dll'
;
RM_SESSION_KEY_LEN = SizeOf(TGUID);
CCH_RM_SESSION_KEY = RM_SESSION_KEY_LEN *
2
;
CCH_RM_MAX_APP_NAME =
255
;
CCH_RM_MAX_SVC_NAME =
63
;
RM_INVALID_TS_SESSION = -
1
;
RM_INVALID_PROCESS = -
1
;
type
TAppName =
array
[
0..
CCH_RM_MAX_APP_NAME]
of
WideChar
;
TServiceName =
array
[
0..
CCH_RM_MAX_SVC_NAME]
of
WideChar
;
TSessionKey =
array
[
0..
CCH_RM_SESSION_KEY]
of
WideChar
;
_RM_APP_TYPE = (
RmUnknownApp =
0
,
RmMainWindow =
1
,
RmOtherWindow =
2
,
RmService =
3
,
RmExplorer =
4
,
RmConsole =
5
,
RmCritical =
1000
);
RM_APP_TYPE = _RM_APP_TYPE;
TRMAppType = RM_APP_TYPE;
_RM_SHUTDOWN_TYPE = (
RmForceShutdown =
$1
,
RmShutdownOnlyRegistered =
$10
);
RM_SHUTDOWN_TYPE = _RM_SHUTDOWN_TYPE;
TRMShutdownType = RM_SHUTDOWN_TYPE;
_RM_APP_STATUS = (
RmStatusUnknown =
$0
,
RmStatusRunning =
$1
,
RmStatusStopped =
$2
,
RmStatusStoppedOther =
$4
,
RmStatusRestarted =
$8
,
RmStatusErrorOnStop =
$10
,
RmStatusErrorOnRestart =
$20
,
RmStatusShutdownMasked =
$40
,
RmStatusRestartMasked =
$80
);
RM_APP_STATUS = _RM_APP_STATUS;
TRMAppStatus = RM_APP_STATUS;
_RM_REBOOT_REASON = (
RmRebootReasonNone =
$0
,
RmRebootReasonPermissionDenied =
$1
,
RmRebootReasonSessionMismatch =
$2
,
RmRebootReasonCriticalProcess =
$4
,
RmRebootReasonCriticalService =
$8
,
RmRebootReasonDetectedSelf =
$10
);
RM_REBOOT_REASON = _RM_REBOOT_REASON;
TRMRebootReason = RM_REBOOT_REASON;
_RM_UNIQUE_PROCESS =
record
dwProcessId: DWORD;
ProcessStartTime: TFileTime;
end
;
RM_UNIQUE_PROCESS = _RM_UNIQUE_PROCESS;
PRM_UNIQUE_PROCESS = ^_RM_UNIQUE_PROCESS;
TRMUniqueProcess = RM_UNIQUE_PROCESS;
PRMUniqueProcess = PRM_UNIQUE_PROCESS;
_RM_PROCESS_INFO =
record
Process: TRMUniqueProcess;
strAppName: TAppName;
strServiceShortName: TServiceName;
ApplicationType: TRMAppType;
AppStatus: ULONG;
TSSessionId: DWORD;
bRestartable: BOOL;
end
;
RM_PROCESS_INFO = _RM_PROCESS_INFO;
PRM_PROCESS_INFO = ^_RM_PROCESS_INFO;
TRMProcessInfo = RM_PROCESS_INFO;
PRMProcessInfo = PRM_PROCESS_INFO;
function
QueryFullProcessImageName(hProcess: THandle; dwFlags: DWORD;
lpExeName:
PChar
;
var
lpdwSize:
Integer
): BOOL; stdcall; external kernel32
name
{$IFDEF UNICODE}'QueryFullProcessImageNameW'{$ELSE}'QueryFullProcessImageNameA'{$ENDIF}
;
function
RmStartSession(out pSessionHandle: DWORD; dwSessionFlags: DWORD;
out strSessionKey: TSessionKey): DWORD; stdcall; external RstrtMgr;
function
RmEndSession(dwSessionHandle: DWORD): DWORD; stdcall; external RstrtMgr;
function
RmRegisterResources(dwSessionHandle: DWORD; nFiles: UINT;
rgsFileNames:
PWideChar
; nApplications: UINT; rgApplications: PRMUniqueProcess;
nServices: UINT; rgsServiceNames: PPWideChar): DWORD; stdcall; external RstrtMgr;
function
RmGetList(dwSessionHandle: DWORD; out pnProcInfoNeeded: UINT;
var
pnProcInfo: UINT;
out rgAffectedApps: TRMProcessInfo; out lpdwRebootReasons: DWORD): DWORD; stdcall; external RstrtMgr;
procedure
TForm1
.
Button1Click(Sender: TObject);
function
StrFromAppType(
const
AAppType: TRMAppType):
String
;
begin
case
AAppType
of
RmMainWindow:
Result :=
'Application is a windows application that displays a top-level window'
;
RmOtherWindow:
Result :=
'Application is a windows app but does not display a top-level window'
;
RmService:
Result :=
'Application is an NT service'
;
RmExplorer:
Result :=
'Application is Explorer'
;
RmConsole:
Result :=
'Application is Console application'
;
RmCritical:
Result :=
'Application is critical system process where a reboot is required to restart'
;
else
Result :=
'Application type cannot be classified in known categories'
;
end
;
end
;
const
Num =
10
;
var
dwSession: DWORD;
szSessionKey: TSessionKey;
pszFile:
PWideChar
;
P:
PWideChar
;
FileName:
WideString
;
dwReason: DWORD;
i:
Integer
;
nProcInfoNeeded: UINT;
nProcInfo: UINT;
rgpi:
array
[
0..
Num-
1
]
of
TRMProcessInfo;
hProcess: THandle;
ftCreate, ftExit, ftKernel, ftUser: TFileTime;
sz:
String
;
cch:
Integer
;
begin
FileName :=
'c:\test.txt'
;
FillChar(szSessionKey, SizeOf(szSessionKey),
0
);
SetLastError(RmStartSession(dwSession,
0
, szSessionKey));
Win32Check(GetLastError = ERROR_SUCCESS);
try
P :=
PWideChar
(FileName);
pszFile := @P;
SetLastError(RmRegisterResources(dwSession,
1
, pszFile,
0
,
nil
,
0
,
nil
));
Win32Check(GetLastError = ERROR_SUCCESS);
nProcInfo := Num;
SetLastError(RmGetList(dwSession, nProcInfoNeeded, nProcInfo, rgpi[
0
], dwReason));
Win32Check(GetLastError = ERROR_SUCCESS);
for
i :=
0
to
nProcInfo -
1
do
begin
ShowMessage(Format(
'%d.ApplicationType = %d (%s)'
,
[i, Ord(rgpi[i].ApplicationType), StrFromAppType(rgpi[i].ApplicationType)]));
ShowMessage(Format(
'%d.strAppName = %s'
, [i, rgpi[i].strAppName]));
ShowMessage(Format(
'%d.Process.dwProcessId = %d'
, [i, rgpi[i].Process
.
dwProcessId]));
hProcess := OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,
False
, rgpi[i].Process
.
dwProcessId);
if
hProcess <>
0
then
try
if
GetProcessTimes(hProcess, ftCreate, ftExit, ftKernel, ftUser)
and
(CompareFileTime(rgpi[i].Process
.
ProcessStartTime, ftCreate) =
0
)
then
begin
cch := MAX_PATH;
SetLength(sz, cch);
if
QueryFullProcessImageName(hProcess,
0
,
PChar
(sz), cch)
and
(cch <= MAX_PATH)
then
begin
SetLength(sz, cch);
ShowMessage(Format(
'%d.Process.Name = %s'
, [i, sz]));
end
;
end
;
finally
CloseHandle(hProcess);
end
;
end
;
finally
RmEndSession(dwSession);
end
;
end
;