From: Tom Yu <tlyu@mit.edu>
Date: Fri, 30 Mar 2007 20:52:43 +0000 (+0000)
Subject: pull up r19234 from trunk
X-Git-Tag: kfw-3.2.0-beta1~30
X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=8a53b71959dbbaf59d25add76122057203f88008;p=krb5.git

pull up r19234 from trunk

 r19234@cathode-dark-space:  kpkoch | 2007-03-16 14:38:28 -0400
 Subject: KfW automated build scripts & supporting files.

 Updated scripts & additional configuration files.

 Ticket: new
 Target_Version: 1.6.1
 tags: pullup

ticket: 5490

git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-6@19348 dc483132-0cff-0310-8789-dd5450dbe970
---

diff --git a/src/windows/build/BKWconfig.xml b/src/windows/build/BKWconfig.xml
index 61e5ee59d..c7296ece4 100644
--- a/src/windows/build/BKWconfig.xml
+++ b/src/windows/build/BKWconfig.xml
@@ -2,40 +2,46 @@
 <!-- BKW: Build Kerberos for Windows -->
 <BKW_Config>
 	<CommandLine>
-	  <!-- The most changeable parameters can be specified on the command line.
-	       Less changeable params are in section Config, below. -->
+		<!-- The most changeable parameters can be specified on the command line.	-->
 		<Tags>
-			<cvs value=""/>
-<!--			<svn value=""/>	-->
-		</Tags>
+			<cvs value="" />
+			<svn value=""/>
+			</Tags>
 		<Directories>
 			<!--	Sources will be checked out of repositories into <src>.  The structure
 						of the repositories will cause pismere/athena to be created under <src>.	-->
-			<src		path="C:\projects\" />
-			
-			<!--	The sample config distributed as a zip must be unzipped into this directory before running the build: -->
-			<extras	path="\auth\krb5\package-extras" />	<!-- Relative to <src>\pismere\athena -->
-			
-			<out		path="path4" />
-		</Directories>
+			<src			path	="C:\projects\Autobuild" />
+			<out			path	="public" /> <!-- Relative to src. -->
+			<unixfind	path	="c:\cygwin\bin" />
+			</Directories>
 		<Options>
-			<debug			value="0" />
-			<logfile			value="1" path="bkw.pl.log" />
-			<repository	value="skip" />
-			<clean			value="0" />
-			<nomake		value="0" />
-			<nopackage	value="0" />
-			<verbose		value="0" />
-			<vverbose		value="0" />
-		</Options>
-	</CommandLine>
-	<Config>
-		<CVSROOT	name=":kserver:cvs.mit.edu:/cvs/pismere" />
-		<SVNURL		name="svn+ssh://svn.mit.edu/" />
-	</Config>
+			<debug value="0" />
+			<logfile value="1" path="bkw.pl.log" />
+			<repository value="skip" />
+			<clean value="0" />
+			<nomake value="0" />
+			<nopackage value="0" />
+			<verbose value="0" />
+			<vverbose value="0" />
+			</Options>
+		</CommandLine>
 	<Stages>
-		<FetchSources></FetchSources>
-		<Make></Make>
+		<FetchSources>
+			<Config>
+				<CVSROOT name=":kserver:cvs.mit.edu:/cvs/pismere" />
+				<SVNURL name="svn.mit.edu" /> <!-- NB:  No protocol or slashes!! -->
+				<KERBEROS_ID name="kpkoch" />
+				<KRB_PLINK name="c:\downloads\plink.exe" /> <!-- Path to a kerberized plink, needed for svn. -->
+				</Config>
+		</FetchSources>
+		<Make>
+			<Prunes> <!-- Files to be removed from current build to match what is in the 3.1 distribution:	-->
+				<Prune dummy="foo" />
+				<Prune name="afsauth" />
+				<Prune name="aklog" />
+				<Prune name="vs" />
+				</Prunes>
+			</Make>
 		<PrePackage>
 			<CopyList>
 				<Config>
@@ -43,8 +49,8 @@
 								The otherwise identical paths differ in one section.  For example:
 								.../target/bin/i386/bin/rel/filename and .../target/bin/i386/dbg/filename.
 								Here we define the two differing sections:	-->
-					<DebugArea		value="dbg" />
-					<ReleaseArea	value="rel" />
+					<DebugArea value="dbg" />
+					<ReleaseArea value="rel" />
 					<!--	Paths in the file list that include <AlwaysTag> will always have the tag replaced 
 								with <DebugArea> or <ReleaseArea>, depending on the type of build.
 								Paths that include <DebugTag> (or <ReleaseTag>) will only have the tag substituted 
@@ -56,16 +62,88 @@
 								Will always be copied, from a build-independent directory:
 								<File name="des.h"	from="auth\krb4\include\"	to="\inc\krb4" newname="foo.h"/>
 								-->
-					<AlwaysTag	value="%bldtype%" />	<!-- Pick a string that won't appear in a path. -->
-					<DebugTag	value="%debug%" />	<!-- Pick a string that won't appear in a path. -->
-					<ReleaseTag	value="%release%" />	<!-- Pick a string that won't appear in a path. -->
-				</Config>
+					<AlwaysTag value="%bldtype%" /> <!-- Pick a string that won't appear in a path. -->
+					<DebugTag value="%debug%" /> <!-- Pick a string that won't appear in a path. -->
+					<ReleaseTag value="%release%" /> <!-- Pick a string that won't appear in a path. -->
+					</Config>
 				<Files>
-					<Include path="copyfiles.xml" />	<!-- Relative to location of bkw.pl. -->
-				</Files>
+					<Include path="copyfiles.xml" />
+					</Files> <!-- Relative to location of bkw.pl. -->
 			</CopyList>
 		</PrePackage>
-		<Package></Package>
-		<PostPackage></PostPackage>
+		<Package>
+			<MSI></MSI>
+			<NSIS></NSIS> <!-- NB:  Most config is done in site-local.nsi.	-->
+			<!-- Theoretically, writing site-local.nsi from xml settings could be done, but isn't.	-->
+		</Package>
+		<PostPackage>
+			<Config>													<!-- This config info will be copied into each CopyList in PostPackage. -->
+				<FileStem name="kfw-3-2-0" />		<!--	<FileStem> will be substituted for %filestem%.	-->
+				</Config>
+			<Zips>
+				<Zip dummy="foo" /> <!-- To force desired XML::Simple behavior	-->
+				<!--	Files will be copied into directory <topdir>; <topdir> will appear in the paths of the files.	-->
+				<!-- File from	paths are relative to <src>/pismere.	-->
+				<!-- File to			paths are relative to <out>.					-->
+				<Zip name="Core Binaries" filename="%filestem%.zip" topdir="%filestem%-final">
+					<CopyList>
+						<Config>
+							<DebugArea value="dbg" />
+							<ReleaseArea value="rel" />
+							<AlwaysTag value="%bldtype%" /> <!-- Pick a string that won't appear in a path. -->
+							<DebugTag value="%debug%" /> <!-- Pick a string that won't appear in a path. -->
+							<ReleaseTag value="%release%" /> <!-- Pick a string that won't appear in a path. -->
+							</Config>
+						<Files>
+							<Include path="corebinaryfiles.xml" />
+							</Files> <!-- Relative to location of bkw.pl. -->
+						</CopyList>
+				</Zip>
+				<Zip name="SDK" filename="%filestem%-sdk.zip" topdir="%filestem%-final">
+					<CopyList>
+						<Files>
+							<Include path="sdkfiles.xml" />
+							</Files> <!-- Relative to location of bkw.pl. -->
+						</CopyList>
+				</Zip>
+				<Zip name="SRC" filename="%filestem%-src.zip" topdir="%filestem%-final">
+					<CopyList>
+						<Files>
+							<!-- File from	paths are relative to <src>/pismere.	-->
+							<!-- File to			paths are relative to <out>.					-->
+							<File dummy="foo" /> <!-- Forces XML::Simple behavior -->
+							<!-- Without this, XML::Simple does not make an anonymous array and I can't figure out how to iterate over it. -->
+							<File name="*.*" from="athena" to="src\athena" />
+							<File name="*.*" from="doc" to="src\doc" />
+							<File name="*.*" from="scripts" to="src\scripts" />
+							</Files>
+					</CopyList>
+					<Prunes> <!-- Files to be removed from current build to match what is in the 3.1 distribution:	-->
+						<Prune dummy="foo" />
+						<Prune name="CVS" />
+						<Prune name=".cvsignore" flags="i" />
+						<Prune name="Changelog" flags="i" />
+						<Prune name="obj" />
+						<Prune name="site" />
+						</Prunes>
+					<Requires>
+						<Switch dummy="foo" />
+						<Switch name="REPOSITORY" value="CHECKOUT"/>
+						<ErrorMsg text="Can't build source zip unless both /REPOSITORY CHECKOUT is specified." />
+						</Requires>
+					</Zip>
+				</Zips>			
+			<CopyList>			<!-- Copied at end of post-package step.	-->
+				<Files>
+					<File dummy="foo" />
+					<!-- File from	paths are relative to <src>/pismere.	-->
+					<!-- File to			paths are relative to <out>.					-->
+					<File name="msi-deployment-guide.txt" from="staging\install\wix\" to="" />
+					<File name="netidmgr_userdoc.pdf" from="staging\doc" to="." />
+					<File name="kfw.msi" from="staging\install\wix\" to="" newname="%filestem%.msi" />
+					<File name="MITKerberosForWindows.exe" from="staging\install\nsis" to="" newname="%filestem%.exe" />
+					</Files>
+				</CopyList>
+			</PostPackage>
 	</Stages>
 </BKW_Config>
\ No newline at end of file
diff --git a/src/windows/build/Logger.pm b/src/windows/build/Logger.pm
new file mode 100644
index 000000000..f74c21807
--- /dev/null
+++ b/src/windows/build/Logger.pm
@@ -0,0 +1,87 @@
+package Logger;
+
+use strict;
+use IO::File;
+use FindBin;
+
+my $bStarted = 0;
+
+sub new {
+    my $class = shift;
+    my $file = shift;
+    my $append = shift;
+    $file || die "Usage: \$foo = new Logger filename [append]\n";
+    my $self = {};
+    bless  $self, $class;
+    $self->{FILE} = $file;
+    $self->{APPEND} = $append?'-a':'';
+    return $self;
+}
+
+sub start {
+    my $self = shift;
+
+    return 1 if $self->{PIPE};
+
+    STDOUT->flush;
+    STDERR->flush;
+
+    my $fh_out = new IO::File;
+    my $fh_err = new IO::File;
+    my $fh_pipe = new IO::File;
+
+    $self->{OUT} = $fh_out;
+    $self->{ERR} = $fh_err;
+    $self->{PIPE} = $fh_pipe;
+
+    $fh_out->open(">&STDOUT") || die;
+    $fh_err->open(">&STDERR") || die;
+    $fh_pipe->open("|$^X $FindBin::Bin/tee.pl $self->{APPEND} $self->{FILE}") || die;
+
+    STDOUT->fdopen(fileno $fh_pipe, "w") || die;
+    STDERR->fdopen(fileno $fh_pipe, "w") || die;
+
+    STDOUT->autoflush(1);
+    STDERR->autoflush(1);
+
+    $SIG{__DIE__} = sub {
+	print STDERR $_[0];
+	$self->stop;
+	die "\n";
+    };
+
+	$bStarted = 1;
+    return 1;
+}
+
+# 20070314 kpkoch:	
+#  There appears to be a bug in ActivePerl where Logger's games with streams
+#  and the SIG DIE handler cause eval to throw exceptions.  By deleting the DIE handler,
+#  subsequent evals do not fail.
+sub no_die_handler {
+	delete $SIG{__DIE__};
+	}
+
+sub stop {
+    my $self = shift;
+
+    return 0 if !$self->{PIPE};
+
+    STDOUT->close;
+    STDERR->close;
+    $self->{PIPE}->close;
+    STDOUT->fdopen(fileno $self->{OUT}, "w");
+    STDERR->fdopen(fileno $self->{ERR}, "w");
+    delete $self->{OUT};
+    delete $self->{ERR};
+    delete $self->{PIPE};
+	$bStarted = 0;
+    return 1;
+}
+
+sub DESTROY {
+    my $self = shift;
+	$self->stop	if ($bStarted);
+	}
+
+1;
diff --git a/src/windows/build/bkw-automation.html b/src/windows/build/bkw-automation.html
index d7ca7a0c3..f018b348b 100644
--- a/src/windows/build/bkw-automation.html
+++ b/src/windows/build/bkw-automation.html
@@ -201,19 +201,6 @@
 													<H2><FONT face="Verdana">Remaining work / bug list</FONT></H2>
 													<P>This is a work in progress. What's left:</P>
 													<UL>
-														<LI>
-															<FONT face="Verdana">Add subversion for checking out krb5. </FONT>
-														<LI>
-															<FONT face="Verdana">Allow empty cvs/svn tags to refer to the trunk. </FONT>
-														<LI>
-															<FONT face="Verdana">Implement ways to skip full checkouts - doing updates or 
-																skipping the repository step completely. </FONT>
-														<LI>
-															<FONT face="Verdana">Figure out which logging package to use and restore original 
-																build.pl logging functionality. </FONT>
-														<LI>
-															<FONT face="Verdana">Pick an unzip package and add the unzip step for the sample 
-																config. Eliminate manual step. </FONT>
 														<LI>
 															<FONT face="Verdana">Produce the remainder of the distribution components. [Listed 
 																above.] </FONT>
diff --git a/src/windows/build/bkw.pl b/src/windows/build/bkw.pl
index 900d4ca44..3785cd438 100644
--- a/src/windows/build/bkw.pl
+++ b/src/windows/build/bkw.pl
@@ -5,17 +5,19 @@ use FindBin;
 use File::Spec;
 use File::Basename;
 use lib "$FindBin::Bin/build/lib";
-use ActivePerl::PPM::Logger;
 use Getopt::Long;
 use Cwd;
 use XML::Simple;
 use Data::Dumper;
+use Archive::Zip;
+use Logger;
+require "copyfiles.pl";
 
 my $BAIL;
 $0 = fileparse($0);
 my $OPT = {foo => 'bar'};
-
 my $MAKE = 'NMAKE';
+our $config;
 
 sub get_info
     {
@@ -35,23 +37,24 @@ Usage: $0 (-f --config) config-file [options] NMAKE-options
   Options are case insensitive.
 
   Options:
-    /help /?      usage information (what you now see)
-    /srcdir dir   Source directory to use.  Should contain 
-                  pismere/athena.  If cvstag or svntag is null, 
-                  the directory should be prepopulated.
-    /outdir dir   Directory to be created where build results will go
+    /help /?        usage information (what you now see).
+    /config path    Path to config file.
+    /srcdir dir     Source directory to use.  Should contain 
+                    pismere/athena.  If cvstag or svntag is null, 
+                    the directory should be prepopulated.
+    /outdir dir     Directory to be created where build results will go
     /repository checkout | co \\  What repository action to take.
 	        update   | up  ) Options are to checkout, update or 
 	        skip          /  take no action [skip].
-    /cvstag tag \\ For whichever of these tags is specified,
-    /svntag tag / the repository action will be done into srcdir
-    /debug        Do debug make instead of release make
-    /nomake       Skip make step
-    /nopackage    Skip packaging step
-    /clean        Build clean target
-    /verbose      Debug mode - verbose output
-    /config path  Path to config file
-    /logfile path Where to write output.  If omitted, ...
+    /kerberos_id id kerberos id used to access svn if checking out.
+    /cvstag tag   \\ If non-empty, the tag is appended to cvs and svn
+    /svntag tag   / commands to select the rev to fetch.
+    /debug          Do debug make instead of release make.
+    /nomake         Skip make step.
+    /clean          Build clean target.
+    /nopackage      Skip packaging step.
+    /verbose        Debug mode - verbose output.
+    /logfile path   Where to write output.  If omitted, ...
   Other:
     NMAKE-options    any options you want to pass to NMAKE, which can be:
                      (note: /nologo is always used)
@@ -72,15 +75,6 @@ EOH
     $BAIL = $bailmsg.$warnmsg;
 }
 
-sub makeDir {
-	my ($path) = @_;
-	if (! -d $path) {
-		mkdir($path) or die "Fatal -- couldn't create $path";
-		print "Debug -- makeDir($path)\n";
-		}
-	else {print "Debug -- makeDir($path) -- directory already exists.\n";}
-	}
-
 sub main {
     Getopt::Long::Configure('no_bundling', 'no_auto_abbrev',
 			    'no_getopt_compat', 'require_order',
@@ -97,10 +91,11 @@ sub main {
 	       'config|f:s',
 	       'logfile|l:s',
 	       'repository:s',
-	       'clean',
+	       'kerberos_id:s',
 	       'verbose',
 	       'vverbose',
 	       'nomake',
+	       'clean',
 	       'nopackage',
 	       );
 
@@ -118,10 +113,8 @@ sub main {
       exit(0);
       }
 
-# #print Dumper($OPT);
-    
     # List of programs which must be in PATH:
-    my @required_list = ('sed', 'awk', 'which', 'cat', 'rm', 'cvs', 'svn', 'doxygen', 'hhc', 'candle', 'light');
+    my @required_list = ('sed', 'awk', 'which', 'cat', 'rm', 'cvs', 'svn', 'doxygen', 'hhc', 'candle', 'light', 'makensis', 'nmake');
     my $requirements_met = 1;
     my $first_missing = 0;
     my $error_list = "";
@@ -145,11 +138,9 @@ sub main {
 	
     use Time::gmtime;
     $ENV{DATE} = gmctime()." GMT";
-	my $originalDir =`cd`;
+	our $originalDir = `cd`;
 	$originalDir =~ s/\n//g;
 
-    my $errorState = 0;		## Cumulative return code.  0 is success.
-
 ##++ Assemble configuration from config file and command line:
 
     my $configfile;
@@ -159,15 +150,14 @@ sub main {
 
     # Get configuration file:
 	my $xml = new XML::Simple();
-	my $config = $xml->XMLin($configfile);
+	$config = $xml->XMLin($configfile);
 
 	# Set up convenience variables:
-	my (@switches, @paths, @tags, @prepackage, @files);
+	my (@switches, @paths, @tags, @fetch);
 	@switches		= $config->{CommandLine}->{Options};
 	@paths			= $config->{CommandLine}->{Directories};
 	@tags				= $config->{CommandLine}->{Tags};
-	@prepackage	= $config->{Stages}->{PrePackage};
-	@files				= $config->{Stages}->{PrePackage}->{CopyList}->{Files};
+	@fetch			= $config->{Stages}->{FetchSources}->{Config};
 
     # Update the configuration with overrides from the command line:
 	$tags[0]->{cvs}->{value} = $OPT->{cvstag}								if exists $OPT->{cvstag};
@@ -176,129 +166,186 @@ sub main {
     $paths[0]->{out}->{path} = $OPT->{outdir}							if exists $OPT->{outdir};
     $switches[0]->{debug}->{value} = $OPT->{debug}				if exists $OPT->{debug};
     $switches[0]->{clean}->{value} = 1											if exists $OPT->{clean};
-    $switches[0]->{logfile}->{value} = 1											if exists $OPT->{logfile};
     $switches[0]->{repository}->{value} = $OPT->{repository}	if exists $OPT->{repository};
+    $fetch[0]->{KERBEROS_ID}->{name} = $OPT->{kerberos_id}	if exists $OPT->{kerberos_id};
     $switches[0]->{nomake}->{value} = 1										if exists $OPT->{nomake};
     $switches[0]->{nopackage}->{value} = 1									if exists $OPT->{nopackage};
     $switches[0]->{verbose}->{value} = $OPT->{verbose}			if exists $OPT->{verbose};
     $switches[0]->{vverbose}->{value} = $OPT->{verbose}		if exists $OPT->{vverbose};
 	if (exists $OPT->{logfile}) {
-		$switches[0]->{log}->{path} = $OPT->{logfile};
-		$switches[0]->{log}->{value} = 1;
+		$switches[0]->{logfile}->{path} = $OPT->{logfile};
+		$switches[0]->{logfile}->{value} = 1;
 		}
-    my $verbose			= $config->{CommandLine}->{Options}->{verbose}->{value};
-    my $vverbose		= $config->{CommandLine}->{Options}->{vverbose}->{value};
+    our $verbose		= $config->{CommandLine}->{Options}->{verbose}->{value};
+    our $vverbose		= $config->{CommandLine}->{Options}->{vverbose}->{value};
+    our $clean				= $switches[0]->{clean}->{value};
+	my $src					= $paths[0]->{src}->{path};
 
-	if ($switches[0]->{clean}->{value} && !$switches[0]->{nopackage}->{value}) {
+	if ($clean && !$switches[0]->{nopackage}->{value}) {
 		print "Info -- /clean forces /nopackage.\n";
 		$switches[0]->{nopackage}->{value} = 1;
 		}
 
-	my $i = 0;
-	# See if there is an included file list:
-	if (exists $files[0]->{Include}->{path}) {
-		my $configfile2 = $files[0]->{Include}->{path};
-		print "Info -- Including files to be copied from $configfile2.\n";
-		my $config2 = $xml->XMLin($configfile2);
-		while ($config2->{File}[$i]) {
-			$files[0]->{File}[++$#{$files[0]->{File}}] = $config2->{File}[$i];
-			$i++;
-			}
-		}
-		
-    if ($vverbose) {print Dumper($config);}
+    if ($vverbose) {print "Debug -- Config: ".Dumper($config);}
     
 	# Examples of use:
 	#print "Logfile path: $switches[0]->{log}->{path}\n";
 	#print "src path: $paths[0]->{src}->{path}\n";
 	#print "cvs tag: $tags[0]->{cvs}->{value}\n";
-	#print "CVSROOT:   $config->{Config}->{CVSROOT}->{name}\n";
+	#print "CVSROOT:   $fetch[0]->{CVSROOT}->{name}\n";
 
 ##-- Assemble configuration from config file and command line.
 
-# Begin logging:
-    my $l;
-    if ($OPT->{logfile}) {
-#		$l = new Logger $OPT->{logfile} or die "Fatal -- Can't create Logger.";
-#		$l->start;
-		}
-
-##++ Begin repository action:
 	my $sw = $switches[0]->{repository}->{value};
 	my $rverb;
-	if ($sw =~ /skip/i)				{print "Info -- Skipping repository access.\n";}
-	elsif ($sw =~ /update/i)		{$rverb = "update";}
-	elsif ($sw =~ /up/i)				{$rverb = "update";}
-	elsif ($sw =~ /checkout/i)	{$rverb = "checkout";}
-	elsif ($sw =~ /co/i)				{$rverb = "checkout";}
+	if		($sw =~ /skip/i)			{$rverb = "skip";}
+	elsif	($sw =~ /update/i)		{$rverb = "update";}
+	elsif	($sw =~ /up/i)				{$rverb = "update";}
+	elsif	($sw =~ /checkout/i)	{$rverb = "checkout";}
+	elsif	($sw =~ /co/i)				{$rverb = "checkout";}
 	else {
 			print "Fatal -- invalid /repository value.\n";
 			usage();
 			die;
 			}
 
-	my $wd 	= $paths[0]->{src}->{path}."\\pismere";
-	
-	if ($rverb) {
+	my $wd 	= $src."\\pismere";
+
+	if ($rverb =~ /checkout/) {
+		print "\n\nHEADS UP!!\n\n";
+		print "/REPOSITORY CHECKOUT will cause everything under $wd to be deleted.\n";
+		print "If this is not what you intended, here's your chance to bail out!\n\n\n";
+		print "Are you sure you want to remove everything under $wd? ";
+		my $char = getc;
+		if (! ($char =~ /y/i)) {die "Info -- operation aborted by user."}
+		!system("rm -rf $wd/*")						or die "Fatal -- Couldn't clean $wd.";
+		!system("rmdir $wd")							or die "Fatal -- Couldn't remove $wd.";
+#		!system("attrib -h -r $wd\\* /s /d")	or die "Fatal -- Couldn't clear read-only attributes.";
+#		!system("del /s /q $wd\\*.*")				or die "Fatal -- Couldn't clean files from $wd."; 
+#		!system("rm -rf $wd\\*.*")					or die "Fatal -- Couldn't clean directories from $wd.";
+		}
+
+# Begin logging:
+    my $l;
+    if ($switches[0]->{logfile}->{value}) {
+		print "Info -- logging to $switches[0]->{logfile}->{path}.\n";
+		$l = new Logger $switches[0]->{logfile}->{path};
+		$l->start;
+		$l->no_die_handler;		## Needed so XML::Simple won't throw exceptions.
+		}
+
+##++ Begin repository action:
+	if ($rverb =~ /skip/) {print "Info -- *** Skipping repository access.\n"	if ($verbose);}
+	else {
 		if ($verbose) {print "Info -- *** Begin fetching sources.\n";}
 
+		# Set up cvs environment variables:
+		$ENV{CVSROOT} = $fetch[0]->{CVSROOT}->{name};
+		chdir($src)											or die "Fatal -- couldn't chdir to $src\n";
+		print "Info -- chdir to ".`cd`."\n"				if ($verbose);
 		my $krb5dir	= $wd."\\athena\\auth\\krb5";
 
-		# If we are fetching into a new directory, the directory structure won't exist and many cd commands will fail.
-		# Use an xcopy to create the directory paths we will need:
-		!system("echo tempfile > kpk.tmp") or die "Fatal -- Couldn't creqte a simple temp file.\n";
-		!system("echo F | xcopy /y kpk.tmp $krb5dir") or die "Fatal -- Couldn't create path $krb5dir\n";
-		!system("del kpk.tmp") or die "Fatal -- Couldn't clean up temporary file.\n";
-		
-		chdir("$wd") or die "Fatal -- couldn't chdir to $wd\n";
-		if ($verbose) {print "Info -- chdir to $wd\n";}
-		
-		#if (! -d "pismere")					{print "Warning -- can't find pismere in $wd.  It will be created.\n";}
-		if (! -d "athena")	{print "Warning -- can't find pismere\\athena in $wd.  It will be created.\n";}
-		
-		# [TODO] Set up cvs environment variables:
-		my $cvscmd = "cvs $rverb ";
-		if ($tags[0]->{cvs}->{value}) {$cvscmd .= $tags[0]->{cvs}->{value};}
-		!system($cvscmd) or die "Fatal -- command \"$cvscmd\" failed; return code $?\n";
-		
-		# [TODO] Set up svn environment variables:
-		chdir("$krb5dir") or die "Fatal -- couldn't chdir to $krb5dir\n";
-		if ($verbose) {print "Info -- chdir to $krb5dir\n";}
+		my $cvscmdroot	= "cvs $rverb";
+		my $cvscmd			= $cvscmdroot;
+		if ($rverb =~ /checkout/) {		
+			my @cvsmodules	= (	
+				'krb',  
+				'pismere/athena/util/lib/afscompat', 
+				'pismere/athena/util/lib/delaydlls', 
+				'pismere/athena/util/lib/getopt', 
+				'pismere/athena/util/guiwrap'
+				);
+#				'pismere/athena/util/lib', 
+
+			foreach my $module (@cvsmodules) {
+				$cvscmd = $cvscmdroot." ".$module;
+				$cvscmd .= " ".$tags[0]->{cvs}->{value}	if ($tags[0]->{cvs}->{value});
+				if ($verbose) {print "Info -- cvs command: $cvscmd\n";}
+				!system($cvscmd)								or die "Fatal -- command \"$cvscmd\" failed; return code $?\n";
+				}
+			}
+		else {				## Update.
+			$cvscmd = $cvscmdroot;
+			$cvscmd .= " ".$tags[0]->{cvs}->{value}	if ($tags[0]->{cvs}->{value});
+			if ($verbose) {print "Info -- cvs command: $cvscmd\n";}
+			!system($cvscmd)									or die "Fatal -- command \"$cvscmd\" failed; return code $?\n";
+			}
+					
+		# Set up svn environment variables:
+		my $dblback_plink	= $fetch[0]->{KRB_PLINK}->{name};
+		$dblback_plink =~ s/\\/\\\\/g;
+		$ENV{SVN_SSH} = $dblback_plink;
+		# If  the directory structure doesn't exist, many cd commands will fail.
+		mkdir($krb5dir);
+		chdir($krb5dir)											or die "Fatal -- couldn't chdir to $krb5dir\n";
+		print "Info -- chdir to ".`cd`."\n"			if ($verbose);
 		my $svncmd = "svn $rverb ";
-		if ($tags[0]->{svn}->{value}) {$svncmd .= $tags[0]->{svn}->{value};}
-		!system($svncmd) or die "Fatal -- command \"$svncmd\" failed; return code $?\n";
-		
+		if ($rverb =~ /checkout/) {		# Append the rest of the checkout command:
+			chdir("..");
+			$svncmd .= "svn+ssh://".$fetch[0]->{KERBEROS_ID}->{name}."@".$fetch[0]->{SVNURL}->{name}."/krb5/trunk krb5";
+			}
+		if ($tags[0]->{svn}->{value}) {$svncmd .= " ".$tags[0]->{svn}->{value};}	# Add any specific tag
+		if ($verbose) {print "Info -- svn command: $svncmd\n";}
+		!system($svncmd)			or die "Fatal -- command \"$svncmd\" failed; return code $?\n";
+
 		if ($verbose) {print "Info -- ***   End fetching sources.\n";}
 		}
 ##-- End  repository action.
-	
-	if ($verbose) {print "Info -- *** Begin preparing for build.\n";}
-	$wd = $paths[0]->{src}->{path};
-	chdir("$wd") or die "Fatal -- couldn't chdir to $wd\n";
-	if ($verbose) {print "Info -- chdir to $wd\n";}
+		
+	if (	(!$switches[0]->{nomake}->{value}) ) {
+		if ($verbose) {print "Info -- *** Begin preparing for build.\n";}
 
-	my ($path, $destpath);
-	
-	# Copy athena\scripts\site\graft\krb5\Makefile.src to athena\auth\krb5:
-	$path = "pismere\\scripts\\site\\graft\\krb5\\Makefile.src";
-	if (!-e  $path) {die "Fatal -- Expected file $wd\\$path not found.";}
-	$destpath = "pismere\\athena\\auth\\krb5\\Makefile.src";
-	!system("echo F | xcopy /D $wd\\$path $wd\\$destpath /Y > NUL") or die "Fatal -- Copy of $wd\\$path to $wd\\$destpath failed.";
-	print "Info -- copied $wd\\$path to $wd\\$destpath\n";
-	
-	# Add DEBUG_SYMBOL to .../wshelper/Makefile.src:
-	$path = "pismere\\athena\\wshelper\\wshelper\\Makefile.src";
-	if (!-e  $path) {die "Fatal -- Expected file $wd\\$path not found.";}
-	if (system("grep DEBUG_SYMBOL $path > NUL") != 0) {
-		!system ("echo DEBUG_SYMBOL=1 >> $wd\\$path") or die "Fatal -- Append line to file failed.\n";
-		print "Info -- Added DEBUG_SYMBOL to $wd\\$path\n";
-		}
+		$wd = $paths[0]->{src}->{path};
+		chdir("$wd") or die "Fatal -- couldn't chdir to $wd\n";
+		print "Info -- chdir to ".`cd`."\n"				if ($verbose);
 	
-	if ($verbose) {print "Info -- ***   End preparing for build.\n";}
+		my ($path, $destpath);
+		
+		# Copy athena\scripts\site\graft\krb5\Makefile.src to athena\auth\krb5:
+		$path = "pismere\\scripts\\site\\graft\\krb5\\Makefile.src";
+		if (!-e  $path) {die "Fatal -- Expected file $wd\\$path not found.";}
+		$destpath = "pismere\\athena\\auth\\krb5\\Makefile.src";
+		!system("echo F | xcopy /D $wd\\$path $wd\\$destpath /Y > NUL") or die "Fatal -- Copy of $wd\\$path to $wd\\$destpath failed.";
+		print "Info -- copied $wd\\$path to $wd\\$destpath\n"		if ($verbose);;
+		
+		# Add DEBUG_SYMBOL to .../wshelper/Makefile.src:
+		$path = "pismere\\athena\\wshelper\\wshelper\\Makefile.src";
+		if (!-e  $path) {die "Fatal -- Expected file $wd\\$path not found.";}
+		if (system("grep DEBUG_SYMBOL $path > NUL") != 0) {
+			!system ("echo DEBUG_SYMBOL=1 >> $wd\\$path") or die "Fatal -- Append line to file failed.\n";
+			print "Info -- Added DEBUG_SYMBOL to $wd\\$path\n"	if ($verbose);
+			}
+		
+		# Prune any unwanted directories before the build:
+		if (exists $config->{Stages}->{Make}->{Prunes}) {
+			# Use Unix find instead of Windows find.  Save PATH so we can restore it when we're done:
+			my $savedPATH	= $ENV{PATH};
+			$ENV{PATH} = $config->{CommandLine}->{Directories}->{unixfind}->{path}.";".$savedPATH;
+			my $prunes = $config->{Stages}->{Make}->{Prunes};
+			my $j=0;
+			print "Info -- Processing prunes in ".`cd`."\n" if ($verbose);
+			while ($prunes->{Prune}->[$j]) {
+				if (exists $prunes->{Prune}->[$j]->{name}) {						## Don't process dummy entry!
+					my $prune	= $prunes->{Prune}->[$j]->{name};
+					my $flags	= $prunes->{Prune}->[$j]->{flags};
+					$flags = "" if (!$flags);
+					my $cmd	= "find . -".$flags."name $prune";
+					print "Info -- Looking for filenames containing $prune\n";
+					my $list = `$cmd`;
+					foreach $target (split("\n", $list)) {
+						print "Info -- Pruning $target\n" if ($verbose);
+						! system("rm -rf $target")				or die "Unable to prune $target";
+						}
+					}
+				$j++;
+				}
+			$ENV{PATH} = $savedPATH;
+			}
+
+		if ($verbose) {print "Info -- ***   End preparing for build.\n";}
 	
-	if (!$switches[0]->{nomake}->{value}) {
 		my ($buildtarget, $buildtext);
-		if ($switches[0]->{clean}->{value}) {
+		if ($clean) {
 			$buildtarget = "clean" ;
 			$buildtext = " clean."
 			}
@@ -306,14 +353,13 @@ sub main {
 			$buildtarget = "" ;
 			$buildtext = "."
 			}
-		if ($verbose) {print "Info -- *** Begin build".$buildtext."\n";}
 		
 		chdir("pismere/athena") or die "Fatal -- couldn't chdir to source directory $wd\\pismere\\athena\n";
 		if ($verbose) {print "Info -- chdir to $wd\\pismere\\athena\n";}
 			!system("perl ../scripts/build.pl --softdirs $buildtarget")	or die "Fatal -- build $buildtarget failed.";
 			
-		chdir("..") or die "Fatal -- couldn't chdir to $wd\\pismere.";
-		if ($switches[0]->{clean}->{value}) {
+		chdir("$wd\\pismere") or die "Fatal -- couldn't chdir to $wd\\pismere.";
+		if ($clean) {
 			if (-d "staging") {
 				!system("rm -rf staging") or die "Fatal -- Couldn't remove pismere/staging.";
 				}
@@ -321,97 +367,29 @@ sub main {
 	
 		if ($verbose) {print "Info -- ***   End build".$buildtext."\n";}
 		}				## End make conditional.
-	
-	if (!$switches[0]->{nopackage}->{value}) {
-		if ($verbose) {print "Info -- *** Begin prepackage.\n";}
+	else {print "Info -- *** Skipping build.\n"	if ($verbose);}
 		
+	if (!$switches[0]->{nopackage}->{value}) {		## If /clean, this switch will have been cleared.
+		if ($verbose) {print "Info -- *** Begin prepackage.\n";}
 		# The build results are copied to a staging area, where the packager expects to find them.
 		#  We put the staging area in the fixed area .../pismere/staging.
+		my $prepackage	= $config->{Stages}->{PrePackage};
 		$wd = $paths[0]->{src}->{path}."\\pismere";
 		my $staging_area = "$wd\\staging";
 		chdir($wd) or die "Fatal -- couldn't chdir to $wd\n";
 		if ($verbose) {print "Info -- chdir to $wd\n";}
-		(-e $staging_area) or makeDir($staging_area);
-		
-		my $src = $paths[0]->{src}->{path};
-		my $CopyList			= $prepackage[0]->{CopyList};
-		
-		# A path can contain a variable part, which will be handled here.  If the variable part is 
-		# the Always or BuildDependent tag, then the variable will be changed to the 
-		# build-type-dependent PathFragment.
-		# If the variable part is the IgnoreTag, then the file will not be copied.
-		my ($PathFragment, $BuildDependentTag, $IgnoreTag); 
-	
-		my $AlwaysTag				= $CopyList->{Config}->{AlwaysTag}->{value};
-		if ($switches[0]->{debug}->{value}) {		## Debug build tags:
-			$PathFragment				= $CopyList->{Config}->{DebugArea}->{value};
-			$BuildDependentTag	= $CopyList->{Config}->{DebugTag}->{value};
-			$IgnoreTag					= $CopyList->{Config}->{ReleaseTag}->{value};
-			}
-		else {																## Release build tags:
-			$PathFragment				= $CopyList->{Config}->{ReleaseArea}->{value};
-			$BuildDependentTag	= $CopyList->{Config}->{ReleaseTag}->{value};
-			$IgnoreTag					= $CopyList->{Config}->{DebugTag}->{value};
-			}			
-	
-		# Copy all the files in the CopyList:
-		$i = 0;
-		my $nfiles			= 0;
-		my $bOldDot	= 1;
-		my $bDot			= 0;
-		while ($files[0]->{File}[$i]) {
-			my ($name, $newname, $from, $to, $ignore);
-			$name		= $files[0]->{File}->[$i]->{name};
-			if (exists $files[0]->{File}->[$i]->{newname})	{$newname = $files[0]->{File}->[$i]->{newname};}
-			else																				{$newname = $name;}
-			if ($name) {
-				$ignore = 0;
-				$from	= "$src\\pismere\\athena\\$files[0]->{File}->[$i]->{from}\\$name";
-				$to		= "$src\\pismere\\staging\\$files[0]->{File}->[$i]->{to}\\$newname";
-				if (index($from.$to, $IgnoreTag) <0) {					## Test for IgnoreTag
-					# Apply PathTag substitutions:
-					$from	=~ s/$AlwaysTag/$PathFragment/g;
-					$to		=~ s/$AlwaysTag/$PathFragment/g;
-					$from	=~ s/$BuildDependentTag/$PathFragment/g;
-					$to		=~ s/$BuildDependentTag/$PathFragment/g;
-					# We use xcopy instead of copy because it will create directories for us:
-					if (system("echo F | xcopy /D /F /Y $from $to > a.tmp 2>NUL") != 0) {
-						# xcopy failed.  
-						if (!exists $files[0]->{File}->[$i]->{notrequired}) {
-							( -e $from) or die "Fatal -- can't find $from";
-							die "Fatal -- Copy of $from to $to failed";
-							}
-						}
-					else {		## To show progress when files aren't copied, print a string of dots.
-						open(MYINPUTFILE, "<a.tmp");
-						my(@lines) = <MYINPUTFILE>;
-						foreach $line (@lines) { 
-							$bDot = ($line =~ /^0/);
-							}
-						close(MYINPUTFILE);
-						if (!$bDot && $bOldDot) {print "\n";}
-						if ($bDot) {print ".";}
-						else {print "$from copied to $to\n";}
-						$bOldDot = $bDot;
-						}
-					}
-				}
-			$i++;
-			}
-		if ($bDot) {print "\n";}
-			
-#		# Copy the extras:
-#		print "Info -- Absent a way of scripting unzip, the instructions require manually unzipping into\n";
-#		print "        the target area $src\\pismere\\staging.\n";
-#		# my $extradir = $paths[0]->{extras}->{path};
-#		# !system("xcopy /d/f/y/s $src\\pismere\\athena\\$extradir\\* $src\\pismere\\staging") or die "Fatal -- Couldn't copy extras from $src\\pismere\\athena\\$extradir";
+		(-e $staging_area) or mkdir($staging_area);
 		
+		# Force Where From and To are relative to:
+		$prepackage->{CopyList}->{Config}->{From}->{root}		= "$src\\pismere\\athena";
+		$prepackage->{CopyList}->{Config}->{To}->{root}			= "$src\\pismere\\staging";
+		copyFiles($prepackage->{CopyList}, $config);		## Copy any files
+
 		chdir("staging\\install\\wix") or die "Fatal -- Couldn't cd to $wd\\staging\\install\\wix";
-		
+		print "Info -- chdir to ".`cd`."\n"										if ($verbose);
 		# Correct errors in files.wxi:
 		!system("sed 's/WorkingDirectory=\"\\[dirbin\\]\"/WorkingDirectory=\"dirbin\"/g' files.wxi > a.tmp") or die "Fatal -- Couldn't modify files.wxi.";
-		!system("copy /y a.tmp files.wxi") or die "Fatal -- Couldn't update files.wxi.";
-		!system("del a.tmp") or print "Warning -- Couldn't clean up temporary file $wd\\staging\\installer\\wix\\a.tmp.\n";
+		!system("mv a.tmp files.wxi") or die "Fatal -- Couldn't update files.wxi.";
 			
 		# Update paths in site-local.wxi:
 		my $dblback_originalDir = $originalDir;
@@ -419,29 +397,141 @@ sub main {
 		!system("sed -f $dblback_originalDir\\site-local.sed site-local.wxi > b.tmp") or die "Fatal -- Couldn't modify site-local.wxi.";
 		my $hexback_wd = $wd;
 		$hexback_wd =~ s/\\/\\\\\\\\\\\\/g;
-		!system("sed 's/%%TARGETDIR%%/$hexback_wd\\\\\\staging\\\\\\/' b.tmp > c.tmp") or die "Fatal -- Couldn't modify site-local.wxi temporary file.";	
-		!system("sed 's/%%CONFIGDIR%%/$hexback_wd\\\\\\staging\\\\\\sample\\\\\\/' c.tmp > d.tmp") or die "Fatal -- Couldn't modify site-local.wxi temporary file.";	
-		!system("copy /y d.tmp site-local.wxi") or die "Fatal -- Couldn't replace site-local.wxi.";
-	
-		# Copy krb.conf from ...\athena\auth\krb5\src\config-files	to pismere\staging\samples\krb5.ini:
-		!system("echo F | xcopy /D $wd\\athena\\auth\\krb5\\src\\config-files\\krb5.conf $wd\\staging\\sample\\krb5.ini") 
-			or die "Fatal -- Couldn't update $wd\\staging\\sample\\krb5.ini.";
-	
+		!system("sed 's/%%TARGETDIR%%/$hexback_wd\\\\\\staging\\\\\\/' b.tmp > c.tmp")							or die "Fatal -- Couldn't modify site-local.wxi temporary file.";	
+		!system("sed 's/%%CONFIGDIR%%/$hexback_wd\\\\\\staging\\\\\\sample\\\\\\/' c.tmp > d.tmp")	or die "Fatal -- Couldn't modify site-local.wxi temporary file.";	
+		!system("mv d.tmp site-local.wxi")																														or die "Fatal -- Couldn't replace site-local.wxi.";
+				
 		if ($verbose) {print "Info -- ***   End prepackage.\n";}
 		
-		# Make the msi:
-		!system("nmake") or die "Fatal -- Couldn't make kfw.msi.";
-	
 		if ($verbose) {print "Info -- *** Begin package.\n";}
+		# Make the msi:
+		chdir("$wd\\staging\\install\\wix") or die "Fatal -- Couldn't cd to $wd\\staging\\install\\wix";
+		print "Info -- *** Make .msi:\n"							if ($verbose);
+		!system("$MAKE")													or die "Error -- msi installer build failed.";
+				
+		chdir("$wd\\staging\\install\\nsis") or die "Fatal -- Couldn't cd to $wd\\staging\\install\\nsis";
+		print "Info -- chdir to ".`cd`."\n"						if ($verbose);
+		print "Info -- *** Make NSIS:\n"							if ($verbose);
+		!system("cl.exe killer.cpp advapi32.lib")			or die "Error -- nsis killer.exe not built.";
+		!system("rename killer.exe Killer.exe")				or die "Error -- Couldn't rename killer.exe";
+		!system("makensis kfw.nsi")								or die "Error -- executable installer build failed.";
+
+# Begin packaging extra items:
+		my $fromRoot	= $paths[0]->{src}->{path};
+		my $toRoot		= $paths[0]->{out}->{path};
+		chdir($fromRoot);		# Now in <src>.
+		print "Info -- chdir to ".`cd`."\n"										if ($verbose);
+		system("rm -rf $toRoot")													if (-d $toRoot);
+		die "Fatal -- Couldn't remove $fromRoot\\$toRoot."	if (-d $toRoot);
+		mkdir($toRoot);
+		my $zipsXML = $config->{Stages}->{PostPackage}->{Zips};
+
+		$config->{Stages}->{PostPackage}->{CopyList}->{Config}->{From}->{root}		= "$src\\pismere";		## Used after zips are made.
+		$config->{Stages}->{PostPackage}->{CopyList}->{Config}->{To}->{root}			= "$src\\$toRoot\\ziptemp";
+		my $filestem		= $config->{Stages}->{PostPackage}->{Config}->{FileStem}->{name};
+
+		local $i = 0;
+		while ($zipsXML->{Zip}[$i]) {
+			my $zip = $zipsXML->{Zip}[$i];
+			if (exists $zip->{name}) {												## Ignore dummy entry.
+				my $zipname	= $zip->{filename};
+				$zipname			=~ s/%filestem%/$filestem/g;
+				my $bMakeIt		= 1;
+				if (exists $zip->{Requires}) {
+					local $j = 0;
+					while ($zip->{Requires}->{Switch}[$j]) {				## Check Require switches
+						local $switch	= $zip->{Requires}->{Switch}[$j];
+						if (exists $switch->{name}) {								## Ignore dummy entry
+							# We handle REPOSITORY and CLEAN switches:
+							if ($switch->{name} =~ /REPOSITORY/i) {
+								$bMakeIt &&= ($switch->{value} =~ /$rverb/i);	## Repository verb must match requirement
+								}
+							elsif ($switch->{name} =~ /CLEAN/i) {		## Clean must be specified
+								$bMakeIt &&= $clean;
+								}
+							else {print "Error -- Unsupported switch $switch->{name} in Requires in ".Dumper($zip);}
+							}
+						$j++;
+						}
+					if ( !$bMakeIt && (exists $zip->{Requires}->{ErrorMsg}) ) {
+						print "Error -- $zip->{Requires}->{ErrorMsg}->{text}\n";
+						}
+					}
+				if ($bMakeIt) {
+					my $todir			= "$src\\$toRoot\\ziptemp";
+					system("rm -rf $todir")								if (-d $todir);
+					die "Fatal -- Couldn't remove $todir"		if (-d $todir);
+					mkdir($todir);
+#	Add to the zip's config section.  Don't copy Postpackage->Config, because the Zip's Config might contain substitution tags.
+					$zip->{CopyList}->{Config}->{FileStem}				= $config->{Stages}->{PostPackage}->{Config}->{FileStem};		## Each zip uses the post package config.
+					$zip->{CopyList}->{Config}->{From}->{root}		= "$src\\pismere";								## Used by zips
+					$zip->{CopyList}->{Config}->{To}->{root}			= "$src\\$toRoot\\ziptemp\\$zip->{topdir}";
+					copyFiles($zip->{CopyList}, $config);
+					# Drop down into <out>/ziptemp so the path to the added file won't include <out>:
+					chdir $todir;
+					print "Info -- chdir to ".`cd`."\n"				if ($verbose);
+
+					# Prune any unwanted files or directories from the directory we're about to zip:
+					if (exists $zip->{Prunes}) {
+						# Use Unix find instead of Windows find.  Save PATH so we can restore it when we're3 done:
+						my $savedPATH	= $ENV{PATH};
+						$ENV{PATH} = $config->{CommandLine}->{Directories}->{unixfind}->{path}.";".$savedPATH;
+						my $prunes = $zip->{Prunes};
+						my $j=0;
+						print "Info -- Processing prunes in ".`cd`."\n" if ($verbose);
+						while ($prunes->{Prune}->[$j]) {
+							if (exists $prunes->{Prune}->[$j]->{name}) {						## Don't process dummy entry!
+								my $prune	= $prunes->{Prune}->[$j]->{name};
+								my $flags	= $prunes->{Prune}->[$j]->{flags};
+								$flags = "" if (!$flags);
+								my $cmd	= "find . -".$flags."name $prune";
+								print "Info -- Looking for filenames containing $prune\n";
+								my $list = `$cmd`;
+								foreach $target (split("\n", $list)) {
+									print "Info -- Pruning $target\n" if ($verbose);
+									!system("rm -rf $target")			or die "Error -- Couldn't remove $target.";;
+									}
+								}
+							$j++;
+							}
+						$ENV{PATH} = $savedPATH;
+						}
+
+					my $zipfile			= Archive::Zip->new();
+					my $topdir		= $zip->{topdir};
+					$topdir				=~ s/%filestem%/$filestem/g;
+					$zipfile->addTree('.', $topdir);
+					if (-e $zipname)	{!system("rm -f $zipname")	or die "Error -- Couldn't remove $zipname.";}
+					$zipfile->writeToFileNamed($zipname);
+					print "Info -- created $src\\$toRoot\\$zipname.\n"	if ($verbose);
+					!system("mv -f $zipname	 ..")					or die "Error -- Couldn't move $zipname to ..";
+					chdir "..";						## Back to <out>
+					print "Info -- chdir to ".`cd`."\n"				if ($verbose);
+					}						## End else OK to process zip
+				}							## End not the dummy entry
+				$i++;					
+			}								## End zip in xml.
+				
+		$todir	= "$src\\$toRoot\\ziptemp";					## Clean up any temp directory.
+		system("rm -rf $todir")											if (-d $todir);
+				
+		my $out		= $config->{CommandLine}->{Directories}->{out}->{path};
+		$config->{Stages}->{PostPackage}->{CopyList}->{Config} = $config->{Stages}->{PostPackage}->{Config};		## Use the post package config.
+		$config->{Stages}->{PostPackage}->{CopyList}->{Config}->{From}->{root}		= "$src\\pismere";
+		$config->{Stages}->{PostPackage}->{CopyList}->{Config}->{To}->{root}			= "$src\\$out";
+		copyFiles($config->{Stages}->{PostPackage}->{CopyList}, $config);			## Copy any files
 		if ($verbose) {print "Info -- ***   End package.\n";}
-		}						## End package conditional.
-	
-#End logging:
-#    if (!$OPT->{nolog}) {
-#		$l->stop;
-#		}
+		}
+	else {
+		print "Info -- Package step skipped.";
+		}
+
+	system("rm -rf $src/a.tmp");									## Clean up junk.
+				
+# End logging:
+    if ($switches[0]->{logfile}->{value})	{$l->stop;}
 
-    return $errorState;
+    return 0;
 	}							## End subroutine main.
 
 $SIG{'INT'} = \&handler;
diff --git a/src/windows/build/copyfiles.pl b/src/windows/build/copyfiles.pl
new file mode 100644
index 000000000..a6b4ededb
--- /dev/null
+++ b/src/windows/build/copyfiles.pl
@@ -0,0 +1,132 @@
+#!perl -w
+
+#use strict;
+use XML::Simple;
+use Data::Dumper;
+
+sub copyFiles {
+	local ($xml, $config)	= @_;
+	local @switches				= $config->{CommandLine}->{Options};
+	local @files						= $xml->{Files};
+	# Check for includes:
+	if (exists $xml->{Files}->{Include}->{path}) {
+		my $includepath	= $xml->{Files}->{Include}->{path};
+		print "Info -- Including files from $includepath\n";
+		my $savedDir = `cd`;
+		$savedDir =~ s/\n//g;
+		chdir $originalDir;										## Includes are relative to where we were invoked.
+		print "Info -- chdir to ".`cd`."\n"				if ($verbose);
+		my $tmp	= new XML::Simple;
+		my $includeXML = $tmp->XMLin($includepath);
+		chdir $savedDir;
+		print "Info -- chdir to ".`cd`."\n"				if ($verbose);
+
+		local $i = 0;
+		while ($includeXML->{File}[$i]) {				## Copy File entries from includeXML.
+			$files[0]->{File}[++$#{$files[0]->{File}}] = $includeXML->{File}[$i];		
+			$i++;
+			}
+		delete $files->{Include};
+		}
+	##++ Set up path substitution variables for use inside the copy loop:
+	# A path can contain a variable part, which will be handled here.  If the variable part is 
+	# the Always or BuildDependent tag, then the variable will be changed to the 
+	# build-type-dependent PathFragment.
+	# If the variable part is the IgnoreTag, then the file will not be copied.
+	# If the variable part is %filestem%, it will be replaced with Config->FileStem->name.
+	my ($PathFragment, $BuildDependentTag, $IgnoreTag, $FileStemFragment, $fromRoot, $toRoot); 
+	my $bPathTags	= (exists $xml->{Config}->{DebugArea}) && (exists $xml->{Config}->{ReleaseArea});
+	my $bFileStem	= (exists $xml->{Config}->{FileStem});
+	
+	if ($switches[0]->{debug}->{value}) {		## Debug build tags:
+		$PathFragment				= $xml->{Config}->{DebugArea}->{value};
+		$BuildDependentTag	= $xml->{Config}->{DebugTag}->{value};
+		$IgnoreTag					= $xml->{Config}->{ReleaseTag}->{value};
+		}
+	else {																## Release build tags:
+		$PathFragment				= $xml->{Config}->{ReleaseArea}->{value};
+		$BuildDependentTag	= $xml->{Config}->{ReleaseTag}->{value};
+		$IgnoreTag					= $xml->{Config}->{DebugTag}->{value};
+		}			
+	my $AlwaysTag				= $xml->{Config}->{AlwaysTag}->{value};
+	$FileStemFragment			= $xml->{Config}->{FileStem}->{name};	
+	$fromRoot							= $xml->{Config}->{From}->{root};	
+	$toRoot								= $xml->{Config}->{To}->{root};	
+	##-- Set up path substitution variables for use inside the copy loop.
+	# For each file in the file list:
+	#  Substitute any variable parts of the path name.
+	#  Handle wildcards
+	#  Copy
+
+	local $i = 0;
+	my $bOldDot	= 1;
+	my $bDot			= 0;
+	while ($files[0]->{File}[$i]) {
+
+		my ($name, $newname, $from, $to, $file);
+		$file			= $files[0]->{File}->[$i];
+		$name	= $file->{name};
+		if (exists $file->{newname})	{$newname = $file->{newname};}
+		else												{$newname = $name;}
+		if ($name && (! exists $file->{ignore})) {		## Ignore or process this entry?
+			$from	= "$fromRoot\\$file->{from}\\$name";
+			$to		= "$toRoot\\$file->{to}\\$newname";
+			if ( $bPathTags || $bFileStem || (index($from.$to, $IgnoreTag) <0) ) {		## Copy this file?
+				if ($bPathTags) {										## Apply PathTag substitutions:
+					$from	=~ s/$AlwaysTag/$PathFragment/g;
+					$to		=~ s/$AlwaysTag/$PathFragment/g;
+					$from	=~ s/$BuildDependentTag/$PathFragment/g;
+					$to		=~ s/$BuildDependentTag/$PathFragment/g;
+					}
+				if ($bFileStem) {										## FileStem substitution?
+					$from	=~ s/%filestem%/$FileStemFragment/g;
+					$to		=~ s/%filestem%/$FileStemFragment/g;
+					}		
+				$to							=~ s/\*.*//;				## Truncate to path before any wildcard
+
+				my $bCopyOK		= 1;
+				my $fromcheck	= $from;
+				my $bRequired		= ! (exists $file->{notrequired});
+				if ($name =~ /\*/) {									## Wildcard case
+					$fromcheck =~ s/\*.*//;
+					if ($bRequired && (! -d $fromcheck)) {
+						if ($bDot) {print "\n";}
+						die "Fatal -- Can't find $fromcheck";
+						}
+					$bCopyOK = !system("echo D | xcopy /D /F /Y /S  $from $to > a.tmp 2>NUL");
+					}
+				else {															## Specific file case
+					if ($bRequired && (! -e $fromcheck)) {
+						if ($bDot) {print "\n";}
+						die "Fatal -- Can't find $fromcheck";
+						}
+					$bCopyOK	= !system("echo F | xcopy /D /F /Y $from $to > a.tmp 2>NUL");
+					}
+
+				if ($bCopyOK) {											## xcopy OK - show progress
+					# To show progress when files aren't copied, print a string of dots.
+					open(MYINPUTFILE, "<a.tmp");
+					my(@lines) = <MYINPUTFILE>;
+					foreach $line (@lines) { 
+						$bDot = ($line =~ /^0/);
+						}
+					close(MYINPUTFILE);
+					if (!$bDot && $bOldDot) {print "\n";}
+					if ($bDot) {print "."; STDOUT->flush;}
+					else {print "$from copied to $to\n";}
+					$bOldDot = $bDot;
+					}
+				else {															## xcopy failed
+					if (!exists $file->{notrequired}) {
+						if ($bDot) {print "\n";}
+						die "Fatal -- Copy of $from to $to failed";
+						}
+					}																## End xcopy succeed or fail
+				}																	## End not dummy entry nor ignored
+			}
+		$i++;
+		}
+	if ($bDot) {print "\n";}
+	}
+
+return 1;
diff --git a/src/windows/build/copyfiles.xml b/src/windows/build/copyfiles.xml
index 86efd5fbd..8187d5352 100644
--- a/src/windows/build/copyfiles.xml
+++ b/src/windows/build/copyfiles.xml
@@ -64,7 +64,7 @@
   		<File name="ms2mit.pdb"	from="..\target\bin\i386\%bldtype%\"	to="\bin\i386" />
   		<File name="leashw32.pdb"	from="..\target\bin\i386\%bldtype%\"	to="\bin\i386" />
   		<File name="leash32.pdb"	from="..\target\bin\i386\%bldtype%\"	to="\bin\i386" />
-<!--  		<File name="leash32.chm"	from="..\target\bin\i386\%bldtype%\"	to="\bin\i386" /> -->
+  		<File name="leash32.chm"	from="..\target\bin\i386\%bldtype%\"	to="\bin\i386" />
   		<File name="kpasswd.pdb"	from="..\target\bin\i386\%bldtype%\"	to="\bin\i386" />
   		<File name="kvno.pdb"	from="..\target\bin\i386\%bldtype%\"	to="\bin\i386" />
   		<File name="krbv4w32.pdb"	from="..\target\bin\i386\%bldtype%\"	to="\bin\i386" />
@@ -103,8 +103,7 @@
   		<File name="wshelp32.dll"	from="..\target\bin\i386\%bldtype%\"	to="\bin\i386" />
   		<File name="ms2mit.exe"	from="..\target\bin\i386\%bldtype%\"	to="\bin\i386" />
   		<File name="leashw32.dll"	from="..\target\bin\i386\%bldtype%\"	to="\bin\i386" />
-<!--  		<File name="leash32.exe"	from="..\target\bin\i386\%bldtype%\"	to="\bin\i386" /> -->
-<!--  		<File name="leash32.chm"	from="..\target\bin\i386\%bldtype%\"	to="\bin\i386" /> -->
+  		<File name="leash32.exe"	from="..\target\bin\i386\%bldtype%\"	to="\bin\i386" />
   		<File name="kpasswd.exe"	from="..\target\bin\i386\%bldtype%\"	to="\bin\i386" />
   		<File name="kvno.exe"	from="..\target\bin\i386\%bldtype%\"	to="\bin\i386" />
   		<File name="krbv4w32.dll"	from="..\target\bin\i386\%bldtype%\"	to="\bin\i386" />
@@ -127,9 +126,9 @@
 
 		<!-- Debug build only: -->
 		<File name="khhelp.h"	from="auth\krb5\src\windows\identity\obj\i386\%debug%\inc\"	to="\inc\netidmgr" />
-		<File name="aklog.pdb"	from="..\target\bin\i386\%debug%\"	to="\bin\i386" />
+<!--		<File name="aklog.pdb"	from="..\target\bin\i386\%debug%\"	to="\bin\i386" />	-->
 		<File name="netidmgr.exe.static.manifest"	from="..\target\bin\i386\%debug%\"	to="\bin\i386" notrequired="true" />
-		<File name="aklog.exe"	from="..\target\bin\i386\%debug%\"	to="\bin\i386" />
+<!--		<File name="aklog.exe"	from="..\target\bin\i386\%debug%\"	to="\bin\i386" />	-->
 
 		<!-- Build-INdependent files, always copied: -->
 		<File name="relnotes.html"	from="..\doc\kerberos\"	to="\doc" />
@@ -218,4 +217,7 @@
 		<File name="strings_1033.wxl"	from="auth\krb5\src\windows\installer\wix\lang\"	to="\install\wix\lang" />
 		<File name="ui_1033.wxi"	from="auth\krb5\src\windows\installer\wix\lang\"	to="\install\wix\lang" />
 		<File name="license.rtf"	from="auth\krb5\src\windows\installer\wix\lang\"	to="\install\wix\lang" />
+		<File name="krb5.conf"	from="auth\krb5\src\config-files\"	to="\sample" newname="krb5.ini" />
+		<File name="krb.con"	from="auth\krb4\sample-config\"	to="\sample" />
+		<File name="krbrealm.con"	from="auth\krb4\sample-config\"	to="\sample" />
 	</Files>
\ No newline at end of file
diff --git a/src/windows/build/corebinaryfiles.xml b/src/windows/build/corebinaryfiles.xml
new file mode 100644
index 000000000..672bca0d0
--- /dev/null
+++ b/src/windows/build/corebinaryfiles.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8" ?>
+	<Files>
+		<!-- File from	paths are relative to <src>/pismere.	-->
+		<!-- File to			paths are relative to <out>.					-->
+		<File dummy="foo" /> <!-- Forces XML::Simple behavior -->
+			<!-- Without this, XML::Simple does not make an anonymous array and I can't figure out how to iterate over it. -->
+
+		<File name="leash_userdoc.pdf" from="staging\doc" to="doc" />
+		<File name="relnotes.html" from="doc\kerberos" to="doc" />
+
+		<File name="comerr32.dll" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="comerr32.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="gss-client.exe" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="gss-client.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="gss-server.exe" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="gss-server.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="gss.exe" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="gss.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="gssapi32.dll" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="gssapi32.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="k524init.exe" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="k524init.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="k5sprt32.dll" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="k5sprt32.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="kclnt32.dll" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="kclnt32.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="kcpytkt.exe" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="kcpytkt.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="kdeltkt.exe" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="kdeltkt.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="kdestroy.exe" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="kdestroy.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="kfwcpcc.exe" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="kfwcpcc.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="kfwlogon.dll" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="kfwlogon.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="kinit.exe" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="kinit.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="klist.exe" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="klist.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="kpasswd.exe" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="kpasswd.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="krb4cred.dll" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="krb4cred.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="krb4cred_en_us.dll" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="krb524.dll" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="krb524.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="krb5cred.dll" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="krb5cred.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="krb5cred_en_us.dll" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="krb5_32.dll" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="krb5_32.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="krbcc32.dll" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="krbcc32.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="krbcc32s.exe" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="krbcc32s.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="krbv4w32.dll" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="krbv4w32.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="kvno.exe" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="kvno.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="leash32.chm" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="leash32.exe" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="leash32.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="leashw32.dll" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="leashw32.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="mit2ms.exe" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="mit2ms.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="ms2mit.exe" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="ms2mit.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="netidmgr.chm" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="netidmgr.exe" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="netidmgr.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="nidmgr32.dll" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="nidmgr32.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="wshelp32.dll" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="wshelp32.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="xpprof32.dll" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+		<File name="xpprof32.pdb" from="target\bin\i386\%bldtype%\" to="\bin\i386\" />
+
+<!--		
+target\bin\i386\%bldtype%\ w2k\netidmgr.exe
+target\bin\i386\%bldtype%\ w2k\netidmgr.pdb
+target\bin\i386\%bldtype%\ w2k\nidmgr32.dll
+target\bin\i386\%bldtype%\ w2k\nidmgr32.pdb
+-->
+
+	</Files>
\ No newline at end of file
diff --git a/src/windows/build/sdkfiles.xml b/src/windows/build/sdkfiles.xml
new file mode 100644
index 000000000..d80a681d7
--- /dev/null
+++ b/src/windows/build/sdkfiles.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8" ?>
+	<Files>
+		<!-- File from	paths are relative to <src>/pismere.	-->
+		<!-- File to			paths are relative to <out>.					-->
+		<File dummy="foo" /> <!-- Forces XML::Simple behavior -->
+			<!-- Without this, XML::Simple does not make an anonymous array and I can't figure out how to iterate over it. -->
+
+		<File name="relnotes.html" from="doc\kerberos" to="doc" />
+		<File name="kclient.rtf" from="athena\auth\krb4\kclient\doc" to="doc" />
+
+		<File  name="*.h" from="staging\inc" to="inc" />
+<!--	
+		<File  name="*.h" from="staging\inc\kclient" to="inc\kclient\" />
+		<File  name="*.h" from="staging\inc\krb4" to="inc\krb4\" />
+		<File  name="*.h" from="staging\inc\krb5" to="inc\krb5\" />
+
+		<File  name="gssapi.h" from="" to="" inc\krb5\gssapi\
+		<File  name="gssapi_generic.h" from="" to="" inc\krb5\gssapi\
+		<File  name="gssapi_krb5.h" from="" to="" inc\krb5\gssapi\
+
+		<File  name="des.h" from="" to="" inc\krb5\KerberosIV\
+		<File  name="kadm_err.h" from="" to="" inc\krb5\KerberosIV\
+		<File  name="krb.h" from="" to="" inc\krb5\KerberosIV\
+		<File  name="krb_err.h" from="" to="" inc\krb5\KerberosIV\
+		<File  name="mit-copyright.h" from="" to="" inc\krb5\KerberosIV\
+
+		<File  name="krb5.h" from="" to="" inc\krb5\krb5\
+
+		<File  name="cacheapi.h" from="" to="" inc\krbcc\
+
+		<File  name="leasherr.h" from="" to="" inc\leash\
+		<File  name="leashinfo.h" from="" to="" inc\leash\
+		<File  name="leashwin.h" from="" to="" inc\leash\
+
+		<File  name="loadfuncs.h" from="" to="" inc\loadfuncs\
+		<File  name="loadfuncs-afs.h" from="" to="" inc\loadfuncs\
+		<File  name="loadfuncs-afs36.h" from="" to="" inc\loadfuncs\
+		<File  name="loadfuncs-com_err.h" from="" to="" inc\loadfuncs\
+		<File  name="loadfuncs-krb.h" from="" to="" inc\loadfuncs\
+		<File  name="loadfuncs-krb5.h" from="" to="" inc\loadfuncs\
+		<File  name="loadfuncs-krb524.h" from="" to="" inc\loadfuncs\
+		<File  name="loadfuncs-leash.h" from="" to="" inc\loadfuncs\
+		<File  name="loadfuncs-lsa.h" from="" to="" inc\loadfuncs\
+		<File  name="loadfuncs-profile.h" from="" to="" inc\loadfuncs\
+		<File  name="loadfuncs-wshelper.h" from="" to="" inc\loadfuncs\
+
+		<File  name="loadfuncs.c" from="" to="" inc\loadfuncs\
+
+		<File  name="hashtable.h" from="" to="" inc\netidmgr\
+		<File  name="kconfig.h" from="" to="" inc\netidmgr\
+		<File  name="kcreddb.h" from="" to="" inc\netidmgr\
+		<File  name="khaction.h" from="" to="" inc\netidmgr\
+		<File  name="khactiondef.h" from="" to="" inc\netidmgr\
+		<File  name="khalerts.h" from="" to="" inc\netidmgr\
+		<File  name="khconfigui.h" from="" to="" inc\netidmgr\
+		<File  name="khdefs.h" from="" to="" inc\netidmgr\
+		<File  name="kherr.h" from="" to="" inc\netidmgr\
+		<File  name="kherror.h" from="" to="" inc\netidmgr\
+		<File  name="khhtlink.h" from="" to="" inc\netidmgr\
+		<File  name="khlist.h" from="" to="" inc\netidmgr\
+		<File  name="khmsgtypes.h" from="" to="" inc\netidmgr\
+		<File  name="khnewcred.h" from="" to="" inc\netidmgr\
+		<File  name="khprops.h" from="" to="" inc\netidmgr\
+		<File  name="khremote.h" from="" to="" inc\netidmgr\
+		<File  name="khrescache.h" from="" to="" inc\netidmgr\
+		<File  name="khtracker.h" from="" to="" inc\netidmgr\
+		<File  name="khuidefs.h" from="" to="" inc\netidmgr\
+		<File  name="kmm.h" from="" to="" inc\netidmgr\
+		<File  name="kmq.h" from="" to="" inc\netidmgr\
+		<File  name="kplugin.h" from="" to="" inc\netidmgr\
+		<File  name="mstring.h" from="" to="" inc\netidmgr\
+		<File  name="netidmgr.h" from="" to="" inc\netidmgr\
+		<File  name="netidmgr_version.h" from="" to="" inc\netidmgr\
+		<File  name="perfstat.h" from="" to="" inc\netidmgr\
+		<File  name="sync.h" from="" to="" inc\netidmgr\
+		<File  name="utils.h" from="" to="" inc\netidmgr\
+
+		<File  name="nameser.h" from="" to="" inc\wshelper\arpa\
+
+		<File  name="hesiod.h" from="" to="" inc\wshelper\
+		<File  name="mitwhich.h" from="" to="" inc\wshelper\
+		<File  name="resolv.h" from="" to="" inc\wshelper\
+		<File  name="wshelper.h" from="" to="" inc\wshelper\
+-->
+
+		<File  name="*.*" from="staging\install\nsis" to="install\nsis\" />
+<!--		<File  name="kfw-fixed.nsi" from="" to="" install\nsis\
+		<File  name="kfw.ico" from="" to="" install\nsis\
+		<File  name="kfw.nsi" from="" to="" install\nsis\
+		<File  name="KfWConfigPage.ini" from="" to="" install\nsis\
+		<File  name="KfWConfigPage2.ini" from="" to="" install\nsis\
+		<File  name="killer.cpp" from="" to="" install\nsis\
+		<File  name="licenses.rtf" from="" to="" install\nsis\
+		<File  name="site-local.nsi" from="" to="" install\nsis\
+		<File  name="utils.nsi" from="" to="" install\nsis\
+-->
+
+		<File  name="config.wxi" from="staging\install\wix" to="install\wix\" />
+		<File  name="features.wxi" from="staging\install\wix" to="install\wix\" />
+		<File  name="files.wxi" from="staging\install\wix" to="install\wix\" />
+		<File  name="kfw.wxs" from="staging\install\wix" to="install\wix\" />
+		<File  name="Makefile" from="staging\install\wix" to="install\wix\" />
+		<File  name="msi-deployment-guide.txt" from="staging\install\wix" to="install\wix\" />
+		<File  name="property.wxi" from="staging\install\wix" to="install\wix\" />
+		<File  name="site-local.wxi" from="staging\install\wix" to="install\wix\" />
+
+		<File  name="*.*" from="staging\install\wix\Binary" to="install\wix\Binary\" />
+<!--		<File  name="bannrbmp.bmp" from="" to="" install\wix\Binary\
+		<File  name="completi.ico" from="" to="" install\wix\Binary\
+		<File  name="custicon.ico" from="" to="" install\wix\Binary\
+		<File  name="dlgbmp.bmp" from="" to="" install\wix\Binary\
+		<File  name="exclamic.ico" from="" to="" install\wix\Binary\
+		<File  name="info.bmp" from="" to="" install\wix\Binary\
+		<File  name="insticon.ico" from="" to="" install\wix\Binary\
+		<File  name="new.bmp" from="" to="" install\wix\Binary\
+		<File  name="removico.ico" from="" to="" install\wix\Binary\
+		<File  name="repairic.ico" from="" to="" install\wix\Binary\
+		<File  name="up.bmp" from="" to="" install\wix\Binary\
+-->		
+
+		<File  name="custom.cpp" from="staging\install\wix\custom" to="install\wix\custom\" />
+		<File  name="custom.h" from="staging\install\wix\custom" to="install\wix\custom\" />
+
+		<File  name="config_1033.wxi" from="staging\install\wix\lang" to="install\wix\lang\" />
+		<File  name="strings_1033.wxl" from="staging\install\wix\lang" to="install\wix\lang\" />
+		<File  name="ui_1033.wxi" from="staging\install\wix\lang" to="install\wix\lang\" />
+		<!-- Why not license.rtf? -->
+
+		<File  name="*.lib" from="staging\lib\i386" to="lib\i386\" />
+<!--		
+		<File  name="comerr32.lib" from="" to="" lib\i386\
+		<File  name="delaydlls.lib" from="" to="" lib\i386\
+		<File  name="getopt.lib" from="" to="" lib\i386\
+		<File  name="gssapi32.lib" from="" to="" lib\i386\
+		<File  name="kclnt32.lib" from="" to="" lib\i386\
+		<File  name="krb524.lib" from="" to="" lib\i386\
+		<File  name="krb5_32.lib" from="" to="" lib\i386\
+		<File  name="krbcc32.lib" from="" to="" lib\i386\
+		<File  name="krbv4w32.lib" from="" to="" lib\i386\
+		<File  name="leashw32.lib" from="" to="" lib\i386\
+		<File  name="loadfuncs.lib" from="" to="" lib\i386\
+		<File  name="nidmgr32.lib" from="" to="" lib\i386\
+		<File  name="wshelp32.lib" from="" to="" lib\i386\
+		<File  name="xpprof32.lib" from="" to="" lib\i386\
+-->	
+	
+	</Files>
\ No newline at end of file
diff --git a/src/windows/build/srcfiles.xml b/src/windows/build/srcfiles.xml
new file mode 100644
index 000000000..58b58af55
--- /dev/null
+++ b/src/windows/build/srcfiles.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" ?>
+	<Files>
+		<!-- File from	paths are relative to <src>/pismere.	-->
+		<!-- File to			paths are relative to <out>.					-->
+		<File dummy="foo" /> <!-- Forces XML::Simple behavior -->
+			<!-- Without this, XML::Simple does not make an anonymous array and I can't figure out how to iterate over it. -->
+
+		<File name="config_1033.wxi"	from="athena\auth\krb5\src\windows\installer\wix\lang\"	to="\install\wix\lang" />
+		<File name="strings_1033.wxl"	from="athena\auth\krb5\src\windows\installer\wix\lang\"	to="\install\wix\lang" />
+		<File name="ui_1033.wxi"	from="athena\auth\krb5\src\windows\installer\wix\lang\"	to="\install\wix\lang" />
+		<File name="license.rtf"	from="athena\auth\krb5\src\windows\installer\wix\lang\"	to="\install\wix\lang" />
+		<File name="krb5.conf"	from="athena\auth\krb5\src\config-files\"	to="\sample" newname="krb5.ini"/>
+	</Files>
\ No newline at end of file