X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=tools%2Fvirt-win-reg;h=2db26712b4f3bb0496bc8d96e683c621183dd3f3;hp=b4bb1f0f6625419f0b2ffd85b13fce003dc67255;hb=bc468c87d04b34faacd208c49cca4a5096e5103c;hpb=4b48f93ce6407923ea23451cfe39ac63811d1f42 diff --git a/tools/virt-win-reg b/tools/virt-win-reg index b4bb1f0..2db2671 100755 --- a/tools/virt-win-reg +++ b/tools/virt-win-reg @@ -20,15 +20,14 @@ use warnings; use strict; use Sys::Guestfs; -use Sys::Guestfs::Lib qw(open_guest get_partitions resolve_windows_path - inspect_all_partitions inspect_partition - inspect_operating_systems mount_operating_system); +use Sys::Guestfs::Lib qw(open_guest); use Win::Hivex; use Win::Hivex::Regedit qw(reg_import reg_export); use Pod::Usage; use Getopt::Long; use File::Temp qw/tempdir/; +use File::Basename; use Locale::TextDomain 'libguestfs'; =encoding utf8 @@ -86,21 +85,6 @@ the Windows Registry: $ virt-win-reg --merge Windows7 changes.reg -=head2 SUPPORTED SYSTEMS - -The program currently supports Windows NT-derived guests starting with -Windows XP through to at least Windows 7. - -Registry support is done for C, -C, C, -C and C. - -You can use C as a shorthand for C, and -C for C. - -C and C are B supported at -this time. - =head2 NOTE This program is only meant for simple access to the registry. If you @@ -109,51 +93,6 @@ download the Registry hive files from the guest using L or L and access them locally, eg. using L, L or L. -=head2 ENCODING - -C expects that regedit files have already been reencoded -in the local encoding. Usually on Linux hosts, this means UTF-8 with -Unix-style line endings. Since Windows regedit files are often in -UTF-16LE with Windows-style line endings, you may need to reencode the -whole file before or after processing. - -To reencode a file from Windows format to Linux (before processing it -with the C<--merge> option), you would do something like this: - - iconv -f utf-16le -t utf-8 < win.reg | dos2unix > linux.reg - -To go in the opposite direction, after exporting and before sending -the file to a Windows user, do something like this: - - unix2dos linux.reg | iconv -f utf-8 -t utf-16le > win.reg - -For more information about encoding, see L. - -If you are unsure about the current encoding, use the L -command. Recent versions of Windows regedit.exe produce a UTF-16LE -file with Windows-style (CRLF) line endings, like this: - - $ file software.reg - software.reg: Little-endian UTF-16 Unicode text, with very long lines, - with CRLF line terminators - -This file would need conversion before you could C<--merge> it. - -=head2 SHELL QUOTING - -Be careful when passing parameters containing C<\> (backslash) in the -shell. Usually you will have to use 'single quotes' or double -backslashes (but not both) to protect them from the shell. - -Paths and value names are case-insensitive. - -=head2 CurrentControlSet etc. - -Registry keys like C don't really exist in the -Windows Registry at the level of the hive file, and therefore you -cannot modify these. Replace this with C, and -similarly for other C keys. - =head1 OPTIONS =over 4 @@ -196,6 +135,23 @@ at all. =cut +my $format; + +=item B<--format> raw + +Specify the format of disk images given on the command line. If this +is omitted then the format is autodetected from the content of the +disk image. + +If disk images are requested from libvirt, then this program asks +libvirt for this information. In this case, the value of the format +parameter is ignored. + +If working with untrusted raw-format guest disk images, you should +ensure the format is always specified. + +=cut + my $merge; =item B<--merge> @@ -229,6 +185,7 @@ GetOptions ("help|?" => \$help, "version" => \$version, "connect|c=s" => \$uri, "debug|d" => \$debug, + "format=s" => \$format, "merge" => \$merge, "encoding=s" => \$encoding, ) or pod2usage (2); @@ -249,29 +206,29 @@ warn "launching libguestfs ..." if $debug; my @lib_args = ([$domname_or_image]); push @lib_args, address => $uri if $uri; push @lib_args, rw => 1 if $merge; +push @lib_args, format => $format if defined $format; my $g = open_guest (@lib_args); $g->launch (); warn "inspecting guest ..." if $debug; -# List of possible filesystems. -my @partitions = get_partitions ($g); - -# Now query each one to build up a picture of what's in it. -my %fses = - inspect_all_partitions ($g, \@partitions, - use_windows_registry => 0); - -my $oses = inspect_operating_systems ($g, \%fses); - -my @roots = keys %$oses; -die __"no root device found in this operating system image" if @roots == 0; -die __"multiboot operating systems are not supported by virt-win-reg" if @roots > 1; -my $root_dev = $roots[0]; +my @roots = $g->inspect_os (); +if (@roots == 0) { + die __x("{prog}: No operating system could be detected inside this disk image.\n\nThis may be because the file is not a disk image, or is not a virtual machine\nimage, or because the OS type is not understood by libguestfs.\n\nIf you feel this is an error, please file a bug report including as much\ninformation about the disk image as possible.\n", + prog => basename ($0)); +} +if (@roots > 1) { + die __x("{prog}: multiboot operating systems are not supported.\n", + prog => basename ($0)) +} +my %fses = $g->inspect_get_mountpoints ($roots[0]); +my @fses = sort { length $a <=> length $b } keys %fses; +my $mountopts = $merge ? "" : "ro"; +foreach (@fses) { + $g->mount_options ($mountopts, $fses{$_}, $_); +} -my $os = $oses->{$root_dev}; -my $ro = $merge ? 0 : 1; -mount_operating_system ($g, $os, $ro); +my $systemroot = $g->inspect_get_windows_systemroot ($roots[0]); # Create a working directory to store the downloaded registry files. my $tmpdir = tempdir (CLEANUP => 1); @@ -323,7 +280,7 @@ else { # Import mode. %hives = (); # Look in the tmpdir for all the hive files which have been - # downloaded / modified by the import mapper, and upload + # downloaded / modified by the import mapper, and upload # each one. opendir my $dh, $tmpdir or die "$tmpdir: $!"; foreach (readdir $dh) { @@ -404,7 +361,6 @@ sub download_hive local $_; my $hivename = shift; - my $systemroot = $os->{root}->{systemroot} || "/windows"; my $winfile_before = "$systemroot/system32/config/$hivename"; my $winfile; eval { $winfile = $g->case_sensitive_path ($winfile_before); }; @@ -427,7 +383,6 @@ sub upload_hive local $_; my $hivename = shift; - my $systemroot = $os->{root}->{systemroot} || "/windows"; my $winfile_before = "$systemroot/system32/config/$hivename"; my $winfile; eval { $winfile = $g->case_sensitive_path ($winfile_before); }; @@ -444,6 +399,176 @@ sub upload_hive } } +=head1 SUPPORTED SYSTEMS + +The program currently supports Windows NT-derived guests starting with +Windows XP through to at least Windows 7. + +Registry support is done for C, +C, C, +C and C. + +You can use C as a shorthand for C, and +C for C. + +C and C are B supported at +this time. + +=head1 ENCODING + +C expects that regedit files have already been reencoded +in the local encoding. Usually on Linux hosts, this means UTF-8 with +Unix-style line endings. Since Windows regedit files are often in +UTF-16LE with Windows-style line endings, you may need to reencode the +whole file before or after processing. + +To reencode a file from Windows format to Linux (before processing it +with the C<--merge> option), you would do something like this: + + iconv -f utf-16le -t utf-8 < win.reg | dos2unix > linux.reg + +To go in the opposite direction, after exporting and before sending +the file to a Windows user, do something like this: + + unix2dos linux.reg | iconv -f utf-8 -t utf-16le > win.reg + +For more information about encoding, see L. + +If you are unsure about the current encoding, use the L +command. Recent versions of Windows regedit.exe produce a UTF-16LE +file with Windows-style (CRLF) line endings, like this: + + $ file software.reg + software.reg: Little-endian UTF-16 Unicode text, with very long lines, + with CRLF line terminators + +This file would need conversion before you could C<--merge> it. + +=head1 CurrentControlSet etc. + +Registry keys like C don't really exist in the +Windows Registry at the level of the hive file, and therefore you +cannot modify these. + +C is usually an alias for C. In +some circumstances it might refer to another control set. The way +to find out is to look at the C key: + + # virt-win-reg WindowsGuest 'HKLM\SYSTEM\Select' + [HKEY_LOCAL_MACHINE\SYSTEM\Select] + "Current"=dword:00000001 + "Default"=dword:00000001 + "Failed"=dword:00000000 + "LastKnownGood"=dword:00000002 + +"Current" is the one which Windows will choose when it boots. + +Similarly, other C keys in the path may need to +be replaced. + +=head1 WINDOWS TIPS + +Note that some of these tips modify the guest disk image. The guest +I be shut off, else you will get disk corruption. + +=head2 RUNNING A BATCH SCRIPT WHEN A USER LOGS IN + +Prepare a DOS batch script, VBScript or executable. Upload this using +L. For this example the script is called C +and it is uploaded into C: + + guestfish -i -d WindowsGuest upload test.bat /test.bat + +Prepare a regedit file containing the registry change: + + cat > test.reg <<'EOF' + [HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce] + "Test"="c:\\test.bat" + EOF + +In this example we use the key C which means that the script +will run precisely once when the first user logs in. If you want it +to run every time a user logs in, replace C with C. + +Now update the registry: + + virt-win-reg --merge WindowsGuest test.reg + +=head2 INSTALLING A SERVICE + +This section assumes you are familiar with Windows services, and you +either have a program which handles the Windows Service Control +Protocol directly or you want to run any program using a service +wrapper like SrvAny or the free RHSrvAny. + +First upload the program and optionally the service wrapper. In this +case the test program is called C and we are using the +RHSrvAny wrapper: + + guestfish -i -d WindowsGuest < service.reg <<'EOF' + [HKLM\SYSTEM\ControlSet001\services\RHSrvAny] + "Type"=dword:00000010 + "Start"=dword:00000002 + "ErrorControl"=dword:00000001 + "ImagePath"="c:\\rhsrvany.exe" + "DisplayName"="RHSrvAny" + "ObjectName"="NetworkService" + + [HKLM\SYSTEM\ControlSet001\services\RHSrvAny\Parameters] + "CommandLine"="c:\\test.exe" + "PWD"="c:\\Temp" + EOF + +Notes: + +=over 4 + +=item * + +For use of C see the section above in this manual page. +You may need to adjust this according to the control set that is in +use by the guest. + +=item * + +C<"ObjectName"> controls the privileges that the service will have. +An alternative is C<"ObjectName"="LocalSystem"> which would be the +most privileged account. + +=item * + +For the meaning of the magic numbers, see this Microsoft KB article: +L. + +=back + +Update the registry: + + virt-win-reg --merge WindowsGuest service.reg + +=head1 SHELL QUOTING + +Be careful when passing parameters containing C<\> (backslash) in the +shell. Usually you will have to use 'single quotes' or double +backslashes (but not both) to protect them from the shell. + +Paths and value names are case-insensitive. + +Libvirt guest names can contain arbitrary characters, some of which +have meaning to the shell such as C<#> and space. You may need to +quote or escape these characters on the command line. See the shell +manual page L for details. + =head1 SEE ALSO L, @@ -472,7 +597,7 @@ L =head1 AUTHOR -Richard W.M. Jones L +Richard W.M. Jones L =head1 COPYRIGHT