From: Paul Gofman <pgofman(a)codeweavers.com>
Fixes FunCom launcher failure to launch games.
v2: Keep table data sorted.
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/wbemprox/builtin.c | 14 +++-
dlls/wbemprox/process.c | 110 +++++++++++++++++++++++++++
dlls/wbemprox/tests/query.c | 123 ++++++++++++++++++++++++++++++-
dlls/wbemprox/wbemprox_private.h | 1 +
4 files changed, 244 insertions(+), 4 deletions(-)
diff --git a/dlls/wbemprox/builtin.c b/dlls/wbemprox/builtin.c
index 3922331f650..862c461d8b7 100644
--- a/dlls/wbemprox/builtin.c
+++ b/dlls/wbemprox/builtin.c
@@ -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 ))
{
diff --git a/dlls/wbemprox/process.c b/dlls/wbemprox/process.c
index 2f11530da2f..5d8af54f217 100644
--- a/dlls/wbemprox/process.c
+++ b/dlls/wbemprox/process.c
@@ -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( ¤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;
--
2.30.2