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;
}