2025-05-13 19:45:22 +03:00

345 lines
10 KiB
C

/*
* Process Hacker Extended Services -
* dependencies and dependents
*
* Copyright (C) 2010 wj32
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "extsrv.h"
typedef struct _SERVICE_LIST_CONTEXT
{
HWND ServiceListHandle;
PH_LAYOUT_MANAGER LayoutManager;
} SERVICE_LIST_CONTEXT, *PSERVICE_LIST_CONTEXT;
LPENUM_SERVICE_STATUS EsEnumDependentServices(
_In_ SC_HANDLE ServiceHandle,
_In_opt_ ULONG State,
_Out_ PULONG Count
)
{
LOGICAL result;
PVOID buffer;
ULONG bufferSize;
ULONG returnLength;
ULONG servicesReturned;
if (!State)
State = SERVICE_STATE_ALL;
bufferSize = 0x800;
buffer = PhAllocate(bufferSize);
if (!(result = EnumDependentServices(
ServiceHandle,
State,
buffer,
bufferSize,
&returnLength,
&servicesReturned
)))
{
if (GetLastError() == ERROR_MORE_DATA)
{
PhFree(buffer);
bufferSize = returnLength;
buffer = PhAllocate(bufferSize);
result = EnumDependentServices(
ServiceHandle,
State,
buffer,
bufferSize,
&returnLength,
&servicesReturned
);
}
if (!result)
{
PhFree(buffer);
return NULL;
}
}
*Count = servicesReturned;
return buffer;
}
VOID EspLayoutServiceListControl(
_In_ HWND hwndDlg,
_In_ HWND ServiceListHandle
)
{
RECT rect;
GetWindowRect(GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), &rect);
MapWindowPoints(NULL, hwndDlg, (POINT *)&rect, 2);
MoveWindow(
ServiceListHandle,
rect.left,
rect.top,
rect.right - rect.left,
rect.bottom - rect.top,
TRUE
);
}
INT_PTR CALLBACK EspServiceDependenciesDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
PSERVICE_LIST_CONTEXT context;
if (uMsg == WM_INITDIALOG)
{
context = PhAllocate(sizeof(SERVICE_LIST_CONTEXT));
memset(context, 0, sizeof(SERVICE_LIST_CONTEXT));
SetProp(hwndDlg, L"Context", (HANDLE)context);
}
else
{
context = (PSERVICE_LIST_CONTEXT)GetProp(hwndDlg, L"Context");
if (uMsg == WM_DESTROY)
RemoveProp(hwndDlg, L"Context");
}
if (!context)
return FALSE;
switch (uMsg)
{
case WM_INITDIALOG:
{
LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam;
PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)propSheetPage->lParam;
HWND serviceListHandle;
PPH_LIST serviceList;
SC_HANDLE serviceHandle;
ULONG win32Result = 0;
BOOLEAN success = FALSE;
PPH_SERVICE_ITEM *services;
SetDlgItemText(hwndDlg, IDC_MESSAGE, L"This service depends on the following services:");
PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), NULL, PH_ANCHOR_ALL);
if (serviceHandle = PhOpenService(serviceItem->Name->Buffer, SERVICE_QUERY_CONFIG))
{
LPQUERY_SERVICE_CONFIG serviceConfig;
if (serviceConfig = PhGetServiceConfig(serviceHandle))
{
PWSTR dependency;
PPH_SERVICE_ITEM dependencyService;
dependency = serviceConfig->lpDependencies;
serviceList = PH_AUTO(PhCreateList(8));
success = TRUE;
if (dependency)
{
ULONG dependencyLength;
while (TRUE)
{
dependencyLength = (ULONG)PhCountStringZ(dependency);
if (dependencyLength == 0)
break;
if (dependency[0] == SC_GROUP_IDENTIFIER)
goto ContinueLoop;
if (dependencyService = PhReferenceServiceItem(dependency))
PhAddItemList(serviceList, dependencyService);
ContinueLoop:
dependency += dependencyLength + 1;
}
}
services = PhAllocateCopy(serviceList->Items, sizeof(PPH_SERVICE_ITEM) * serviceList->Count);
serviceListHandle = PhCreateServiceListControl(hwndDlg, services, serviceList->Count);
context->ServiceListHandle = serviceListHandle;
EspLayoutServiceListControl(hwndDlg, serviceListHandle);
ShowWindow(serviceListHandle, SW_SHOW);
PhFree(serviceConfig);
}
else
{
win32Result = GetLastError();
}
CloseServiceHandle(serviceHandle);
}
else
{
win32Result = GetLastError();
}
if (!success)
{
SetDlgItemText(hwndDlg, IDC_SERVICES_LAYOUT, PhaConcatStrings2(L"Unable to enumerate dependencies: ",
((PPH_STRING)PH_AUTO(PhGetWin32Message(win32Result)))->Buffer)->Buffer);
ShowWindow(GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), SW_SHOW);
}
}
break;
case WM_DESTROY:
{
PhDeleteLayoutManager(&context->LayoutManager);
PhFree(context);
}
break;
case WM_SIZE:
{
PhLayoutManagerLayout(&context->LayoutManager);
if (context->ServiceListHandle)
EspLayoutServiceListControl(hwndDlg, context->ServiceListHandle);
}
break;
}
return FALSE;
}
INT_PTR CALLBACK EspServiceDependentsDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
PSERVICE_LIST_CONTEXT context;
if (uMsg == WM_INITDIALOG)
{
context = PhAllocate(sizeof(SERVICE_LIST_CONTEXT));
memset(context, 0, sizeof(SERVICE_LIST_CONTEXT));
SetProp(hwndDlg, L"Context", (HANDLE)context);
}
else
{
context = (PSERVICE_LIST_CONTEXT)GetProp(hwndDlg, L"Context");
if (uMsg == WM_DESTROY)
RemoveProp(hwndDlg, L"Context");
}
if (!context)
return FALSE;
switch (uMsg)
{
case WM_INITDIALOG:
{
LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam;
PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)propSheetPage->lParam;
HWND serviceListHandle;
PPH_LIST serviceList;
SC_HANDLE serviceHandle;
ULONG win32Result = 0;
BOOLEAN success = FALSE;
PPH_SERVICE_ITEM *services;
SetDlgItemText(hwndDlg, IDC_MESSAGE, L"The following services depend on this service:");
PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), NULL, PH_ANCHOR_ALL);
if (serviceHandle = PhOpenService(serviceItem->Name->Buffer, SERVICE_ENUMERATE_DEPENDENTS))
{
LPENUM_SERVICE_STATUS dependentServices;
ULONG numberOfDependentServices;
if (dependentServices = EsEnumDependentServices(serviceHandle, 0, &numberOfDependentServices))
{
ULONG i;
PPH_SERVICE_ITEM dependentService;
serviceList = PH_AUTO(PhCreateList(8));
success = TRUE;
for (i = 0; i < numberOfDependentServices; i++)
{
if (dependentService = PhReferenceServiceItem(dependentServices[i].lpServiceName))
PhAddItemList(serviceList, dependentService);
}
services = PhAllocateCopy(serviceList->Items, sizeof(PPH_SERVICE_ITEM) * serviceList->Count);
serviceListHandle = PhCreateServiceListControl(hwndDlg, services, serviceList->Count);
context->ServiceListHandle = serviceListHandle;
EspLayoutServiceListControl(hwndDlg, serviceListHandle);
ShowWindow(serviceListHandle, SW_SHOW);
PhFree(dependentServices);
}
else
{
win32Result = GetLastError();
}
CloseServiceHandle(serviceHandle);
}
else
{
win32Result = GetLastError();
}
if (!success)
{
SetDlgItemText(hwndDlg, IDC_SERVICES_LAYOUT, PhaConcatStrings2(L"Unable to enumerate dependents: ",
((PPH_STRING)PH_AUTO(PhGetWin32Message(win32Result)))->Buffer)->Buffer);
ShowWindow(GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), SW_SHOW);
}
}
break;
case WM_DESTROY:
{
PhDeleteLayoutManager(&context->LayoutManager);
PhFree(context);
}
break;
case WM_SIZE:
{
PhLayoutManagerLayout(&context->LayoutManager);
if (context->ServiceListHandle)
EspLayoutServiceListControl(hwndDlg, context->ServiceListHandle);
}
break;
}
return FALSE;
}