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