X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=tools%2Fvirt-win-reg;h=10636172f915d4c9e1d68b8faa0f09639376ca3c;hp=056ecce8faf1aa246908a8b1f95974b26ac19551;hb=35900223df1d05d0b8f4da79c854bee9899f81be;hpb=3b4bb214c36d2659dff58e1a79bad8a9c48fa51d diff --git a/tools/virt-win-reg b/tools/virt-win-reg index 056ecce..1063617 100755 --- a/tools/virt-win-reg +++ b/tools/virt-win-reg @@ -125,7 +125,9 @@ Enable debugging messages. my $uri; -=item B<--connect URI> | B<-c URI> +=item B<-c URI> + +=item B<--connect URI> If using libvirt, connect to the given I. If omitted, then we connect to the default libvirt hypervisor. @@ -367,44 +369,144 @@ sub import_mapper sub map_path_to_hive { local $_ = shift; - my ($hiveshortname, $hivefile, $prefix); + my ($hiveshortname, $hivefile, $path, $prefix); if (/^\\?(?:HKEY_LOCAL_MACHINE|HKLM)\\SAM(\\.*)?$/i) { $hiveshortname = "sam"; $hivefile = "$systemroot/system32/config/$hiveshortname"; - $_ = defined $1 ? $1 : "\\"; + $path = defined $1 ? $1 : "\\"; $prefix = "HKEY_LOCAL_MACHINE\\SAM"; } elsif (/^\\?(?:HKEY_LOCAL_MACHINE|HKLM)\\SECURITY(\\.*)?$/i) { $hiveshortname = "security"; $hivefile = "$systemroot/system32/config/$hiveshortname"; - $_ = defined $1 ? $1 : "\\"; + $path = defined $1 ? $1 : "\\"; $prefix = "HKEY_LOCAL_MACHINE\\SECURITY"; } elsif (/^\\?(?:HKEY_LOCAL_MACHINE|HKLM)\\SOFTWARE(\\.*)?$/i) { $hiveshortname = "software"; $hivefile = "$systemroot/system32/config/$hiveshortname"; - $_ = defined $1 ? $1 : "\\"; + $path = defined $1 ? $1 : "\\"; $prefix = "HKEY_LOCAL_MACHINE\\SOFTWARE"; } elsif (/^\\?(?:HKEY_LOCAL_MACHINE|HKLM)\\SYSTEM(\\.*)?$/i) { $hiveshortname = "system"; $hivefile = "$systemroot/system32/config/$hiveshortname"; - $_ = defined $1 ? $1 : "\\"; + $path = defined $1 ? $1 : "\\"; $prefix = "HKEY_LOCAL_MACHINE\\SYSTEM"; } elsif (/^\\?(?:HKEY_USERS|HKU)\\.DEFAULT(\\.*)?$/i) { $hiveshortname = "default"; $hivefile = "$systemroot/system32/config/$hiveshortname"; - $_ = defined $1 ? $1 : "\\"; + $path = defined $1 ? $1 : "\\"; $prefix = "HKEY_LOCAL_MACHINE\\.DEFAULT"; } + elsif (/^\\?(?:HKEY_USERS|HKU)\\(S-1-5-[-\d]+)(\\.*)?$/i) { + my $sid = $1; + $hiveshortname = $sid; + $prefix = "HKEY_USERS\\$sid"; + $path = defined $2 ? $2 : "\\"; + # This requires a recursive call to download the SOFTWARE hive. + $hivefile = lookup_pip_of_user_sid ($sid) . "/ntuser.dat"; + } + elsif (/^\\?(?:HKEY_USERS|HKU)\\LocalSystem(\\.*)?$/i) { + my $sid = "S-1-5-18"; + $hiveshortname = $sid; + $prefix = "HKEY_USERS\\$sid"; + $path = defined $1 ? $1 : "\\"; + # This requires a recursive call to download the SOFTWARE hive. + $hivefile = lookup_pip_of_user_sid ($sid) . "/ntuser.dat"; + } + elsif (/^\\?(?:HKEY_USERS|HKU)\\LocalService(\\.*)?$/i) { + my $sid = "S-1-5-19"; + $hiveshortname = $sid; + $prefix = "HKEY_USERS\\$sid"; + $path = defined $1 ? $1 : "\\"; + # This requires a recursive call to download the SOFTWARE hive. + $hivefile = lookup_pip_of_user_sid ($sid) . "/ntuser.dat"; + } + elsif (/^\\?(?:HKEY_USERS|HKU)\\NetworkService(\\.*)?$/i) { + my $sid = "S-1-5-20"; + $hiveshortname = $sid; + $prefix = "HKEY_USERS\\$sid"; + $path = defined $1 ? $1 : "\\"; + # This requires a recursive call to download the SOFTWARE hive. + $hivefile = lookup_pip_of_user_sid ($sid) . "/ntuser.dat"; + } + elsif (/^\\?(?:HKEY_USERS|HKU)\\(.*?)(\\.*)?$/i) { + $hiveshortname = "user_$1"; + $prefix = "HKEY_USERS\\$1"; + $path = defined $2 ? $2 : "\\"; + # XXX We should probably look this up properly. + if (is_dir_nocase ("/Users/$1")) { + $hivefile = "/Users/$1/ntuser.dat" + } elsif (is_dir_nocase ("/Documents and Settings/$1")) { + $hivefile = "/Documents and Settings/$1/ntuser.dat" + } else { + die __x("virt-win-reg: {p}: cannot find user directory\n", + p => $1) + } + } else { die __x("virt-win-reg: {p}: not a supported Windows Registry path\n", p => $_) } - return ($hiveshortname, $hivefile, $_, $prefix); + return ($hiveshortname, $hivefile, $path, $prefix); +} + +# Given a User SID, consult +# HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$sid +# and return the ProfileImagePath value. +sub lookup_pip_of_user_sid +{ + local $_; + my $sid = shift; + + my $path = + "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\". + $sid; + + my ($hiveshortname, $hivefile, $prefix); + ($hiveshortname, $hivefile, $path, $prefix) = map_path_to_hive ($path); + + download_hive ($hivefile, $hiveshortname) + unless -f "$tmpdir/$hiveshortname"; + + my @args = ("$tmpdir/$hiveshortname", $path, "ProfileImagePath"); + warn "running hivexget ", join (" ", @args), " ..." if $debug; + + my $fh; + open $fh, "-|", "hivexget", @args + or die "hivexget: see earlier errors: $!"; + $_ = <$fh>; + close $fh or die "hivexget: see earlier errors: $!"; + + chomp; + + # The contents of the registry are a windows path, possibly + # containing %systemroot% and %systemdrive% (on Win XP). Expand + # it and remove some other windows-isms. The caller will do + # case_sensitive_path for us, so we don't need to do that. + s/%systemroot%/$systemroot/i; + s/%systemdrive%//i; + s/^c://i; + s,\\,/,g; + + $_; +} + +sub is_dir_nocase +{ + local $_; + my $dir = shift; + + my $windir; + eval { $windir = $g->case_sensitive_path ($dir); }; + if ($@) { + return 0; + } + return $g->is_dir ($windir); } # Download a named hive file. Die on failure. @@ -456,15 +558,35 @@ sub upload_hive 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. +The following Registry keys are supported: + +=over 4 + +=item C + +=item C + +=item C + +=item C + +=item C + +=item C> + +where I is a Windows User SID (eg. C). + +=item C> + +where I is a local user name (this is a libguestfs extension). + +=back You can use C as a shorthand for C, and C for C. -C and C are B supported at -this time. +The literal keys C and C are not +supported (there is no "current user"). =head1 ENCODING @@ -518,6 +640,17 @@ to find out is to look at the C key: Similarly, other C keys in the path may need to be replaced. +=head1 DELETING REGISTRY KEYS AND VALUES + +To delete a whole registry key, use the syntax: + + [-HKEY_LOCAL_MACHINE\Foo] + +To delete a single value within a key, use the syntax: + + [HKEY_LOCAL_MACHINE\Foo] + "Value"=- + =head1 WINDOWS TIPS Note that some of these tips modify the guest disk image. The guest