]> git.proxmox.com Git - mirror_qemu.git/blobdiff - qga/vss-win32/install.cpp
qga/vss-win32: fix warning for clang++-15
[mirror_qemu.git] / qga / vss-win32 / install.cpp
index b0e4426c72dd22ed3b89b8d62f36b42caa9c8365..b8087e5baaa84a0f6dbd72a83bc91b511f15c145 100644 (file)
  * See the COPYING file in the top-level directory.
  */
 
-#include <stdio.h>
-#include <string.h>
+#include "qemu/osdep.h"
 
 #include "vss-common.h"
-#include "inc/win2003/vscoordint.h"
-
-#include <comadmin.h>
+#ifdef HAVE_VSS_SDK
+#include <vscoordint.h>
+#else
+#include <vsadmin.h>
+#endif
+#include "install.h"
 #include <wbemidl.h>
 #include <comdef.h>
 #include <comutil.h>
+#include <sddl.h>
+#include <winsvc.h>
+
+#define BUFFER_SIZE 1024
 
 extern HINSTANCE g_hinstDll;
 
@@ -40,7 +46,8 @@ void errmsg(DWORD err, const char *text)
      * If text doesn't contains '(', negative precision is given, which is
      * treated as though it were missing.
      */
-    char *msg = NULL, *nul = strchr(text, '(');
+    char *msg = NULL;
+    const char *nul = strchr(text, '(');
     int len = nul ? nul - text : -1;
 
     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
@@ -137,6 +144,32 @@ out:
     return hr;
 }
 
+/* Acquire group or user name by SID */
+static HRESULT getNameByStringSID(
+    const wchar_t *sid, LPWSTR buffer, LPDWORD bufferLen)
+{
+    HRESULT hr = S_OK;
+    PSID psid = NULL;
+    SID_NAME_USE groupType;
+    DWORD domainNameLen = BUFFER_SIZE;
+    wchar_t domainName[BUFFER_SIZE];
+
+    if (!ConvertStringSidToSidW(sid, &psid)) {
+        hr = HRESULT_FROM_WIN32(GetLastError());
+        goto out;
+    }
+    if (!LookupAccountSidW(NULL, psid, buffer, bufferLen,
+                           domainName, &domainNameLen, &groupType)) {
+        hr = HRESULT_FROM_WIN32(GetLastError());
+        /* Fall through and free psid */
+    }
+
+    LocalFree(psid);
+
+out:
+    return hr;
+}
+
 /* Find and iterate QGA VSS provider in COM+ Application Catalog */
 static HRESULT QGAProviderFind(
     HRESULT (*found)(ICatalogCollection *, int, void *), void *arg)
@@ -218,6 +251,10 @@ STDAPI COMRegister(void)
     CHAR dllPath[MAX_PATH], tlbPath[MAX_PATH];
     bool unregisterOnFailure = false;
     int count = 0;
+    DWORD bufferLen = BUFFER_SIZE;
+    wchar_t buffer[BUFFER_SIZE];
+    const wchar_t *administratorsGroupSID = L"S-1-5-32-544";
+    const wchar_t *systemUserSID = L"S-1-5-18";
 
     if (!g_hinstDll) {
         errmsg(E_FAIL, "Failed to initialize DLL");
@@ -278,7 +315,7 @@ STDAPI COMRegister(void)
 
     chk(pCatalog->CreateServiceForApplication(
             _bstr_t(QGA_PROVIDER_LNAME), _bstr_t(QGA_PROVIDER_LNAME),
-            _bstr_t(L"SERVICE_AUTO_START"), _bstr_t(L"SERVICE_ERROR_NORMAL"),
+            _bstr_t(L"SERVICE_DEMAND_START"), _bstr_t(L"SERVICE_ERROR_NORMAL"),
             _bstr_t(L""), _bstr_t(L".\\localsystem"), _bstr_t(L""), FALSE));
     chk(pCatalog->InstallComponent(_bstr_t(QGA_PROVIDER_LNAME),
                                    _bstr_t(dllPath), _bstr_t(tlbPath),
@@ -286,11 +323,12 @@ STDAPI COMRegister(void)
 
     /* Setup roles of the applicaion */
 
+    chk(getNameByStringSID(administratorsGroupSID, buffer, &bufferLen));
     chk(pApps->GetCollection(_bstr_t(L"Roles"), key,
                              (IDispatch **)pRoles.replace()));
     chk(pRoles->Populate());
     chk(pRoles->Add((IDispatch **)pObj.replace()));
-    chk(put_Value(pObj, L"Name",        L"Administrators"));
+    chk(put_Value(pObj, L"Name", buffer));
     chk(put_Value(pObj, L"Description", L"Administrators group"));
     chk(pRoles->SaveChanges(&n));
     chk(pObj->get_Key(&key));
@@ -305,8 +343,10 @@ STDAPI COMRegister(void)
     chk(GetAdminName(&name));
     chk(put_Value(pObj, L"User", _bstr_t(".\\") + name));
 
+    bufferLen = BUFFER_SIZE;
+    chk(getNameByStringSID(systemUserSID, buffer, &bufferLen));
     chk(pUsersInRole->Add((IDispatch **)pObj.replace()));
-    chk(put_Value(pObj, L"User", L"SYSTEM"));
+    chk(put_Value(pObj, L"User", buffer));
     chk(pUsersInRole->SaveChanges(&n));
 
 out:
@@ -409,6 +449,17 @@ STDAPI DllRegisterServer(void)
                                      VSS_PROV_SOFTWARE,
                                      const_cast<WCHAR*>(QGA_PROVIDER_VERSION),
                                      g_gProviderVersion);
+    if (hr == (long int) VSS_E_PROVIDER_ALREADY_REGISTERED) {
+        DllUnregisterServer();
+        hr = pVssAdmin->RegisterProvider(g_gProviderId, CLSID_QGAVSSProvider,
+                                         const_cast<WCHAR * >
+                                         (QGA_PROVIDER_LNAME),
+                                         VSS_PROV_SOFTWARE,
+                                         const_cast<WCHAR * >
+                                         (QGA_PROVIDER_VERSION),
+                                         g_gProviderVersion);
+    }
+
     if (FAILED(hr)) {
         errmsg_dialog(hr, "RegisterProvider failed");
     }
@@ -463,3 +514,33 @@ namespace _com_util
         return bstr;
     }
 }
+
+/* Stop QGA VSS provider service using Winsvc API  */
+STDAPI StopService(void)
+{
+    HRESULT hr = S_OK;
+    SC_HANDLE manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+    SC_HANDLE service = NULL;
+
+    if (!manager) {
+        errmsg(E_FAIL, "Failed to open service manager");
+        hr = E_FAIL;
+        goto out;
+    }
+    service = OpenService(manager, QGA_PROVIDER_NAME, SC_MANAGER_ALL_ACCESS);
+
+    if (!service) {
+        errmsg(E_FAIL, "Failed to open service");
+        hr =  E_FAIL;
+        goto out;
+    }
+    if (!(ControlService(service, SERVICE_CONTROL_STOP, NULL))) {
+        errmsg(E_FAIL, "Failed to stop service");
+        hr = E_FAIL;
+    }
+
+out:
+    CloseServiceHandle(service);
+    CloseServiceHandle(manager);
+    return hr;
+}