Richard W.M. Jones
2017-Feb-18 08:05 UTC
[Libguestfs] [PATCH 0/8] Miscellaneous cleanups to Windows registry code.
A very miscellaneous set of cleanups to how we handle the Windows registry in virt-v2v, firstboot, and inspection code. This should all be straightforward non-controversial refactoring. Some highlights: - Add a new mllib Registry module containing various utility functions that are currently scattered all around. - Only compute the software/system hive paths once during inspection, and make those paths available to the tools through new APIs. - Simplify parameter passing inside virt-v2v so we pass around fewer long lists of parameters. Rich.
Richard W.M. Jones
2017-Feb-18 08:05 UTC
[Libguestfs] [PATCH 1/8] mllib: Move Windows Registry functions from v2v to common code.
Move the functions decode_utf16le, encode_utf16le, get_node,
with_hive_readonly and with_hive_write to common code in a new module
called Registry.
This also defines types for nodes and values, instead of using int64
directly.
Just code motion.
---
mllib/Makefile.am | 2 ++
mllib/regedit.ml | 32 ++------------------
mllib/regedit.mli | 8 +----
mllib/registry.ml | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++
mllib/registry.mli | 45 +++++++++++++++++++++++++++
v2v/convert_windows.ml | 44 +++++++++++++--------------
v2v/windows.ml | 31 -------------------
v2v/windows.mli | 17 -----------
v2v/windows_virtio.mli | 2 +-
9 files changed, 156 insertions(+), 107 deletions(-)
create mode 100644 mllib/registry.ml
create mode 100644 mllib/registry.mli
diff --git a/mllib/Makefile.am b/mllib/Makefile.am
index aa5472a..ff687b6 100644
--- a/mllib/Makefile.am
+++ b/mllib/Makefile.am
@@ -43,6 +43,7 @@ SOURCES_MLI = \
planner.mli \
progress.mli \
regedit.mli \
+ registry.mli \
StatVFS.mli \
stringMap.mli \
URI.mli \
@@ -64,6 +65,7 @@ SOURCES_ML = \
visit.ml \
fnmatch.ml \
planner.ml \
+ registry.ml \
regedit.ml \
StatVFS.ml \
JSON.ml \
diff --git a/mllib/regedit.ml b/mllib/regedit.ml
index 1ec7d4b..a97699c 100644
--- a/mllib/regedit.ml
+++ b/mllib/regedit.ml
@@ -32,32 +32,6 @@ and regtype | REG_DWORD of int32
| REG_MULTI_SZ of string list
-(* Take a 7 bit ASCII string and encode it as UTF16LE. *)
-let encode_utf16le str - let len = String.length str in
- let copy = Bytes.make (len*2) '\000' in
- for i = 0 to len-1 do
- Bytes.unsafe_set copy (i*2) (String.unsafe_get str i)
- done;
- Bytes.to_string copy
-
-(* Take a UTF16LE string and decode it to UTF-8. Actually this
- * fails if the string is not 7 bit ASCII. XXX Use iconv here.
- *)
-let decode_utf16le str - let len = String.length str in
- if len mod 2 <> 0 then
- error (f_"decode_utf16le: Windows string does not appear to be in
UTF16-LE encoding. This could be a bug in %s.") prog;
- let copy = Bytes.create (len/2) in
- for i = 0 to (len/2)-1 do
- let cl = String.unsafe_get str (i*2) in
- let ch = String.unsafe_get str ((i*2)+1) in
- if ch != '\000' || Char.code cl >= 127 then
- error (f_"decode_utf16le: Windows UTF16-LE string contains non-7-bit
characters. This is a bug in %s, please report it.") prog;
- Bytes.unsafe_set copy i cl
- done;
- Bytes.to_string copy
-
let rec import_key (g : Guestfs.guestfs) root (path, values) (* Create the
path starting at the root node. *)
let node @@ -91,9 +65,9 @@ and import_value g node = function
* bytes at the end of string fields.
*)
| key, REG_SZ s ->
- g#hivex_node_set_value node key 1L (encode_utf16le s ^
"\000\000")
+ g#hivex_node_set_value node key 1L (Registry.encode_utf16le s ^
"\000\000")
| key, REG_EXPAND_SZ s ->
- g#hivex_node_set_value node key 2L (encode_utf16le s ^
"\000\000")
+ g#hivex_node_set_value node key 2L (Registry.encode_utf16le s ^
"\000\000")
| key, REG_BINARY bin ->
g#hivex_node_set_value node key 3L bin
| key, REG_DWORD dw ->
@@ -102,7 +76,7 @@ and import_value g node = function
(* http://blogs.msdn.com/oldnewthing/archive/2009/10/08/9904646.aspx *)
List.iter (fun s -> assert (s <> "")) ss;
let ss = ss @ [""] in
- let ss = List.map (fun s -> encode_utf16le s ^ "\000\000") ss
in
+ let ss = List.map (fun s -> Registry.encode_utf16le s ^
"\000\000") ss in
let ss = String.concat "" ss in
g#hivex_node_set_value node key 7L ss
diff --git a/mllib/regedit.mli b/mllib/regedit.mli
index a65f5d3..6a5e383 100644
--- a/mllib/regedit.mli
+++ b/mllib/regedit.mli
@@ -55,11 +55,5 @@ and regtype UTF-16LE, and integers are automatically
packed and
byte-swapped. *)
-val reg_import : Guestfs.guestfs -> int64 -> regedits -> unit
+val reg_import : Guestfs.guestfs -> Registry.node -> regedits -> unit
(** Import the edits in [regedits] into the currently opened hive. *)
-
-val encode_utf16le : string -> string
-(** Helper: Take a 7 bit ASCII string and encode it as UTF-16LE. *)
-
-val decode_utf16le : string -> string
-(** Helper: Take a UTF-16LE string and decode it to UTF-8. *)
diff --git a/mllib/registry.ml b/mllib/registry.ml
new file mode 100644
index 0000000..a5f195f
--- /dev/null
+++ b/mllib/registry.ml
@@ -0,0 +1,82 @@
+(* virt-v2v
+ * Copyright (C) 2009-2017 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+open Printf
+
+open Common_gettext.Gettext
+open Common_utils
+
+type node = int64
+type value = int64
+
+let with_hive_readonly (g : Guestfs.guestfs) hive_filename f + let verbose =
verbose () in
+ g#hivex_open ~write:false ~unsafe:true ~verbose (* ~debug:verbose *)
+ hive_filename;
+ protect ~f:(
+ fun () ->
+ let root = g#hivex_root () in
+ f root
+ ) ~finally:g#hivex_close
+
+let with_hive_write (g : Guestfs.guestfs) hive_filename f + let verbose =
verbose () in
+ g#hivex_open ~write:true ~verbose (* ~debug:verbose *) hive_filename;
+ protect ~f:(
+ fun () ->
+ let root = g#hivex_root () in
+ let ret = f root in
+ g#hivex_commit None;
+ ret
+ ) ~finally:g#hivex_close
+
+(* Find the given node in the current hive, relative to the starting
+ * point. Returns [None] if the node is not found.
+ *)
+let rec get_node (g : Guestfs.guestfs) node = function
+ | [] -> Some node
+ | x :: xs ->
+ let node = g#hivex_node_get_child node x in
+ if node = 0L then None
+ else get_node g node xs
+
+(* Take a 7 bit ASCII string and encode it as UTF16LE. *)
+let encode_utf16le str + let len = String.length str in
+ let copy = Bytes.make (len*2) '\000' in
+ for i = 0 to len-1 do
+ Bytes.unsafe_set copy (i*2) (String.unsafe_get str i)
+ done;
+ Bytes.to_string copy
+
+(* Take a UTF16LE string and decode it to UTF-8. Actually this
+ * fails if the string is not 7 bit ASCII. XXX Use iconv here.
+ *)
+let decode_utf16le str + let len = String.length str in
+ if len mod 2 <> 0 then
+ error (f_"decode_utf16le: Windows string does not appear to be in
UTF16-LE encoding. This could be a bug in %s.") prog;
+ let copy = Bytes.create (len/2) in
+ for i = 0 to (len/2)-1 do
+ let cl = String.unsafe_get str (i*2) in
+ let ch = String.unsafe_get str ((i*2)+1) in
+ if ch != '\000' || Char.code cl >= 127 then
+ error (f_"decode_utf16le: Windows UTF16-LE string contains non-7-bit
characters. This is a bug in %s, please report it.") prog;
+ Bytes.unsafe_set copy i cl
+ done;
+ Bytes.to_string copy
diff --git a/mllib/registry.mli b/mllib/registry.mli
new file mode 100644
index 0000000..1c9790d
--- /dev/null
+++ b/mllib/registry.mli
@@ -0,0 +1,45 @@
+(* mllib
+ * Copyright (C) 2009-2017 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+(** Common Windows Registry types and functions. *)
+
+type node = int64
+type value = int64
+
+val with_hive_readonly : Guestfs.guestfs -> string -> (node -> 'a)
-> 'a
+val with_hive_write : Guestfs.guestfs -> string -> (node -> 'a)
-> 'a
+(** [with_hive_(readonly|write) g hive_filename f]
+ are wrappers that handle opening and closing the hive
+ named [hive_filename] around a function [f].
+
+ [with_hive_readonly] opens the hive for read-only (attempts
+ to write will throw an error). [with_hive_write] opens the
+ hive for writes, and commits the changes at the end if there
+ were no errors. *)
+
+val get_node : Guestfs.guestfs -> node -> string list -> node option
+(** [get_node g root path] starts at the [root] node of the hive (it does
+ not need to be the actual hive root), and searches down the [path].
+ It returns [Some node] of the final node if found, or [None] if
+ not found. *)
+
+val encode_utf16le : string -> string
+(** Helper: Take a 7 bit ASCII string and encode it as UTF-16LE. *)
+
+val decode_utf16le : string -> string
+(** Helper: Take a UTF-16LE string and decode it to UTF-8. *)
diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
index 424288d..a231219 100644
--- a/v2v/convert_windows.ml
+++ b/v2v/convert_windows.ml
@@ -87,13 +87,13 @@ let convert ~keep_serial_console (g : G.guestfs) inspect
source rcaps
(* If the Windows guest appears to be using group policy. *)
let has_group_policy - Windows.with_hive_readonly g software_hive_filename
+ Registry.with_hive_readonly g software_hive_filename
(fun root ->
try
let path = ["Microsoft"; "Windows";
"CurrentVersion";
"Group Policy"; "History"] in
let node - match Windows.get_node g root path with
+ match Registry.get_node g root path with
| None -> raise Not_found
| Some node -> node in
let children = g#hivex_node_children node in
@@ -130,13 +130,13 @@ let convert ~keep_serial_console (g : G.guestfs) inspect
source rcaps let xenpv_uninst let xenpvreg = "Red Hat
Paravirtualized Xen Drivers for Windows(R)" in
- Windows.with_hive_readonly g software_hive_filename
+ Registry.with_hive_readonly g software_hive_filename
(fun root ->
try
let path = ["Microsoft"; "Windows";
"CurrentVersion"; "Uninstall";
xenpvreg] in
let node - match Windows.get_node g root path with
+ match Registry.get_node g root path with
| None -> raise Not_found
| Some node -> node in
let uninstkey = "UninstallString" in
@@ -147,7 +147,7 @@ let convert ~keep_serial_console (g : G.guestfs) inspect
source rcaps raise Not_found
);
let data = g#hivex_value_value valueh in
- let data = Regedit.decode_utf16le data in
+ let data = Registry.decode_utf16le data in
(* The uninstall program will be uninst.exe. This is a wrapper
* around _uninst.exe which prompts the user. As we don't want
@@ -171,12 +171,12 @@ let convert ~keep_serial_console (g : G.guestfs) inspect
source rcaps let prltools_uninsts let uninsts = ref [] in
- Windows.with_hive_readonly g software_hive_filename
+ Registry.with_hive_readonly g software_hive_filename
(fun root ->
try
let path = ["Microsoft"; "Windows";
"CurrentVersion"; "Uninstall"] in
let node - match Windows.get_node g root path with
+ match Registry.get_node g root path with
| None -> raise Not_found
| Some node -> node in
let uninstnodes = g#hivex_node_children node in
@@ -286,7 +286,7 @@ reg delete \"%s\" /v %s /f" strkey name
let key_path = ["Policies"; "Microsoft";
"Windows"; "DeviceInstall";
"Settings"] in
let name = "SuppressNewHWUI" in
- let value = Windows.with_hive_write g software_hive_filename (
+ let value = Registry.with_hive_write g software_hive_filename (
fun root ->
set_reg_val_dword_1 root key_path name
) in
@@ -296,7 +296,7 @@ reg delete \"%s\" /v %s /f" strkey name
| 5, 2 ->
let key_path = ["Services"; "PlugPlay";
"Parameters"] in
let name = "SuppressUI" in
- let value = Windows.with_hive_write g system_hive_filename (
+ let value = Registry.with_hive_write g system_hive_filename (
fun root ->
let current_cs = get_current_cs root in
set_reg_val_dword_1 root (current_cs :: key_path) name
@@ -413,7 +413,7 @@ if errorlevel 3010 exit /b 0
and disable_xenpv_win_drivers root current_cs (* Disable xenpv-win
service (RHBZ#809273). *)
- let services = Windows.get_node g root [current_cs; "Services"]
in
+ let services = Registry.get_node g root [current_cs; "Services"]
in
match services with
| None -> ()
@@ -424,7 +424,7 @@ if errorlevel 3010 exit /b 0
and disable_prl_drivers root current_cs (* Prevent Parallels drivers
from loading at boot. *)
- let services = Windows.get_node g root [current_cs; "Services"]
in
+ let services = Registry.get_node g root [current_cs; "Services"]
in
let prl_svcs = [ "prl_boot"; "prl_dd";
"prl_eth5"; "prl_fs"; "prl_memdev";
"prl_mouf"; "prl_pv32";
"prl_pv64"; "prl_scsi";
"prl_sound"; "prl_strg";
"prl_tg"; "prl_time";
@@ -446,7 +446,7 @@ if errorlevel 3010 exit /b 0
(* perfrom the equivalent of DelReg from prl_strg.inf:
* HKLM,
System\CurrentControlSet\Control\Class\{4d36e967-e325-11ce-bfc1-08002be10318},
LowerFilters, 0x00018002, prl_strg
*)
- let strg_cls = Windows.get_node g root
+ let strg_cls = Registry.get_node g root
[current_cs; "Control"; "Class";
"{4d36e967-e325-11ce-bfc1-08002be10318}"] in
match strg_cls with
@@ -456,12 +456,12 @@ if errorlevel 3010 exit /b 0
let valueh = g#hivex_node_get_value strg_cls lfkey in
if valueh <> 0L then (
let data = g#hivex_value_value valueh in
- let filters = String.nsplit "\000" (Regedit.decode_utf16le
data) in
+ let filters = String.nsplit "\000" (Registry.decode_utf16le
data) in
let filters = List.filter (
fun x -> x <> "prl_strg" && x <>
""
) filters in
let filters = List.map (
- fun x -> Regedit.encode_utf16le x ^ "\000\000"
+ fun x -> Registry.encode_utf16le x ^ "\000\000"
) (filters @ [""]) in
let data = String.concat "" filters in
g#hivex_node_set_value strg_cls lfkey 7_L data
@@ -472,7 +472,7 @@ if errorlevel 3010 exit /b 0
* error (eg. the infamous 0x0000007B). Turn off autoreboot.
*)
let crash_control - Windows.get_node g root [current_cs;
"Control"; "CrashControl"] in
+ Registry.get_node g root [current_cs; "Control";
"CrashControl"] in
match crash_control with
| None -> ()
| Some crash_control ->
@@ -489,10 +489,10 @@ if errorlevel 3010 exit /b 0
* path to this key.
*)
let node - Windows.get_node g root ["Microsoft";
"Windows"; "CurrentVersion"] in
+ Registry.get_node g root ["Microsoft"; "Windows";
"CurrentVersion"] in
match node with
| Some node ->
- let append = Regedit.encode_utf16le
";%SystemRoot%\\Drivers\\VirtIO" in
+ let append = Registry.encode_utf16le
";%SystemRoot%\\Drivers\\VirtIO" in
let values = Array.to_list (g#hivex_node_values node) in
let rec loop = function
| [] -> () (* DevicePath not found -- ignore this case *)
@@ -594,19 +594,19 @@ if errorlevel 3010 exit /b 0
let fix_win_uefi_bcd esp_path try
let bcd_path = "/EFI/Microsoft/Boot/BCD" in
- Windows.with_hive_write g (esp_path ^ bcd_path) (
+ Registry.with_hive_write g (esp_path ^ bcd_path) (
(* Remove the 'graphicsmodedisabled' key in BCD *)
fun root ->
let path = ["Objects";
"{9dea862c-5cdd-4e70-acc1-f32b344d4795}";
"Elements"; "23000003"] in
let boot_mgr_default_link - match Windows.get_node g root
path with
+ match Registry.get_node g root path with
| None -> raise Not_found
| Some node -> node in
let current_boot_entry = g#hivex_value_utf8 (
g#hivex_node_get_value boot_mgr_default_link "Element")
in
let path = ["Objects"; current_boot_entry;
"Elements"; "16000046"] in
- match Windows.get_node g root path with
+ match Registry.get_node g root path with
| None -> raise Not_found
| Some graphics_mode_disabled ->
g#hivex_node_delete_child graphics_mode_disabled
@@ -635,10 +635,10 @@ if errorlevel 3010 exit /b 0
(* Open the system hive for writes and update it. *)
let block_driver, net_driver, video_driver - Windows.with_hive_write g
system_hive_filename update_system_hive in
+ Registry.with_hive_write g system_hive_filename update_system_hive in
(* Open the software hive for writes and update it. *)
- Windows.with_hive_write g software_hive_filename update_software_hive;
+ Registry.with_hive_write g software_hive_filename update_software_hive;
fix_ntfs_heads ();
diff --git a/v2v/windows.ml b/v2v/windows.ml
index 79a14aa..6c6ed01 100644
--- a/v2v/windows.ml
+++ b/v2v/windows.ml
@@ -46,34 +46,3 @@ and check_app { Guestfs.app2_name = name;
and (=~) str rex try ignore (Str.search_forward rex str 0); true with
Not_found -> false
-
-let with_hive_readonly (g : Guestfs.guestfs) hive_filename f - let verbose =
verbose () in
- g#hivex_open ~write:false ~unsafe:true ~verbose (* ~debug:verbose *)
- hive_filename;
- protect ~f:(
- fun () ->
- let root = g#hivex_root () in
- f root
- ) ~finally:g#hivex_close
-
-let with_hive_write (g : Guestfs.guestfs) hive_filename f - let verbose =
verbose () in
- g#hivex_open ~write:true ~verbose (* ~debug:verbose *) hive_filename;
- protect ~f:(
- fun () ->
- let root = g#hivex_root () in
- let ret = f root in
- g#hivex_commit None;
- ret
- ) ~finally:g#hivex_close
-
-(* Find the given node in the current hive, relative to the starting
- * point. Returns [None] if the node is not found.
- *)
-let rec get_node (g : Guestfs.guestfs) node = function
- | [] -> Some node
- | x :: xs ->
- let node = g#hivex_node_get_child node x in
- if node = 0L then None
- else get_node g node xs
diff --git a/v2v/windows.mli b/v2v/windows.mli
index 95c4471..619a786 100644
--- a/v2v/windows.mli
+++ b/v2v/windows.mli
@@ -21,20 +21,3 @@
val detect_antivirus : Types.inspect -> bool
(** Return [true] if anti-virus (AV) software was detected in
this Windows guest. *)
-
-val with_hive_readonly : Guestfs.guestfs -> string -> (int64 ->
'a) -> 'a
-val with_hive_write : Guestfs.guestfs -> string -> (int64 -> 'a)
-> 'a
-(** [with_hive_(readonly|write) g hive_filename f]
- are wrappers that handle opening and closing the hive
- named [hive_filename] around a function [f].
-
- [with_hive_readonly] opens the hive for read-only (attempts
- to write will throw an error). [with_hive_write] opens the
- hive for writes, and commits the changes at the end if there
- were no errors. *)
-
-val get_node : Guestfs.guestfs -> int64 -> string list -> int64 option
-(** [get_node g root path] starts at the [root] node of the hive (it does
- not need to be the actual hive root), and searches down the [path].
- It returns [Some node] of the final node if found, or [None] if
- not found. *)
diff --git a/v2v/windows_virtio.mli b/v2v/windows_virtio.mli
index e6f984c..1d25260 100644
--- a/v2v/windows_virtio.mli
+++ b/v2v/windows_virtio.mli
@@ -19,7 +19,7 @@
(** Functions for installing Windows virtio drivers. *)
val install_drivers
- : Guestfs.guestfs -> Types.inspect -> string -> int64 -> string
->
+ : Guestfs.guestfs -> Types.inspect -> string -> Registry.node
-> string ->
Types.requested_guestcaps ->
Types.guestcaps_block_type * Types.guestcaps_net_type *
Types.guestcaps_video_type
(** [install_drivers g inspect systemroot root current_cs rcaps]
--
2.10.2
Richard W.M. Jones
2017-Feb-18 08:05 UTC
[Libguestfs] [PATCH 2/8] customize: firstboot: Use Registry.with_hive_write instead of open coding.
---
customize/firstboot.ml | 61 +++++++++++++++++++++++---------------------------
1 file changed, 28 insertions(+), 33 deletions(-)
diff --git a/customize/firstboot.ml b/customize/firstboot.ml
index 4e51260..5396ded 100644
--- a/customize/firstboot.ml
+++ b/customize/firstboot.ml
@@ -316,43 +316,38 @@ echo uninstalling firstboot service
let systemroot = g#inspect_get_windows_systemroot root in
let filename = sprintf "%s/system32/config/SYSTEM" systemroot in
let filename = g#case_sensitive_path filename in
- g#hivex_open ~write:true filename;
+ Registry.with_hive_write g filename
+ (fun root_node ->
+ (* Find the 'Current' ControlSet. *)
+ let current_cs + let select = g#hivex_node_get_child root_node
"Select" in
+ let valueh = g#hivex_node_get_value select "Current" in
+ let value = int_of_le32 (g#hivex_value_value valueh) in
+ sprintf "ControlSet%03Ld" value in
- let root_node = g#hivex_root () in
+ (* Add a new rhsrvany service to the system registry to execute
+ * firstboot. NB: All these edits are in the HKLM\SYSTEM hive.
+ * No other hive may be modified here.
+ *)
+ let regedits = [
+ [ current_cs; "services"; "firstboot" ],
+ [ "Type", REG_DWORD 0x10_l;
+ "Start", REG_DWORD 0x2_l;
+ "ErrorControl", REG_DWORD 0x1_l;
+ "ImagePath",
+ REG_SZ (sprintf "%s\\%s -s firstboot" firstboot_dir_win
srvany);
+ "DisplayName", REG_SZ "Virt tools firstboot
service";
+ "ObjectName", REG_SZ "LocalSystem" ];
- (* Find the 'Current' ControlSet. *)
- let current_cs - let select = g#hivex_node_get_child root_node
"Select" in
- let valueh = g#hivex_node_get_value select "Current" in
- let value = int_of_le32 (g#hivex_value_value valueh) in
- sprintf "ControlSet%03Ld" value in
-
- (* Add a new rhsrvany service to the system registry to execute firstboot.
- * NB: All these edits are in the HKLM\SYSTEM hive. No other
- * hive may be modified here.
- *)
- let regedits = [
- [ current_cs; "services"; "firstboot" ],
- [ "Type", REG_DWORD 0x10_l;
- "Start", REG_DWORD 0x2_l;
- "ErrorControl", REG_DWORD 0x1_l;
- "ImagePath",
- REG_SZ (sprintf "%s\\%s -s firstboot" firstboot_dir_win
srvany);
- "DisplayName", REG_SZ "Virt tools firstboot
service";
- "ObjectName", REG_SZ "LocalSystem" ];
-
- [ current_cs; "services"; "firstboot";
"Parameters" ],
- [ "CommandLine",
- REG_SZ ("cmd /c \"" ^ firstboot_dir_win ^
"\\firstboot.bat\"");
- "PWD", REG_SZ firstboot_dir_win ];
- ] in
- reg_import g root_node regedits;
-
- g#hivex_commit None;
- g#hivex_close ();
+ [ current_cs; "services"; "firstboot";
"Parameters" ],
+ [ "CommandLine",
+ REG_SZ ("cmd /c \"" ^ firstboot_dir_win ^
"\\firstboot.bat\"");
+ "PWD", REG_SZ firstboot_dir_win ];
+ ] in
+ reg_import g root_node regedits
+ );
firstboot_dir
-
end
let script_count = ref 0
--
2.10.2
Richard W.M. Jones
2017-Feb-18 08:05 UTC
[Libguestfs] [PATCH 3/8] customize, v2v: Use %systemroot% and CurrentControlSet from inspection.
For reasons unknown virt-v2v recomputed the CurrentControlSet from
first principles, and passed %systemroot% around to all functions.
However that data is available from the libguestfs inspection APIs.
---
customize/firstboot.ml | 7 +------
v2v/convert_windows.ml | 52 ++++++++++++++++++++++----------------------------
v2v/inspect_source.ml | 17 ++++++++++++++++-
v2v/types.ml | 6 ++++++
v2v/types.mli | 2 ++
v2v/v2v_unit_tests.ml | 3 ++-
v2v/windows_virtio.ml | 31 +++++++++++++++---------------
v2v/windows_virtio.mli | 7 +++----
8 files changed, 69 insertions(+), 56 deletions(-)
diff --git a/customize/firstboot.ml b/customize/firstboot.ml
index 5396ded..3a5c10a 100644
--- a/customize/firstboot.ml
+++ b/customize/firstboot.ml
@@ -318,12 +318,7 @@ echo uninstalling firstboot service
let filename = g#case_sensitive_path filename in
Registry.with_hive_write g filename
(fun root_node ->
- (* Find the 'Current' ControlSet. *)
- let current_cs - let select = g#hivex_node_get_child root_node
"Select" in
- let valueh = g#hivex_node_get_value select "Current" in
- let value = int_of_le32 (g#hivex_value_value valueh) in
- sprintf "ControlSet%03Ld" value in
+ let current_cs = g#inspect_get_windows_current_control_set root in
(* Add a new rhsrvany service to the system registry to execute
* firstboot. NB: All these edits are in the HKLM\SYSTEM hive.
diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
index a231219..eabbd56 100644
--- a/v2v/convert_windows.ml
+++ b/v2v/convert_windows.ml
@@ -68,17 +68,16 @@ let convert ~keep_serial_console (g : G.guestfs) inspect
source rcaps None
) in
- (* Get the Windows %systemroot%. *)
- let systemroot = g#inspect_get_windows_systemroot inspect.i_root in
-
(* Get the software and system hive files. *)
let software_hive_filename - let filename = sprintf
"%s/system32/config/software" systemroot in
+ let filename = sprintf "%s/system32/config/software"
+ inspect.i_windows_systemroot in
let filename = g#case_sensitive_path filename in
filename in
let system_hive_filename - let filename = sprintf
"%s/system32/config/system" systemroot in
+ let filename = sprintf "%s/system32/config/system"
+ inspect.i_windows_systemroot in
let filename = g#case_sensitive_path filename in
filename in
@@ -223,13 +222,6 @@ let convert ~keep_serial_console (g : G.guestfs) inspect
source rcaps
(*----------------------------------------------------------------------*)
(* Perform the conversion of the Windows guest. *)
- (* Find the 'Current' ControlSet. *)
- let get_current_cs root - let select = g#hivex_node_get_child root
"Select" in
- let valueh = g#hivex_node_get_value select "Current" in
- let value = int_of_le32 (g#hivex_value_value valueh) in
- sprintf "ControlSet%03Ld" value in
-
let rec configure_firstboot () wait_pnp ();
(match installer with
@@ -298,8 +290,8 @@ reg delete \"%s\" /v %s /f" strkey name
let name = "SuppressUI" in
let value = Registry.with_hive_write g system_hive_filename (
fun root ->
- let current_cs = get_current_cs root in
- set_reg_val_dword_1 root (current_cs :: key_path) name
+ set_reg_val_dword_1 root (inspect.i_windows_current_control_set
+ :: key_path) name
) in
reg_restore ("HKLM\\SYSTEM\\CurrentControlSet" :: key_path)
name
value
@@ -402,18 +394,16 @@ if errorlevel 3010 exit /b 0
(* Update the SYSTEM hive. When this function is called the hive has
* already been opened as a hivex handle inside guestfs.
*)
- let current_cs = get_current_cs root in
- debug "current ControlSet is %s" current_cs;
+ disable_xenpv_win_drivers root;
+ disable_prl_drivers root;
+ disable_autoreboot root;
+ Windows_virtio.install_drivers g inspect root rcaps
- disable_xenpv_win_drivers root current_cs;
- disable_prl_drivers root current_cs;
- disable_autoreboot root current_cs;
- Windows_virtio.install_drivers g inspect systemroot
- root current_cs rcaps
-
- and disable_xenpv_win_drivers root current_cs + and
disable_xenpv_win_drivers root (* Disable xenpv-win service (RHBZ#809273).
*)
- let services = Registry.get_node g root [current_cs; "Services"]
in
+ let services + Registry.get_node g root
+ [inspect.i_windows_current_control_set;
"Services"] in
match services with
| None -> ()
@@ -422,9 +412,11 @@ if errorlevel 3010 exit /b 0
if node <> 0L then
g#hivex_node_set_value node "Start" 4_L (le32_of_int 4_L)
- and disable_prl_drivers root current_cs + and disable_prl_drivers root
(* Prevent Parallels drivers from loading at boot. *)
- let services = Registry.get_node g root [current_cs; "Services"]
in
+ let services + Registry.get_node g root
+ [inspect.i_windows_current_control_set;
"Services"] in
let prl_svcs = [ "prl_boot"; "prl_dd";
"prl_eth5"; "prl_fs"; "prl_memdev";
"prl_mouf"; "prl_pv32";
"prl_pv64"; "prl_scsi";
"prl_sound"; "prl_strg";
"prl_tg"; "prl_time";
@@ -447,7 +439,8 @@ if errorlevel 3010 exit /b 0
* HKLM,
System\CurrentControlSet\Control\Class\{4d36e967-e325-11ce-bfc1-08002be10318},
LowerFilters, 0x00018002, prl_strg
*)
let strg_cls = Registry.get_node g root
- [current_cs; "Control"; "Class";
+ [inspect.i_windows_current_control_set;
+ "Control"; "Class";
"{4d36e967-e325-11ce-bfc1-08002be10318}"] in
match strg_cls with
| None -> ()
@@ -467,12 +460,13 @@ if errorlevel 3010 exit /b 0
g#hivex_node_set_value strg_cls lfkey 7_L data
)
- and disable_autoreboot root current_cs + and disable_autoreboot root (*
If the guest reboots after a crash, it's hard to see the original
* error (eg. the infamous 0x0000007B). Turn off autoreboot.
*)
let crash_control - Registry.get_node g root [current_cs;
"Control"; "CrashControl"] in
+ Registry.get_node g root [inspect.i_windows_current_control_set;
+ "Control"; "CrashControl"]
in
match crash_control with
| None -> ()
| Some crash_control ->
diff --git a/v2v/inspect_source.ml b/v2v/inspect_source.ml
index 3936e72..3b16c42 100644
--- a/v2v/inspect_source.ml
+++ b/v2v/inspect_source.ml
@@ -32,6 +32,8 @@ let rec inspect_source root_choice g
reject_if_not_installed_image g root;
+ let typ = g#inspect_get_type root in
+
(* Mount up the filesystems. *)
let mps = g#inspect_get_mountpoints root in
let cmp (a,_) (b,_) = compare (String.length a) (String.length b) in
@@ -65,9 +67,20 @@ let rec inspect_source root_choice g StringMap.add
name (app :: vs) map
) StringMap.empty apps in
+ (* If the guest is Windows, get some Windows-specific inspection
+ * data, else (for simplicity when accessing) use empty strings.
+ *)
+ let systemroot, current_cs + match typ with
+ | "windows" ->
+ g#inspect_get_windows_systemroot root,
+ g#inspect_get_windows_current_control_set root
+ | _ ->
+ "", "" in
+
let inspect = {
i_root = root;
- i_type = g#inspect_get_type root;
+ i_type = typ;
i_distro = g#inspect_get_distro root;
i_arch = g#inspect_get_arch root;
i_major_version = g#inspect_get_major_version root;
@@ -80,6 +93,8 @@ let rec inspect_source root_choice g i_apps = apps;
i_apps_map = apps_map;
i_firmware = get_firmware_bootable_device g;
+ i_windows_systemroot = systemroot;
+ i_windows_current_control_set = current_cs;
} in
debug "%s" (string_of_inspect inspect);
diff --git a/v2v/types.ml b/v2v/types.ml
index afeb178..7fd6327 100644
--- a/v2v/types.ml
+++ b/v2v/types.ml
@@ -324,6 +324,8 @@ type inspect = {
i_apps : Guestfs.application2 list;
i_apps_map : Guestfs.application2 list StringMap.t;
i_firmware : i_firmware;
+ i_windows_systemroot : string;
+ i_windows_current_control_set : string;
}
let string_of_inspect inspect @@ -339,6 +341,8 @@ i_package_management = %s
i_product_name = %s
i_product_variant = %s
i_firmware = %s
+i_windows_systemroot = %s
+i_windows_current_control_set = %s
" inspect.i_root
inspect.i_type
inspect.i_distro
@@ -352,6 +356,8 @@ i_firmware = %s
(match inspect.i_firmware with
| I_BIOS -> "BIOS"
| I_UEFI devices -> sprintf "UEFI [%s]" (String.concat ",
" devices))
+ inspect.i_windows_systemroot
+ inspect.i_windows_current_control_set
type mpstat = {
mp_dev : string;
diff --git a/v2v/types.mli b/v2v/types.mli
index 96ab36a..df50b1b 100644
--- a/v2v/types.mli
+++ b/v2v/types.mli
@@ -230,6 +230,8 @@ type inspect = {
i_firmware : i_firmware;
(** The list of EFI system partitions for the guest with UEFI,
otherwise the BIOS identifier. *)
+ i_windows_systemroot : string;
+ i_windows_current_control_set : string;
}
(** Inspection information. *)
diff --git a/v2v/v2v_unit_tests.ml b/v2v/v2v_unit_tests.ml
index 1133d92..af86afa 100644
--- a/v2v/v2v_unit_tests.ml
+++ b/v2v/v2v_unit_tests.ml
@@ -30,7 +30,8 @@ let inspect_defaults = {
i_major_version = 0; i_minor_version = 0;
i_root = ""; i_package_format = ""; i_package_management
= "";
i_product_name = ""; i_product_variant = "";
i_mountpoints = [];
- i_apps = []; i_apps_map = StringMap.empty; i_firmware = I_BIOS
+ i_apps = []; i_apps_map = StringMap.empty; i_firmware = I_BIOS;
+ i_windows_systemroot = ""; i_windows_current_control_set =
"";
}
let test_get_ostype ctx diff --git a/v2v/windows_virtio.ml
b/v2v/windows_virtio.ml
index a63ab44..2c28524 100644
--- a/v2v/windows_virtio.ml
+++ b/v2v/windows_virtio.ml
@@ -37,9 +37,9 @@ let scsi_class_guid =
"{4D36E97B-E325-11CE-BFC1-08002BE10318}"
let viostor_pciid =
"VEN_1AF4&DEV_1001&SUBSYS_00021AF4&REV_00"
let vioscsi_pciid =
"VEN_1AF4&DEV_1004&SUBSYS_00081AF4&REV_00"
-let rec install_drivers g inspect systemroot root current_cs rcaps +let rec
install_drivers g inspect root rcaps (* Copy the virtio drivers to the guest.
*)
- let driverdir = sprintf "%s/Drivers/VirtIO" systemroot in
+ let driverdir = sprintf "%s/Drivers/VirtIO"
inspect.i_windows_systemroot in
g#mkdir_p driverdir;
if not (copy_drivers g inspect driverdir) then (
@@ -98,22 +98,22 @@ let rec install_drivers g inspect systemroot root current_cs
rcaps (* Block driver needs tweaks to allow booting; the rest is set up
by PnP
* manager *)
let source = driverdir // (driver_name ^ ".sys") in
- let target = sprintf "%s/system32/drivers/%s.sys" systemroot
driver_name in
+ let target = sprintf "%s/system32/drivers/%s.sys"
+ inspect.i_windows_systemroot driver_name in
let target = g#case_sensitive_path target in
g#cp source target;
- add_guestor_to_registry g root current_cs driver_name
- viostor_pciid;
+ add_guestor_to_registry g inspect root driver_name viostor_pciid;
Virtio_blk
| Some Virtio_SCSI, _, true ->
(* Block driver needs tweaks to allow booting; the rest is set up by
PnP
* manager *)
let source = driverdir // "vioscsi.sys" in
- let target = sprintf "%s/system32/drivers/vioscsi.sys"
systemroot in
+ let target = sprintf "%s/system32/drivers/vioscsi.sys"
+ inspect.i_windows_systemroot in
let target = g#case_sensitive_path target in
g#cp source target;
- add_guestor_to_registry g root current_cs "vioscsi"
- vioscsi_pciid;
+ add_guestor_to_registry g inspect root "vioscsi"
vioscsi_pciid;
Virtio_SCSI
| Some IDE, _, _ ->
@@ -168,18 +168,18 @@ let rec install_drivers g inspect systemroot root
current_cs rcaps (block, net, video)
)
-and add_guestor_to_registry g root current_cs drv_name drv_pciid +and
add_guestor_to_registry g inspect root drv_name drv_pciid let ddb_node =
g#hivex_node_get_child root "DriverDatabase" in
let regedits if ddb_node = 0L then
- cdb_regedits current_cs drv_name drv_pciid
+ cdb_regedits inspect drv_name drv_pciid
else
- ddb_regedits current_cs drv_name drv_pciid in
+ ddb_regedits inspect drv_name drv_pciid in
let drv_sys_path = sprintf "system32\\drivers\\%s.sys" drv_name in
let common_regedits = [
- [ current_cs; "Services"; drv_name ],
+ [ inspect.i_windows_current_control_set; "Services"; drv_name
],
[ "Type", REG_DWORD 0x1_l;
"Start", REG_DWORD 0x0_l;
"Group", REG_SZ "SCSI miniport";
@@ -189,19 +189,20 @@ and add_guestor_to_registry g root current_cs drv_name
drv_pciid
reg_import g root (regedits @ common_regedits)
-and cdb_regedits current_cs drv_name drv_pciid +and cdb_regedits inspect
drv_name drv_pciid (* See
http://rwmj.wordpress.com/2010/04/30/tip-install-a-device-driver-in-a-windows-vm/
* NB: All these edits are in the HKLM\SYSTEM hive. No other
* hive may be modified here.
*)
[
- [ current_cs; "Control"; "CriticalDeviceDatabase";
+ [ inspect.i_windows_current_control_set;
+ "Control"; "CriticalDeviceDatabase";
"PCI#" ^ drv_pciid ],
[ "Service", REG_SZ drv_name;
"ClassGUID", REG_SZ scsi_class_guid ];
]
-and ddb_regedits current_cs drv_name drv_pciid +and ddb_regedits inspect
drv_name drv_pciid (* Windows >= 8 doesn't use the
CriticalDeviceDatabase. Instead
* one must add keys into the DriverDatabase.
*)
diff --git a/v2v/windows_virtio.mli b/v2v/windows_virtio.mli
index 1d25260..4ceeebe 100644
--- a/v2v/windows_virtio.mli
+++ b/v2v/windows_virtio.mli
@@ -19,17 +19,16 @@
(** Functions for installing Windows virtio drivers. *)
val install_drivers
- : Guestfs.guestfs -> Types.inspect -> string -> Registry.node
-> string ->
+ : Guestfs.guestfs -> Types.inspect -> Registry.node ->
Types.requested_guestcaps ->
Types.guestcaps_block_type * Types.guestcaps_net_type *
Types.guestcaps_video_type
-(** [install_drivers g inspect systemroot root current_cs rcaps]
+(** [install_drivers g inspect root rcaps]
installs virtio drivers from the driver directory or driver
ISO into the guest driver directory and updates the registry
so that the [viostor.sys] driver gets loaded by Windows at boot.
[root] is the root node of the system hive (which is open for writes
- when this function is called). [current_cs] is the name of the
- [CurrentControlSet] (eg. ["ControlSet001"]).
+ when this function is called).
[rcaps] is the set of guest "capabilities" requested by the
caller. This
may include the type of the block driver, network driver, and video driver.
--
2.10.2
Richard W.M. Jones
2017-Feb-18 08:05 UTC
[Libguestfs] [PATCH 4/8] mllib: Add Registry.t = Guestfs.guestfs * Registry.node
Add a convenient tuple Registry.t for the currently open hive. It
contains the guestfs handle and the root node of a registry.
The functions with_hive_readonly and with_hive_write are modified to
pass this tuple to their callbacks.
---
customize/firstboot.ml | 4 ++--
mllib/regedit.ml | 4 ++--
mllib/regedit.mli | 2 +-
mllib/registry.ml | 15 +++++--------
mllib/registry.mli | 12 ++++++----
v2v/convert_windows.ml | 60 +++++++++++++++++++++++++-------------------------
v2v/windows_virtio.ml | 10 ++++-----
v2v/windows_virtio.mli | 9 ++++----
8 files changed, 58 insertions(+), 58 deletions(-)
diff --git a/customize/firstboot.ml b/customize/firstboot.ml
index 3a5c10a..5489c21 100644
--- a/customize/firstboot.ml
+++ b/customize/firstboot.ml
@@ -317,7 +317,7 @@ echo uninstalling firstboot service
let filename = sprintf "%s/system32/config/SYSTEM" systemroot in
let filename = g#case_sensitive_path filename in
Registry.with_hive_write g filename
- (fun root_node ->
+ (fun reg ->
let current_cs = g#inspect_get_windows_current_control_set root in
(* Add a new rhsrvany service to the system registry to execute
@@ -339,7 +339,7 @@ echo uninstalling firstboot service
REG_SZ ("cmd /c \"" ^ firstboot_dir_win ^
"\\firstboot.bat\"");
"PWD", REG_SZ firstboot_dir_win ];
] in
- reg_import g root_node regedits
+ reg_import reg regedits
);
firstboot_dir
diff --git a/mllib/regedit.ml b/mllib/regedit.ml
index a97699c..f49d931 100644
--- a/mllib/regedit.ml
+++ b/mllib/regedit.ml
@@ -32,7 +32,7 @@ and regtype | REG_DWORD of int32
| REG_MULTI_SZ of string list
-let rec import_key (g : Guestfs.guestfs) root (path, values) +let rec
import_key ((g, root) : Registry.t) (path, values) (* Create the path
starting at the root node. *)
let node let rec loop parent = function
@@ -80,4 +80,4 @@ and import_value g node = function
let ss = String.concat "" ss in
g#hivex_node_set_value node key 7L ss
-let reg_import g root = List.iter (import_key g root)
+let reg_import reg = List.iter (import_key reg)
diff --git a/mllib/regedit.mli b/mllib/regedit.mli
index 6a5e383..06828cb 100644
--- a/mllib/regedit.mli
+++ b/mllib/regedit.mli
@@ -55,5 +55,5 @@ and regtype UTF-16LE, and integers are automatically
packed and
byte-swapped. *)
-val reg_import : Guestfs.guestfs -> Registry.node -> regedits -> unit
+val reg_import : Registry.t -> regedits -> unit
(** Import the edits in [regedits] into the currently opened hive. *)
diff --git a/mllib/registry.ml b/mllib/registry.ml
index a5f195f..ac85b50 100644
--- a/mllib/registry.ml
+++ b/mllib/registry.ml
@@ -24,23 +24,20 @@ open Common_utils
type node = int64
type value = int64
+type t = Guestfs.guestfs * node
+
let with_hive_readonly (g : Guestfs.guestfs) hive_filename f let verbose =
verbose () in
g#hivex_open ~write:false ~unsafe:true ~verbose (* ~debug:verbose *)
hive_filename;
- protect ~f:(
- fun () ->
- let root = g#hivex_root () in
- f root
- ) ~finally:g#hivex_close
+ protect ~f:(fun () -> f (g, g#hivex_root ())) ~finally:g#hivex_close
let with_hive_write (g : Guestfs.guestfs) hive_filename f let verbose =
verbose () in
g#hivex_open ~write:true ~verbose (* ~debug:verbose *) hive_filename;
protect ~f:(
fun () ->
- let root = g#hivex_root () in
- let ret = f root in
+ let ret = f (g, g#hivex_root ()) in
g#hivex_commit None;
ret
) ~finally:g#hivex_close
@@ -48,12 +45,12 @@ let with_hive_write (g : Guestfs.guestfs) hive_filename f
(* Find the given node in the current hive, relative to the starting
* point. Returns [None] if the node is not found.
*)
-let rec get_node (g : Guestfs.guestfs) node = function
+let rec get_node ((g, node) : t) = function
| [] -> Some node
| x :: xs ->
let node = g#hivex_node_get_child node x in
if node = 0L then None
- else get_node g node xs
+ else get_node (g, node) xs
(* Take a 7 bit ASCII string and encode it as UTF16LE. *)
let encode_utf16le str diff --git a/mllib/registry.mli b/mllib/registry.mli
index 1c9790d..9727cd5 100644
--- a/mllib/registry.mli
+++ b/mllib/registry.mli
@@ -21,8 +21,12 @@
type node = int64
type value = int64
-val with_hive_readonly : Guestfs.guestfs -> string -> (node -> 'a)
-> 'a
-val with_hive_write : Guestfs.guestfs -> string -> (node -> 'a)
-> 'a
+type t = Guestfs.guestfs * node
+(** [Registry.t] describes a currently open hive. It contains the
+ guestfs handle and the root node of a registry. *)
+
+val with_hive_readonly : Guestfs.guestfs -> string -> (t -> 'a)
-> 'a
+val with_hive_write : Guestfs.guestfs -> string -> (t -> 'a) ->
'a
(** [with_hive_(readonly|write) g hive_filename f]
are wrappers that handle opening and closing the hive
named [hive_filename] around a function [f].
@@ -32,8 +36,8 @@ val with_hive_write : Guestfs.guestfs -> string -> (node
-> 'a) -> 'a
hive for writes, and commits the changes at the end if there
were no errors. *)
-val get_node : Guestfs.guestfs -> node -> string list -> node option
-(** [get_node g root path] starts at the [root] node of the hive (it does
+val get_node : t -> string list -> node option
+(** [get_node (g, root) path] starts at the [root] node of the hive (it does
not need to be the actual hive root), and searches down the [path].
It returns [Some node] of the final node if found, or [None] if
not found. *)
diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
index eabbd56..9e3849a 100644
--- a/v2v/convert_windows.ml
+++ b/v2v/convert_windows.ml
@@ -87,12 +87,12 @@ let convert ~keep_serial_console (g : G.guestfs) inspect
source rcaps (* If the Windows guest appears to be using group policy. *)
let has_group_policy Registry.with_hive_readonly g
software_hive_filename
- (fun root ->
+ (fun reg ->
try
let path = ["Microsoft"; "Windows";
"CurrentVersion";
"Group Policy"; "History"] in
let node - match Registry.get_node g root path with
+ match Registry.get_node reg path with
| None -> raise Not_found
| Some node -> node in
let children = g#hivex_node_children node in
@@ -130,12 +130,12 @@ let convert ~keep_serial_console (g : G.guestfs) inspect
source rcaps let xenpvreg = "Red Hat Paravirtualized Xen Drivers for
Windows(R)" in
Registry.with_hive_readonly g software_hive_filename
- (fun root ->
+ (fun reg ->
try
let path = ["Microsoft"; "Windows";
"CurrentVersion"; "Uninstall";
xenpvreg] in
let node - match Registry.get_node g root path with
+ match Registry.get_node reg path with
| None -> raise Not_found
| Some node -> node in
let uninstkey = "UninstallString" in
@@ -171,11 +171,11 @@ let convert ~keep_serial_console (g : G.guestfs) inspect
source rcaps let uninsts = ref [] in
Registry.with_hive_readonly g software_hive_filename
- (fun root ->
+ (fun reg ->
try
let path = ["Microsoft"; "Windows";
"CurrentVersion"; "Uninstall"] in
let node - match Registry.get_node g root path with
+ match Registry.get_node reg path with
| None -> raise Not_found
| Some node -> node in
let uninstnodes = g#hivex_node_children node in
@@ -232,7 +232,7 @@ let convert ~keep_serial_console (g : G.guestfs) inspect
source rcaps unconfigure_xenpv ();
unconfigure_prltools ()
- and set_reg_val_dword_1 root key_path name + and set_reg_val_dword_1 (g,
root) key_path name (* set reg value to REG_DWORD 1, creating intermediate
keys if needed *)
let node let rec loop parent = function
@@ -279,8 +279,8 @@ reg delete \"%s\" /v %s /f" strkey name
"Settings"] in
let name = "SuppressNewHWUI" in
let value = Registry.with_hive_write g software_hive_filename (
- fun root ->
- set_reg_val_dword_1 root key_path name
+ fun reg ->
+ set_reg_val_dword_1 reg key_path name
) in
reg_restore ("HKLM\\Software" :: key_path) name value
@@ -289,9 +289,9 @@ reg delete \"%s\" /v %s /f" strkey name
let key_path = ["Services"; "PlugPlay";
"Parameters"] in
let name = "SuppressUI" in
let value = Registry.with_hive_write g system_hive_filename (
- fun root ->
- set_reg_val_dword_1 root (inspect.i_windows_current_control_set
- :: key_path) name
+ fun reg ->
+ set_reg_val_dword_1 reg (inspect.i_windows_current_control_set
+ :: key_path) name
) in
reg_restore ("HKLM\\SYSTEM\\CurrentControlSet" :: key_path)
name
value
@@ -390,19 +390,19 @@ if errorlevel 3010 exit /b 0
) prltools_uninsts
in
- let rec update_system_hive root + let rec update_system_hive reg (*
Update the SYSTEM hive. When this function is called the hive has
* already been opened as a hivex handle inside guestfs.
*)
- disable_xenpv_win_drivers root;
- disable_prl_drivers root;
- disable_autoreboot root;
- Windows_virtio.install_drivers g inspect root rcaps
+ disable_xenpv_win_drivers reg;
+ disable_prl_drivers reg;
+ disable_autoreboot reg;
+ Windows_virtio.install_drivers reg inspect rcaps
- and disable_xenpv_win_drivers root + and disable_xenpv_win_drivers reg
(* Disable xenpv-win service (RHBZ#809273). *)
let services - Registry.get_node g root
+ Registry.get_node reg
[inspect.i_windows_current_control_set;
"Services"] in
match services with
@@ -412,10 +412,10 @@ if errorlevel 3010 exit /b 0
if node <> 0L then
g#hivex_node_set_value node "Start" 4_L (le32_of_int 4_L)
- and disable_prl_drivers root + and disable_prl_drivers reg (* Prevent
Parallels drivers from loading at boot. *)
let services - Registry.get_node g root
+ Registry.get_node reg
[inspect.i_windows_current_control_set;
"Services"] in
let prl_svcs = [ "prl_boot"; "prl_dd";
"prl_eth5"; "prl_fs"; "prl_memdev";
"prl_mouf"; "prl_pv32";
"prl_pv64"; "prl_scsi";
@@ -438,7 +438,7 @@ if errorlevel 3010 exit /b 0
(* perfrom the equivalent of DelReg from prl_strg.inf:
* HKLM,
System\CurrentControlSet\Control\Class\{4d36e967-e325-11ce-bfc1-08002be10318},
LowerFilters, 0x00018002, prl_strg
*)
- let strg_cls = Registry.get_node g root
+ let strg_cls = Registry.get_node reg
[inspect.i_windows_current_control_set;
"Control"; "Class";
"{4d36e967-e325-11ce-bfc1-08002be10318}"] in
@@ -460,19 +460,19 @@ if errorlevel 3010 exit /b 0
g#hivex_node_set_value strg_cls lfkey 7_L data
)
- and disable_autoreboot root + and disable_autoreboot reg (* If the
guest reboots after a crash, it's hard to see the original
* error (eg. the infamous 0x0000007B). Turn off autoreboot.
*)
let crash_control - Registry.get_node g root
[inspect.i_windows_current_control_set;
- "Control"; "CrashControl"]
in
+ Registry.get_node reg [inspect.i_windows_current_control_set;
+ "Control"; "CrashControl"] in
match crash_control with
| None -> ()
| Some crash_control ->
g#hivex_node_set_value crash_control "AutoReboot" 4_L
(le32_of_int 0_L)
- and update_software_hive root + and update_software_hive reg (* Update
the SOFTWARE hive. When this function is called the
* hive has already been opened as a hivex handle inside
* guestfs.
@@ -483,7 +483,7 @@ if errorlevel 3010 exit /b 0
* path to this key.
*)
let node - Registry.get_node g root ["Microsoft";
"Windows"; "CurrentVersion"] in
+ Registry.get_node reg ["Microsoft"; "Windows";
"CurrentVersion"] in
match node with
| Some node ->
let append = Registry.encode_utf16le
";%SystemRoot%\\Drivers\\VirtIO" in
@@ -590,17 +590,17 @@ if errorlevel 3010 exit /b 0
let bcd_path = "/EFI/Microsoft/Boot/BCD" in
Registry.with_hive_write g (esp_path ^ bcd_path) (
(* Remove the 'graphicsmodedisabled' key in BCD *)
- fun root ->
+ fun reg ->
let path = ["Objects";
"{9dea862c-5cdd-4e70-acc1-f32b344d4795}";
"Elements"; "23000003"] in
let boot_mgr_default_link - match Registry.get_node g root
path with
+ match Registry.get_node reg path with
| None -> raise Not_found
| Some node -> node in
let current_boot_entry = g#hivex_value_utf8 (
g#hivex_node_get_value boot_mgr_default_link "Element")
in
let path = ["Objects"; current_boot_entry;
"Elements"; "16000046"] in
- match Registry.get_node g root path with
+ match Registry.get_node reg path with
| None -> raise Not_found
| Some graphics_mode_disabled ->
g#hivex_node_delete_child graphics_mode_disabled
diff --git a/v2v/windows_virtio.ml b/v2v/windows_virtio.ml
index 2c28524..2f5349d 100644
--- a/v2v/windows_virtio.ml
+++ b/v2v/windows_virtio.ml
@@ -37,7 +37,7 @@ let scsi_class_guid =
"{4D36E97B-E325-11CE-BFC1-08002BE10318}"
let viostor_pciid =
"VEN_1AF4&DEV_1001&SUBSYS_00021AF4&REV_00"
let vioscsi_pciid =
"VEN_1AF4&DEV_1004&SUBSYS_00081AF4&REV_00"
-let rec install_drivers g inspect root rcaps +let rec install_drivers ((g, _)
as reg) inspect rcaps (* Copy the virtio drivers to the guest. *)
let driverdir = sprintf "%s/Drivers/VirtIO"
inspect.i_windows_systemroot in
g#mkdir_p driverdir;
@@ -102,7 +102,7 @@ let rec install_drivers g inspect root rcaps
inspect.i_windows_systemroot driver_name in
let target = g#case_sensitive_path target in
g#cp source target;
- add_guestor_to_registry g inspect root driver_name viostor_pciid;
+ add_guestor_to_registry reg inspect driver_name viostor_pciid;
Virtio_blk
| Some Virtio_SCSI, _, true ->
@@ -113,7 +113,7 @@ let rec install_drivers g inspect root rcaps
inspect.i_windows_systemroot in
let target = g#case_sensitive_path target in
g#cp source target;
- add_guestor_to_registry g inspect root "vioscsi"
vioscsi_pciid;
+ add_guestor_to_registry reg inspect "vioscsi" vioscsi_pciid;
Virtio_SCSI
| Some IDE, _, _ ->
@@ -168,7 +168,7 @@ let rec install_drivers g inspect root rcaps (block,
net, video)
)
-and add_guestor_to_registry g inspect root drv_name drv_pciid +and
add_guestor_to_registry ((g, root) as reg) inspect drv_name drv_pciid let
ddb_node = g#hivex_node_get_child root "DriverDatabase" in
let regedits @@ -187,7 +187,7 @@ and add_guestor_to_registry g inspect root
drv_name drv_pciid "ImagePath", REG_EXPAND_SZ drv_sys_path ];
] in
- reg_import g root (regedits @ common_regedits)
+ reg_import reg (regedits @ common_regedits)
and cdb_regedits inspect drv_name drv_pciid (* See
http://rwmj.wordpress.com/2010/04/30/tip-install-a-device-driver-in-a-windows-vm/
diff --git a/v2v/windows_virtio.mli b/v2v/windows_virtio.mli
index 4ceeebe..0bc6faa 100644
--- a/v2v/windows_virtio.mli
+++ b/v2v/windows_virtio.mli
@@ -19,16 +19,15 @@
(** Functions for installing Windows virtio drivers. *)
val install_drivers
- : Guestfs.guestfs -> Types.inspect -> Registry.node ->
- Types.requested_guestcaps ->
+ : Registry.t -> Types.inspect -> Types.requested_guestcaps ->
Types.guestcaps_block_type * Types.guestcaps_net_type *
Types.guestcaps_video_type
-(** [install_drivers g inspect root rcaps]
+(** [install_drivers reg inspect rcaps]
installs virtio drivers from the driver directory or driver
ISO into the guest driver directory and updates the registry
so that the [viostor.sys] driver gets loaded by Windows at boot.
- [root] is the root node of the system hive (which is open for writes
- when this function is called).
+ [reg] is the system hive which is open for writes when this
+ function is called.
[rcaps] is the set of guest "capabilities" requested by the
caller. This
may include the type of the block driver, network driver, and video driver.
--
2.10.2
Richard W.M. Jones
2017-Feb-18 08:05 UTC
[Libguestfs] [PATCH 5/8] mllib: registry: New function for creating paths in the registry.
---
mllib/regedit.ml | 12 +-----------
mllib/registry.ml | 9 +++++++++
mllib/registry.mli | 5 +++++
3 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/mllib/regedit.ml b/mllib/regedit.ml
index f49d931..dd03f5a 100644
--- a/mllib/regedit.ml
+++ b/mllib/regedit.ml
@@ -34,17 +34,7 @@ and regtype
let rec import_key ((g, root) : Registry.t) (path, values) (* Create the
path starting at the root node. *)
- let node - let rec loop parent = function
- | [] -> parent
- | x :: xs ->
- let node - match g#hivex_node_get_child parent x with
- | 0L -> g#hivex_node_add_child parent x (* not found, create *)
- | node -> node in
- loop node xs
- in
- loop root path in
+ let node = Registry.create_path (g, root) path in
(* Delete any existing values in this node. *)
(* g#hivex_node_set_values ...
diff --git a/mllib/registry.ml b/mllib/registry.ml
index ac85b50..767092c 100644
--- a/mllib/registry.ml
+++ b/mllib/registry.ml
@@ -52,6 +52,15 @@ let rec get_node ((g, node) : t) = function
if node = 0L then None
else get_node (g, node) xs
+let rec create_path ((g, parent) : t) = function
+ | [] -> parent
+ | x :: xs ->
+ let node + match g#hivex_node_get_child parent x with
+ | 0L -> g#hivex_node_add_child parent x (* not found, create *)
+ | node -> node in
+ create_path (g, node) xs
+
(* Take a 7 bit ASCII string and encode it as UTF16LE. *)
let encode_utf16le str let len = String.length str in
diff --git a/mllib/registry.mli b/mllib/registry.mli
index 9727cd5..293fc99 100644
--- a/mllib/registry.mli
+++ b/mllib/registry.mli
@@ -42,6 +42,11 @@ val get_node : t -> string list -> node option
It returns [Some node] of the final node if found, or [None] if
not found. *)
+val create_path : t -> string list -> node
+(** [create_path (g, root) path] is like {!get_node} except that it
+ creates registry nodes as it goes along if they don't exist.
+ It returns the final node in the path. *)
+
val encode_utf16le : string -> string
(** Helper: Take a 7 bit ASCII string and encode it as UTF-16LE. *)
--
2.10.2
Richard W.M. Jones
2017-Feb-18 08:05 UTC
[Libguestfs] [PATCH 6/8] v2v: Simplify and document gnarly set_reg_val_dword_1 function.
---
v2v/convert_windows.ml | 28 +++++++++++-----------------
1 file changed, 11 insertions(+), 17 deletions(-)
diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
index 9e3849a..e929e1c 100644
--- a/v2v/convert_windows.ml
+++ b/v2v/convert_windows.ml
@@ -232,19 +232,14 @@ let convert ~keep_serial_console (g : G.guestfs) inspect
source rcaps unconfigure_xenpv ();
unconfigure_prltools ()
- and set_reg_val_dword_1 (g, root) key_path name - (* set reg value to
REG_DWORD 1, creating intermediate keys if needed *)
- let node - let rec loop parent = function
- | [] -> parent
- | x :: xs ->
- let node - match g#hivex_node_get_child parent x with
- | 0L -> g#hivex_node_add_child parent x (* not found, create *)
- | node -> node in
- loop node xs
- in
- loop root key_path in
+ (* [set_reg_val_dword_1 path name] creates a registry key
+ * called [name = dword:1] in the registry [path].
+ * Intermediate nodes are created along the path if required.
+ *
+ * It returns the old value, if there was one, else [None].
+ *)
+ and set_reg_val_dword_1 ((g, root) as reg) path name + let node =
Registry.create_path reg path in
let valueh = g#hivex_node_get_value node name in
let value match valueh with
@@ -279,8 +274,7 @@ reg delete \"%s\" /v %s /f" strkey name
"Settings"] in
let name = "SuppressNewHWUI" in
let value = Registry.with_hive_write g software_hive_filename (
- fun reg ->
- set_reg_val_dword_1 reg key_path name
+ fun reg -> set_reg_val_dword_1 reg key_path name
) in
reg_restore ("HKLM\\Software" :: key_path) name value
@@ -290,8 +284,8 @@ reg delete \"%s\" /v %s /f" strkey name
let name = "SuppressUI" in
let value = Registry.with_hive_write g system_hive_filename (
fun reg ->
- set_reg_val_dword_1 reg (inspect.i_windows_current_control_set
- :: key_path) name
+ let path = inspect.i_windows_current_control_set :: key_path in
+ set_reg_val_dword_1 reg path name
) in
reg_restore ("HKLM\\SYSTEM\\CurrentControlSet" :: key_path)
name
value
--
2.10.2
Richard W.M. Jones
2017-Feb-18 08:05 UTC
[Libguestfs] [PATCH 7/8] New APIs: guestfs_inspect_get_windows_software_hive and guestfs_inspect_get_windows_system_hive.
The inspection code already computed the paths of the software hive
(twice!) and the system hive, plus we also recompute the same paths
elsewhere, in virt-v2v for example. Therefore it makes sense to store
the paths from the inspection code and make them available through two
new APIs.
---
generator/actions.ml | 34 +++++++++++++++
lib/guestfs-internal.h | 2 +
lib/inspect-apps.c | 8 +---
lib/inspect-fs-windows.c | 110 ++++++++++++++++++++++++++++++-----------------
lib/inspect.c | 30 +++++++++++++
5 files changed, 139 insertions(+), 45 deletions(-)
diff --git a/generator/actions.ml b/generator/actions.ml
index 67db08c..8a897a8 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -3756,6 +3756,40 @@ Searches all the entries associated with the given inode.
For each entry, a C<tsk_dirent> structure is returned.
See C<filesystem_walk> for more information about C<tsk_dirent>
structures." };
+ { defaults with
+ name = "inspect_get_windows_software_hive"; added = (1, 35, 26);
+ style = RString "path", [Mountable "root"], [];
+ shortdesc = "get the path of the Windows software hive";
+ longdesc = "\
+This returns the path to the hive (binary Windows Registry file)
+corresponding to HKLM\\SOFTWARE.
+
+This call assumes that the guest is Windows and that the guest
+has a software hive file with the right name. If this is not the
+case then an error is returned. This call does not check that the
+hive is a valid Windows Registry hive.
+
+You can use C<guestfs_hivex_open> to read or write to the hive.
+
+Please read L<guestfs(3)/INSPECTION> for more details." };
+
+ { defaults with
+ name = "inspect_get_windows_system_hive"; added = (1, 35, 26);
+ style = RString "path", [Mountable "root"], [];
+ shortdesc = "get the path of the Windows system hive";
+ longdesc = "\
+This returns the path to the hive (binary Windows Registry file)
+corresponding to HKLM\\SYSTEM.
+
+This call assumes that the guest is Windows and that the guest
+has a system hive file with the right name. If this is not the
+case then an error is returned. This call does not check that the
+hive is a valid Windows Registry hive.
+
+You can use C<guestfs_hivex_open> to read or write to the hive.
+
+Please read L<guestfs(3)/INSPECTION> for more details." };
+
]
(* daemon_functions are any functions which cause some action
diff --git a/lib/guestfs-internal.h b/lib/guestfs-internal.h
index 04d087b..7126b88 100644
--- a/lib/guestfs-internal.h
+++ b/lib/guestfs-internal.h
@@ -659,6 +659,8 @@ struct inspect_fs {
char *arch;
char *hostname;
char *windows_systemroot;
+ char *windows_software_hive;
+ char *windows_system_hive;
char *windows_current_control_set;
char **drive_mappings;
enum inspect_os_format format;
diff --git a/lib/inspect-apps.c b/lib/inspect-apps.c
index 0f2b505..1216c52 100644
--- a/lib/inspect-apps.c
+++ b/lib/inspect-apps.c
@@ -782,16 +782,12 @@ static void list_applications_windows_from_path (guestfs_h
*g, struct guestfs_ap
static struct guestfs_application2_list *
list_applications_windows (guestfs_h *g, struct inspect_fs *fs)
{
- CLEANUP_FREE char *software - safe_asprintf (g,
"%s/system32/config/software", fs->windows_systemroot);
- CLEANUP_FREE char *software_path;
struct guestfs_application2_list *ret = NULL;
- software_path = guestfs_case_sensitive_path (g, software);
- if (!software_path)
+ if (!fs->windows_software_hive)
return NULL;
- if (guestfs_hivex_open (g, software_path,
+ if (guestfs_hivex_open (g, fs->windows_software_hive,
GUESTFS_HIVEX_OPEN_VERBOSE, g->verbose,
GUESTFS_HIVEX_OPEN_UNSAFE, 1,
-1) == -1)
diff --git a/lib/inspect-fs-windows.c b/lib/inspect-fs-windows.c
index fc0b42b..35f7cc8 100644
--- a/lib/inspect-fs-windows.c
+++ b/lib/inspect-fs-windows.c
@@ -55,6 +55,7 @@ COMPILE_REGEXP (re_boot_ini_os,
"^(multi|scsi)\\((\\d+)\\)disk\\((\\d+)\\)rdisk\\((\\d+)\\)partition\\((\\d+)\\)([^=]+)=",
0)
static int check_windows_arch (guestfs_h *g, struct inspect_fs *fs);
+static int check_windows_registry_paths (guestfs_h *g, struct inspect_fs *fs);
static int check_windows_software_registry (guestfs_h *g, struct inspect_fs
*fs);
static int check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs);
static char *map_registry_disk_blob (guestfs_h *g, const void *blob);
@@ -218,6 +219,10 @@ guestfs_int_check_windows_root (guestfs_h *g, struct
inspect_fs *fs,
if (check_windows_arch (g, fs) == -1)
return -1;
+ /* Get system and software registry paths. */
+ if (check_windows_registry_paths (g, fs) == -1)
+ return -1;
+
/* Product name and version. */
if (check_windows_software_registry (g, fs) == -1)
return -1;
@@ -249,6 +254,58 @@ check_windows_arch (guestfs_h *g, struct inspect_fs *fs)
return 0;
}
+static int
+check_windows_registry_paths (guestfs_h *g, struct inspect_fs *fs)
+{
+ int r;
+ CLEANUP_FREE char *software = NULL, *system = NULL;
+
+ if (!fs->windows_systemroot)
+ return 0;
+
+ software = safe_asprintf (g, "%s/system32/config/software",
+ fs->windows_systemroot);
+
+ fs->windows_software_hive = guestfs_case_sensitive_path (g, software);
+ if (!fs->windows_software_hive)
+ return -1;
+
+ r = guestfs_is_file (g, fs->windows_software_hive);
+ if (r == -1) {
+ free (fs->windows_software_hive);
+ fs->windows_software_hive = NULL;
+ return -1;
+ }
+
+ if (r == 0) { /* doesn't exist, or not a file */
+ free (fs->windows_software_hive);
+ fs->windows_software_hive = NULL;
+ /*FALLTHROUGH*/
+ }
+
+ system = safe_asprintf (g, "%s/system32/config/system",
+ fs->windows_systemroot);
+
+ fs->windows_system_hive = guestfs_case_sensitive_path (g, system);
+ if (!fs->windows_system_hive)
+ return -1;
+
+ r = guestfs_is_file (g, fs->windows_system_hive);
+ if (r == -1) {
+ free (fs->windows_system_hive);
+ fs->windows_system_hive = NULL;
+ return -1;
+ }
+
+ if (r == 0) { /* doesn't exist, or not a file */
+ free (fs->windows_system_hive);
+ fs->windows_system_hive = NULL;
+ /*FALLTHROUGH*/
+ }
+
+ return 0;
+}
+
/* At the moment, pull just the ProductName and version numbers from
* the registry. In future there is a case for making many more
* registry fields available to callers.
@@ -257,24 +314,6 @@ static int
check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs)
{
int ret = -1;
- int r;
-
- CLEANUP_FREE char *software - safe_asprintf (g,
"%s/system32/config/software", fs->windows_systemroot);
-
- CLEANUP_FREE char *software_path = guestfs_case_sensitive_path (g, software);
- if (!software_path)
- return -1;
-
- r = guestfs_is_file (g, software_path);
- if (r == -1)
- return -1;
- /* If the software hive doesn't exist, just accept that we cannot
- * find product_name etc.
- */
- if (r == 0)
- return 0;
-
int64_t node;
const char *hivepath[] { "Microsoft", "Windows NT",
"CurrentVersion" };
@@ -282,7 +321,13 @@ check_windows_software_registry (guestfs_h *g, struct
inspect_fs *fs)
CLEANUP_FREE_HIVEX_VALUE_LIST struct guestfs_hivex_value_list *values = NULL;
bool ignore_currentversion = false;
- if (guestfs_hivex_open (g, software_path,
+ /* If the software hive doesn't exist, just accept that we cannot
+ * find product_name etc.
+ */
+ if (!fs->windows_software_hive)
+ return 0;
+
+ if (guestfs_hivex_open (g, fs->windows_software_hive,
GUESTFS_HIVEX_OPEN_VERBOSE, g->verbose,
GUESTFS_HIVEX_OPEN_UNSAFE, 1,
-1) == -1)
@@ -375,26 +420,7 @@ check_windows_software_registry (guestfs_h *g, struct
inspect_fs *fs)
static int
check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
{
- int r;
static const char gpt_prefix[] = "DMIO:ID:";
-
- CLEANUP_FREE char *system - safe_asprintf (g,
"%s/system32/config/system",
- fs->windows_systemroot);
-
- CLEANUP_FREE char *system_path = guestfs_case_sensitive_path (g, system);
- if (!system_path)
- return -1;
-
- r = guestfs_is_file (g, system_path);
- if (r == -1)
- return -1;
- /* If the system hive doesn't exist, just accept that we cannot
- * find hostname etc.
- */
- if (r == 0)
- return 0;
-
int ret = -1;
int64_t root, node, value;
CLEANUP_FREE_HIVEX_VALUE_LIST struct guestfs_hivex_value_list *values = NULL;
@@ -406,7 +432,13 @@ check_windows_system_registry (guestfs_h *g, struct
inspect_fs *fs)
const char *hivepath[] { NULL /* current control set */,
"Services", "Tcpip", "Parameters" };
- if (guestfs_hivex_open (g, system_path,
+ /* If the system hive doesn't exist, just accept that we cannot
+ * find hostname etc.
+ */
+ if (!fs->windows_system_hive)
+ return 0;
+
+ if (guestfs_hivex_open (g, fs->windows_system_hive,
GUESTFS_HIVEX_OPEN_VERBOSE, g->verbose,
GUESTFS_HIVEX_OPEN_UNSAFE, 1,
-1) == -1)
diff --git a/lib/inspect.c b/lib/inspect.c
index da80e47..24ee6fe 100644
--- a/lib/inspect.c
+++ b/lib/inspect.c
@@ -432,6 +432,36 @@ guestfs_impl_inspect_get_windows_systemroot (guestfs_h *g,
const char *root)
}
char *
+guestfs_impl_inspect_get_windows_software_hive (guestfs_h *g, const char *root)
+{
+ struct inspect_fs *fs = guestfs_int_search_for_root (g, root);
+ if (!fs)
+ return NULL;
+
+ if (!fs->windows_software_hive) {
+ error (g, _("not a Windows guest, or software hive not found"));
+ return NULL;
+ }
+
+ return safe_strdup (g, fs->windows_software_hive);
+}
+
+char *
+guestfs_impl_inspect_get_windows_system_hive (guestfs_h *g, const char *root)
+{
+ struct inspect_fs *fs = guestfs_int_search_for_root (g, root);
+ if (!fs)
+ return NULL;
+
+ if (!fs->windows_system_hive) {
+ error (g, _("not a Windows guest, or system hive not found"));
+ return NULL;
+ }
+
+ return safe_strdup (g, fs->windows_system_hive);
+}
+
+char *
guestfs_impl_inspect_get_windows_current_control_set (guestfs_h *g,
const char *root)
{
--
2.10.2
Richard W.M. Jones
2017-Feb-18 08:05 UTC
[Libguestfs] [PATCH 8/8] Use the new Windows software/system hive APIs in various places.
---
customize/firstboot.ml | 5 +----
examples/virt-dhcp-address.c | 5 ++---
v2v/convert_windows.ml | 43 +++++++++++++++++--------------------------
v2v/inspect_source.ml | 8 ++++++--
v2v/types.ml | 6 ++++++
v2v/types.mli | 2 ++
v2v/v2v_unit_tests.ml | 4 +++-
7 files changed, 37 insertions(+), 36 deletions(-)
diff --git a/customize/firstboot.ml b/customize/firstboot.ml
index 5489c21..09ffca8 100644
--- a/customize/firstboot.ml
+++ b/customize/firstboot.ml
@@ -313,10 +313,7 @@ echo uninstalling firstboot service
g#write (firstboot_dir // "firstboot.bat") (unix2dos
firstboot_script);
(* Open the SYSTEM hive. *)
- let systemroot = g#inspect_get_windows_systemroot root in
- let filename = sprintf "%s/system32/config/SYSTEM" systemroot in
- let filename = g#case_sensitive_path filename in
- Registry.with_hive_write g filename
+ Registry.with_hive_write g (g#inspect_get_windows_system_hive root)
(fun reg ->
let current_cs = g#inspect_get_windows_current_control_set root in
diff --git a/examples/virt-dhcp-address.c b/examples/virt-dhcp-address.c
index df06ebe..0c7e763 100644
--- a/examples/virt-dhcp-address.c
+++ b/examples/virt-dhcp-address.c
@@ -203,9 +203,8 @@ print_dhcp_address_windows (guestfs_h *g, char *root_fs)
size_t i;
char *p;
- /* Locate the SYSTEM hive case-sensitive path. */
- system_path - guestfs_case_sensitive_path (g,
"/windows/system32/config/system");
+ /* Locate the SYSTEM hive. */
+ system_path = guestfs_inspect_get_windows_system_hive (g, root_fs);
if (!system_path)
exit (EXIT_FAILURE);
diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
index e929e1c..e259c22 100644
--- a/v2v/convert_windows.ml
+++ b/v2v/convert_windows.ml
@@ -68,25 +68,12 @@ let convert ~keep_serial_console (g : G.guestfs) inspect
source rcaps None
) in
- (* Get the software and system hive files. *)
- let software_hive_filename - let filename = sprintf
"%s/system32/config/software"
- inspect.i_windows_systemroot in
- let filename = g#case_sensitive_path filename in
- filename in
-
- let system_hive_filename - let filename = sprintf
"%s/system32/config/system"
- inspect.i_windows_systemroot in
- let filename = g#case_sensitive_path filename in
- filename in
-
(*----------------------------------------------------------------------*)
(* Inspect the Windows guest. *)
(* If the Windows guest appears to be using group policy. *)
let has_group_policy - Registry.with_hive_readonly g
software_hive_filename
+ Registry.with_hive_readonly g inspect.i_windows_software_hive
(fun reg ->
try
let path = ["Microsoft"; "Windows";
"CurrentVersion";
@@ -129,7 +116,7 @@ let convert ~keep_serial_console (g : G.guestfs) inspect
source rcaps let xenpv_uninst let xenpvreg = "Red Hat
Paravirtualized Xen Drivers for Windows(R)" in
- Registry.with_hive_readonly g software_hive_filename
+ Registry.with_hive_readonly g inspect.i_windows_software_hive
(fun reg ->
try
let path = ["Microsoft"; "Windows";
"CurrentVersion"; "Uninstall";
@@ -170,7 +157,7 @@ let convert ~keep_serial_console (g : G.guestfs) inspect
source rcaps let prltools_uninsts let uninsts = ref [] in
- Registry.with_hive_readonly g software_hive_filename
+ Registry.with_hive_readonly g inspect.i_windows_software_hive
(fun reg ->
try
let path = ["Microsoft"; "Windows";
"CurrentVersion"; "Uninstall"] in
@@ -273,20 +260,22 @@ reg delete \"%s\" /v %s /f" strkey name
let key_path = ["Policies"; "Microsoft";
"Windows"; "DeviceInstall";
"Settings"] in
let name = "SuppressNewHWUI" in
- let value = Registry.with_hive_write g software_hive_filename (
- fun reg -> set_reg_val_dword_1 reg key_path name
- ) in
+ let value + Registry.with_hive_write g
inspect.i_windows_software_hive (
+ fun reg -> set_reg_val_dword_1 reg key_path name
+ ) in
reg_restore ("HKLM\\Software" :: key_path) name value
(* WinXP 64bit / Win2k3 *)
| 5, 2 ->
let key_path = ["Services"; "PlugPlay";
"Parameters"] in
let name = "SuppressUI" in
- let value = Registry.with_hive_write g system_hive_filename (
- fun reg ->
- let path = inspect.i_windows_current_control_set :: key_path in
- set_reg_val_dword_1 reg path name
- ) in
+ let value + Registry.with_hive_write g
inspect.i_windows_system_hive (
+ fun reg ->
+ let path = inspect.i_windows_current_control_set :: key_path in
+ set_reg_val_dword_1 reg path name
+ ) in
reg_restore ("HKLM\\SYSTEM\\CurrentControlSet" :: key_path)
name
value
@@ -623,10 +612,12 @@ if errorlevel 3010 exit /b 0
(* Open the system hive for writes and update it. *)
let block_driver, net_driver, video_driver - Registry.with_hive_write g
system_hive_filename update_system_hive in
+ Registry.with_hive_write g inspect.i_windows_system_hive
+ update_system_hive in
(* Open the software hive for writes and update it. *)
- Registry.with_hive_write g software_hive_filename update_software_hive;
+ Registry.with_hive_write g inspect.i_windows_software_hive
+ update_software_hive;
fix_ntfs_heads ();
diff --git a/v2v/inspect_source.ml b/v2v/inspect_source.ml
index 3b16c42..2b422e0 100644
--- a/v2v/inspect_source.ml
+++ b/v2v/inspect_source.ml
@@ -70,13 +70,15 @@ let rec inspect_source root_choice g (* If the guest is
Windows, get some Windows-specific inspection
* data, else (for simplicity when accessing) use empty strings.
*)
- let systemroot, current_cs + let systemroot, software_hive, system_hive,
current_cs match typ with
| "windows" ->
g#inspect_get_windows_systemroot root,
+ g#inspect_get_windows_software_hive root,
+ g#inspect_get_windows_system_hive root,
g#inspect_get_windows_current_control_set root
| _ ->
- "", "" in
+ "", "", "", "" in
let inspect = {
i_root = root;
@@ -94,6 +96,8 @@ let rec inspect_source root_choice g i_apps_map =
apps_map;
i_firmware = get_firmware_bootable_device g;
i_windows_systemroot = systemroot;
+ i_windows_software_hive = software_hive;
+ i_windows_system_hive = system_hive;
i_windows_current_control_set = current_cs;
} in
debug "%s" (string_of_inspect inspect);
diff --git a/v2v/types.ml b/v2v/types.ml
index 7fd6327..9d94dca 100644
--- a/v2v/types.ml
+++ b/v2v/types.ml
@@ -325,6 +325,8 @@ type inspect = {
i_apps_map : Guestfs.application2 list StringMap.t;
i_firmware : i_firmware;
i_windows_systemroot : string;
+ i_windows_software_hive : string;
+ i_windows_system_hive : string;
i_windows_current_control_set : string;
}
@@ -342,6 +344,8 @@ i_product_name = %s
i_product_variant = %s
i_firmware = %s
i_windows_systemroot = %s
+i_windows_software_hive = %s
+i_windows_system_hive = %s
i_windows_current_control_set = %s
" inspect.i_root
inspect.i_type
@@ -357,6 +361,8 @@ i_windows_current_control_set = %s
| I_BIOS -> "BIOS"
| I_UEFI devices -> sprintf "UEFI [%s]" (String.concat ",
" devices))
inspect.i_windows_systemroot
+ inspect.i_windows_software_hive
+ inspect.i_windows_system_hive
inspect.i_windows_current_control_set
type mpstat = {
diff --git a/v2v/types.mli b/v2v/types.mli
index df50b1b..48e47b0 100644
--- a/v2v/types.mli
+++ b/v2v/types.mli
@@ -231,6 +231,8 @@ type inspect = {
(** The list of EFI system partitions for the guest with UEFI,
otherwise the BIOS identifier. *)
i_windows_systemroot : string;
+ i_windows_software_hive : string;
+ i_windows_system_hive : string;
i_windows_current_control_set : string;
}
(** Inspection information. *)
diff --git a/v2v/v2v_unit_tests.ml b/v2v/v2v_unit_tests.ml
index af86afa..bd65788 100644
--- a/v2v/v2v_unit_tests.ml
+++ b/v2v/v2v_unit_tests.ml
@@ -31,7 +31,9 @@ let inspect_defaults = {
i_root = ""; i_package_format = ""; i_package_management
= "";
i_product_name = ""; i_product_variant = "";
i_mountpoints = [];
i_apps = []; i_apps_map = StringMap.empty; i_firmware = I_BIOS;
- i_windows_systemroot = ""; i_windows_current_control_set =
"";
+ i_windows_systemroot = "";
+ i_windows_software_hive = ""; i_windows_system_hive = "";
+ i_windows_current_control_set = "";
}
let test_get_ostype ctx --
2.10.2
Pino Toscano
2017-Feb-21 13:59 UTC
Re: [Libguestfs] [PATCH 0/8] Miscellaneous cleanups to Windows registry code.
On Saturday, 18 February 2017 08:05:27 CET Richard W.M. Jones wrote:> A very miscellaneous set of cleanups to how we handle the Windows > registry in virt-v2v, firstboot, and inspection code. This should all > be straightforward non-controversial refactoring. Some highlights: > > - Add a new mllib Registry module containing various utility > functions that are currently scattered all around.IMHO it should be better named as WinRegistry, although I won't hold my breath on it. The rest of the changes LGTM (even if I'm not familiar with this code base). Thanks, -- Pino Toscano
Richard W.M. Jones
2017-Feb-21 14:06 UTC
Re: [Libguestfs] [PATCH 0/8] Miscellaneous cleanups to Windows registry code.
On Tue, Feb 21, 2017 at 02:59:38PM +0100, Pino Toscano wrote:> On Saturday, 18 February 2017 08:05:27 CET Richard W.M. Jones wrote: > > A very miscellaneous set of cleanups to how we handle the Windows > > registry in virt-v2v, firstboot, and inspection code. This should all > > be straightforward non-controversial refactoring. Some highlights: > > > > - Add a new mllib Registry module containing various utility > > functions that are currently scattered all around. > > IMHO it should be better named as WinRegistry, although I won't hold > my breath on it.Originally I wrote it as Windows_registry. It was a bit long :-) Rich.> The rest of the changes LGTM (even if I'm not familiar with this code > base). > > Thanks, > -- > Pino Toscano> _______________________________________________ > Libguestfs mailing list > Libguestfs@redhat.com > https://www.redhat.com/mailman/listinfo/libguestfs-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://libguestfs.org
Richard W.M. Jones
2017-Feb-21 14:07 UTC
Re: [Libguestfs] [PATCH 0/8] Miscellaneous cleanups to Windows registry code.
On Tue, Feb 21, 2017 at 02:59:38PM +0100, Pino Toscano wrote:> On Saturday, 18 February 2017 08:05:27 CET Richard W.M. Jones wrote: > > A very miscellaneous set of cleanups to how we handle the Windows > > registry in virt-v2v, firstboot, and inspection code. This should all > > be straightforward non-controversial refactoring. Some highlights: > > > > - Add a new mllib Registry module containing various utility > > functions that are currently scattered all around. > > IMHO it should be better named as WinRegistry, although I won't hold > my breath on it. > > The rest of the changes LGTM (even if I'm not familiar with this code > base).BTW there was a memory leak in the patches posted (fs->windows_{software,system}_hive not freed). I have fixed that in my latest version. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 100 libraries supported. http://fedoraproject.org/wiki/MinGW
Possibly Parallel Threads
- [PATCH v2 0/2] v2v:windows: prevent conflicts with PnP on firstboot
- [PATCH FOR DISCUSSION ONLY 0/2] v2v: Copy static IP address information over for Windows guests (RHBZ#1626503).
- [PATCH v2 2/2] v2v: Copy static IP address information over for Windows guests (RHBZ#1626503).
- [PATCH] v2v:windows: prevent Parallels drivers from loading at boot
- Re: [PATCH 2/2] v2v:windows: prevent conflicts with PnP on firstboot