[PATCH v2 2/2] wbemprox: Partially implement Win32_Process.Create method.

Hans Leidekker hans at codeweavers.com
Tue May 18 02:49:45 CDT 2021


From: Paul Gofman <pgofman at codeweavers.com>

Fixes FunCom launcher failure to launch games.

v2: Keep table data sorted.

Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
Signed-off-by: Hans Leidekker <hans at 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( &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;
+}
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, &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,
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




More information about the wine-devel mailing list