[glib: 1/9] GWin32AppInfo: Ensure COM is initialized when activating UWP apps




commit d3ae4cc8097909b42d0d8fc279cd25cb1ce6301f
Author: Luca Bacci <luca bacci982 gmail com>
Date:   Thu Jul 14 14:25:05 2022 +0200

    GWin32AppInfo: Ensure COM is initialized when activating UWP apps
    
    Using the Application Activation Manager coclass. Its threading model
    is marked as 'both', so it can be instantiated in any apartment type
    without marshaling.

 gio/gwin32appinfo.c | 60 +++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 51 insertions(+), 9 deletions(-)
---
diff --git a/gio/gwin32appinfo.c b/gio/gwin32appinfo.c
index 0960eef5c6..265cae686d 100644
--- a/gio/gwin32appinfo.c
+++ b/gio/gwin32appinfo.c
@@ -4693,35 +4693,77 @@ g_win32_app_info_launch_uwp_internal (GWin32AppInfo           *info,
                                       GWin32AppInfoShellVerb  *shverb,
                                       GError                 **error)
 {
-  DWORD pid;
   IApplicationActivationManager* paam = NULL;
-  gboolean result = TRUE;
+  gboolean com_initialized = FALSE;
+  gboolean result = FALSE;
+  DWORD pid = 0;
   HRESULT hr;
+  const wchar_t *app_canonical_name = (const wchar_t *) info->app->canonical_name;
+
+  /* ApplicationActivationManager threading model is both,
+   * prefer the multithreaded apartment type, as we don't
+   * need anything of the STA here. */
+  hr = CoInitializeEx (NULL, COINIT_MULTITHREADED);
+  if (SUCCEEDED (hr))
+    com_initialized = TRUE;
+  else if (hr != RPC_E_CHANGED_MODE)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Failed to initialize the COM support library for the thread: 0x%lx", hr);
+      goto cleanup;
+    }
 
-  hr = CoCreateInstance (&CLSID_ApplicationActivationManager, NULL, CLSCTX_INPROC_SERVER, 
&IID_IApplicationActivationManager, (void **) &paam);
+  hr = CoCreateInstance (&CLSID_ApplicationActivationManager, NULL,
+                         CLSCTX_INPROC_SERVER,
+                         &IID_IApplicationActivationManager, (void **) &paam);
   if (FAILED (hr))
     {
       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                    "Failed to create ApplicationActivationManager: 0x%lx", hr);
-      return FALSE;
+      goto cleanup;
     }
 
+  /* The Activate methods return a process identifier (PID), so we should consider
+   * those methods as potentially blocking */
   if (items == NULL)
-    hr = IApplicationActivationManager_ActivateApplication (paam, (const wchar_t *) 
info->app->canonical_name, NULL, AO_NONE, &pid);
+    hr = IApplicationActivationManager_ActivateApplication (paam,
+                                                            app_canonical_name,
+                                                            NULL, AO_NONE,
+                                                            &pid);
   else if (for_files)
-    hr = IApplicationActivationManager_ActivateForFile (paam, (const wchar_t *) info->app->canonical_name, 
items, shverb->verb_name, &pid);
+    hr = IApplicationActivationManager_ActivateForFile (paam,
+                                                        app_canonical_name,
+                                                        items, shverb->verb_name,
+                                                        &pid);
   else
-    hr = IApplicationActivationManager_ActivateForProtocol (paam, (const wchar_t *) 
info->app->canonical_name, items, &pid);
+    hr = IApplicationActivationManager_ActivateForProtocol (paam,
+                                                            app_canonical_name,
+                                                            items,
+                                                            &pid);
 
   if (FAILED (hr))
     {
       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                    "The app %s failed to launch: 0x%lx",
                    g_win32_appinfo_application_get_some_name (info->app), hr);
-      result = FALSE;
+      goto cleanup;
+    }
+
+  result = TRUE;
+
+cleanup:
+
+  if (paam)
+    {
+      IApplicationActivationManager_Release (paam);
+      paam = NULL;
     }
 
-  IApplicationActivationManager_Release (paam);
+  if (com_initialized)
+    {
+      CoUninitialize ();
+      com_initialized = FALSE;
+    }
 
   return result;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]