forked from jrsoftware/issrc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRestartManager.pas
178 lines (129 loc) · 4.58 KB
/
RestartManager.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
unit RestartManager;
{
Basic RestartManager API interface unit by Martijn Laan
}
interface
uses
ActiveX, Windows;
procedure FreeRestartManagerLibrary;
function InitRestartManagerLibrary: Boolean;
function UseRestartManager: Boolean;
const
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
RM_APP_TYPE = DWORD;
const
RmUnknownApp = 0;
RmMainWindow = 1;
RmOtherWindow = 2;
RmService = 3;
RmExplorer = 4;
RmConsole = 5;
RmCritical = 1000;
type
RM_SHUTDOWN_TYPE = DWORD;
const
RmForceShutdown = $01;
RmShutdownOnlyRegistered = $10;
//RM_APP_STATUS
type
RM_REBOOT_REASON = DWORD;
const
RmRebootReasonNone = $0;
RmRebootReasonPermissionDenied = $1;
RmRebootReasonSessionMismatch = $2;
RmRebootReasonCriticalProcess = $4;
RmRebootReasonCriticalService = $8;
RmRebootReasonDetectedSelf = $10;
type
RM_UNIQUE_PROCESS = record
dwProcessId: DWORD;
ProcessStartTime: TFileTime;
end;
RM_PROCESS_INFO = record
Process: RM_UNIQUE_PROCESS;
strAppName: array[0..CCH_RM_MAX_APP_NAME] of WideChar;
strServiceShortName: array[0..CCH_RM_MAX_SVC_NAME] of WideChar;
ApplicationType: RM_APP_TYPE;
AppStatus: ULONG;
TSSessionId: DWORD;
bRestartable: BOOL;
end;
//RM_FILTER_TRIGGER
//RM_FILTER_ACTION
//RM_FILTER_INFO
//RM_WRITE_STATUS_CALLBACK
var
RmStartSession: function (pSessionHandle: LPDWORD; dwSessionFlags: DWORD; strSessionKey: LPWSTR): DWORD; stdcall;
RmRegisterResources: function (dwSessionHandle: DWORD; nFiles: UINT; rgsFilenames: Pointer; nApplications: UINT; rgApplications: Pointer; nServices: UINT; rgsServiceNames: Pointer): DWORD; stdcall;
RmGetList: function (dwSessionHandle: DWORD; pnProcInfoNeeded, pnProcInfo: PUINT; rgAffectedApps: Pointer; lpdwRebootReasons: LPDWORD): DWORD; stdcall;
RmShutdown: function (dwSessionHandle: DWORD; lActionFlags: ULONG; fnStatus: Pointer): DWORD; stdcall;
RmRestart: function (dwSessionHandle: DWORD; dwRestartFlags: DWORD; fnStatus: Pointer): DWORD; stdcall;
RmEndSession: function (dwSessionHandle: DWORD): DWORD; stdcall;
implementation
//----------------------------------------------------------------------------------------------------------------------
uses
SysUtils, PathFunc;
const
restartmanagerlib = 'Rstrtmgr.dll';
var
RestartManagerLibrary: THandle;
ReferenceCount: Integer; // We have to keep track of several load/unload calls.
procedure FreeRestartManagerLibrary;
begin
if ReferenceCount > 0 then
Dec(ReferenceCount);
if (RestartManagerLibrary <> 0) and (ReferenceCount = 0) then
begin
FreeLibrary(RestartManagerLibrary);
RestartManagerLibrary := 0;
RmStartSession := nil;
RmRegisterResources := nil;
RmGetList := nil;
RmShutdown := nil;
RmRestart := nil;
RmEndSession := nil;
end;
end;
//----------------------------------------------------------------------------------------------------------------------
function InitRestartManagerLibrary: Boolean;
function GetSystemDir: String;
var
Buf: array[0..MAX_PATH-1] of Char;
begin
GetSystemDirectory(Buf, SizeOf(Buf) div SizeOf(Buf[0]));
Result := StrPas(Buf);
end;
begin
Inc(ReferenceCount);
if RestartManagerLibrary = 0 then
begin
RestartManagerLibrary := LoadLibrary(PChar(AddBackslash(GetSystemDir) + restartmanagerlib));
if RestartManagerLibrary <> 0 then
begin
RmStartSession := GetProcAddress(RestartManagerLibrary, 'RmStartSession');
RmRegisterResources := GetProcAddress(RestartManagerLibrary, 'RmRegisterResources');
RmGetList := GetProcAddress(RestartManagerLibrary, 'RmGetList');
RmShutdown := GetProcAddress(RestartManagerLibrary, 'RmShutdown');
RmRestart := GetProcAddress(RestartManagerLibrary, 'RmRestart');
RmEndSession := GetProcAddress(RestartManagerLibrary, 'RmEndSession');
end;
end;
Result := RestartManagerLibrary <> 0;
end;
//----------------------------------------------------------------------------------------------------------------------
function UseRestartManager: Boolean;
begin
Result := RestartManagerLibrary <> 0;
end;
//----------------------------------------------------------------------------------------------------------------------
initialization
finalization
while ReferenceCount > 0 do
FreeRestartManagerLibrary;
end.