On 9/25/23 16:04, Richard W.M. Jones wrote:
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.
*)
[*] Just guessing, but I'm not sure if assuming UTC is right when the
key is found but its type is unrecognized, in light of determining
localtime when the key is absent or has type REG_NONE.
Either way, the warning is honest about it!
@@ -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>
With the BIOS -> RTC typo (?) fixed everywhere:
series
Reviewed-by: Laszlo Ersek <lersek(a)redhat.com>