3
3
* service provider
4
4
*
5
5
* Copyright (C) 2009-2015 wj32
6
- * Copyright (C) 2017 dmex
6
+ * Copyright (C) 2017-2021 dmex
7
7
*
8
8
* This file is part of Process Hacker.
9
9
*
@@ -69,7 +69,8 @@ typedef struct _PHP_SERVICE_NOTIFY_CONTEXT
69
69
{
70
70
BOOLEAN IsServiceManager : 1 ;
71
71
BOOLEAN JustAddedNotifyRegistration : 1 ;
72
- BOOLEAN Spare : 6 ;
72
+ BOOLEAN NonPollDisabled : 1 ;
73
+ BOOLEAN Spare : 5 ;
73
74
};
74
75
};
75
76
PHP_SERVICE_NOTIFY_STATE State ;
@@ -124,6 +125,11 @@ VOID PhpRemoveProcessItemService(
124
125
_In_ PPH_SERVICE_ITEM ServiceItem
125
126
);
126
127
128
+ VOID PhpSubscribeServiceChangeNotifications (
129
+ _In_ SC_HANDLE ScManagerHandle ,
130
+ _In_ PPH_SERVICE_ITEM ServiceItem
131
+ );
132
+
127
133
VOID PhpInitializeServiceNonPoll (
128
134
VOID
129
135
);
@@ -161,6 +167,17 @@ BOOLEAN PhServiceProviderInitialization(
161
167
162
168
RtlInitializeSListHead (& PhpServiceQueryDataListHead );
163
169
170
+ if (WindowsVersion >= WINDOWS_8 )
171
+ {
172
+ PVOID sechostHandle ;
173
+
174
+ if (sechostHandle = PhLoadLibrary (L"sechost.dll" ))
175
+ {
176
+ SubscribeServiceChangeNotifications_I = PhGetDllBaseProcedureAddress (sechostHandle , "SubscribeServiceChangeNotifications" , 0 );
177
+ UnsubscribeServiceChangeNotifications_I = PhGetDllBaseProcedureAddress (sechostHandle , "UnsubscribeServiceChangeNotifications" , 0 );
178
+ }
179
+ }
180
+
164
181
return TRUE;
165
182
}
166
183
@@ -863,9 +880,13 @@ VOID PhServiceProviderUpdate(
863
880
// Create the service item and fill in basic information.
864
881
865
882
serviceItem = PhCreateServiceItem (serviceEntry );
866
-
867
883
PhpUpdateServiceItemConfig (scManagerHandle , serviceItem );
868
884
885
+ if (!PhEnableServiceNonPoll )
886
+ {
887
+ PhpSubscribeServiceChangeNotifications (scManagerHandle , serviceItem );
888
+ }
889
+
869
890
// Add the service to its process, if appropriate.
870
891
if (
871
892
(
@@ -1119,7 +1140,9 @@ VOID PhpDestroyServiceNotifyContext(
1119
1140
if (NotifyContext -> Buffer .pszServiceNames )
1120
1141
LocalFree (NotifyContext -> Buffer .pszServiceNames );
1121
1142
1122
- CloseServiceHandle (NotifyContext -> ServiceHandle );
1143
+ if (NotifyContext -> ServiceHandle )
1144
+ CloseServiceHandle (NotifyContext -> ServiceHandle );
1145
+
1123
1146
PhClearReference (& NotifyContext -> ServiceName );
1124
1147
PhFree (NotifyContext );
1125
1148
}
@@ -1132,10 +1155,17 @@ VOID CALLBACK PhpServicePropertyChangeNotifyCallback(
1132
1155
PPHP_SERVICE_NOTIFY_CONTEXT notifyContext = Context ;
1133
1156
PPH_SERVICE_ITEM serviceItem ;
1134
1157
1135
- // Note: Ignore deleted nofications since we handle this elsewhere and our
1158
+ // Note: Ignore deleted nofications since NonPoll handles these elsewhere and our
1136
1159
// notify context gets destroyed before services.exe invokes this callback. (dmex)
1137
1160
if (ServiceNotifyFlags == SERVICE_NOTIFY_DELETED )
1161
+ {
1162
+ // Note: We can handle delete notifications only when NonPoll is disabled. (dmex)
1163
+ if (notifyContext && notifyContext -> NonPollDisabled )
1164
+ {
1165
+ PhpDestroyServiceNotifyContext (notifyContext );
1166
+ }
1138
1167
return ;
1168
+ }
1139
1169
1140
1170
if (!notifyContext )
1141
1171
return ;
@@ -1157,6 +1187,51 @@ VOID CALLBACK PhpServicePropertyChangeNotifyCallback(
1157
1187
}
1158
1188
}
1159
1189
1190
+ VOID PhpSubscribeServiceChangeNotifications (
1191
+ _In_ SC_HANDLE ScManagerHandle ,
1192
+ _In_ PPH_SERVICE_ITEM ServiceItem
1193
+ )
1194
+ {
1195
+ PSC_NOTIFICATION_REGISTRATION serviceNotifyRegistration ;
1196
+ PPHP_SERVICE_NOTIFY_CONTEXT notifyContext ;
1197
+ SC_HANDLE serviceHandle ;
1198
+
1199
+ if (!SubscribeServiceChangeNotifications_I )
1200
+ return ;
1201
+
1202
+ serviceHandle = OpenService (
1203
+ ScManagerHandle ,
1204
+ PhGetStringOrEmpty (ServiceItem -> Name ),
1205
+ SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG
1206
+ );
1207
+
1208
+ if (!serviceHandle )
1209
+ return ;
1210
+
1211
+ notifyContext = PhAllocateZero (sizeof (PHP_SERVICE_NOTIFY_CONTEXT ));
1212
+ notifyContext -> ServiceName = PhReferenceObject (ServiceItem -> Name );
1213
+ notifyContext -> JustAddedNotifyRegistration = TRUE;
1214
+ notifyContext -> NonPollDisabled = TRUE;
1215
+
1216
+ if (SubscribeServiceChangeNotifications_I (
1217
+ serviceHandle ,
1218
+ SC_EVENT_PROPERTY_CHANGE ,
1219
+ PhpServicePropertyChangeNotifyCallback ,
1220
+ notifyContext ,
1221
+ & serviceNotifyRegistration
1222
+ ) == ERROR_SUCCESS )
1223
+ {
1224
+ notifyContext -> NotifyRegistration = serviceNotifyRegistration ;
1225
+ }
1226
+ else
1227
+ {
1228
+ PhDereferenceObject (notifyContext -> ServiceName );
1229
+ PhFree (notifyContext );
1230
+ }
1231
+
1232
+ CloseServiceHandle (serviceHandle );
1233
+ }
1234
+
1160
1235
NTSTATUS PhpServiceNonPollThreadStart (
1161
1236
_In_ PVOID Parameter
1162
1237
)
0 commit comments