Change Windows file.truncate() to (a) restore the original file position,
and (b) stop trying to prevent file growth.

Beef up the file.truncate() docs.

Change test_largefile.py to stop assuming that f.truncate() moves the
file pointer to the truncation point, and to verify instead that it leaves
the file position alone.  Remove the test for what happens when a
specified size exceeds the original file size (it's ill-defined, according
to the Single Unix Spec).
diff --git a/Doc/lib/libstdtypes.tex b/Doc/lib/libstdtypes.tex
index 27f1c52..2bd6420 100644
--- a/Doc/lib/libstdtypes.tex
+++ b/Doc/lib/libstdtypes.tex
@@ -161,7 +161,7 @@
 
 \subsection{Numeric Types \label{typesnumeric}}
 
-There are four numeric types: \dfn{plain integers}, \dfn{long integers}, 
+There are four numeric types: \dfn{plain integers}, \dfn{long integers},
 \dfn{floating point numbers}, and \dfn{complex numbers}.
 Plain integers (also just called \dfn{integers})
 are implemented using \ctype{long} in C, which gives them at least 32
@@ -178,7 +178,7 @@
 
 Complex numbers have a real and imaginary part, which are both
 implemented using \ctype{double} in C.  To extract these parts from
-a complex number \var{z}, use \code{\var{z}.real} and \code{\var{z}.imag}.  
+a complex number \var{z}, use \code{\var{z}.real} and \code{\var{z}.imag}.
 
 Numbers are created by numeric literals or as the result of built-in
 functions and operators.  Unadorned integer literals (including hex
@@ -248,7 +248,7 @@
 
 \item[(1)]
 For (plain or long) integer division, the result is an integer.
-The result is always rounded towards minus infinity: 1/2 is 0, 
+The result is always rounded towards minus infinity: 1/2 is 0,
 (-1)/2 is -1, 1/(-2) is -1, and (-1)/(-2) is 0.  Note that the result
 is a long integer if either operand is a long integer, regardless of
 the numeric value.
@@ -472,7 +472,7 @@
   the end of the string: \code{len(\var{s}) + \var{i}} or
   \code{len(\var{s}) + \var{j}} is substituted.  But note that \code{-0} is
   still \code{0}.
-  
+
 \item[(3)] The slice of \var{s} from \var{i} to \var{j} is defined as
   the sequence of items with index \var{k} such that \code{\var{i} <=
   \var{k} < \var{j}}.  If \var{i} or \var{j} is greater than
@@ -808,7 +808,7 @@
 
 Additional string operations are defined in standard modules
 \refmodule{string}\refstmodindex{string} and
-\refmodule{re}.\refstmodindex{re} 
+\refmodule{re}.\refstmodindex{re}
 
 
 \subsubsection{XRange Type \label{typesseq-xrange}}
@@ -881,7 +881,7 @@
   no longer works in Python 2.0.  Use of this misfeature has been
   deprecated since Python 1.4.
 
-\item[(2)] Raises an exception when \var{x} is not a list object.  The 
+\item[(2)] Raises an exception when \var{x} is not a list object.  The
   \method{extend()} method is experimental and not supported by
   mutable sequence types other than lists.
 
@@ -1034,7 +1034,7 @@
 
 File objects\obindex{file} are implemented using C's \code{stdio}
 package and can be created with the built-in constructor
-\function{file()}\bifuncindex{file} described in section 
+\function{file()}\bifuncindex{file} described in section
 \ref{built-in-funcs}, ``Built-in Functions.''\footnote{\function{file()}
 is new in Python 2.2.  The older built-in \function{open()} is an
 alias for \function{file()}.}
@@ -1100,10 +1100,10 @@
 \begin{methoddesc}[file]{readline}{\optional{size}}
   Read one entire line from the file.  A trailing newline character is
   kept in the string\footnote{
-	The advantage of leaving the newline on is that an empty string 
-	can be returned to mean \EOF{} without being ambiguous.  Another 
-	advantage is that (in cases where it might matter, for example. if you 
-	want to make an exact copy of a file while scanning its lines) 
+	The advantage of leaving the newline on is that an empty string
+	can be returned to mean \EOF{} without being ambiguous.  Another
+	advantage is that (in cases where it might matter, for example. if you
+	want to make an exact copy of a file while scanning its lines)
 	you can tell whether the last line of a file ended in a newline
 	or not (yes this happens!).
   } (but may be absent when a file ends with an
@@ -1152,9 +1152,14 @@
 \end{methoddesc}
 
 \begin{methoddesc}[file]{truncate}{\optional{size}}
-  Truncate the file's size.  If the optional \var{size} argument
+  Truncate the file's size.  If the optional \var{size} argument is
   present, the file is truncated to (at most) that size.  The size
-  defaults to the current position.
+  defaults to the current position.  The current file position is
+  not changed.  Note that if a specified size exceeds the file's
+  current size, the result is platform-dependent:  possibilities
+  include that file may remain unchanged, increase to the specified
+  size as if zero-filled, or increase to the specified size with
+  undefined new content.
   Availability:  Windows, many \UNIX variants.
 \end{methoddesc}
 
diff --git a/Lib/test/test_largefile.py b/Lib/test/test_largefile.py
index bc24635..8bff5df 100644
--- a/Lib/test/test_largefile.py
+++ b/Lib/test/test_largefile.py
@@ -133,24 +133,30 @@
         print 'try truncate'
     f = open(name, 'r+b')
     f.seek(0, 2)
-    expect(f.tell(), size+1)
+    expect(f.tell(), size+1)    # else we've lost track of the true size
     # Cut it back via seek + truncate with no argument.
     newsize = size - 10
     f.seek(newsize)
     f.truncate()
-    expect(f.tell(), newsize)
-    # Ensure that truncate(bigger than true size) doesn't grow the file.
-    f.truncate(size)
-    expect(f.tell(), newsize)
+    expect(f.tell(), newsize)   # else pointer moved
+    f.seek(0, 2)
+    expect(f.tell(), newsize)   # else wasn't truncated
     # Ensure that truncate(smaller than true size) shrinks the file.
     newsize -= 1
-    f.seek(0)
+    f.seek(42)
     f.truncate(newsize)
-    expect(f.tell(), newsize)
+    expect(f.tell(), 42)        # else pointer moved
+    f.seek(0, 2)
+    expect(f.tell(), newsize)   # else wasn't truncated
+
+    # XXX truncate(larger than true size) is ill-defined across platforms
+
     # cut it waaaaay back
-    f.truncate(1)
     f.seek(0)
-    expect(len(f.read()), 1)
+    f.truncate(1)
+    expect(f.tell(), 0)         # else pointer moved
+    expect(len(f.read()), 1)    # else wasn't truncated
+
     f.close()
 
 os.unlink(name)
diff --git a/Objects/fileobject.c b/Objects/fileobject.c
index f2f5dcf..7bcc82a 100644
--- a/Objects/fileobject.c
+++ b/Objects/fileobject.c
@@ -415,46 +415,59 @@
 
 #ifdef MS_WIN32
 	/* MS _chsize doesn't work if newsize doesn't fit in 32 bits,
-	   so don't even try using it.  truncate() should never grow the
-	   file, but MS SetEndOfFile will grow a file, so we need to
-	   compare the specified newsize to the actual size.  Some
-	   optimization could be done here when newsizeobj is NULL. */
+	   so don't even try using it. */
 	{
-		Py_off_t currentEOF;	/* actual size */
+		Py_off_t current;	/* current file position */
 		HANDLE hFile;
 		int error;
 
-		/* First move to EOF, and set currentEOF to the size. */
-		errno = 0;
-		if (_portable_fseek(f->f_fp, 0, SEEK_END) != 0)
-			goto onioerror;
-		errno = 0;
-		currentEOF = _portable_ftell(f->f_fp);
-		if (currentEOF == -1)
-			goto onioerror;
-
-		if (newsize > currentEOF)
-			newsize = currentEOF;	/* never grow the file */
-
-		/* Move to newsize, and truncate the file there. */
-		if (newsize != currentEOF) {
-			errno = 0;
-			if (_portable_fseek(f->f_fp, newsize, SEEK_SET) != 0)
-				goto onioerror;
+		/* current <- current file postion. */
+		if (newsizeobj == NULL)
+			current = newsize;
+		else {
 			Py_BEGIN_ALLOW_THREADS
 			errno = 0;
-			hFile = (HANDLE)_get_osfhandle(fileno(f->f_fp));
-			error = hFile == (HANDLE)-1;
-			if (!error) {
-				error = SetEndOfFile(hFile) == 0;
-				if (error)
-					errno = EACCES;
-			}
+			current = _portable_ftell(f->f_fp);
+			Py_END_ALLOW_THREADS
+			if (current == -1)
+				goto onioerror;
+		}
+
+		/* Move to newsize. */
+		if (current != newsize) {
+			Py_BEGIN_ALLOW_THREADS
+			errno = 0;
+			error = _portable_fseek(f->f_fp, newsize, SEEK_SET)
+				!= 0;
 			Py_END_ALLOW_THREADS
 			if (error)
 				goto onioerror;
 		}
 
+		/* Truncate.  Note that this may grow the file! */
+		Py_BEGIN_ALLOW_THREADS
+		errno = 0;
+		hFile = (HANDLE)_get_osfhandle(fileno(f->f_fp));
+		error = hFile == (HANDLE)-1;
+		if (!error) {
+			error = SetEndOfFile(hFile) == 0;
+			if (error)
+				errno = EACCES;
+		}
+		Py_END_ALLOW_THREADS
+		if (error)
+			goto onioerror;
+
+		/* Restore original file position. */
+		if (current != newsize) {
+			Py_BEGIN_ALLOW_THREADS
+			errno = 0;
+			error = _portable_fseek(f->f_fp, current, SEEK_SET)
+				!= 0;
+			Py_END_ALLOW_THREADS
+			if (error)
+				goto onioerror;
+		}
 	}
 #else
 	Py_BEGIN_ALLOW_THREADS