Read HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation key
"RealTimeIsUniversal" to see if the Windows guest is expecting BIOS
set to localtime (not present) or UTC (present and set to 1).
See:
https://wiki.archlinux.org/title/System_time#UTC_in_Microsoft_Windows
See:
https://listman.redhat.com/archives/libguestfs/2023-September/thread.html...
Reported-by: Lee Garrett
---
convert/convert_windows.ml | 38 +++++++++++++++++++++++++++++++++++++-
tests/test-v2v-i-ova.xml | 2 +-
2 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/convert/convert_windows.ml b/convert/convert_windows.ml
index f6e039be7e..84e8f7b7d3 100644
--- a/convert/convert_windows.ml
+++ b/convert/convert_windows.ml
@@ -103,6 +103,42 @@ let convert (g : G.guestfs) _ inspect i_firmware block_driver _
static_ips =
(* If the Windows guest has AV installed. *)
let has_antivirus = Windows.detect_antivirus inspect in
+ (* Does the guest expect the BIOS to be set to UTC or localtime?
+ * See
https://wiki.archlinux.org/title/System_time#UTC_in_Microsoft_Windows
+ * Note this might be a QWORD on 64 bit Windows instances.
+ *)
+ let bios_utc =
+ Registry.with_hive_readonly g inspect.i_windows_system_hive
+ (fun reg ->
+ try
+ let key_path = [ "Control"; "TimeZoneInformation" ] in
+ let path = inspect.i_windows_current_control_set :: key_path in
+ let node =
+ match Registry.get_node reg path with
+ | None -> raise Not_found
+ | Some node -> node in
+ let valueh = g#hivex_node_get_value node "RealTimeIsUniversal" in
+ if valueh = 0L then raise Not_found;
+ let t = g#hivex_value_type valueh in
+ let data = g#hivex_value_value valueh in
+ let is_utc =
+ match t with
+ | 0_L (* REG_NONE *) -> false (* localtime *)
+ | 4_L (* REG_DWORD *) -> data = "\001\000\000\000"
+ | 11_L (* REG_QWORD *) -> data =
"\001\000\000\000\000\000\000\000"
+ | _ (* who knows ... *) ->
+ warning (f_"unknown CurrentControlSet\\Control\\\
+ TimeZoneInformation key RealTimeIsUniversal \
+ type 0x%Lx, assuming BIOS set to UTC") t;
+ true in
+ is_utc
+ with Not_found ->
+ (* If the key is not found then by default we assume
+ * that Windows is expecting the BIOS to be set to localtime.
+ *)
+ false
+ ) in
+
(* Open the software hive (readonly) and find the Xen PV uninstaller,
* if it exists.
*)
@@ -275,7 +311,7 @@ let convert (g : G.guestfs) _ inspect i_firmware block_driver _
static_ips =
gcaps_arch = Utils.kvm_arch inspect.i_arch;
gcaps_arch_min_version = 0;
gcaps_virtio_1_0 = virtio_win_installed.Inject_virtio_win.virtio_1_0;
- gcaps_bios_utc = true;
+ gcaps_bios_utc = bios_utc;
} in
guestcaps
diff --git a/tests/test-v2v-i-ova.xml b/tests/test-v2v-i-ova.xml
index a41827bfd5..fa7b4dbfc5 100644
--- a/tests/test-v2v-i-ova.xml
+++ b/tests/test-v2v-i-ova.xml
@@ -18,7 +18,7 @@
<os>
<type arch='x86_64' machine='q35'>hvm</type>
</os>
- <clock offset='utc'/>
+ <clock offset='localtime'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
--
2.41.0