wine/dlls/wbemprox/process.c
Paul Gofman 85abea6070 wbemprox: Partially implement Win32_Process.Create method.
Fixes FunCom launcher failure to launch games.

Signed-off-by: Paul Gofman <pgofman@codeweavers.com>
Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
2021-05-18 09:58:53 +02:00

222 lines
6.7 KiB
C

/*
* Win32_Process methods implementation
*
* Copyright 2013 Hans Leidekker for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "wbemcli.h"
#include "wine/debug.h"
#include "wbemprox_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
static HRESULT get_owner( VARIANT *user, VARIANT *domain, VARIANT *retval )
{
DWORD len;
UINT error = 8;
len = 0;
GetUserNameW( NULL, &len );
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) goto done;
if (!(V_BSTR( user ) = SysAllocStringLen( NULL, len - 1 ))) goto done;
if (!GetUserNameW( V_BSTR( user ), &len )) goto done;
V_VT( user ) = VT_BSTR;
len = 0;
GetComputerNameW( NULL, &len );
if (GetLastError() != ERROR_BUFFER_OVERFLOW) goto done;
if (!(V_BSTR( domain ) = SysAllocStringLen( NULL, len - 1 ))) goto done;
if (!GetComputerNameW( V_BSTR( domain ), &len )) goto done;
V_VT( domain ) = VT_BSTR;
error = 0;
done:
if (error)
{
VariantClear( user );
VariantClear( domain );
}
set_variant( VT_UI4, error, NULL, retval );
return S_OK;
}
HRESULT process_get_owner( IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out )
{
VARIANT user, domain, retval;
IWbemClassObject *sig, *out_params = NULL;
HRESULT hr;
TRACE("%p, %p, %p, %p\n", obj, context, in, out);
hr = create_signature( L"Win32_Process", L"GetOwner", PARAM_OUT, &sig );
if (hr != S_OK) return hr;
if (out)
{
hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
if (hr != S_OK)
{
IWbemClassObject_Release( sig );
return hr;
}
}
VariantInit( &user );
VariantInit( &domain );
hr = get_owner( &user, &domain, &retval );
if (hr != S_OK) goto done;
if (out_params)
{
if (!V_UI4( &retval ))
{
hr = IWbemClassObject_Put( out_params, L"User", 0, &user, CIM_STRING );
if (hr != S_OK) goto done;
hr = IWbemClassObject_Put( out_params, L"Domain", 0, &domain, CIM_STRING );
if (hr != S_OK) goto done;
}
hr = IWbemClassObject_Put( out_params, L"ReturnValue", 0, &retval, CIM_UINT32 );
}
done:
VariantClear( &user );
VariantClear( &domain );
IWbemClassObject_Release( sig );
if (hr == S_OK && out)
{
*out = out_params;
IWbemClassObject_AddRef( out_params );
}
if (out_params) IWbemClassObject_Release( out_params );
return hr;
}
HRESULT process_create( IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out )
{
VARIANT command_line, current_directory, startup_info;
HRESULT ret = WBEM_E_INVALID_PARAMETER, hr;
IWbemClassObject *sig, *out_params = NULL;
PROCESS_INFORMATION pi;
STARTUPINFOW si;
UINT32 error;
VARIANT v;
BOOL bret;
CIMTYPE type;
FIXME("%p, %p, %p, %p stub\n", obj, context, in, out);
*out = NULL;
if ((hr = create_signature( L"Win32_Process", L"Create", PARAM_OUT, &sig ))) return hr;
VariantInit( &command_line );
VariantInit( &current_directory );
VariantInit( &startup_info );
if (FAILED(hr = IWbemClassObject_Get( in, L"CommandLine", 0, &command_line, &type, NULL ))
|| V_VT( &command_line ) != VT_BSTR)
WARN( "Invalid CommandLine, hr %#x, type %u.\n", hr, V_VT( &command_line ));
else
TRACE( "CommandLine %s.\n", debugstr_w( V_BSTR( &command_line )));
if (FAILED(hr = IWbemClassObject_Get( in, L"CurrentDirectory", 0, &current_directory, &type, NULL ))
|| V_VT( &current_directory ) != VT_BSTR)
WARN("Invalid CurrentDirectory, hr %#x, type %u.\n", hr, V_VT( &current_directory ));
else
TRACE( "CurrentDirectory %s.\n", debugstr_w( V_BSTR( &current_directory )));
if (SUCCEEDED(IWbemClassObject_Get( in, L"ProcessStartupInformation", 0, &startup_info, &type, NULL ))
&& V_VT( &startup_info ) == VT_UNKNOWN && V_UNKNOWN( &startup_info ))
FIXME( "ProcessStartupInformation is not implemented, vt_type %u, type %u, val %p.\n",
V_VT( &startup_info ), type, V_UNKNOWN( &startup_info ));
if (out && (hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params )))
{
ret = hr;
goto done;
}
memset( &si, 0, sizeof(si) );
si.cb = sizeof(si);
if (V_VT( &command_line ) == VT_BSTR && V_BSTR( &command_line ))
{
bret = CreateProcessW( NULL, V_BSTR( &command_line ), NULL, NULL, FALSE, 0L,
V_VT( &current_directory ) == VT_BSTR ? V_BSTR( &current_directory ) : NULL,
NULL, &si, &pi );
TRACE( "CreateProcessW ret %#x, GetLastError() %u.\n", bret, GetLastError() );
if (bret)
{
CloseHandle( pi.hThread );
CloseHandle( pi.hProcess );
error = 0;
}
else
{
switch (GetLastError())
{
case ERROR_FILE_NOT_FOUND:
case ERROR_PATH_NOT_FOUND:
error = 9;
break;
case ERROR_ACCESS_DENIED:
error = 2;
break;
default:
error = 8;
break;
}
}
}
else
{
bret = FALSE;
error = 21;
}
if (out)
{
VariantInit( &v );
V_VT( &v ) = VT_UI4;
V_UI4( &v ) = pi.dwProcessId;
if (bret && (ret = IWbemClassObject_Put( out_params, L"ProcessId", 0, &v, 0 ))) goto done;
V_UI4( &v ) = error;
if ((ret = IWbemClassObject_Put( out_params, L"ReturnValue", 0, &v, 0 ))) goto done;
*out = out_params;
IWbemClassObject_AddRef( out_params );
}
ret = S_OK;
done:
IWbemClassObject_Release( sig );
if (out_params) IWbemClassObject_Release( out_params );
VariantClear( &command_line );
VariantClear( &current_directory );
VariantClear( &startup_info );
TRACE( "ret %#x.\n", ret );
return ret;
}