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

856 lines
28 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 <windows.h>
#include <stdlib.h>
#include <assert.h>
#include <combaseapi.h>
#include "helper.h"
#include "MSFT_WindowsProcess.h"
#include "WindowsProcess.h"
MI_Result GetOSName(
__out_ecount(nSize) LPWSTR buf,
__in size_t nSize)
{
MI_Result result = MI_RESULT_FAILED;
OSVERSIONINFO osvi;
assert(buf != NULL);
buf[0] = L'\0';
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
#pragma warning( push )
#pragma warning( disable : 4996 ) // 'GetVersionEx': was declared deprecated
if(GetVersionEx(&osvi))
{
if(SUCCEEDED(StringCchPrintfW(buf, nSize, L"Microsoft Windows Version %d.%d (Build %d)", osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber)))
{
result = MI_RESULT_OK;
}
else
{
result = ResultFromWin32Error(GetLastError());
}
}
else
{
result = ResultFromWin32Error(GetLastError());
}
return result;
#pragma warning( pop ) // 'GetVersionEx': was declared deprecated
}
BOOL EnablePrivilege()
{
LUID PrivilegeRequired ;
DWORD dwLen = 0, iCount = 0;
BOOL bRes = FALSE;
HANDLE hToken = NULL;
BYTE *pBuffer = NULL;
TOKEN_PRIVILEGES* pPrivs = NULL;
bRes = LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &PrivilegeRequired);
if( !bRes) return FALSE;
bRes = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, TRUE, &hToken);
if(!bRes) return FALSE;
bRes = GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwLen);
if (TRUE == bRes)
{
CloseHandle(hToken);
return FALSE;
}
pBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLen);
if(NULL == pBuffer) return FALSE;
if (!GetTokenInformation(hToken, TokenPrivileges, pBuffer, dwLen, &dwLen))
{
CloseHandle(hToken);
HeapFree(GetProcessHeap(), 0, pBuffer);
return FALSE;
}
// Iterate through all the privileges and enable the one required
bRes = FALSE;
pPrivs = (TOKEN_PRIVILEGES*)pBuffer;
for(iCount = 0; iCount < pPrivs->PrivilegeCount; iCount++)
{
if (pPrivs->Privileges[iCount].Luid.LowPart == PrivilegeRequired.LowPart &&
pPrivs->Privileges[iCount].Luid.HighPart == PrivilegeRequired.HighPart )
{
pPrivs->Privileges[iCount].Attributes |= SE_PRIVILEGE_ENABLED;
// here it's found
bRes = AdjustTokenPrivileges(hToken, FALSE, pPrivs, dwLen, NULL, NULL);
break;
}
}
CloseHandle(hToken);
HeapFree(GetProcessHeap(), 0, pBuffer);
return bRes;
}
MI_Result ConvertFileTimeToDateTime(
_In_ LPFILETIME pfTime,
_Out_ MI_Datetime *pdTime)
{
SYSTEMTIME sTime;
assert(pfTime != NULL);
assert(pdTime != NULL);
memset(pdTime, 0, sizeof(MI_Datetime));
if(FileTimeToSystemTime(pfTime, &sTime))
{
pdTime->isTimestamp = TRUE;
pdTime->u.timestamp.year = sTime.wYear;
pdTime->u.timestamp.month = sTime.wMonth;
pdTime->u.timestamp.day = sTime.wDay;
pdTime->u.timestamp.hour = sTime.wHour;
pdTime->u.timestamp.minute = sTime.wMinute;
pdTime->u.timestamp.second = sTime.wSecond;
pdTime->u.timestamp.microseconds = sTime.wMilliseconds * 1000;
pdTime->u.timestamp.utc = 0;
}
else
{
return ResultFromWin32Error(GetLastError());
}
return MI_RESULT_OK;
}
//
// Helper function to set properties of MSFT_WindowsProcess instance,
// All the key properties must be set, while other properties could
// be optional and depends on the provider.
//
MI_Result SetInstance(
_Out_ MSFT_WindowsProcess* self,
DWORD processId,
_In_ MI_Context* context
)
{
HANDLE hProcess = NULL;
MI_Result result = MSFT_WindowsProcess_Construct(self, context);
if(result != MI_RESULT_OK)
{
return result;
}
// Get a handle to the process.
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE,
processId);
if(NULL != hProcess)
{
// Set process handle in the instance - putting the PID of the process in string format
MI_Char PIDInString[15];
if(! _i64tow_s(processId, PIDInString, sizeof(PIDInString)/sizeof(MI_Char), 10) )
{
result = MSFT_WindowsProcess_Set_Handle(self, PIDInString);
if(result != MI_RESULT_OK)
{
CloseHandle( hProcess );
MSFT_WindowsProcess_Destruct(self);
return result;
}
}
else
{
CloseHandle( hProcess );
MSFT_WindowsProcess_Destruct(self);
return MI_RESULT_FAILED;
}
// Setting the name of the process
{
HMODULE hMod;
DWORD cbNeeded;
MI_Char szProcessName[MAX_PATH] = L"";
if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod),
&cbNeeded) )
{
GetModuleBaseName( hProcess, hMod, szProcessName,
sizeof(szProcessName)/sizeof(TCHAR) );
}
result = MSFT_WindowsProcess_Set_Name(self, szProcessName);
if( result != MI_RESULT_OK )
{
CloseHandle( hProcess );
MSFT_WindowsProcess_Destruct(self);
return result;
}
// Setting the process name as caption too
result = MSFT_WindowsProcess_Set_Caption(self, szProcessName);
if(result != MI_RESULT_OK)
{
CloseHandle( hProcess );
MSFT_WindowsProcess_Destruct(self);
return result;
}
}
// Setting the execution state to running
result = MSFT_WindowsProcess_Set_ExecutionState(self, 3);
if(result != MI_RESULT_OK)
{
CloseHandle( hProcess );
MSFT_WindowsProcess_Destruct(self);
return result;
}
// Setting the priority of the process
{
DWORD priority;
priority = GetPriorityClass(hProcess);
if(priority)
{
result = MSFT_WindowsProcess_Set_Priority(self, priority);
if(result != MI_RESULT_OK)
{
CloseHandle(hProcess);
MSFT_WindowsProcess_Destruct(self);
return result;
}
}
}
// Setting the WorkingSetSize property with the minimum working set size of the process.
{
SIZE_T minimumWorkingSetSize, maximumWorkingSetSize;
if(GetProcessWorkingSetSize(hProcess, &minimumWorkingSetSize, &maximumWorkingSetSize))
{
result = MSFT_WindowsProcess_Set_WorkingSetSize(self, minimumWorkingSetSize);
if(result != MI_RESULT_OK)
{
CloseHandle(hProcess);
MSFT_WindowsProcess_Destruct(self);
return result;
}
}
}
// Setting CreationDate, KernelModeTime, UserModeTime
{
FILETIME fCreationTime, fKernelTime, fUserTime, fExitTime;
if(GetProcessTimes(hProcess, &fCreationTime, &fExitTime, &fKernelTime, &fUserTime))
{
MI_Datetime dTime;
result = ConvertFileTimeToDateTime(&fCreationTime, &dTime);
if(result == MI_RESULT_OK)
{
result = MSFT_WindowsProcess_Set_CreationDate(self, dTime);
if(result != MI_RESULT_OK)
{
CloseHandle(hProcess);
MSFT_WindowsProcess_Destruct(self);
return result;
}
}
{
// Setting KernelModeTime in milliseconds
// FILETIME contains two 32-bit values that combine to form a 64 bit count of 100-nanosecond time units.
UINT64 temp, timeInMilliseconds;
temp = fKernelTime.dwHighDateTime;
temp = temp << 32;
temp += fKernelTime.dwLowDateTime;
//temp = (UINT64) (((UINT32)fKernelTime.dwHighDateTime << 32) | (UINT32)fKernelTime.dwLowDateTime);
timeInMilliseconds = temp / 10000; // Converting 100-nanosecond time units to milliseconds.
result = MSFT_WindowsProcess_Set_KernelModeTime (self, timeInMilliseconds);
if(result != MI_RESULT_OK)
{
CloseHandle(hProcess);
MSFT_WindowsProcess_Destruct(self);
return result;
}
// Setting UserModeTime in milliseconds
temp = fUserTime.dwHighDateTime;
temp = temp << 32;
temp += fUserTime.dwLowDateTime;
timeInMilliseconds = temp / 10000; // Converting 100-nanosecond time units to milliseconds.
result = MSFT_WindowsProcess_Set_UserModeTime (self, timeInMilliseconds);
if(result != MI_RESULT_OK)
{
CloseHandle(hProcess);
MSFT_WindowsProcess_Destruct(self);
return result;
}
}
result = ConvertFileTimeToDateTime(&fCreationTime, &dTime);
if(result == MI_RESULT_OK)
{
result = MSFT_WindowsProcess_Set_CreationDate(self, dTime);
if(result != MI_RESULT_OK)
{
CloseHandle(hProcess);
MSFT_WindowsProcess_Destruct(self);
return result;
}
}
}
}
// Release the handle to the process.
CloseHandle( hProcess );
// Setting a dummy value in this example for CSCreationClassName key property.
result = MSFT_WindowsProcess_Set_CSCreationClassName(self, CS_CREATION_CLASS_NAME);
if(result != MI_RESULT_OK)
{
MSFT_WindowsProcess_Destruct(self);
return result;
}
result = MSFT_WindowsProcess_Set_OSCreationClassName(self, OS_CREATION_CLASS_NAME);
if(result != MI_RESULT_OK)
{
MSFT_WindowsProcess_Destruct(self);
return result;
}
// Current creation class is MSFT_WindowsProcess
result = MSFT_WindowsProcess_Set_CreationClassName(self, CLASS_CREATION_NAME);
if(result != MI_RESULT_OK)
{
MSFT_WindowsProcess_Destruct(self);
return result;
}
//OSName
{
MI_Char buf[INFO_BUFFER_SIZE];
result = GetOSName(buf, INFO_BUFFER_SIZE);
if(result == MI_RESULT_OK)
{
result = MSFT_WindowsProcess_Set_OSName(self, buf);
if(result != MI_RESULT_OK)
{
MSFT_WindowsProcess_Destruct(self);
return result;
}
}
}
//CSName - host name
{
MI_Char buf[INFO_BUFFER_SIZE];
DWORD bufCharCount = INFO_BUFFER_SIZE;
memset(buf, 0, sizeof(buf));
if(GetComputerNameW(buf, &bufCharCount))
{
result = MSFT_WindowsProcess_Set_CSName(self, buf);
if(result != MI_RESULT_OK)
{
MSFT_WindowsProcess_Destruct(self);
return result;
}
}
}
}
else
{
// Converting the failure code to suitable MI_Result code.
result = ResultFromWin32Error(GetLastError());
MSFT_WindowsProcess_Destruct(self);
}
return result;
}
//
// Validating the given instance is non NULL, and
// all key properties having same value as set by the provider,
// check handle property exists as well.
//
MI_Result IsValidInstance(_In_ const MSFT_WindowsProcess* instanceName)
{
MI_Result result = MI_RESULT_OK;
// Check to make sure that instance is not null and instance has all the key properties.
if(instanceName &&
instanceName->CSCreationClassName.exists == MI_TRUE &&
instanceName->CSName.exists == MI_TRUE &&
instanceName->OSCreationClassName.exists == MI_TRUE &&
instanceName->OSName.exists == MI_TRUE &&
instanceName->CreationClassName.exists == MI_TRUE &&
instanceName->Handle.exists == MI_TRUE)
{
// Making sure that key properties are same as the one set by the provider
if( (_wcsicmp(instanceName->CSCreationClassName.value, CS_CREATION_CLASS_NAME) != 0) ||
(_wcsicmp(instanceName->OSCreationClassName.value, OS_CREATION_CLASS_NAME) != 0) ||
(_wcsicmp(instanceName->CreationClassName.value, CLASS_CREATION_NAME) != 0) )
{
// The instance with the user passed in key is not found.
return MI_RESULT_NOT_FOUND;
}
else
{
MI_Char buf[INFO_BUFFER_SIZE];
DWORD bufCharCount = INFO_BUFFER_SIZE;
// Checking to see OSName key property is same as the one set by the provider
result = GetOSName(buf, INFO_BUFFER_SIZE);
if(result == MI_RESULT_OK)
{
if(_wcsicmp(instanceName->OSName.value, buf) != 0)
{
return MI_RESULT_NOT_FOUND;
}
}
else
{
return result;
}
// Checking to see CSName key propertye is same as the one set by the provider
//memset(buf, 0, sizeof(buf));
if(GetComputerNameW(buf, &bufCharCount))
{
if(_wcsicmp(instanceName->CSName.value, buf) != 0)
{
return MI_RESULT_NOT_FOUND;
}
}
else
{
return MI_RESULT_FAILED;
}
}
}
else
{
result = MI_RESULT_INVALID_PARAMETER;
}
return result;
}
MI_Result EnumerateProcesses(
_In_ MI_Context* context,
_In_ MI_Boolean keysOnly)
{
DWORD aProcesses[1024];
DWORD cbNeeded;
DWORD cProcesses;
unsigned int i;
MI_Result result = MI_RESULT_OK;
// -*- use it later
MI_UNREFERENCED_PARAMETER(keysOnly);
// Here enabling privileges will help to list processes from different users if the caller has not enabled it already.
EnablePrivilege( );
// Get the list of process identifiers.
// -*- change the size to operate dynamically
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
return MI_RESULT_FAILED;
// Calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD);
// Print the names of the modules for each process.
for ( i = 0; i < cProcesses; i++ )
{
MSFT_WindowsProcess instance;
result = SetInstance(&instance, aProcesses[i], context);
if(result != MI_RESULT_OK)
{
// Ignoring the failure to open specific processes as the caller may not have permission to open all processes.
continue;
}
// Post instance to wmi server
result = MSFT_WindowsProcess_Post(&instance, context);
// Now we can free the instance which will free the resources allocated as part of setting the properties.
MSFT_WindowsProcess_Destruct(&instance);
if(result != MI_RESULT_OK)
break;
}
return result;
}
MI_Result GetProcessInstance(
_In_ MI_Context* context,
_In_ const MSFT_WindowsProcess* instanceName)
{
MI_Result result = MI_RESULT_OK;
MSFT_WindowsProcess instance;
EnablePrivilege();
result = IsValidInstance(instanceName);
if(result == MI_RESULT_OK)
{
DWORD processId;
// Retrieving the process id from handle parameter
processId = (DWORD)_wtoi64(instanceName->Handle.value);
result = SetInstance(&instance, processId, context);
if(result == MI_RESULT_OK)
{
// Post instance to wmi server
result = MSFT_WindowsProcess_Post(&instance, context);
// Now we can free the instance which will free the resources allocated as part of setting the properties.
MSFT_WindowsProcess_Destruct(&instance);
}
}
return result;
}
MI_Result DeleteProcessInstance(
_In_ MI_Context* context,
_In_ const MSFT_WindowsProcess* instanceName)
{
MI_Result result = MI_RESULT_OK;
MI_UNREFERENCED_PARAMETER(context);
EnablePrivilege();
result = IsValidInstance(instanceName);
if(result == MI_RESULT_OK)
{
DWORD processId;
HANDLE hProcess;
// Retrieving the process id from handle parameter
processId = (DWORD)_wtoi64(instanceName->Handle.value);
hProcess = OpenProcess( PROCESS_TERMINATE,
FALSE, processId );
if(NULL != hProcess)
{
if(! TerminateProcess(hProcess, 0) )
{
result = ResultFromWin32Error(GetLastError());
}
CloseHandle(hProcess);
}
else
{
// Converting the failure code to suitable MI_Result code.
result = ResultFromWin32Error(GetLastError());
}
}
return result;
}
MI_Result ModifyProcessInstance(
_In_ MI_Context* context,
_In_ const MSFT_WindowsProcess* modifiedInstance)
{
MI_Result result = MI_RESULT_OK;
MI_UNREFERENCED_PARAMETER(context);
EnablePrivilege();
// Modify has to find the instance with the key properties passed in and modify non-key properties passed by client.
// And then post the modified instance.
result = IsValidInstance(modifiedInstance);
if(result == MI_RESULT_OK)
{
DWORD processId;
HANDLE hProcess;
// Retrieving the process id from handle parameter
processId = (DWORD)_wtoi64(modifiedInstance->Handle.value);
hProcess = OpenProcess(PROCESS_SET_INFORMATION, FALSE, processId );
if(NULL != hProcess)
{
// In this sample provider modifying only Priority property of the instance if it is changed by client.
if(modifiedInstance->Priority.exists == MI_TRUE)
{
if(SetPriorityClass(hProcess, modifiedInstance->Priority.value))
{
MSFT_WindowsProcess instance;
// Retrieving the modified process instance
result = SetInstance(&instance, processId, context);
if(result == MI_RESULT_OK)
{
// Post modified instance to wmi server
result = MSFT_WindowsProcess_Post(&instance, context);
// Now we can free the instance which will free the resources allocated as part of setting the properties.
MSFT_WindowsProcess_Destruct(&instance);
}
}
else
{
result = ResultFromWin32Error(GetLastError());
}
}
CloseHandle(hProcess);
}
else
{
// Converting the failure code to suitable MI_Result code.
result = ResultFromWin32Error(GetLastError());
}
}
return result;
}
MI_Result Invoke_SetPriority(
_In_ MI_Context* context,
_In_ const MSFT_WindowsProcess* instanceName,
_In_opt_ const MSFT_WindowsProcess_SetPriority* in)
{
MI_Result result = MI_RESULT_OK;
MI_UNREFERENCED_PARAMETER(context);
// Checking to see if the priority value is passed in by client.
if(NULL == in || in->Priority.exists == FALSE)
{
return MI_RESULT_INVALID_PARAMETER;
}
EnablePrivilege();
// Instance method has to find the instance with the key properties passed in and modify non-key properties passed by client.
// And then post the output instance.
result = IsValidInstance(instanceName);
if(result == MI_RESULT_OK)
{
DWORD processId;
HANDLE hProcess;
// Retrieving the process id from handle parameter
processId = (DWORD)_wtoi64(instanceName->Handle.value);
hProcess = OpenProcess( PROCESS_SET_INFORMATION,
FALSE, processId );
if(NULL != hProcess)
{
// Setting the new priority
if(SetPriorityClass(hProcess, in->Priority.value))
{
MSFT_WindowsProcess_SetPriority outputInstance;
result = MSFT_WindowsProcess_SetPriority_Construct(&outputInstance, context);
if(result == MI_RESULT_OK)
{
result = MSFT_WindowsProcess_SetPriority_Set_MIReturn(&outputInstance, MI_RESULT_OK);
if(result == MI_RESULT_OK)
{
// Posting the output instance with the return value set
result = MSFT_WindowsProcess_SetPriority_Post(&outputInstance, context);
}
MSFT_WindowsProcess_SetPriority_Destruct(&outputInstance);
}
}
else
{
result = ResultFromWin32Error(GetLastError());
}
CloseHandle(hProcess);
}
else
{
// Converting the failure code to suitable MI_Result code.
result = ResultFromWin32Error(GetLastError());
}
}
return result;
}
//
// Helper function of allocating memory from process heap
//
// Argument:
// dwBytes number of bytes to allocate.
//
// Return value:
// allocated memory address
//
LPVOID AllocateMemory(SIZE_T dwBytes)
{
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytes);
}
//
// Helper function of freeing memory
//
// Argument:
// lpMem memory address to free.
//
void FreeMemory(LPVOID lpMem)
{
HeapFree(GetProcessHeap(), 0, lpMem);
}
//
// Create a process based on given commandline.
// The newly created process will be posted back to client
// upon successfully creation.
//
MI_Result CreateProcessHelper(
_In_ MI_Context* context,
_In_z_ const MI_Char* commandLine,
_Out_ MSFT_WindowsProcess* pProcess)
{
PROCESS_INFORMATION processInformation;
STARTUPINFO startupInfo;
BOOL creationResult;
size_t nLength = wcslen(commandLine) + 1;
LPWSTR cmdLine;
LPWSTR cmdLineTemp;
HRESULT revertResult;
ZeroMemory(pProcess, sizeof(MSFT_WindowsProcess));
// Revert to host account, otherwise CreateProcess does not work
revertResult = CoRevertToSelf();
if (revertResult != S_OK)
{
return ResultFromWin32Error(revertResult);
}
cmdLine = (LPWSTR)AllocateMemory(nLength * 2 * sizeof(wchar_t));
cmdLineTemp = cmdLine;
if (commandLine[0] != L'"')
{
cmdLineTemp[0] = L'"';
cmdLineTemp ++;
}
CopyMemory(cmdLineTemp, commandLine, nLength * sizeof(wchar_t));
if (commandLine[0] != L'"')
{
cmdLineTemp += (nLength - 1);
cmdLineTemp[0] = L'"';
cmdLineTemp[1] = L'\0';
}
ZeroMemory(&processInformation, sizeof(processInformation));
ZeroMemory(&startupInfo, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);
// The target process will be created in session of the
// provider host process. If the provider was hosted in
// wmiprvse.exe process, the target process will be launched
// in session 0 and UI is invisible to the logged on user,
// but the process can be found through task manager.
creationResult = CreateProcess(
NULL, // No module name (use command line)
cmdLine, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP, // creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&startupInfo, // Pointer to STARTUPINFO structure
&processInformation); // Pointer to PROCESS_INFORMATION structure
FreeMemory(cmdLine);
if (!creationResult)
{
// create process failed
DWORD errorCode = GetLastError();
return ResultFromWin32Error(errorCode);
}
// close process and thread handles
CloseHandle(processInformation.hProcess);
CloseHandle(processInformation.hThread);
// create process successfully,
// read the MSFT_WindowsProcess instance and post back to client
return SetInstance(pProcess, processInformation.dwProcessId, context);
}
//
// Create a process based on given instance.
// Only CommandLine property will be used to create a process.
// The newly created process will be posted back to client
// upon successfully creation.
//
MI_Result InvokeIntrisicCreateMethod(
_In_ MI_Context* context,
_In_ const MSFT_WindowsProcess* newInstance)
{
if (newInstance->CommandLine.exists == MI_TRUE)
{
MSFT_WindowsProcess newProcess;
MI_Result r = CreateProcessHelper(context, newInstance->CommandLine.value, &newProcess);
if (r == MI_RESULT_OK)
{
// Posting the created instance is necessary, this is the way client will know the key properties of instance created.
r = MSFT_WindowsProcess_Post(&newProcess, context);
MSFT_WindowsProcess_Destruct(&newProcess);
}
return r;
}
return MI_RESULT_INVALID_PARAMETER;
}
//
// Create a process based on given argument,
// CommandLine argument will be used here.
// The reference to newly created process will be posted back to client
// upon successfully creation.
//
MI_Result InvokeExtrinsicCreateMethod(
_In_ MI_Context* context,
_In_ const MSFT_WindowsProcess_Create* createArg)
{
if (createArg->CommandLine.exists == MI_TRUE)
{
MSFT_WindowsProcess_Create createResult;
MSFT_WindowsProcess newProcess;
MI_Result r = CreateProcessHelper(context, createArg->CommandLine.value, &newProcess);
if (r == MI_RESULT_OK)
{
// build creation result object
r = MSFT_WindowsProcess_Create_Construct(&createResult, context);
if (r == MI_RESULT_OK)
{
// set the newly created process object to result object
r = MSFT_WindowsProcess_Create_Set_Process(&createResult, (CIM_Process *)&newProcess);
if (r == MI_RESULT_OK)
{
r = MSFT_WindowsProcess_Create_Set_MIReturn(&createResult, 0);
}
if (r == MI_RESULT_OK)
{
r = MSFT_WindowsProcess_Create_Post(&createResult, context);
}
MSFT_WindowsProcess_Create_Destruct(&createResult);
}
MSFT_WindowsProcess_Destruct(&newProcess);
}
return r;
}
return MI_RESULT_INVALID_PARAMETER;
}