]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
qga: Move CoInitialize/CoInitializeSecurity to main process thread
authorElizabeth Ashurov <eashurov@redhat.com>
Wed, 11 Feb 2026 10:17:43 +0000 (12:17 +0200)
committerKostiantyn Kostiuk <kkostiuk@redhat.com>
Wed, 18 Feb 2026 09:27:57 +0000 (11:27 +0200)
Problem:
Two issues with COM initialization:

Issue #1: Incorrect call order
- requester_init() called CoInitializeSecurity first
- Per Microsoft documentation, CoInitialize() must be called BEFORE
  CoInitializeSecurity()

Issue #2: Incorrect call location
- CoInitializeSecurity was called from dll instead of the main process
- Per Microsoft documentation, CoInitializeSecurity() must be called exactly once per process from
  the main executable, not from a DLL

Reference:
https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-coinitializesecurity
https://learn.microsoft.com/en-us/windows/win32/api/objbase/nf-objbase-coinitialize

This caused incorrect COM initialization, preventing VSS Writers from
calling back via IVssWriterCallback (hr = 0x80070005, Access denied,
Event ID 8194).

Fix:
- Initialize COM in main.c for both service and CLI modes
- Call CoInitialize() followed by CoInitializeSecurity() in correct order
  in the main thread before any VSS operations
- Add proper CoUninitialize() cleanup

Result:
VSS Writers can now successfully call back to the agent. Event ID 8194
error is resolved.

Signed-off-by: Elizabeth Ashurov <eashurov@redhat.com>
Reviewed-by: Kostiantyn Kostiuk <kkostiuk@redhat.com>
Tested-by: Dehan Meng <demeng@redhat.com>
Link: https://lore.kernel.org/qemu-devel/20260211101744.757548-1-eashurov@redhat.com
Signed-off-by: Kostiantyn Kostiuk <kkostiuk@redhat.com>
qga/main.c
qga/vss-win32/requester.cpp

index dd1c216f9a13a643f605d696f5dad71b29360919..fd19c7037db1d25ac3c1ae01098e5fa73719d7c7 100644 (file)
@@ -32,6 +32,8 @@
 #include "qemu/systemd.h"
 #include "qemu-version.h"
 #ifdef _WIN32
+#include <windows.h>
+#include <objbase.h>
 #include <dbt.h>
 #include <pdh.h>
 #include "qga/service-win32.h"
@@ -830,6 +832,29 @@ DWORD WINAPI service_ctrl_handler(DWORD ctrl, DWORD type, LPVOID data,
     return ret;
 }
 
+/* Initialize COM for VSS operations */
+static HRESULT init_com(void)
+{
+    HRESULT hr;
+
+    hr = CoInitialize(NULL);
+    if (FAILED(hr)) {
+        return hr;
+    }
+
+    hr = CoInitializeSecurity(
+        NULL, -1, NULL, NULL,
+        RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
+        RPC_C_IMP_LEVEL_IDENTIFY,
+        NULL, EOAC_NONE, NULL);
+    if (FAILED(hr)) {
+        CoUninitialize();
+        return hr;
+    }
+
+    return S_OK;
+}
+
 VOID WINAPI service_main(DWORD argc, TCHAR *argv[])
 {
     GAService *service = &ga_state->service;
@@ -842,6 +867,13 @@ VOID WINAPI service_main(DWORD argc, TCHAR *argv[])
         return;
     }
 
+    /* Initialize COM for VSS operations in the service thread */
+    HRESULT hr_com = init_com();
+    if (FAILED(hr_com)) {
+        g_critical("Failed to initialize COM in service thread: 0x%lx", hr_com);
+        return;
+    }
+
     service->status.dwServiceType = SERVICE_WIN32;
     service->status.dwCurrentState = SERVICE_RUNNING;
     service->status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
@@ -866,6 +898,8 @@ VOID WINAPI service_main(DWORD argc, TCHAR *argv[])
 
     run_agent(ga_state);
 
+    CoUninitialize();
+
     UnregisterDeviceNotification(service->device_notification_handle);
     service->status.dwCurrentState = SERVICE_STOPPED;
     SetServiceStatus(service->status_handle, &service->status);
@@ -1719,7 +1753,15 @@ int main(int argc, char **argv)
         StartServiceCtrlDispatcher(service_table);
         ret = EXIT_SUCCESS;
     } else {
+        HRESULT hr_com = init_com();
+        if (FAILED(hr_com)) {
+            g_critical("Failed to initialize COM: 0x%lx", hr_com);
+            ret = EXIT_FAILURE;
+            goto end;
+        }
+
         ret = run_agent(s);
+        CoUninitialize();
     }
 #else
     ret = run_agent(s);
index 74489fcd0ae69208c0dd041b6e5c1b1d2858ff02..626d6ab1ff4bf0f4ecc9bf080557023e8f13b91f 100644 (file)
@@ -60,15 +60,6 @@ STDAPI requester_init(void)
 {
     qga_debug_begin;
 
-    COMInitializer initializer; /* to call CoInitializeSecurity */
-    HRESULT hr = CoInitializeSecurity(
-        NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
-        RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE, NULL);
-    if (FAILED(hr)) {
-        qga_debug("failed to CoInitializeSecurity (error %lx)", hr);
-        return hr;
-    }
-
     hLib = LoadLibraryA("VSSAPI.DLL");
     if (!hLib) {
         qga_debug("failed to load VSSAPI.DLL");
@@ -320,8 +311,6 @@ void requester_freeze(int *num_vols, void *mountpoints, ErrorSet *errset)
         return;
     }
 
-    CoInitialize(NULL);
-
     /* Allow unrestricted access to events */
     InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
     SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
@@ -562,7 +551,6 @@ out:
 
 out1:
     requester_cleanup();
-    CoUninitialize();
 
     qga_debug_end;
 }
@@ -643,7 +631,6 @@ void requester_thaw(int *num_vols, void *mountpints, ErrorSet *errset)
     *num_vols = vss_ctx.cFrozenVols;
     requester_cleanup();
 
-    CoUninitialize();
     StopService();
 
     qga_debug_end;