Skip to content

Commit e195256

Browse files
committed
Fix service changes not being reflected when NonPoll disabled
1 parent 1c57301 commit e195256

File tree

1 file changed

+80
-5
lines changed

1 file changed

+80
-5
lines changed

ProcessHacker/srvprv.c

Lines changed: 80 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* service provider
44
*
55
* Copyright (C) 2009-2015 wj32
6-
* Copyright (C) 2017 dmex
6+
* Copyright (C) 2017-2021 dmex
77
*
88
* This file is part of Process Hacker.
99
*
@@ -69,7 +69,8 @@ typedef struct _PHP_SERVICE_NOTIFY_CONTEXT
6969
{
7070
BOOLEAN IsServiceManager : 1;
7171
BOOLEAN JustAddedNotifyRegistration : 1;
72-
BOOLEAN Spare : 6;
72+
BOOLEAN NonPollDisabled : 1;
73+
BOOLEAN Spare : 5;
7374
};
7475
};
7576
PHP_SERVICE_NOTIFY_STATE State;
@@ -124,6 +125,11 @@ VOID PhpRemoveProcessItemService(
124125
_In_ PPH_SERVICE_ITEM ServiceItem
125126
);
126127

128+
VOID PhpSubscribeServiceChangeNotifications(
129+
_In_ SC_HANDLE ScManagerHandle,
130+
_In_ PPH_SERVICE_ITEM ServiceItem
131+
);
132+
127133
VOID PhpInitializeServiceNonPoll(
128134
VOID
129135
);
@@ -161,6 +167,17 @@ BOOLEAN PhServiceProviderInitialization(
161167

162168
RtlInitializeSListHead(&PhpServiceQueryDataListHead);
163169

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+
164181
return TRUE;
165182
}
166183

@@ -863,9 +880,13 @@ VOID PhServiceProviderUpdate(
863880
// Create the service item and fill in basic information.
864881

865882
serviceItem = PhCreateServiceItem(serviceEntry);
866-
867883
PhpUpdateServiceItemConfig(scManagerHandle, serviceItem);
868884

885+
if (!PhEnableServiceNonPoll)
886+
{
887+
PhpSubscribeServiceChangeNotifications(scManagerHandle, serviceItem);
888+
}
889+
869890
// Add the service to its process, if appropriate.
870891
if (
871892
(
@@ -1119,7 +1140,9 @@ VOID PhpDestroyServiceNotifyContext(
11191140
if (NotifyContext->Buffer.pszServiceNames)
11201141
LocalFree(NotifyContext->Buffer.pszServiceNames);
11211142

1122-
CloseServiceHandle(NotifyContext->ServiceHandle);
1143+
if (NotifyContext->ServiceHandle)
1144+
CloseServiceHandle(NotifyContext->ServiceHandle);
1145+
11231146
PhClearReference(&NotifyContext->ServiceName);
11241147
PhFree(NotifyContext);
11251148
}
@@ -1132,10 +1155,17 @@ VOID CALLBACK PhpServicePropertyChangeNotifyCallback(
11321155
PPHP_SERVICE_NOTIFY_CONTEXT notifyContext = Context;
11331156
PPH_SERVICE_ITEM serviceItem;
11341157

1135-
// Note: Ignore deleted nofications since we handle this elsewhere and our
1158+
// Note: Ignore deleted nofications since NonPoll handles these elsewhere and our
11361159
// notify context gets destroyed before services.exe invokes this callback. (dmex)
11371160
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+
}
11381167
return;
1168+
}
11391169

11401170
if (!notifyContext)
11411171
return;
@@ -1157,6 +1187,51 @@ VOID CALLBACK PhpServicePropertyChangeNotifyCallback(
11571187
}
11581188
}
11591189

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+
11601235
NTSTATUS PhpServiceNonPollThreadStart(
11611236
_In_ PVOID Parameter
11621237
)

0 commit comments

Comments
 (0)