Tested-by: Dehan Meng <[email protected]> On Wed, Feb 11, 2026 at 6:49 PM Kostiantyn Kostiuk <[email protected]> wrote:
> Reviewed-by: Kostiantyn Kostiuk <[email protected]> > > On Wed, Feb 11, 2026 at 12:18 PM Elizabeth Ashurov <[email protected]> > wrote: > >> 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 <[email protected]> >> --- >> qga/main.c | 42 +++++++++++++++++++++++++++++++++++++ >> qga/vss-win32/requester.cpp | 13 ------------ >> 2 files changed, 42 insertions(+), 13 deletions(-) >> >> diff --git a/qga/main.c b/qga/main.c >> index dd1c216f9a..fd19c7037d 100644 >> --- a/qga/main.c >> +++ b/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); >> diff --git a/qga/vss-win32/requester.cpp b/qga/vss-win32/requester.cpp >> index 74489fcd0a..626d6ab1ff 100644 >> --- a/qga/vss-win32/requester.cpp >> +++ b/qga/vss-win32/requester.cpp >> @@ -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; >> -- >> 2.51.0 >> >>
