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>
This commit is contained in:
Paul Gofman 2021-05-18 09:49:45 +02:00 committed by Alexandre Julliard
parent 09b0154ac1
commit 85abea6070
4 changed files with 244 additions and 4 deletions

View File

@ -312,6 +312,7 @@ static const struct column col_process[] =
{ L"ThreadCount", CIM_UINT32 },
{ L"WorkingSetSize", CIM_UINT64 },
/* methods */
{ L"Create", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
{ L"GetOwner", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
};
static const struct column col_processor[] =
@ -725,6 +726,7 @@ struct record_process
UINT32 thread_count;
UINT64 workingsetsize;
/* methods */
class_method *create;
class_method *get_owner;
};
struct record_processor
@ -892,6 +894,9 @@ static const struct record_param data_param[] =
{ L"StdRegProv", L"CreateKey", 1, L"hDefKey", CIM_SINT32, 0x80000002 },
{ L"StdRegProv", L"CreateKey", 1, L"sSubKeyName", CIM_STRING },
{ L"StdRegProv", L"CreateKey", -1, L"ReturnValue", CIM_UINT32 },
{ L"StdRegProv", L"DeleteKey", 1, L"hDefKey", CIM_SINT32, 0x80000002 },
{ L"StdRegProv", L"DeleteKey", 1, L"sSubKeyName", CIM_STRING },
{ L"StdRegProv", L"DeleteKey", -1, L"ReturnValue", CIM_UINT32 },
{ L"StdRegProv", L"EnumKey", 1, L"hDefKey", CIM_SINT32, 0x80000002 },
{ L"StdRegProv", L"EnumKey", 1, L"sSubKeyName", CIM_STRING },
{ L"StdRegProv", L"EnumKey", -1, L"ReturnValue", CIM_UINT32 },
@ -916,13 +921,14 @@ static const struct record_param data_param[] =
{ L"StdRegProv", L"SetDWORDValue", 1, L"sValueName", CIM_STRING },
{ L"StdRegProv", L"SetDWORDValue", 1, L"uValue", CIM_UINT32 },
{ L"StdRegProv", L"SetDWORDValue", -1, L"ReturnValue", CIM_UINT32 },
{ L"StdRegProv", L"DeleteKey", 1, L"hDefKey", CIM_SINT32, 0x80000002 },
{ L"StdRegProv", L"DeleteKey", 1, L"sSubKeyName", CIM_STRING },
{ L"StdRegProv", L"DeleteKey", -1, L"ReturnValue", CIM_UINT32 },
{ L"SystemRestore", L"Disable", 1, L"Drive", CIM_STRING },
{ L"SystemRestore", L"Disable", -1, L"ReturnValue", CIM_UINT32 },
{ L"SystemRestore", L"Enable", 1, L"Drive", CIM_STRING },
{ L"SystemRestore", L"Enable", -1, L"ReturnValue", CIM_UINT32 },
{ L"Win32_Process", L"Create", 1, L"CommandLine", CIM_STRING },
{ L"Win32_Process", L"Create", 1, L"CurrentDirectory", CIM_STRING },
{ L"Win32_Process", L"Create", -1, L"ProcessId", CIM_UINT32 },
{ L"Win32_Process", L"Create", -1, L"ReturnValue", CIM_UINT32 },
{ L"Win32_Process", L"GetOwner", -1, L"ReturnValue", CIM_UINT32 },
{ L"Win32_Process", L"GetOwner", -1, L"User", CIM_STRING },
{ L"Win32_Process", L"GetOwner", -1, L"Domain", CIM_STRING },
@ -3162,6 +3168,8 @@ static enum fill_status fill_process( struct table *table, const struct expr *co
rec->pprocess_id = entry.th32ParentProcessID;
rec->thread_count = entry.cntThreads;
rec->workingsetsize = 0;
/* methods */
rec->create = process_create;
rec->get_owner = process_get_owner;
if (!match_row( table, row, cond, &status ))
{

View File

@ -110,3 +110,113 @@ done:
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;
}

View File

@ -453,6 +453,10 @@ static void test_Win32_Baseboard( IWbemServices *services )
SysFreeString( wql );
}
static void test_Win32_Process_created_process(void)
{
}
static void test_Win32_Process( IWbemServices *services, BOOL use_full_path )
{
static const LONG expected_flavor = WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE |
@ -460,15 +464,19 @@ static void test_Win32_Process( IWbemServices *services, BOOL use_full_path )
WBEM_FLAVOR_ORIGIN_PROPAGATED;
WCHAR full_path[MAX_COMPUTERNAME_LENGTH + ARRAY_SIZE( L"\\\\%s\\ROOT\\CIMV2:" )];
BSTR class, method;
IWbemClassObject *process, *sig_in, *sig_out, *out;
IWbemClassObject *process, *sig_in, *sig_out, *out, *params;
WCHAR cmdlineW[MAX_PATH + 64 + 1];
IWbemQualifierSet *qualifiers;
VARIANT retval, val;
SAFEARRAY *names;
LONG bound, i;
DWORD full_path_len = 0;
ULONG refcount;
LONG flavor;
CIMTYPE type;
HRESULT hr;
DWORD ret;
HANDLE h;
if (use_full_path)
{
@ -511,6 +519,109 @@ static void test_Win32_Process( IWbemServices *services, BOOL use_full_path )
ok( !sig_in, "Got unexpected sig_in %p.\n", sig_in );
ok( !sig_out, "Got unexpected sig_out %p.\n", sig_out );
sig_in = (void *)0xdeadbeef;
sig_out = (void *)0xdeadbeef;
hr = IWbemClassObject_GetMethod( process, L"Create", 0, &sig_in, &sig_out );
ok( hr == S_OK, "Got unexpected hr %#x\n", hr );
ok( !!sig_in, "Got unexpected sig_in %p.\n", sig_in );
ok( !!sig_out, "Got unexpected sig_out %p.\n", sig_out );
hr = IWbemClassObject_SpawnInstance( sig_in, 0, &params );
ok( hr == S_OK, "got %08x\n", hr );
out = NULL;
class = SysAllocString( L"Win32_Process" );
method = SysAllocString( L"Create" );
hr = IWbemServices_ExecMethod( services, class, method, 0, NULL, params, &out, NULL );
ok( hr == S_OK, "failed to execute method %08x\n", hr );
SysFreeString( method );
SysFreeString( class );
VariantInit( &retval );
hr = IWbemClassObject_Get( out, L"ReturnValue", 0, &retval, &type, NULL );
ok( hr == S_OK, "failed to get return value %08x\n", hr );
ok( V_VT( &retval ) == VT_I4, "unexpected variant type 0x%x\n", V_VT( &retval ) );
ok( V_I4( &retval ) == 21, "unexpected error %u\n", V_I4( &retval ) );
IWbemClassObject_Release( out );
V_VT( &val ) = VT_BSTR;
V_BSTR( &val ) = SysAllocString( L"unknown" );
hr = IWbemClassObject_Put( params, L"CommandLine", 0, &val, 0 );
ok( hr == S_OK, "got %08x\n", hr );
VariantClear( &val );
out = NULL;
class = SysAllocString( L"Win32_Process" );
method = SysAllocString( L"Create" );
hr = IWbemServices_ExecMethod( services, class, method, 0, NULL, params, &out, NULL );
ok( hr == S_OK, "failed to execute method %08x\n", hr );
SysFreeString( method );
SysFreeString( class );
VariantInit( &retval );
hr = IWbemClassObject_Get( out, L"ReturnValue", 0, &retval, &type, NULL );
ok( hr == S_OK, "failed to get return value %08x\n", hr );
ok( V_VT( &retval ) == VT_I4, "unexpected variant type 0x%x\n", V_VT( &retval ) );
ok( V_I4( &retval ) == 9, "unexpected error %u\n", V_I4( &retval ) );
VariantInit( &retval );
V_VT( &retval ) = VT_I4;
hr = IWbemClassObject_Get( out, L"ProcessId", 0, &retval, &type, NULL );
ok( hr == S_OK, "failed to get return value %08x\n", hr );
todo_wine ok( V_VT( &retval ) == VT_NULL && type == CIM_UINT32, "unexpected variant type 0x%x, type %u\n",
V_VT( &retval ), type );
IWbemClassObject_Release( out );
ret = GetModuleFileNameW( NULL, cmdlineW, MAX_PATH + 1 );
ok( ret < MAX_PATH + 1, "Got unexpected ret %u.\n", ret );
lstrcatW( cmdlineW, L" query created_process");
V_VT( &val ) = VT_BSTR;
V_BSTR( &val ) = SysAllocString( cmdlineW );
hr = IWbemClassObject_Put( params, L"CommandLine", 0, &val, 0 );
ok( hr == S_OK, "got %08x\n", hr );
VariantClear( &val );
out = NULL;
class = SysAllocString( L"Win32_Process" );
method = SysAllocString( L"Create" );
hr = IWbemServices_ExecMethod( services, class, method, 0, NULL, params, &out, NULL );
ok( hr == S_OK, "failed to execute method %08x\n", hr );
SysFreeString( method );
SysFreeString( class );
VariantInit( &retval );
hr = IWbemClassObject_Get( out, L"ReturnValue", 0, &retval, &type, NULL );
ok( hr == S_OK, "failed to get return value %08x\n", hr );
ok( V_VT( &retval ) == VT_I4, "unexpected variant type 0x%x\n", V_VT( &retval ) );
ok( !V_I4( &retval ), "unexpected error %u\n", V_I4( &retval ) );
VariantInit( &retval );
V_VT( &retval ) = VT_I4;
hr = IWbemClassObject_Get( out, L"ProcessId", 0, &retval, &type, NULL );
ok( hr == S_OK, "failed to get return value %08x\n", hr );
ok( V_VT( &retval ) == VT_I4 && type == CIM_UINT32, "unexpected variant type 0x%x, type %u\n",
V_VT( &retval ), type );
ok( !!V_UI4( &retval ), "unexpected zero pid\n" );
IWbemClassObject_Release( out );
h = OpenProcess( SYNCHRONIZE, FALSE, V_UI4( &retval ));
ok( !!h, "failed to open process %#x.\n", V_UI4( &retval ));
ret = WaitForSingleObject( h, INFINITE );
ok( ret == WAIT_OBJECT_0, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError() );
CloseHandle( h );
refcount = IWbemClassObject_Release( params );
ok( !refcount, "Got unexpected refcount %u.\n", refcount );
refcount = IWbemClassObject_Release( sig_in );
ok( !refcount, "Got unexpected refcount %u.\n", refcount );
refcount = IWbemClassObject_Release( sig_out );
ok( !refcount, "Got unexpected refcount %u.\n", refcount );
sig_in = (void*)0xdeadbeef;
hr = IWbemClassObject_GetMethod( process, L"getowner", 0, &sig_in, NULL );
ok( hr == S_OK, "failed to get GetOwner method %08x\n", hr );
@ -1956,7 +2067,17 @@ START_TEST(query)
IWbemLocator *locator;
IWbemServices *services;
DWORD authn_svc;
char **argv;
HRESULT hr;
int argc;
argc = winetest_get_mainargs( &argv );
if (argc >= 3)
{
if (!strcmp( argv[2], "created_process" ))
test_Win32_Process_created_process();
return;
}
CoInitialize( NULL );
CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT,

View File

@ -245,6 +245,7 @@ HRESULT EnumWbemClassObject_create(struct query *, LPVOID *) DECLSPEC_HIDDEN;
HRESULT WbemQualifierSet_create(const WCHAR *, const WCHAR *, LPVOID *) DECLSPEC_HIDDEN;
HRESULT process_get_owner(IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out) DECLSPEC_HIDDEN;
HRESULT process_create(IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out) DECLSPEC_HIDDEN;
HRESULT reg_create_key(IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out) DECLSPEC_HIDDEN;
HRESULT reg_enum_key(IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out) DECLSPEC_HIDDEN;
HRESULT reg_enum_values(IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out) DECLSPEC_HIDDEN;