Best Regards, Kostiantyn Kostiuk.
On Wed, Feb 11, 2026 at 11:05 AM 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 | 43 +++++++++++++++++++++++++++++++++++++ > qga/vss-win32/requester.cpp | 15 ++----------- > 2 files changed, 45 insertions(+), 13 deletions(-) > > diff --git a/qga/main.c b/qga/main.c > index dd1c216f9a..210d9983ab 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" > @@ -842,6 +844,24 @@ VOID WINAPI service_main(DWORD argc, TCHAR *argv[]) > return; > } > > + /* Initialize COM for VSS operations in the service thread */ > + HRESULT hr_com = CoInitialize(NULL); > + if (FAILED(hr_com)) { > + g_critical("Failed to initialize COM in service thread: 0x%lx", > hr_com); > + return; > + } > + > + hr_com = CoInitializeSecurity( > + NULL, -1, NULL, NULL, > + RPC_C_AUTHN_LEVEL_PKT_PRIVACY, > + RPC_C_IMP_LEVEL_IDENTIFY, > + NULL, EOAC_NONE, NULL); > + if (FAILED(hr_com)) { > + g_critical("Failed to initialize COM security in service thread: > 0x%lx", hr_com); > + CoUninitialize(); > + return; > + } > + > Lets preven code duplication and definitely for CoInitializeSecurity with a huge amount of arguments, so wrap this into a new function. > service->status.dwServiceType = SERVICE_WIN32; > service->status.dwCurrentState = SERVICE_RUNNING; > service->status.dwControlsAccepted = SERVICE_ACCEPT_STOP | > SERVICE_ACCEPT_SHUTDOWN; > @@ -866,6 +886,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); > @@ -1714,12 +1736,33 @@ int main(int argc, char **argv) > > #ifdef _WIN32 > if (config->daemonize) { > + /* Service mode */ > SERVICE_TABLE_ENTRY service_table[] = { > { (char *)QGA_SERVICE_NAME, service_main }, { NULL, NULL } }; > StartServiceCtrlDispatcher(service_table); > ret = EXIT_SUCCESS; > } else { > + HRESULT hr_com = CoInitialize(NULL); > + if (FAILED(hr_com)) { > + g_critical("Failed to initialize COM: 0x%lx", hr_com); > + ret = EXIT_FAILURE; > + goto end; > + } > + > + hr_com = CoInitializeSecurity( > + NULL, -1, NULL, NULL, > + RPC_C_AUTHN_LEVEL_PKT_PRIVACY, > + RPC_C_IMP_LEVEL_IDENTIFY, > + NULL, EOAC_NONE, NULL); > + if (FAILED(hr_com)) { > + g_critical("Failed to initialize COM security: 0x%lx", > hr_com); > + CoUninitialize(); > + 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..9d978759f1 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,7 @@ out: > > out1: > requester_cleanup(); > - CoUninitialize(); > + /* COM is managed at process level in main.c - don't call > CoUninitialize here */ > > qga_debug_end; > } > @@ -643,7 +632,7 @@ void requester_thaw(int *num_vols, void *mountpints, > ErrorSet *errset) > *num_vols = vss_ctx.cFrozenVols; > requester_cleanup(); > > - CoUninitialize(); > + /* COM is managed at process level in main.c - don't call > CoUninitialize here */ > StopService(); > > qga_debug_end; > -- > 2.51.0 > > >
