vss-win32.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * QEMU Guest Agent VSS utility functions
  3. *
  4. * Copyright Hitachi Data Systems Corp. 2013
  5. *
  6. * Authors:
  7. * Tomoki Sekiyama <tomoki.sekiyama@hds.com>
  8. *
  9. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  10. * See the COPYING file in the top-level directory.
  11. */
  12. #include "qemu/osdep.h"
  13. #include <windows.h>
  14. #include "qapi/error.h"
  15. #include "qemu/error-report.h"
  16. #include "guest-agent-core.h"
  17. #include "vss-win32.h"
  18. #include "vss-win32/requester.h"
  19. #define QGA_VSS_DLL "qga-vss.dll"
  20. static HMODULE provider_lib;
  21. /* Call a function in qga-vss.dll with the specified name */
  22. static HRESULT call_vss_provider_func(const char *func_name)
  23. {
  24. FARPROC WINAPI func;
  25. g_assert(provider_lib);
  26. func = GetProcAddress(provider_lib, func_name);
  27. if (!func) {
  28. char *msg;
  29. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  30. FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
  31. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  32. (char *)&msg, 0, NULL);
  33. fprintf(stderr, "failed to load %s from %s: %s",
  34. func_name, QGA_VSS_DLL, msg);
  35. LocalFree(msg);
  36. return E_FAIL;
  37. }
  38. return func();
  39. }
  40. /* Check whether this OS version supports VSS providers */
  41. static bool vss_check_os_version(void)
  42. {
  43. OSVERSIONINFO OSver;
  44. OSver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  45. GetVersionEx(&OSver);
  46. if ((OSver.dwMajorVersion == 5 && OSver.dwMinorVersion >= 2) ||
  47. OSver.dwMajorVersion > 5) {
  48. BOOL wow64 = false;
  49. #ifndef _WIN64
  50. /* Provider doesn't work under WOW64 (32bit agent on 64bit OS) */
  51. if (!IsWow64Process(GetCurrentProcess(), &wow64)) {
  52. fprintf(stderr, "failed to IsWow64Process (Error: %lx\n)\n",
  53. GetLastError());
  54. return false;
  55. }
  56. if (wow64) {
  57. warn_report("Running under WOW64");
  58. }
  59. #endif
  60. return !wow64;
  61. }
  62. return false;
  63. }
  64. /* Load qga-vss.dll */
  65. bool vss_init(bool init_requester)
  66. {
  67. if (!vss_check_os_version()) {
  68. /* Do nothing if OS doesn't support providers. */
  69. fprintf(stderr, "VSS provider is not supported in this OS version: "
  70. "fsfreeze is disabled.\n");
  71. return false;
  72. }
  73. provider_lib = LoadLibraryA(QGA_VSS_DLL);
  74. if (!provider_lib) {
  75. char *msg;
  76. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  77. FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
  78. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  79. (char *)&msg, 0, NULL);
  80. fprintf(stderr, "failed to load %s: %sfsfreeze is disabled\n",
  81. QGA_VSS_DLL, msg);
  82. LocalFree(msg);
  83. return false;
  84. }
  85. if (init_requester) {
  86. HRESULT hr = call_vss_provider_func("requester_init");
  87. if (FAILED(hr)) {
  88. fprintf(stderr, "fsfreeze is disabled.\n");
  89. vss_deinit(false);
  90. return false;
  91. }
  92. }
  93. return true;
  94. }
  95. /* Unload qga-provider.dll */
  96. void vss_deinit(bool deinit_requester)
  97. {
  98. if (deinit_requester) {
  99. call_vss_provider_func("requester_deinit");
  100. }
  101. FreeLibrary(provider_lib);
  102. provider_lib = NULL;
  103. }
  104. bool vss_initialized(void)
  105. {
  106. return !!provider_lib;
  107. }
  108. int ga_install_vss_provider(void)
  109. {
  110. HRESULT hr;
  111. if (!vss_init(false)) {
  112. fprintf(stderr, "Installation of VSS provider is skipped. "
  113. "fsfreeze will be disabled.\n");
  114. return 0;
  115. }
  116. hr = call_vss_provider_func("COMRegister");
  117. vss_deinit(false);
  118. return SUCCEEDED(hr) ? 0 : EXIT_FAILURE;
  119. }
  120. void ga_uninstall_vss_provider(void)
  121. {
  122. if (!vss_init(false)) {
  123. fprintf(stderr, "Removal of VSS provider is skipped.\n");
  124. return;
  125. }
  126. call_vss_provider_func("COMUnregister");
  127. vss_deinit(false);
  128. }
  129. /* Call VSS requester and freeze/thaw filesystems and applications */
  130. void qga_vss_fsfreeze(int *nr_volume, bool freeze,
  131. strList *mountpoints, Error **errp)
  132. {
  133. const char *func_name = freeze ? "requester_freeze" : "requester_thaw";
  134. QGAVSSRequesterFunc func;
  135. ErrorSet errset = {
  136. .error_setg_win32_wrapper = error_setg_win32_internal,
  137. .errp = errp,
  138. };
  139. g_assert(errp); /* requester.cpp requires it */
  140. func = (QGAVSSRequesterFunc)GetProcAddress(provider_lib, func_name);
  141. if (!func) {
  142. error_setg_win32(errp, GetLastError(), "failed to load %s from %s",
  143. func_name, QGA_VSS_DLL);
  144. return;
  145. }
  146. func(nr_volume, mountpoints, &errset);
  147. }