| #!/usr/bin/perl -w | 
 |  | 
 | # This program generates wine.conf files on STDOUT. | 
 | # Copyright (C) 1996 Stephen Simmons | 
 | # | 
 | # This library is free software; you can redistribute it and/or | 
 | # modify it under the terms of the GNU Lesser General Public | 
 | # License as published by the Free Software Foundation; either | 
 | # version 2.1 of the License, or (at your option) any later version. | 
 | # | 
 | # This library 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 | 
 | # Lesser General Public License for more details. | 
 | # | 
 | # You should have received a copy of the GNU Lesser General Public | 
 | # License along with this library; if not, write to the Free Software | 
 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | 
 | # | 
 | # NOTES: | 
 | # | 
 | # This program examines the contents of the DOS filesystems and | 
 | # attempts to generate a sensible wine.conf file.  This is output | 
 | # to STDOUT. | 
 | # It reads /etc/fstab to find mounting locations of the hard disk drives | 
 | # It uses the correct algorithm for ordering DOS drives, with the | 
 | # exception of the case of multiple drive controller types, where I don't | 
 | # know what DOS's algorithm is. | 
 | # It uses find to find all of the win.ini files on any DOS partition | 
 | # and sorts them by age to guess which is part of the active Windows | 
 | # installation. | 
 | # It reads the autoexec.bat file (if found) and records all variable | 
 | # settings.   There are some inaccuracies in its determination. | 
 | # First, while variables are interpolated properly, no control | 
 | # structures are supported so calls and execs to other batch files are | 
 | # ignored, and all variable settings take effect regardless of whether | 
 | # they would in DOS (i,e., both if and else clauses are read). | 
 | # This is used to determine the path and temp directories.  Duplicate | 
 | # path directories and path directories that don't exist are thrown | 
 | # out. | 
 | # On failing to find C:\AUTOEXEC.BAT, wineconf finds all executables | 
 | # in the windows directory and subdirectories, and generates an | 
 | # optimized path statement encompassing all the executables. | 
 | # Then it also looks for \TEMP and \TMP on all drives taking the first | 
 | # one it finds. | 
 | # wineconf doesn't support floppy drives, network drives, printers, | 
 | # and serial device configuration is hardcoded and not configured for | 
 | # the machine it runs on.  Similarly, spy parameters are hard coded. | 
 |  | 
 | # It would make sense to incorporate much of the heuristic code in | 
 | # this program into a library to be shared with a dosemu configuration | 
 | # program, because it seems that at least some of the same stuff will | 
 | # be wanted.  The program needs to be cleaned up still.  A better tmp | 
 | # search algorithm could be written.  A fast option is planned.  Less | 
 | # Linux-dependence is desired.  Should look for devices independent | 
 | # of /etc/fstab; then sanity checks on /etc/fstab can be performed. | 
 |  | 
 | use Getopt::Long; | 
 | use File::Basename; | 
 | use strict; | 
 | use Carp; | 
 |  | 
 | sub Usage() { | 
 |     print "Usage: $0 <options>\n"; | 
 | #    print "-fstab <filename>    Location of alternate fstab file\n"; | 
 |     print "-windir <filename>   Location of windows dir in DOS space\n"; | 
 |     print "-thorough            Do careful analysis (default)\n"; | 
 |     print "-sysdir <filename>   Location of systems dir in DOS space\n"; | 
 |     print "-inifile <filename>  Path to the wine.ini file (by default './wine.ini')\n"; | 
 | #    print "-tmpdir <filename>   Location of tmp directory\n"; | 
 |     print "Generates (to STDOUT) a wine configuration file based on\n"; | 
 |     print "/etc/fstab and searching around in DOS directories\n"; | 
 |     print "The options above can override certain values\n"; | 
 |     print "This should be considered ALPHA code\n"; | 
 |     exit(0); | 
 | } | 
 |  | 
 | # Returns 1 if the device is mounted; -1 if mount check failed; 0 if not | 
 | # mounted. | 
 | # This code is Linux specific, and needs to be broadened. | 
 | sub IsMounted($) { | 
 |     my $Device = shift; | 
 |     if (-d "/proc") { | 
 | 	if (-e "/proc/mounts") { | 
 | 	    open(MOUNTS, "/proc/mounts") || | 
 | 		(warn "Cannot open /proc/mounts, although it exists\n" && | 
 | 		 return -1); | 
 | 	    while(<MOUNTS>) { | 
 | 		if (/^$Device/) { | 
 | 		    return 1; # Tested 1.4 | 
 | 		} | 
 | 	    } | 
 | 	    return 0; # Tested 1.4 | 
 | 	} | 
 |     } | 
 |     return -1; | 
 | } | 
 |  | 
 | sub RegisterDrive($$) { | 
 |     my($DOSdrive, $Drive) = @_; | 
 |     $::DOS2Unix{$DOSdrive} = $Drive; | 
 |     $::Device2DOS{$Drive->[0]} = $DOSdrive; | 
 |     $::MntPoint2DOS{$Drive->[1]} = $DOSdrive; | 
 |     $::DOS2MntPoint{$DOSdrive} = $Drive->[1]; | 
 |     $::DOS2Device{$DOSdrive} = $Drive->[0]; | 
 | } | 
 |  | 
 | sub byDriveOrder() { | 
 |     my($DeviceA) = $a->[0]; | 
 |     my($DeviceB) = $b->[0]; | 
 |  | 
 |     # Primary drives come first, logical drives last | 
 |     # DOS User's Guide (version 6) p. 70, IBM version. | 
 |     # If both drives are the same type, sort alphabetically | 
 |     # This makes drive a come before b, etc. | 
 |     # It also makes SCSI drives come before IDE drives; | 
 |     # this may or may not be right :-( | 
 |     my($Alogical, $Blogical); | 
 |     if (substr($DeviceA, 3, 1) >= 5) { $Alogical++; } | 
 |     if (substr($DeviceB, 3, 1) >= 5) { $Blogical++; } | 
 |     if ($Alogical && !$Blogical) { return -1; } | 
 |     elsif ($Blogical && !$Alogical) { return 1; } | 
 |     else { return ($DeviceA cmp $DeviceB); } | 
 | } | 
 |  | 
 | sub byCdOrder() { | 
 |     my($DeviceA) = $a->[0]; | 
 |     my($DeviceB) = $b->[0]; | 
 |     $DeviceA cmp $DeviceB; | 
 | } | 
 |  | 
 | sub ReadFSTAB() { | 
 |     $::opt_f = $::opt_f ? $::opt_f : '/etc/fstab'; | 
 |     open(FSTAB, $::opt_f) || die "Cannot read $::opt_f\n"; | 
 |     while(<FSTAB>) { | 
 | 	next if /^\s*\#/; | 
 | 	next if /^\s*$/; | 
 |  | 
 | 	my ($device, $mntpoint, $type, @rest) = split(' ', $_); | 
 | 	if ($device !~ m"^/dev/fd") { | 
 | 	    if ($type eq "ntfs") { | 
 | 		push(@::FatDrives, [$device, $mntpoint, 'win95']); | 
 | 	    } | 
 | 	    elsif ($type eq "msdos" || $type eq "vfat") { | 
 | 		push(@::FatDrives, [$device, $mntpoint, $type]); | 
 | 	    } | 
 | 	    elsif ($type eq "iso9660" || | 
 | 		   ($mntpoint eq "/cdrom" && ! $type eq 'supermount') || | 
 | 		   ($device eq '/dev/cdrom' && $type eq 'auto') ) { | 
 | 		push(@::CdromDrives, [$device, $mntpoint, 'win95']); | 
 | 	    } | 
 | 	    elsif ( ($mntpoint eq '/mnt/cdrom' || $mntpoint eq '/cdrom') | 
 | 		  && $type eq 'supermount') { | 
 | 		push(@::CdromDrives, ['/dev/cdrom', $mntpoint, 'win95']); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     if (!@::FatDrives) { | 
 | 	warn "ERROR ($0): Cannot find any MSDOS drives.\n"; | 
 | 	warn "This does not mean you cannot run Wine, but $0\n"; | 
 | 	warn "cannot help you (yet)\n"; | 
 | 	exit(1); | 
 |     } | 
 |     push(@::UnixDrives, ['', '/tmp', 'hd']); | 
 |     push(@::UnixDrives, ['', '${HOME}', 'network']); | 
 |     my $MagicDrive = 'C'; | 
 |     @::FatDrives = sort byDriveOrder @::FatDrives; | 
 |     @::CdromDrives = sort byCdOrder @::CdromDrives; | 
 |     foreach my $FatDrive (@::FatDrives) { | 
 | 	print "[Drive $MagicDrive]\n"; | 
 | 	my $MntPoint = $FatDrive->[1]; | 
 | 	my $FileSys = $FatDrive->[2]; | 
 | 	print "\"Path\" = \"$MntPoint\"\n"; | 
 | 	print "\"Type\" = \"hd\"\n"; | 
 | 	print "\"Filesystem\" = \"$FileSys\"\n"; | 
 | 	print "\n"; | 
 | 	RegisterDrive($MagicDrive, $FatDrive); | 
 | 	if(!IsMounted($FatDrive->[0])) { | 
 | 	    warn "WARNING: DOS Drive $MagicDrive (" . $FatDrive->[0] . | 
 | 		") is not mounted\n"; | 
 | 	} | 
 | 	$MagicDrive++; | 
 |     } | 
 |     foreach my $CdromDrive (@::CdromDrives) { | 
 | 	print "[Drive $MagicDrive]\n"; | 
 | 	my $Device = $CdromDrive->[0]; | 
 | 	my $MntPoint = $CdromDrive->[1]; | 
 | 	my $FileSys = $CdromDrive->[2]; | 
 | 	print "\"Path\" = \"$MntPoint\"\n"; | 
 | 	print "\"Type\" = \"cdrom\"\n"; | 
 | 	print "\"Device\" = \"$Device\"\n"; | 
 | 	print "\"Filesystem\" = \"$FileSys\"\n"; | 
 | 	print "\n"; | 
 | 	RegisterDrive($MagicDrive, $CdromDrive); | 
 | 	$MagicDrive++; | 
 |     } | 
 |     foreach my $UnixDrive (@::UnixDrives) { | 
 | 	print "[Drive $MagicDrive]\n"; | 
 | 	my $MntPoint = $UnixDrive->[1]; | 
 | 	my $Type = $UnixDrive->[2]; | 
 | 	print "\"Path\" = \"$MntPoint\"\n"; | 
 | 	print "\"Type\" = \"$Type\"\n"; | 
 | 	print "\"Filesystem\" = \"win95\"\n"; | 
 | 	print "\n"; | 
 | 	$MagicDrive++; | 
 |     } | 
 | } | 
 |  | 
 | # FNunix = ToUnix(FNdos); | 
 | #   Converts DOS filenames to Unix filenames, leaving Unix filenames | 
 | #   untouched. | 
 | sub ToUnix($) { | 
 |     my $FNdos = shift; | 
 |     my $FNunix; | 
 |  | 
 |     # Initialize tables if necessary. | 
 |     if (!%::DOS2Unix) { ReadFSTAB(); } | 
 |  | 
 |     # Determine which type of conversion is necessary | 
 |     if ($FNdos =~ /^([A-Z])\:(.*)$/) { # DOS drive specified | 
 | 	$FNunix = $::DOS2MntPoint{$1} . "/$2"; | 
 |     } | 
 |     elsif ($FNdos =~ m%\\%) { # DOS drive not specified, C: is default | 
 | 	$FNunix = $::DOS2MntPoint{"C"} . "/$FNdos"; | 
 |     } | 
 |     else { # Unix filename | 
 | 	$FNunix = $FNdos; | 
 |     } | 
 |     1 while ($FNunix =~ s%\\%/%);    # Convert \ to / | 
 |     $FNunix =~ tr/A-Z/a-z/;          # Translate to lower case | 
 |     1 while ($FNunix =~ s%//%/%);    # Translate double / to / | 
 |     return $FNunix; | 
 | } | 
 |  | 
 | # FNdos = ToDos(FNunix) | 
 | #   Converts Unix filenames to DOS filenames | 
 | sub ToDos($) { | 
 |     my $FNunix = shift; | 
 |     my(@MntList) = keys %::MntPoint2DOS; | 
 |     my ($TheMntPt, $FNdos); | 
 |  | 
 |     foreach my $MntPt (@MntList) { # Scan mount point list to see if path matches | 
 | 	if ($FNunix =~ /^$MntPt/) { | 
 | 	    $TheMntPt = $MntPt; | 
 | 	    last; | 
 | 	} | 
 |     } | 
 |     if (!$TheMntPt) { | 
 | 	Carp("ERROR: $FNunix not found in DOS directories\n"); | 
 | 	exit(1); | 
 |     } | 
 |     $FNdos = $FNunix; | 
 |     $FNdos =~ s/^$TheMntPt//; | 
 |     $FNdos = $::MntPoint2DOS{$TheMntPt} . ":" . $FNdos; | 
 |     1 while($FNdos =~ s%/%\\%); | 
 |     return $FNdos; | 
 | } | 
 |  | 
 | sub InsertDefaultFile($$) { | 
 |     my ($fileName, $tag) = @_; | 
 |     my $state = 0; | 
 |  | 
 |     if (open(DEFFILE, "$fileName")) { | 
 |        while (<DEFFILE>) { | 
 | 	  $state = 0 if ($state == 1 && $_ =~ /^[ \t]*\#/o && index($_, "[/$tag]") >= 0); | 
 | 	  print $_ if ($state == 1); | 
 | 	  $state = 1 if ($state == 0 && $_ =~ /^[ \t]*\#/o && index($_, "[$tag]" ) >= 0); | 
 |        } | 
 |        close(DEFFILE); | 
 |     } else { | 
 |        print STDERR "Cannot read $fileName\n"; | 
 |     } | 
 | } | 
 |  | 
 | sub marshall($) { | 
 |     my $s = $_[0]; | 
 |     $s =~ s/\\/\\\\/g; | 
 |     return "\"$s\""; | 
 | } | 
 |  | 
 | sub byFileAge() { | 
 |     -M $a <=> -M $b; | 
 | } | 
 |  | 
 | sub FindWindowsDir() { | 
 |     my($MagicDrive) = 'C'; | 
 |     my(@FATD)=@::FatDrives; | 
 |     my(@wininis) = (); | 
 |     my ($winini); | 
 |     my ($ThisDrive); | 
 |  | 
 |     if (!$::opt_windir && !$::opt_fast && !$::opt_thorough) { | 
 | 	$::opt_thorough++; | 
 |     } | 
 |     if ($::opt_windir) { | 
 | 	$winini = ToUnix($::opt_windir); | 
 | 	if (!-e $winini) { | 
 | 	    die "ERROR: Specified winini file does not exist\n"; | 
 | 	} | 
 |     } | 
 |     elsif ($::opt_fast) { | 
 | 	die "-fast code can be implemented\n"; | 
 |     } | 
 |     elsif ($::opt_thorough) { | 
 | 	if ($::opt_debug) { print STDERR "DEBUG: Num FATD = ", $#FATD+1, "\n"; } | 
 |        foreach $ThisDrive (@FATD) { | 
 | 	    my $MntPoint = $ThisDrive->[1]; | 
 | 	    push(@wininis, `find $MntPoint -iname win.ini -print`); | 
 | 	} | 
 | 	foreach $winini (@wininis) { | 
 | 	    chomp $winini; | 
 | 	} | 
 | 	my ($winini_cnt) = $#wininis+1; | 
 | 	if ($::opt_debug) { | 
 | 	    print STDERR "DEBUG: Num wininis found: $winini_cnt\n";} | 
 | 	if ($winini_cnt > 1) { | 
 | 	    warn "$winini_cnt win.ini files found:\n"; | 
 | 	    @wininis = sort byFileAge @wininis; | 
 | 	    warn join("\n", @wininis), "\n"; | 
 | 	    $winini = $wininis[0]; | 
 | 	    warn "Using most recent one: $winini\n"; | 
 | 	} | 
 | 	elsif ($winini_cnt == 0) { | 
 | 	    die "ERROR: No win.ini found in DOS partitions\n"; | 
 | 	} | 
 | 	else { | 
 | 	    $winini = $wininis[0]; | 
 | 	} | 
 |     } | 
 |     else { | 
 | 	die "ERROR: None of -windir, -fast, or -thorough set\n"; | 
 |     } | 
 |     $::windir = ToDos(dirname($winini)); | 
 |     print "[wine]\n"; | 
 |     print "\"windows\" = ", marshall ($::windir), "\n"; | 
 |     if ($::opt_sysdir) { | 
 | 	print "\"system\" = ", marshall ($::opt_sysdir), "\n"; | 
 |     } | 
 |     else { | 
 | 	print "\"system\" = ", marshall ("$::windir\\SYSTEM"), "\n"; | 
 |     } | 
 | } | 
 |  | 
 | sub ReadAutoexecBat() { | 
 |     if (!%::DOS2Unix) { ReadFSTAB(); } | 
 |     my($DriveC) = $::DOS2MntPoint{"C"}; | 
 |     $DriveC =~ s%/$%%; | 
 |     my($path); | 
 |     if ($::opt_debug) { | 
 | 	print STDERR "DEBUG: Looking for $DriveC/autoexec.bat\n"; } | 
 |     if (-e "$DriveC/autoexec.bat") { | 
 | 	# Tested 1.4 | 
 |         open(AUTOEXEC, "$DriveC/autoexec.bat") || | 
 |             die "Cannot read autoexec.bat\n"; | 
 |         while(<AUTOEXEC>) { | 
 | 	    s/\015//; | 
 |             if (/^\s*(set\s+)?(\w+)\s*[\s\=]\s*(.*)$/i) { | 
 | 		my($varname) = $2; | 
 | 	        my($varvalue) = $3; | 
 | 		chomp($varvalue); | 
 | 		$varname =~ tr/A-Z/a-z/; | 
 | 		while ($varvalue =~ /%(\w+)%/) { | 
 | 		    my $matchname = $1; | 
 | 		    my $subname = $1; | 
 | 		    $subname =~ tr/A-Z/a-z/; | 
 | 		    if (($::opt_debug) && ($::opt_debug =~ /path/i)) { | 
 | 			print STDERR "DEBUG: Found $matchname as $subname\n"; | 
 | 			print STDERR "DEBUG: Old varvalue:\n$varvalue\n"; | 
 | 			print STDERR "DEBUG: Old subname value:\n" . | 
 | 			    $::DOSenv{$subname} . "\n"; | 
 | 		    } | 
 | 		    if ($::DOSenv{$subname}) { | 
 | 			$varvalue =~ s/\%$matchname\%/$::DOSenv{$subname}/; | 
 | 		    } | 
 | 		    else { | 
 | 			warn "DOS environment variable $subname not\n"; | 
 | 			warn "defined in autoexec.bat. (Reading config.sys\n"; | 
 | 			warn "is not implemented.)  Using null value\n"; | 
 | 			$varvalue =~ s/%$matchname%//; | 
 | 		    } | 
 | 		    if (($::opt_debug) && ($::opt_debug =~ /path/i)) { | 
 | 			print STDERR "DEBUG: New varvalue:\n$varvalue\n"; | 
 | 		    } | 
 | 		} | 
 | 		if ($::opt_debug) { | 
 | 		    print STDERR "DEBUG: $varname = $varvalue\n"; | 
 | 		} | 
 | 		$::DOSenv{$varname} = $varvalue; | 
 |             } | 
 |         } | 
 | 	close(AUTOEXEC); | 
 |     } | 
 |     else { | 
 | 	# Tested 1.4 | 
 | 	warn "WARNING: C:\\AUTOEXEC.BAT was not found.\n"; | 
 |     } | 
 |  | 
 |     if ($::DOSenv{"path"}) { | 
 | 	my @pathdirs = split(/\s*;\s*/, $::DOSenv{"path"}); | 
 | 	if (($::opt_debug) && ($::opt_debug =~ /path/i)) { | 
 | 	    print STDERR "DEBUG (path): @pathdirs\n"; | 
 | 	} | 
 | 	foreach my $pathdir (@pathdirs) { | 
 | 	    if (-d ToUnix($pathdir)) { | 
 | 		if ($::DOSpathdir{$pathdir}++) { | 
 | 		    warn "Ignoring duplicate DOS path entry $pathdir\n"; | 
 | 		} | 
 | 		else { | 
 | 		    if (($::opt_debug) && ($::opt_debug =~ /path/i)) { | 
 | 			print STDERR "DEBUG (path): Found $pathdir\n"; | 
 | 		    } | 
 | 		    push(@::DOSpathlist, $pathdir); | 
 | 		} | 
 | 	    } | 
 | 	    else { | 
 | 	        warn "Ignoring DOS path directory $pathdir, as it does not\n"; | 
 | 		warn "exist\n"; | 
 | 	    } | 
 | 	} | 
 | 	print "\"path\" = ", marshall (join (";", @::DOSpathlist)), "\n"; | 
 |     } | 
 |     else { | 
 | 	# Code status: tested 1.4 | 
 | 	warn "WARNING: Making assumptions for PATH\n"; | 
 | 	warn "Will scan windows directory for executables and generate\n"; | 
 | 	warn "path from that\n"; | 
 | 	my $shellcmd = 'find ' . ToUnix($::windir) . " -iregex '" . | 
 | 	    '.*\.\(exe\|bat\|com\|dll\)' . "' -print"; | 
 | 	if ($::opt_debug) { | 
 | 	    print STDERR "DEBUG: autoexec.bat search command:\n $shellcmd\n"; | 
 | 	} | 
 | 	push(@::DOScommand, `$shellcmd`); | 
 | 	if ($::opt_debug && $::opt_debug =~ /autoexec/i) { | 
 | 	    print STDERR "DEBUG: autoexec.bat search results:\n\@DOS::command\n"; | 
 | 	} | 
 | 	foreach my $command (@::DOScommand) { | 
 | 	    $command =~ s%[^/]+$%%; | 
 | 	    $::DOSexecdir{ToDos($command)}++; | 
 | 	} | 
 | 	print "\"path\" = " . | 
 | 	    marshall (join(";", | 
 | 			    grep(s%\\$%%, | 
 | 				 sort {$::DOSexecdir{$b} <=> $::DOSexecdir{$a}} | 
 | 				 (keys %::DOSexecdir)))) . "\n"; | 
 |     } | 
 |  | 
 |     if ($::DOSenv{"temp"} && -d ToUnix($::DOSenv{"temp"})) { | 
 | 	print "\"temp\" = ", marshall ($::DOSenv{"temp"}), "\n"; | 
 |     } | 
 |     else { | 
 |         my $TheTemp; | 
 |  | 
 |         warn "WARNING: Making assumptions for TEMP\n"; | 
 | 	warn "Looking for \\TEMP and then \\TMP on every drive\n"; | 
 | 	# Watch out .. might pick CDROM drive :-) | 
 | 	foreach my $DOSdrive (keys %::DOS2Unix) { | 
 | 	    my $tmp = ToUnix("$DOSdrive:\\temp"); | 
 | 	    if (-d $tmp) { $TheTemp = "$DOSdrive:\\temp"; last; } | 
 | 	    $tmp = ToUnix("$DOSdrive:\\tmp"); | 
 | 	    if (-d $tmp) { $TheTemp = "$DOSdrive:\\tmp"; last; } | 
 | 	} | 
 | 	$TheTemp = '/tmp' if (!$TheTemp && -d '/tmp'); | 
 | 	if ($TheTemp) { | 
 | 	    warn "Using $TheTemp\n"; | 
 | 	    print "\"temp\" = ", marshall ($TheTemp), "\n"; | 
 | 	} | 
 | 	else { | 
 | 	    warn "Using C:\\\n"; | 
 | 	    print "\"temp\" = ", marshall ("C:\\"), "\n"; | 
 | 	} | 
 |     } | 
 |     print "\n"; | 
 | } | 
 |  | 
 | sub StandardStuff() { | 
 |     if (!$::opt_inifile) { | 
 | 	InsertDefaultFile("./wine.ini", "wineconf"); | 
 |     } else { | 
 | 	InsertDefaultFile($::opt_inifile, "wineconf"); | 
 |     } | 
 | } | 
 |  | 
 | ### Main | 
 |  | 
 | GetOptions('windir=s', 'sysdir=s', 'thorough', 'debug:s', 'inifile=s') || Usage; | 
 |  | 
 | print "WINE REGISTRY Version 2\n"; | 
 | print ";; All keys relative to \\\\Machine\\\\Software\\\\Wine\\\\Wine\\\\Config\n\n"; | 
 | ReadFSTAB(); | 
 | FindWindowsDir(); | 
 | ReadAutoexecBat(); | 
 | StandardStuff(); |