Reimplemented GetFileType and SetEndOfFile using ntdll functions.

diff --git a/dlls/kernel/file.c b/dlls/kernel/file.c
index 35372a9..5dd744f 100644
--- a/dlls/kernel/file.c
+++ b/dlls/kernel/file.c
@@ -2,7 +2,7 @@
  * File handling functions
  *
  * Copyright 1993 John Burton
- * Copyright 1996 Alexandre Julliard
+ * Copyright 1996, 2004 Alexandre Julliard
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -17,10 +17,6 @@
  * 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
- *
- * TODO:
- *    Fix the CopyFileEx methods to implement the "extended" functionality.
- *    Right now, they simply call the CopyFile method.
  */
 
 #include "config.h"
@@ -36,6 +32,7 @@
 #include "winbase.h"
 #include "winreg.h"
 #include "winternl.h"
+#include "winioctl.h"
 #include "wincon.h"
 #include "wine/winbase16.h"
 #include "kernel_private.h"
@@ -331,6 +328,39 @@
 
 
 /***********************************************************************
+ *           GetFileType   (KERNEL32.@)
+ */
+DWORD WINAPI GetFileType( HANDLE hFile )
+{
+    FILE_FS_DEVICE_INFORMATION info;
+    IO_STATUS_BLOCK io;
+    NTSTATUS status;
+
+    if (is_console_handle( hFile )) return FILE_TYPE_CHAR;
+
+    status = NtQueryVolumeInformationFile( hFile, &io, &info, sizeof(info), FileFsDeviceInformation );
+    if (status != STATUS_SUCCESS)
+    {
+        SetLastError( RtlNtStatusToDosError(status) );
+        return FILE_TYPE_UNKNOWN;
+    }
+
+    switch(info.DeviceType)
+    {
+    case FILE_DEVICE_NULL:
+    case FILE_DEVICE_SERIAL_PORT:
+    case FILE_DEVICE_PARALLEL_PORT:
+    case FILE_DEVICE_UNKNOWN:
+        return FILE_TYPE_CHAR;
+    case FILE_DEVICE_NAMED_PIPE:
+        return FILE_TYPE_PIPE;
+    default:
+        return FILE_TYPE_DISK;
+    }
+}
+
+
+/***********************************************************************
  *             GetFileInformationByHandle   (KERNEL32.@)
  */
 BOOL WINAPI GetFileInformationByHandle( HANDLE hFile, BY_HANDLE_FILE_INFORMATION *info )
@@ -395,6 +425,28 @@
 }
 
 
+/**************************************************************************
+ *           SetEndOfFile   (KERNEL32.@)
+ */
+BOOL WINAPI SetEndOfFile( HANDLE hFile )
+{
+    FILE_POSITION_INFORMATION pos;
+    FILE_END_OF_FILE_INFORMATION eof;
+    IO_STATUS_BLOCK io;
+    NTSTATUS status;
+
+    status = NtQueryInformationFile( hFile, &io, &pos, sizeof(pos), FilePositionInformation );
+    if (status == STATUS_SUCCESS)
+    {
+        eof.EndOfFile = pos.CurrentByteOffset;
+        status = NtSetInformationFile( hFile, &io, &eof, sizeof(eof), FileEndOfFileInformation );
+    }
+    if (status == STATUS_SUCCESS) return TRUE;
+    SetLastError( RtlNtStatusToDosError(status) );
+    return FALSE;
+}
+
+
 /***********************************************************************
  *           GetFileTime   (KERNEL32.@)
  */
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 4d3d50e..457b20f 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -1124,6 +1124,29 @@
         else io->u.Status = STATUS_INVALID_PARAMETER_3;
         break;
 
+    case FileEndOfFileInformation:
+        if (len >= sizeof(FILE_END_OF_FILE_INFORMATION))
+        {
+            const FILE_END_OF_FILE_INFORMATION *info = ptr;
+
+            if (info->EndOfFile.QuadPart > lseek( fd, 0, SEEK_END ))
+            {
+                static const char zero;
+
+                /* extend the file one byte beyond the requested size and then truncate it */
+                /* this should work around ftruncate implementations that can't extend files */
+                if (pwrite( fd, &zero, 1, (off_t)info->EndOfFile.QuadPart ) == -1)
+                {
+                    io->u.Status = FILE_GetNtStatus();
+                    break;
+                }
+            }
+            if (ftruncate( fd, (off_t)info->EndOfFile.QuadPart ) == -1)
+                io->u.Status = FILE_GetNtStatus();
+        }
+        else io->u.Status = STATUS_INVALID_PARAMETER_3;
+        break;
+
     default:
         FIXME("Unsupported class (%d)\n", class);
         io->u.Status = STATUS_NOT_IMPLEMENTED;
@@ -1278,11 +1301,7 @@
         {
             FILE_FS_DEVICE_INFORMATION *info = buffer;
 
-#if defined(linux) && defined(HAVE_FSTATFS)
-            struct statfs stfs;
-
             info->Characteristics = 0;
-
             if (fstat( fd, &st ) < 0)
             {
                 io->u.Status = FILE_GetNtStatus();
@@ -1290,6 +1309,8 @@
             }
             if (S_ISCHR( st.st_mode ))
             {
+                info->DeviceType = FILE_DEVICE_UNKNOWN;
+#ifdef linux
                 switch(major(st.st_rdev))
                 {
                 case MEM_MAJOR:
@@ -1301,10 +1322,8 @@
                 case LP_MAJOR:
                     info->DeviceType = FILE_DEVICE_PARALLEL_PORT;
                     break;
-                default:
-                    info->DeviceType = FILE_DEVICE_UNKNOWN;
-                    break;
                 }
+#endif
             }
             else if (S_ISBLK( st.st_mode ))
             {
@@ -1316,7 +1335,8 @@
             }
             else  /* regular file or directory */
             {
-                info->Characteristics |= FILE_DEVICE_IS_MOUNTED;
+#if defined(linux) && defined(HAVE_FSTATFS)
+                struct statfs stfs;
 
                 /* check for floppy disk */
                 if (major(st.st_dev) == FLOPPY_MAJOR)
@@ -1346,13 +1366,13 @@
                     info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
                     break;
                 }
-            }
 #else
-            static int warned;
-            if (!warned++) FIXME( "device info not supported on this platform\n" );
-            info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
-            info->Characteristics = 0;
+                static int warned;
+                if (!warned++) FIXME( "device info not properly supported on this platform\n" );
+                info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
 #endif
+                info->Characteristics |= FILE_DEVICE_IS_MOUNTED;
+            }
             io->Information = sizeof(*info);
             io->u.Status = STATUS_SUCCESS;
         }