199 lines
6.4 KiB
C
199 lines
6.4 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 <Mi.h>
|
|
#include "WindowsService.h"
|
|
#include "MSFT_WindowsServiceManager.h"
|
|
|
|
// Streaming instances
|
|
MI_Result StreamInstance(_In_ MI_Context* context, _In_z_ MI_Char *propertyName, _In_count_(size) MI_Instance** arrInstances, MI_Uint32 size)
|
|
{
|
|
MI_Result result = MI_RESULT_FAILED;
|
|
MI_Value val;
|
|
MI_Uint32 i;
|
|
|
|
if(arrInstances == NULL)
|
|
return result;
|
|
|
|
if(size > 1)
|
|
{
|
|
//Streaming more than one instance at a time.
|
|
val.instancea.data = arrInstances;
|
|
val.instancea.size = size;
|
|
|
|
result = MI_Context_WriteStreamParameter(context, propertyName, &val, MI_INSTANCEA, MI_FLAG_STREAM);
|
|
}
|
|
else
|
|
{
|
|
val.instance = *arrInstances;
|
|
result = MI_Context_WriteStreamParameter(context, propertyName, &val, MI_INSTANCE, MI_FLAG_STREAM);
|
|
}
|
|
|
|
for( i = 0 ; i < size; i++)
|
|
{
|
|
MI_Instance_Destruct(arrInstances[i]);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
MI_Result Invoke_GetWindowsServices(
|
|
_In_ MI_Context* context,
|
|
_In_opt_ const MSFT_WindowsServiceManager_GetWindowsServices* in)
|
|
{
|
|
SC_HANDLE hSvcCtlMgr;
|
|
DWORD dwServiceIndex, dwBytesNeeded, dwServiceCount, dwResumeHandle = 0;
|
|
ENUM_SERVICE_STATUS * lpServiceArray = NULL;
|
|
BOOL returnValue;
|
|
MI_Result result = MI_RESULT_OK;
|
|
MI_Boolean bRequiredAllServices = TRUE;
|
|
|
|
// If value is zero this method will post all stopped services instances.
|
|
// If the value is 1 this method will return all running service instances.
|
|
// For all other values this method will return all services instances.
|
|
if(in->status.exists == TRUE)
|
|
{
|
|
if(in->status.value < 2)
|
|
{
|
|
bRequiredAllServices = FALSE;
|
|
}
|
|
}
|
|
|
|
hSvcCtlMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_CONNECT);
|
|
if (hSvcCtlMgr == NULL)
|
|
{
|
|
// Cannot get access to SCManager object.
|
|
return ResultFromWin32Error(GetLastError());
|
|
}
|
|
|
|
returnValue = EnumServicesStatus(
|
|
hSvcCtlMgr,
|
|
SERVICE_WIN32,
|
|
SERVICE_STATE_ALL,
|
|
NULL,
|
|
0,
|
|
&dwBytesNeeded,
|
|
&dwServiceCount,
|
|
&dwResumeHandle);
|
|
|
|
if (!returnValue)
|
|
{
|
|
DWORD lastError = GetLastError();
|
|
if ((lastError == ERROR_INSUFFICIENT_BUFFER) || (lastError == ERROR_MORE_DATA))
|
|
{
|
|
lpServiceArray = (ENUM_SERVICE_STATUS *)AllocateMemory(dwBytesNeeded);
|
|
if (lpServiceArray == NULL)
|
|
{
|
|
CloseServiceHandle(hSvcCtlMgr);
|
|
return MI_RESULT_SERVER_LIMITS_EXCEEDED;
|
|
}
|
|
|
|
dwResumeHandle = 0;
|
|
returnValue = EnumServicesStatus(
|
|
hSvcCtlMgr,
|
|
SERVICE_WIN32,
|
|
SERVICE_STATE_ALL,
|
|
lpServiceArray,
|
|
dwBytesNeeded,
|
|
&dwBytesNeeded,
|
|
&dwServiceCount,
|
|
&dwResumeHandle);
|
|
if (!returnValue)
|
|
{
|
|
FreeMemory(lpServiceArray);
|
|
CloseServiceHandle(hSvcCtlMgr);
|
|
return ResultFromWin32Error(GetLastError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CloseServiceHandle(hSvcCtlMgr);
|
|
return ResultFromWin32Error(lastError);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CloseServiceHandle(hSvcCtlMgr);
|
|
return MI_RESULT_FAILED;
|
|
}
|
|
|
|
// Enumerating through all the services and posting the instance to wmi service.
|
|
for(dwServiceIndex = 0; dwServiceIndex < dwServiceCount; dwServiceIndex++)
|
|
{
|
|
MSFT_WindowsService serviceInstance;
|
|
|
|
if(!bRequiredAllServices)
|
|
{
|
|
if( (in->status.value == 0 && lpServiceArray[dwServiceIndex].ServiceStatus.dwCurrentState == SERVICE_STOPPED) ||
|
|
(in->status.value == 1 && lpServiceArray[dwServiceIndex].ServiceStatus.dwCurrentState == SERVICE_RUNNING) )
|
|
{
|
|
// Desired service instance, process further
|
|
}
|
|
else
|
|
{
|
|
// Proceeding to next service as client is not interest in this service
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//Setting service instance properties
|
|
result = SetService(&serviceInstance, &hSvcCtlMgr, &lpServiceArray[dwServiceIndex], context);
|
|
if(result == MI_RESULT_OK)
|
|
{
|
|
MI_Instance *instance;
|
|
|
|
instance = &(serviceInstance.__instance);
|
|
result = StreamInstance(context, L"services", &instance, 1); //Streaming one instance at a time
|
|
if(result != MI_RESULT_OK)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Notifying the user of the failure to query particular service information.
|
|
// And also requesting for resonse whether to continue or stop processing further
|
|
MI_Boolean bContinue = FALSE;
|
|
MI_Char errMsg[MAX_PATH];
|
|
StringCchPrintfW(errMsg,MAX_PATH,L"Error Querying the service config %s", lpServiceArray[dwServiceIndex].lpServiceName);
|
|
MI_Context_WriteError(context, result, MI_RESULT_TYPE_MI,errMsg, &bContinue);
|
|
|
|
if(!bContinue)
|
|
{
|
|
// The user asked to cancel the operation
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// Continue with the next service
|
|
}
|
|
}
|
|
}
|
|
|
|
FreeMemory(lpServiceArray);
|
|
CloseServiceHandle(hSvcCtlMgr);
|
|
|
|
if(result == MI_RESULT_OK)
|
|
{
|
|
//Posting the output instance with return value
|
|
MSFT_WindowsServiceManager_GetWindowsServices outputInstance;
|
|
result = MSFT_WindowsServiceManager_GetWindowsServices_Construct(&outputInstance, context);
|
|
if(result == MI_RESULT_OK)
|
|
{
|
|
result = MSFT_WindowsServiceManager_GetWindowsServices_Set_MIReturn(&outputInstance, MI_RESULT_OK);
|
|
if(result == MI_RESULT_OK)
|
|
{
|
|
result = MSFT_WindowsServiceManager_GetWindowsServices_Post(&outputInstance, context);
|
|
}
|
|
MSFT_WindowsServiceManager_GetWindowsServices_Destruct(&outputInstance);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
} |