Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/wbemprox/class.c | 17 +++++++++++++++++ dlls/wbemprox/tests/query.c | 11 +++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/dlls/wbemprox/class.c b/dlls/wbemprox/class.c index f48c815ef8d..2f2d3ef2bfb 100644 --- a/dlls/wbemprox/class.c +++ b/dlls/wbemprox/class.c @@ -875,10 +875,27 @@ static HRESULT WINAPI class_object_GetMethod( { struct class_object *co = impl_from_IWbemClassObject( iface ); IWbemClassObject *in, *out; + struct table *table; + unsigned int i; HRESULT hr;
TRACE("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, ppInSignature, ppOutSignature);
+ if (ppInSignature) *ppInSignature = NULL; + if (ppOutSignature) *ppOutSignature = NULL; + + table = get_view_table( impl_from_IEnumWbemClassObject( co->iter )->query->view, co->index ); + + for (i = 0; i < table->num_cols; ++i) + { + if (is_method( table, i ) && !lstrcmpiW( table->columns[i].name, wszName )) break; + } + if (i == table->num_cols) + { + FIXME("Method %s not found in class %s.\n", debugstr_w(wszName), debugstr_w(co->name)); + return WBEM_E_NOT_FOUND; + } + hr = create_signature( co->name, wszName, PARAM_IN, &in ); if (hr != S_OK) return hr;
diff --git a/dlls/wbemprox/tests/query.c b/dlls/wbemprox/tests/query.c index a79bc759bea..85b242aba6f 100644 --- a/dlls/wbemprox/tests/query.c +++ b/dlls/wbemprox/tests/query.c @@ -460,7 +460,7 @@ 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, *out; + IWbemClassObject *process, *sig_in, *sig_out, *out; IWbemQualifierSet *qualifiers; VARIANT retval, val; SAFEARRAY *names; @@ -504,8 +504,15 @@ static void test_Win32_Process( IWbemServices *services, BOOL use_full_path ) } SafeArrayDestroy( names );
+ sig_in = (void *)0xdeadbeef; + sig_out = (void *)0xdeadbeef; + hr = IWbemClassObject_GetMethod( process, L"unknown", 0, &sig_in, &sig_out ); + ok( hr == WBEM_E_NOT_FOUND, "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 ); + sig_in = (void*)0xdeadbeef; - hr = IWbemClassObject_GetMethod( process, L"GetOwner", 0, &sig_in, NULL ); + hr = IWbemClassObject_GetMethod( process, L"getowner", 0, &sig_in, NULL ); ok( hr == S_OK, "failed to get GetOwner method %08x\n", hr ); ok( !sig_in, "sig_in != NULL\n"); IWbemClassObject_Release( process );
Fixes FunCom launcher failure to launch games.
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/wbemprox/builtin.c | 7 ++ dlls/wbemprox/process.c | 114 ++++++++++++++++++++++++++++ dlls/wbemprox/tests/query.c | 123 ++++++++++++++++++++++++++++++- dlls/wbemprox/wbemprox_private.h | 1 + 4 files changed, 244 insertions(+), 1 deletion(-)
diff --git a/dlls/wbemprox/builtin.c b/dlls/wbemprox/builtin.c index 3922331f650..1bc58f06d84 100644 --- a/dlls/wbemprox/builtin.c +++ b/dlls/wbemprox/builtin.c @@ -313,6 +313,7 @@ static const struct column col_process[] = { L"WorkingSetSize", CIM_UINT64 }, /* methods */ { L"GetOwner", CIM_FLAG_ARRAY|COL_FLAG_METHOD }, + { L"Create", CIM_FLAG_ARRAY|COL_FLAG_METHOD }, }; static const struct column col_processor[] = { @@ -726,6 +727,7 @@ struct record_process UINT64 workingsetsize; /* methods */ class_method *get_owner; + class_method *create; }; struct record_processor { @@ -926,6 +928,10 @@ static const struct record_param data_param[] = { 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 }, + { 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_Service", L"PauseService", -1, L"ReturnValue", CIM_UINT32 }, { L"Win32_Service", L"ResumeService", -1, L"ReturnValue", CIM_UINT32 }, { L"Win32_Service", L"StartService", -1, L"ReturnValue", CIM_UINT32 }, @@ -3163,6 +3169,7 @@ static enum fill_status fill_process( struct table *table, const struct expr *co rec->thread_count = entry.cntThreads; rec->workingsetsize = 0; rec->get_owner = process_get_owner; + rec->create = process_create; if (!match_row( table, row, cond, &status )) { free_row_values( table, row ); diff --git a/dlls/wbemprox/process.c b/dlls/wbemprox/process.c index 2f11530da2f..5dd8d69779b 100644 --- a/dlls/wbemprox/process.c +++ b/dlls/wbemprox/process.c @@ -110,3 +110,117 @@ 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( ¤t_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, ¤t_directory, &type, NULL )) + || V_VT( ¤t_directory ) != VT_BSTR) + WARN("Invalid CurrentDirectory, hr %#x, type %u.\n", hr, V_VT( ¤t_directory )); + else + TRACE( "CurrentDirectory %s.\n", debugstr_w( V_BSTR( ¤t_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( ¤t_directory ) == VT_BSTR ? V_BSTR( ¤t_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( ¤t_directory ); + VariantClear( &startup_info ); + TRACE( "ret %#x.\n", ret ); + return ret; +} diff --git a/dlls/wbemprox/tests/query.c b/dlls/wbemprox/tests/query.c index 85b242aba6f..784ebd3503d 100644 --- a/dlls/wbemprox/tests/query.c +++ b/dlls/wbemprox/tests/query.c @@ -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, ¶ms ); + 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, diff --git a/dlls/wbemprox/wbemprox_private.h b/dlls/wbemprox/wbemprox_private.h index fec67f47e1b..ded413c99a7 100644 --- a/dlls/wbemprox/wbemprox_private.h +++ b/dlls/wbemprox/wbemprox_private.h @@ -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;