mirror of
https://github.com/qemu/qemu.git
synced 2026-04-05 22:00:58 +00:00
qga: Move CoInitialize/CoInitializeSecurity to main process thread
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>
This commit is contained in:
committed by
Kostiantyn Kostiuk
parent
595a77289d
commit
0257ec9905
42
qga/main.c
42
qga/main.c
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user