# (c) Copyright 2008, 2010-2012. CodeWeavers, Inc.
package CXBT_win7;
use strict;
use CXLog;
use CXUtils;
my $productid=CXUtils::get_product_id();
my $template="win7";
my $datadir="$ENV{CX_ROOT}/share/crossover/bottle_data";
my $templatedir="$ENV{CX_ROOT}/share/crossover/bottle_templates/$template";
my $windows_version="win7";
my $winearch="win32";
my $default_eassocids=".asf:.cfc:.disco:.doc:.dochtml:.dot:.dwr:.dwt:.efx:.em:.emp:.fla:.mdb:.moh:.mov:.mpw:.mpx:.net:.pdf:.pic:.pict:.ppt:.prj:.psd:.psf:.psp:.qdb:.qdf:.qdt:.qfx:.qt:.sch:.swf:.vrml:.vsd:.vst:.vss:.wma:.wmv:.xls";
my $alternative_eassocids=".csv:.rtf";
my $ignore_plugins="_NPDOC\\.DLL\$:_NPDocBox\\.dll\$:_npmozax\\.dll\$:_nppdf32\\.dll\$";
#
# Bottle template query
#
sub new($$)
{
my ($class)=@_;
my $self={ };
bless $self, $class;
return $self;
}
sub query($$$)
{
my ($self, $type, $params)=@_;
if ($type eq "introspect")
{
# Return a very general description of the template.
# This query is supported by all templates.
return { properties => { category => "crossover" } };
}
$@="Unknown query type '$type'";
return undef;
}
#
# Bottle creation / upgrade helpers
#
sub create_windows_label()
{
my $filename="$ENV{WINEPREFIX}/dosdevices/c:/.windows-label";
if (!-f $filename and open(my $fh, ">", $filename))
{
print $fh "drive_c";
close($fh);
}
}
sub run_inf($$$;$)
{
my ($winver, $scope, $upgrade, $unix_paths)=@_;
my $section;
if ($upgrade)
{
# Upgrades shouldn't change the bottle version
$section="DefaultInstall";
}
elsif (($winver || "") =~ /^(win98|win2000|winxp|vista|win7|win8|win10)$/)
{
# Registry key names are case insensitive :-)
$section="${winver}Install";
}
else
{
cxerr("unknown Windows version '$winver'\n");
}
my @cxoptions=();
if (defined $winver)
{
# We must both use --winver, for when called from cxbottle, and set
# CX_WINDOWS_VERSION, for when called by wine, i.e. when the Wine
# environment is already set.
$ENV{CX_WINDOWS_VERSION}=$winver;
push @cxoptions, "--winver", $winver;
}
my $shdocvwmode="b";
my $shdocvwpath=$unix_paths->{"c:/windows/system32/shdocvw.dll"};
if ($shdocvwpath and open(my $shdocvwdll, "<", $shdocvwpath))
{
binmode $shdocvwdll;
seek($shdocvwdll, 0x40, 0);
my $tag;
read($shdocvwdll, $tag, 20);
close($shdocvwdll);
$shdocvwmode="d" if ($tag ne "Wine placeholder DLL");
}
# Set up some dll overrides to register Wine's dlls
$ENV{WINEDLLOVERRIDES}=join(";",
"advpack=b", # Older native advpack miss an API for builtin IE
"atl=b", # Older native atl break registration
"oleaut32=b", # Workaround for a native oleaut32 bug
"rpcrt4=b", # Incompatibility with native rpcrt4
"shdocvw=$shdocvwmode", # wine.inf invokes 'iexplore -regserver' which
"*iexplore.exe=b" # is specific to the builtin version
);
# Note that this will also run wine.inf if needed
if ($section)
{
if (cxsystem("$ENV{CX_ROOT}/bin/wine", "--wl-app", "rundll32.exe",
"--no-quotes", "--scope", $scope, @cxoptions,
"--desktop", "root", "--dll", $ENV{WINEDLLOVERRIDES},
"setupapi.dll,InstallHinfSection", $section, "128",
"$datadir/crossover.inf"))
{
$@="'rundll32 $section crossover.inf' failed\n";
return undef;
}
if ($winearch eq "win64" and
-f "$ENV{CX_ROOT}/bin/wineloader" and
cxsystem("$ENV{CX_ROOT}/bin/wine", "--wl32-app", "rundll32.exe",
"--no-quotes", "--scope", $scope, @cxoptions,
"--desktop", "root", "--dll", $ENV{WINEDLLOVERRIDES},
"setupapi.dll,InstallHinfSection", $section, "128",
"$datadir/crossover.inf"))
{
$@="'rundll32 $section crossover.inf' failed\n";
return undef;
}
}
delete $ENV{CX_WINDOWS_VERSION};
return 1;
}
#
# Bottle creation
#
sub create($$$)
{
my ($self, $cxconfig, $params)=@_;
$@="";
# Set up the cxbottle.conf configuration file
require CXRWConfig;
my $cxbottle=CXRWConfig->new("$datadir/cxbottle.conf");
my $s=$cxbottle->append_section("Bottle");
$s->set("BottleID", CXUtils::get_unique_id($ENV{WINEPREFIX}));
$s->set("Timestamp", $cxconfig->get("CrossOver", "BuildTimestamp"));
$s->set("Encoding", CXUtils::get_system_encoding(1));
$s->set("Template", $template);
$s->set("Description", $params->{description}) if (defined $params->{description});
$s->set("Updater", $params->{updater}) if (defined $params->{updater});
my $menu_root=$cxconfig->get("BottleDefaults", "MenuRoot");
$s->set("MenuRoot", $menu_root) if (defined $menu_root);
my $menu_strip=$cxconfig->get("BottleDefaults", "MenuStrip");
$s->set("MenuStrip", $menu_strip) if (defined $menu_strip);
$s->set("MenuMode", "ignore");
$s->set("AssocMode", "ignore");
$s->set("NSPluginMode", "ignore");
$s->set("WineArch", $winearch);
$cxbottle->write("$ENV{WINEPREFIX}/cxbottle.conf");
# CXBottle::find_bottle() checks for the presence of system.reg to detect
# invalid bottle directories. This creates a race condition due to
# wineserver's delayed save. So touch system.reg now.
if (open(my $fh, ">", "$ENV{WINEPREFIX}/system.reg"))
{
print $fh "WINE REGISTRY Version 2\n";
print $fh "#arch=$winearch\n";
close($fh);
}
return undef if (!run_inf($windows_version, $params->{scope}, 0));
# Adjust the drives
create_windows_label();
# Force the re-creation of the y: drive
my $home=$ENV{HOME} || (getpwuid($>))[7];
my $drive="$ENV{WINEPREFIX}/dosdevices/y:";
unlink $drive;
if (!symlink($home, $drive))
{
cxwarn("unable to create the y: drive symlink: $!\n");
}
# Update the registry
my $start=CXLog::cxtime();
my $cmd=shquote_string("$ENV{CX_ROOT}/bin/wine") .
" --scope $params->{scope} --wl-app regedit.exe -";
cxlog("Piping into $cmd\n");
if (open(my $regedit, "| $cmd"))
{
my $outlook=$cxconfig->get("BottleDefaults", "OutlookSecurity");
if ($outlook)
{
$outlook=$cxconfig->get("BottleDefaults", "BlockedExtensions");
print $regedit "[HKEY_CURRENT_USER\\Software\\Wine\\AppDefaults\\Outlook.exe]\n";
print $regedit "\"DenyShellExecute\"=\"$outlook\"\n";
}
close($regedit);
cxlog("-> rc=$? (took ", CXLog::cxtime()-$start, " seconds)\n");
if ($?)
{
$@="'$cmd' failed: $?\n";
return undef;
}
}
# Notify the bottle hooks
CXBottle::run_bottle_hooks(["create", $templatedir]);
return 1;
}
#
# Bottle upgrade
#
sub rename_fake_windows()
{
my $fake_windows="$ENV{WINEPREFIX}/fake_windows";
if (-d $fake_windows and !-l $fake_windows)
{
# Rename fake_windows to drive_c, but leave a symlinked
# fake_windows behind in order not to break existing scripts.
my $drive_c="$ENV{WINEPREFIX}/drive_c";
if (!rename $fake_windows, $drive_c)
{
$@="unable to move '$fake_windows' to '$drive_c': $!\n";
return undef;
}
if (!symlink "drive_c", $fake_windows)
{
cxwarn("unable to create '$fake_windows' link: $!\n");
}
my $drive_link="$ENV{WINEPREFIX}/dosdevices/c:";
if (-l $drive_link and readlink($drive_link) eq "../fake_windows")
{
unlink $drive_link;
if (!symlink "../drive_c", $drive_link)
{
$@="unable to create '$drive_link' link\n";
return undef;
}
}
}
return 1;
}
sub upgrade_cxbottle($$)
{
my ($cxconfig, $params)=@_;
require CXUpgrade;
my $filename="$ENV{WINEPREFIX}/cxbottle.conf";
cxlog("\n** Upgrading $filename\n\n");
my $src=CXUpgrade->new($filename);
$src=CXUpgrade->new(undef) if (!defined $src);
my $s=$src->get_section("Bottle");
my $old_version;
if (defined $s)
{
$old_version=$s->get("Version", "2.0.0");
unlink "$ENV{WINEPREFIX}/.eval" if ($old_version ne CXUtils::get_product_version());
$old_version=~s/[^0-9.].*$//;
}
else
{
$old_version=$params->{old_version} || "1.3.1";
}
$old_version=~s/^([0-9]\.)/0$1/;
cxlog("Old Version=$old_version\n");
my $template="$datadir/cxbottle.conf";
my $dst=CXUpgrade->new($template);
if (!defined $dst)
{
cxerr("unable to read '$template': $!\n");
return ($old_version, $src);
}
# Tweak the configuration values
my ($encoding, $bottleid);
$s=$src->get_section("Bottle");
if (defined $s)
{
# Reset the Version field
$s->remove_field("Version");
$s->set("Timestamp", $cxconfig->get("CrossOver", "BuildTimestamp", ""));
$encoding=$s->get("Encoding");
# In version < 2.0 the Updater field was called WinePrefixCreate
# and was stored in cxoffice.conf! So for these antique versions,
# simply assume that if this looks like a managed bottle,
# it probably is.
my $updater=$s->get("Updater");
if (!defined $updater and $old_version lt "02.0" and $> == 0 and
$ENV{WINEPREFIX} eq "$ENV{CX_ROOT}/support/dotwine")
{
$s->set("Updater", "wineprefixcreate");
}
$bottleid=$s->get("BottleID");
}
else
{
$s=$src->add_section("Bottle");
}
# Before these existed, bottles were always considered to be installed
$s->set("MenuMode", "install") if (!defined $s->get("MenuMode"));
$s->set("AssocMode", "install") if (!defined $s->get("AssocMode"));
$s->set("NSPluginMode", "install") if (!defined $s->get("NSPluginMode"));
if (!defined $bottleid)
{
# Make sure the bottle gets an id
# (in case of an upgrade from a pre-2.0 tree)
$s->set("BottleID", CXUtils::get_unique_id($ENV{WINEPREFIX}));
}
if (($encoding || "ANSI_X3.4-1968") eq "ANSI_X3.4-1968")
{
# ANSI_X3.4-1968 is ASCII's little name so we assume that it's
# going to be compatible with whatever encoding is used by
# this system.
$s->set("Encoding", CXUtils::get_system_encoding(1));
}
if (!$src->get_filename())
{
# Brand new cxbottle.conf, get MenuRoot from $productid.conf
Loading ...