345 lines
10 KiB
C
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;
|
|
}
|