2025-11-28 00:35:46 +09:00

314 lines
11 KiB
C

//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved
//
#include "WindowsServiceProcess.h"
#define MSFT_WINDOWS_PROCESS L"MSFT_WindowsProcess"
#define MSFT_WINDOWS_SERVICE L"MSFT_WindowsService"
void GetServiceInstances(_In_ MI_Context* context, _In_opt_z_ const MI_Char* nameSpace, _In_ MI_Uint32 handleID,
_In_opt_ const MI_Instance *existingEndPoint)
{
SC_HANDLE hSvcCtlMgr;
BOOL returnValue;
LPENUM_SERVICE_STATUS_PROCESS pServiceList = NULL ;
MI_Uint32 dwByteCount = 0, hEnumHandle = 0 , dwEntryCount = 0 , iCount = 0;
MI_Char queryString[MAX_PATH*4], tempQueryString[MAX_PATH];
MI_Boolean bFirst = MI_TRUE;
HRESULT hr = StringCchPrintf(queryString, MAX_PATH*4,L"Select * from MSFT_WindowsService");
if( FAILED(hr) )
{
MI_Context_PostResult(context, ResultFromWin32Error(HRESULT_TO_WIN32(hr)));
return;
}
hSvcCtlMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_CONNECT);
if (hSvcCtlMgr == NULL)
{
// Cannot get access to SCManager object.
MI_Context_PostResult(context, ResultFromWin32Error(GetLastError()));
return;
}
returnValue = EnumServicesStatusEx(
hSvcCtlMgr,
SC_ENUM_PROCESS_INFO,
SERVICE_WIN32,
SERVICE_ACTIVE | SERVICE_INACTIVE,
( LPBYTE ) pServiceList,
dwByteCount,
(LPDWORD)&dwByteCount,
(LPDWORD)&dwEntryCount,
(LPDWORD)&hEnumHandle,
NULL );
if (!returnValue)
{
MI_Uint32 lastError = GetLastError();
if ((lastError == ERROR_INSUFFICIENT_BUFFER) || (lastError == ERROR_MORE_DATA))
{
pServiceList = (LPENUM_SERVICE_STATUS_PROCESS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwByteCount);
if( pServiceList == NULL )
{
CloseServiceHandle(hSvcCtlMgr);
MI_Context_PostResult(context, MI_RESULT_FAILED);
return;
}
memset(pServiceList, 0, dwByteCount) ;
returnValue = EnumServicesStatusEx(
hSvcCtlMgr,
SC_ENUM_PROCESS_INFO,
SERVICE_WIN32,
SERVICE_ACTIVE | SERVICE_INACTIVE,
( LPBYTE ) pServiceList,
dwByteCount,
(LPDWORD)&dwByteCount,
(LPDWORD)&dwEntryCount,
(LPDWORD)&hEnumHandle,
NULL );
if( !returnValue)
{
HeapFree(GetProcessHeap(), 0, pServiceList);
CloseServiceHandle(hSvcCtlMgr);
MI_Context_PostResult(context, MI_RESULT_FAILED);
return;
}
}
else
{
CloseServiceHandle(hSvcCtlMgr);
MI_Context_PostResult(context, MI_RESULT_FAILED);
return;
}
}
else
{
CloseServiceHandle(hSvcCtlMgr);
MI_Context_PostResult(context, MI_RESULT_FAILED);
return;
}
// Enumerating through all services and finding the ones which has process ID = handleID
for( iCount = 0 ; iCount< dwEntryCount ; iCount++)
{
if( pServiceList[iCount].ServiceStatusProcess.dwProcessId == handleID )
{
if( bFirst )
{
hr = StringCchPrintfW(tempQueryString, MAX_PATH,L" where Name=\"%s\"", pServiceList[iCount].lpServiceName);
bFirst = MI_FALSE;
}
else
{
hr = StringCchPrintfW(tempQueryString, MAX_PATH,L" or Name=\"%s\"", pServiceList[iCount].lpServiceName);
}
if( FAILED(hr) )
{
HeapFree(GetProcessHeap(), 0, pServiceList);
CloseServiceHandle(hSvcCtlMgr);
MI_Context_PostResult(context, MI_RESULT_FAILED);
return;
}
hr = StringCchCatW(queryString, MAX_PATH*4,tempQueryString);
if( FAILED(hr) )
{
HeapFree(GetProcessHeap(), 0, pServiceList);
CloseServiceHandle(hSvcCtlMgr);
MI_Context_PostResult(context, MI_RESULT_FAILED);
return;
}
}
}
if( bFirst ) // no matching instance
{
MI_Context_PostResult(context, MI_RESULT_OK);
}
else
{
GetInstances(context, nameSpace, queryString, existingEndPoint , MI_TRUE);
}
HeapFree(GetProcessHeap(), 0, pServiceList);
CloseServiceHandle(hSvcCtlMgr);
}
void GetProcessInstances(_In_ MI_Context* context, _In_opt_z_ const MI_Char* nameSpace, _In_z_ const MI_Char* serviceName,
_In_opt_ const MI_Instance *existingEndPoint)
{
SC_HANDLE hSvcCtlMgr, hSvcHandle;
BOOL returnValue;
SERVICE_STATUS_PROCESS StatusInfo ;
MI_Uint32 dwBytesNeeded = 0;
MI_Char queryString[MAX_PATH], tempQueryString[MAX_PATH];
HRESULT hr = StringCchPrintf(queryString, MAX_PATH,L"Select * from MSFT_WindowsProcess");
if( FAILED(hr) )
{
MI_Context_PostResult(context, ResultFromWin32Error(HRESULT_TO_WIN32(hr)));
return;
}
hSvcCtlMgr = OpenSCManager(NULL, NULL, GENERIC_READ);
if (hSvcCtlMgr == NULL)
{
// Cannot get access to SCManager object.
MI_Context_PostResult(context, ResultFromWin32Error(GetLastError()));
return;
}
hSvcHandle = OpenService(hSvcCtlMgr, serviceName, SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_INTERROGATE );
if (hSvcHandle == NULL)
{
// Cannot get access to SCManager object.
CloseServiceHandle(hSvcCtlMgr);
MI_Context_PostResult(context, ResultFromWin32Error(GetLastError()));
return;
}
returnValue = QueryServiceStatusEx( hSvcHandle,
SC_STATUS_PROCESS_INFO,
( UCHAR * ) &StatusInfo ,
sizeof ( StatusInfo ) ,
(LPDWORD)&dwBytesNeeded );
if( !returnValue)
{
CloseServiceHandle(hSvcCtlMgr);
CloseServiceHandle(hSvcHandle);
MI_Context_PostResult(context, ResultFromWin32Error(GetLastError()));
return;
}
hr = StringCchPrintfW(tempQueryString, MAX_PATH,L" where Handle=\"%d\"", StatusInfo.dwProcessId);
if( FAILED(hr) )
{
CloseServiceHandle(hSvcCtlMgr);
CloseServiceHandle(hSvcHandle);
MI_Context_PostResult(context, MI_RESULT_FAILED);
return;
}
hr = StringCchCatW(queryString, MAX_PATH,tempQueryString);
if( FAILED(hr) )
{
CloseServiceHandle(hSvcCtlMgr);
CloseServiceHandle(hSvcHandle);
MI_Context_PostResult(context, MI_RESULT_FAILED);
return;
}
GetInstances(context, nameSpace, queryString, existingEndPoint, MI_FALSE);
CloseServiceHandle(hSvcCtlMgr);
CloseServiceHandle(hSvcHandle);
}
void GetInstances(_In_ MI_Context* context, _In_opt_z_ const MI_Char* nameSpace, _In_z_ const MI_Char* queryString,
_In_opt_ const MI_Instance *existingEndPoint, _In_ MI_Boolean bExistingEndPointIsProcessObject)
{
MI_Session localSession = MI_SESSION_NULL;
MI_Result result = MI_RESULT_OK;
MI_Boolean moreResults = MI_FALSE;
MI_Operation miOperation = MI_OPERATION_NULL;
result = MI_Context_GetLocalSession(context ,&localSession);
if( result != MI_RESULT_OK)
{
MI_Context_PostResult(context, result);
return ;
}
MI_Session_QueryInstances(&localSession, 0, NULL, nameSpace, L"WQL", queryString, NULL, &miOperation);
/* Must loop through all results until moreResults == MI_FALSE */
do
{
const MI_Instance *miInstance;
MI_Result _miResult;
const MI_Char *errorString = NULL;
const MI_Instance *errorDetails = NULL;
/* Retrieve a single instance result */
_miResult = MI_Operation_GetInstance(&miOperation, &miInstance, &moreResults, &result, &errorString, &errorDetails);
if (_miResult != MI_RESULT_OK)
{
if( errorDetails )
{
MI_Context_PostCimError(context, errorDetails);
}
else
{
MI_Context_PostResult(context, result);
}
MI_Operation_Close(&miOperation);
return;
}
if (miInstance)
{
if( bExistingEndPointIsProcessObject )
{
result = PostInstance(context, existingEndPoint, miInstance, bExistingEndPointIsProcessObject);
}
else
{
result = PostInstance(context, miInstance, existingEndPoint, bExistingEndPointIsProcessObject);
}
}
} while (result == MI_RESULT_OK && moreResults == MI_TRUE);
MI_Operation_Close(&miOperation);
MI_Context_PostResult(context, result);
}
MI_Result PostInstance( _In_ MI_Context* context, _In_opt_ const MI_Instance *miInstanceProcess, _In_opt_ const MI_Instance *miInstanceService,
_In_ MI_Boolean bExistingEndPointIsProcessObject)
{
MI_Result result = MI_RESULT_OK;
MSFT_WindowsServiceProcess associationObject;
MI_Value valueProcess, valueService;
if( bExistingEndPointIsProcessObject && !miInstanceProcess && miInstanceService)
{
return MI_Context_PostInstance(context, miInstanceService);
}
else if( !bExistingEndPointIsProcessObject && !miInstanceService && miInstanceProcess)
{
return MI_Context_PostInstance(context, miInstanceProcess);
}
//Need to send association object
result = MSFT_WindowsServiceProcess_Construct(&associationObject,context);
if( result != MI_RESULT_OK)
{
return result;
}
valueProcess.reference = (MI_Instance*)miInstanceProcess;
result = MI_Instance_SetElement(&associationObject.__instance, L"Process", &valueProcess ,MI_REFERENCE,0);
if( result != MI_RESULT_OK)
{
MSFT_WindowsServiceProcess_Destruct(&associationObject);
return result;
}
valueService.reference = (MI_Instance*)miInstanceService;
result = MI_Instance_SetElement(&associationObject.__instance, L"Service", &valueService ,MI_REFERENCE,0);
if( result != MI_RESULT_OK)
{
MSFT_WindowsServiceProcess_Destruct(&associationObject);
return result;
}
result = MI_Context_PostInstance(context, &associationObject.__instance);
MSFT_WindowsServiceProcess_Destruct(&associationObject);
return result;
}