check for console handles in Get/SetFileAttributesByHandle()
[reactos.git] / reactos / lib / kernel32 / file / file.c
index bf9e63f..9256f15 100644 (file)
@@ -1,4 +1,5 @@
-/*
+/* $Id$
+ *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
  * FILE:            lib/kernel32/file/file.c
  *                  Created 01/11/98
  */
 
-/* FIXME: the large integer manipulations in this file dont handle overflow  */
-
-/* INCLUDES ****************************************************************/
+/* INCLUDES *****************************************************************/
 
-#include <windows.h>
-#include <ddk/ntddk.h>
-#include <wchar.h>
-#include <string.h>
+#include <k32.h>
 
-//#define NDEBUG
-#include <kernel32/kernel32.h>
+#define NDEBUG
+#include "../include/debug.h"
 
-#define LPPROGRESS_ROUTINE void*
 
 /* GLOBALS ******************************************************************/
 
-static BOOLEAN  bIsFileApiAnsi; // set the file api to ansi or oem
+BOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem
 
 /* FUNCTIONS ****************************************************************/
 
-VOID STDCALL SetFileApisToOEM(VOID)
+
+
+PWCHAR
+FilenameA2W(LPCSTR NameA, BOOL alloc)
 {
-   bIsFileApiAnsi = FALSE;     
+   ANSI_STRING str;
+   UNICODE_STRING strW;
+   PUNICODE_STRING pstrW;
+   NTSTATUS Status;
+
+   ASSERT(NtCurrentTeb()->StaticUnicodeString.Buffer == NtCurrentTeb()->StaticUnicodeBuffer);
+   ASSERT(NtCurrentTeb()->StaticUnicodeString.MaximumLength == sizeof(NtCurrentTeb()->StaticUnicodeBuffer));
+
+   RtlInitAnsiString(&str, NameA);
+   pstrW = alloc ? &strW : &NtCurrentTeb()->StaticUnicodeString;
+
+   if (bIsFileApiAnsi)
+        Status= RtlAnsiStringToUnicodeString( pstrW, &str, alloc );
+   else
+        Status= RtlOemStringToUnicodeString( pstrW, &str, alloc );
+
+    if (NT_SUCCESS(Status))
+       return pstrW->Buffer;
+
+    if (Status== STATUS_BUFFER_OVERFLOW)
+        SetLastError( ERROR_FILENAME_EXCED_RANGE );
+    else
+        SetLastErrorByStatus(Status);
+
+    return NULL;
 }
 
-WINBASEAPI VOID WINAPI SetFileApisToANSI(VOID)
+
+/*
+No copy/conversion is done if the dest. buffer is too small.
+
+Returns:
+   Success: number of TCHARS copied into dest. buffer NOT including nullterm
+   Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm
+*/
+DWORD
+FilenameU2A_FitOrFail(
+   LPSTR  DestA,
+   INT destLen, /* buffer size in TCHARS incl. nullchar */
+   PUNICODE_STRING SourceU
+   )
 {
-   bIsFileApiAnsi = TRUE;
+   DWORD ret;
+
+   ret = bIsFileApiAnsi? RtlUnicodeStringToAnsiSize(SourceU) : RtlUnicodeStringToOemSize(SourceU);
+   /* ret incl. nullchar */
+
+   if (DestA && (INT)ret <= destLen)
+   {
+      ANSI_STRING str;
+
+      str.Buffer = DestA;
+      str.MaximumLength = destLen;
+
+
+      if (bIsFileApiAnsi)
+         RtlUnicodeStringToAnsiString(&str, SourceU, FALSE );
+      else
+         RtlUnicodeStringToOemString(&str, SourceU, FALSE );
+
+      ret = str.Length;  /* SUCCESS: length without terminating 0 */
+   }
+
+   return ret;
 }
 
-WINBOOL STDCALL AreFileApisANSI(VOID)
+
+/*
+No copy/conversion is done if the dest. buffer is too small.
+
+Returns:
+   Success: number of TCHARS copied into dest. buffer NOT including nullterm
+   Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm
+*/
+DWORD
+FilenameW2A_FitOrFail(
+   LPSTR  DestA,
+   INT destLen, /* buffer size in TCHARS incl. nullchar */
+   LPCWSTR SourceW,
+   INT sourceLen /* buffer size in TCHARS incl. nullchar */
+   )
 {
-   return(bIsFileApiAnsi);
+   UNICODE_STRING strW;
+
+   if (sourceLen < 0) sourceLen = wcslen(SourceW) + 1;
+
+   strW.Buffer = (PWCHAR)SourceW;
+   strW.MaximumLength = sourceLen * sizeof(WCHAR);
+   strW.Length = strW.MaximumLength - sizeof(WCHAR);
+
+   return FilenameU2A_FitOrFail(DestA, destLen, &strW);
 }
 
-HFILE STDCALL OpenFile(LPCSTR lpFileName,
-                      LPOFSTRUCT lpReOpenBuff,
-                      UINT uStyle)
+
+/*
+Return: num. TCHARS copied into dest including nullterm
+*/
+DWORD
+FilenameA2W_N(
+   LPWSTR dest,
+   INT destlen, /* buffer size in TCHARS incl. nullchar */
+   LPCSTR src,
+   INT srclen /* buffer size in TCHARS incl. nullchar */
+   )
 {
-   NTSTATUS errCode;
-   HANDLE FileHandle = NULL;
-   UNICODE_STRING FileNameString;
-   WCHAR FileNameW[MAX_PATH];
-   WCHAR PathNameW[MAX_PATH];
-   ULONG i;
-   OBJECT_ATTRIBUTES ObjectAttributes;
-   IO_STATUS_BLOCK IoStatusBlock;
-   WCHAR *FilePart;    
-   ULONG Len;
-   
-   if (lpReOpenBuff == NULL) 
-     {
-       return FALSE;
-     }
-     
-   i = 0;
-   while ((*lpFileName)!=0 && i < MAX_PATH)
-     {
-       FileNameW[i] = *lpFileName;
-       lpFileName++;
-       i++;
-     }
-   FileNameW[i] = 0;
-
-   Len = SearchPathW(NULL,FileNameW,NULL,MAX_PATH,PathNameW,&FilePart);
-   if ( Len == 0 )
-     return (HFILE)NULL;
-
-   if ( Len > MAX_PATH )
-     return (HFILE)NULL;
-   
-   FileNameString.Length = lstrlenW(PathNameW)*sizeof(WCHAR);
-   FileNameString.Buffer = PathNameW;
-   FileNameString.MaximumLength = FileNameString.Length+sizeof(WCHAR);
-   
-   ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
-   ObjectAttributes.RootDirectory = NULL;
-   ObjectAttributes.ObjectName = &FileNameString;
-   ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT;
-   ObjectAttributes.SecurityDescriptor = NULL;
-   ObjectAttributes.SecurityQualityOfService = NULL;
-
-   // FILE_SHARE_READ
-   // FILE_NO_INTERMEDIATE_BUFFERING
-   
-   if ((uStyle & OF_PARSE) == OF_PARSE ) 
-     return (HFILE)NULL;
-   
-   errCode = NtOpenFile(&FileHandle,
-                       GENERIC_READ|SYNCHRONIZE,
-                       &ObjectAttributes,
-                       &IoStatusBlock,   
-                       FILE_SHARE_READ,         
-                       FILE_NON_DIRECTORY_FILE);
-   
-   lpReOpenBuff->nErrCode = RtlNtStatusToDosError(errCode);
-   
-   if (!NT_SUCCESS(errCode)) 
-     {
-       SetLastError(RtlNtStatusToDosError(errCode));
-       return (HFILE)INVALID_HANDLE_VALUE;
-     }
-   
-   return (HFILE)FileHandle;
+    DWORD ret;
+
+    if (srclen < 0) srclen = strlen( src ) + 1;
+
+    if (bIsFileApiAnsi)
+        RtlMultiByteToUnicodeN( dest, destlen* sizeof(WCHAR), &ret, (LPSTR)src, srclen  );
+    else
+        RtlOemToUnicodeN( dest, destlen* sizeof(WCHAR), &ret, (LPSTR)src, srclen );
+
+    if (ret) dest[(ret/sizeof(WCHAR))-1]=0;
+
+    return ret/sizeof(WCHAR);
+}
+
+/*
+Return: num. TCHARS copied into dest including nullterm
+*/
+DWORD
+FilenameW2A_N(
+   LPSTR dest,
+   INT destlen, /* buffer size in TCHARS incl. nullchar */
+   LPCWSTR src,
+   INT srclen /* buffer size in TCHARS incl. nullchar */
+   )
+{
+    DWORD ret;
+
+    if (srclen < 0) srclen = wcslen( src ) + 1;
+
+    if (bIsFileApiAnsi)
+        RtlUnicodeToMultiByteN( dest, destlen, &ret, (LPWSTR) src, srclen * sizeof(WCHAR));
+    else
+        RtlUnicodeToOemN( dest, destlen, &ret, (LPWSTR) src, srclen * sizeof(WCHAR) );
+
+    if (ret) dest[ret-1]=0;
+
+    return ret;
+}
+
+
+/*
+ * @implemented
+ */
+VOID
+STDCALL
+SetFileApisToOEM(VOID)
+{
+    /* Set the correct Base Api */
+    Basep8BitStringToUnicodeString = RtlOemStringToUnicodeString;
+
+    /* FIXME: Old, deprecated way */
+    bIsFileApiAnsi = FALSE;
+}
+
+
+/*
+ * @implemented
+ */
+VOID
+STDCALL
+SetFileApisToANSI(VOID)
+{
+    /* Set the correct Base Api */
+    Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
+
+    /* FIXME: Old, deprecated way */
+    bIsFileApiAnsi = TRUE;
 }
 
-WINBOOL STDCALL FlushFileBuffers(HANDLE hFile)
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+AreFileApisANSI(VOID)
+{
+   return bIsFileApiAnsi;
+}
+
+
+/*
+ * @implemented
+ */
+HFILE STDCALL
+OpenFile(LPCSTR lpFileName,
+        LPOFSTRUCT lpReOpenBuff,
+        UINT uStyle)
+{
+       OBJECT_ATTRIBUTES ObjectAttributes;
+       IO_STATUS_BLOCK IoStatusBlock;
+       UNICODE_STRING FileNameString;
+       UNICODE_STRING FileNameU;
+       ANSI_STRING FileName;
+       WCHAR PathNameW[MAX_PATH];
+       HANDLE FileHandle = NULL;
+       NTSTATUS errCode;
+       PWCHAR FilePart;
+       ULONG Len;
+
+       DPRINT("OpenFile('%s', lpReOpenBuff %x, uStyle %x)\n", lpFileName, lpReOpenBuff, uStyle);
+
+       if (lpReOpenBuff == NULL)
+       {
+               return FALSE;
+       }
+
+       if ((uStyle & OF_CREATE) == OF_CREATE)
+       {
+               DWORD Sharing;
+               switch (uStyle & 0x70)
+               {
+                       case OF_SHARE_EXCLUSIVE: Sharing = 0; break;
+                       case OF_SHARE_DENY_WRITE: Sharing = FILE_SHARE_READ; break;
+                       case OF_SHARE_DENY_READ: Sharing = FILE_SHARE_WRITE; break;
+                       case OF_SHARE_DENY_NONE:
+                       case OF_SHARE_COMPAT:
+                       default:
+                               Sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
+               }
+               return (HFILE) CreateFileA (lpFileName,
+                                           GENERIC_READ | GENERIC_WRITE,
+                                           Sharing,
+                                           NULL,
+                                           CREATE_ALWAYS,
+                                           FILE_ATTRIBUTE_NORMAL,
+                                           0);
+       }
+
+       RtlInitAnsiString (&FileName, (LPSTR)lpFileName);
+
+       /* convert ansi (or oem) string to unicode */
+       if (bIsFileApiAnsi)
+               RtlAnsiStringToUnicodeString (&FileNameU, &FileName, TRUE);
+       else
+               RtlOemStringToUnicodeString (&FileNameU, &FileName, TRUE);
+
+       Len = SearchPathW (NULL,
+                          FileNameU.Buffer,
+                          NULL,
+                          OFS_MAXPATHNAME,
+                          PathNameW,
+                          &FilePart);
+
+       RtlFreeUnicodeString(&FileNameU);
+
+       if (Len == 0 || Len > OFS_MAXPATHNAME)
+       {
+               return (HFILE)INVALID_HANDLE_VALUE;
+       }
+
+       FileName.Buffer = lpReOpenBuff->szPathName;
+       FileName.Length = 0;
+       FileName.MaximumLength = OFS_MAXPATHNAME;
+
+       RtlInitUnicodeString(&FileNameU, PathNameW);
+
+       /* convert unicode string to ansi (or oem) */
+       if (bIsFileApiAnsi)
+               RtlUnicodeStringToAnsiString (&FileName, &FileNameU, FALSE);
+       else
+               RtlUnicodeStringToOemString (&FileName, &FileNameU, FALSE);
+
+       if (!RtlDosPathNameToNtPathName_U ((LPWSTR)PathNameW,
+                                          &FileNameString,
+                                          NULL,
+                                          NULL))
+       {
+               return (HFILE)INVALID_HANDLE_VALUE;
+       }
+
+       // FILE_SHARE_READ
+       // FILE_NO_INTERMEDIATE_BUFFERING
+
+       if ((uStyle & OF_PARSE) == OF_PARSE)
+       {
+               RtlFreeUnicodeString(&FileNameString);
+               return (HFILE)NULL;
+       }
+
+       ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
+       ObjectAttributes.RootDirectory = NULL;
+       ObjectAttributes.ObjectName = &FileNameString;
+       ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT;
+       ObjectAttributes.SecurityDescriptor = NULL;
+       ObjectAttributes.SecurityQualityOfService = NULL;
+
+       errCode = NtOpenFile (&FileHandle,
+                             GENERIC_READ|SYNCHRONIZE,
+                             &ObjectAttributes,
+                             &IoStatusBlock,
+                             FILE_SHARE_READ,
+                             FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT);
+
+       RtlFreeUnicodeString(&FileNameString);
+
+       lpReOpenBuff->nErrCode = RtlNtStatusToDosError(errCode);
+
+       if (!NT_SUCCESS(errCode))
+       {
+               SetLastErrorByStatus (errCode);
+               return (HFILE)INVALID_HANDLE_VALUE;
+       }
+
+       return (HFILE)FileHandle;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+FlushFileBuffers(HANDLE hFile)
 {
    NTSTATUS errCode;
    IO_STATUS_BLOCK IoStatusBlock;
-   
+
+   if (IsConsoleHandle(hFile))
+   {
+      return FALSE;
+   }
+
    errCode = NtFlushBuffersFile(hFile,
                                &IoStatusBlock);
-   if (!NT_SUCCESS(errCode)) 
+   if (!NT_SUCCESS(errCode))
      {
-       SetLastError(RtlNtStatusToDosError(errCode));
+       SetLastErrorByStatus(errCode);
        return(FALSE);
      }
    return(TRUE);
 }
 
 
-DWORD STDCALL SetFilePointer(HANDLE hFile,
-                            LONG lDistanceToMove,
-                            PLONG lpDistanceToMoveHigh,
-                            DWORD dwMoveMethod)
+/*
+ * @implemented
+ */
+DWORD STDCALL
+SetFilePointer(HANDLE hFile,
+              LONG lDistanceToMove,
+              PLONG lpDistanceToMoveHigh,
+              DWORD dwMoveMethod)
 {
    FILE_POSITION_INFORMATION FilePosition;
-   FILE_END_OF_FILE_INFORMATION FileEndOfFile;
+   FILE_STANDARD_INFORMATION FileStandard;
    NTSTATUS errCode;
    IO_STATUS_BLOCK IoStatusBlock;
-   
+   LARGE_INTEGER Distance;
+
    DPRINT("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
          hFile,lDistanceToMove,dwMoveMethod);
-   
-   if (dwMoveMethod == FILE_CURRENT) 
-     {
+
+   if(IsConsoleHandle(hFile))
+   {
+     SetLastError(ERROR_INVALID_HANDLE);
+     return -1;
+   }
+
+   Distance.u.LowPart = lDistanceToMove;
+   if (lpDistanceToMoveHigh)
+   {
+      Distance.u.HighPart = *lpDistanceToMoveHigh;
+   }
+   else if (lDistanceToMove >= 0)
+   {
+      Distance.u.HighPart = 0;
+   }
+   else
+   {
+      Distance.u.HighPart = -1;
+   }
+
+   switch(dwMoveMethod)
+   {
+     case FILE_CURRENT:
        NtQueryInformationFile(hFile,
                               &IoStatusBlock,
-                              &FilePosition, 
+                              &FilePosition,
                               sizeof(FILE_POSITION_INFORMATION),
                               FilePositionInformation);
-       SET_LARGE_INTEGER_LOW_PART(FilePosition.CurrentByteOffset,
-                                  GET_LARGE_INTEGER_LOW_PART(FilePosition.CurrentByteOffset) + 
-                                  lDistanceToMove);
-       if (lpDistanceToMoveHigh != NULL)
-         {
-            SET_LARGE_INTEGER_HIGH_PART(FilePosition.CurrentByteOffset,
-                                        GET_LARGE_INTEGER_HIGH_PART(FilePosition.CurrentByteOffset) +
-                                        *lpDistanceToMoveHigh);
-         }
-     }
-   else if (dwMoveMethod == FILE_END) 
+       FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart;
+       break;
+     case FILE_END:
+       NtQueryInformationFile(hFile,
+                               &IoStatusBlock,
+                               &FileStandard,
+                               sizeof(FILE_STANDARD_INFORMATION),
+                               FileStandardInformation);
+        FilePosition.CurrentByteOffset.QuadPart =
+                  FileStandard.EndOfFile.QuadPart + Distance.QuadPart;
+       break;
+     case FILE_BEGIN:
+        FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart;
+       break;
+     default:
+        SetLastError(ERROR_INVALID_PARAMETER);
+       return -1;
+   }
+
+   if(FilePosition.CurrentByteOffset.QuadPart < 0)
+   {
+     SetLastError(ERROR_NEGATIVE_SEEK);
+     return -1;
+   }
+
+   errCode = NtSetInformationFile(hFile,
+                                 &IoStatusBlock,
+                                 &FilePosition,
+                                 sizeof(FILE_POSITION_INFORMATION),
+                                 FilePositionInformation);
+   if (!NT_SUCCESS(errCode))
      {
-       NtQueryInformationFile(hFile,&IoStatusBlock,&FileEndOfFile, sizeof(FILE_END_OF_FILE_INFORMATION),FileEndOfFileInformation);
-       SET_LARGE_INTEGER_LOW_PART(FilePosition.CurrentByteOffset,
-                                  GET_LARGE_INTEGER_LOW_PART(FileEndOfFile.EndOfFile) - 
-                                  lDistanceToMove);
-       if ( lpDistanceToMoveHigh != NULL ) 
-         {
-            SET_LARGE_INTEGER_HIGH_PART(FilePosition.CurrentByteOffset,
-                                        GET_LARGE_INTEGER_HIGH_PART(FileEndOfFile.EndOfFile) - 
-                                        *lpDistanceToMoveHigh);
-         } 
-       else 
-         {
-            SET_LARGE_INTEGER_HIGH_PART(FilePosition.CurrentByteOffset,
-                                        GET_LARGE_INTEGER_HIGH_PART(FileEndOfFile.EndOfFile));
-         }
+       SetLastErrorByStatus(errCode);
+       return -1;
      }
-   else if ( dwMoveMethod == FILE_BEGIN ) 
+
+   if (lpDistanceToMoveHigh != NULL)
      {
-       SET_LARGE_INTEGER_LOW_PART(FilePosition.CurrentByteOffset,
-                                  lDistanceToMove);
-       if ( lpDistanceToMoveHigh != NULL ) 
-         {
-            SET_LARGE_INTEGER_HIGH_PART(FilePosition.CurrentByteOffset,
-                                        *lpDistanceToMoveHigh);
-         } 
-       else 
-         {
-            SET_LARGE_INTEGER_HIGH_PART(FilePosition.CurrentByteOffset,
-                                        0);
-         }
+        *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
      }
-   
+   return FilePosition.CurrentByteOffset.u.LowPart;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+SetFilePointerEx(HANDLE hFile,
+                LARGE_INTEGER liDistanceToMove,
+                PLARGE_INTEGER lpNewFilePointer,
+                DWORD dwMoveMethod)
+{
+   FILE_POSITION_INFORMATION FilePosition;
+   FILE_STANDARD_INFORMATION FileStandard;
+   NTSTATUS errCode;
+   IO_STATUS_BLOCK IoStatusBlock;
+
+   if(IsConsoleHandle(hFile))
+   {
+     SetLastError(ERROR_INVALID_HANDLE);
+     return FALSE;
+   }
+
+   switch(dwMoveMethod)
+   {
+     case FILE_CURRENT:
+       NtQueryInformationFile(hFile,
+                              &IoStatusBlock,
+                              &FilePosition,
+                              sizeof(FILE_POSITION_INFORMATION),
+                              FilePositionInformation);
+       FilePosition.CurrentByteOffset.QuadPart += liDistanceToMove.QuadPart;
+       break;
+     case FILE_END:
+       NtQueryInformationFile(hFile,
+                               &IoStatusBlock,
+                               &FileStandard,
+                               sizeof(FILE_STANDARD_INFORMATION),
+                               FileStandardInformation);
+        FilePosition.CurrentByteOffset.QuadPart =
+                  FileStandard.EndOfFile.QuadPart + liDistanceToMove.QuadPart;
+       break;
+     case FILE_BEGIN:
+        FilePosition.CurrentByteOffset.QuadPart = liDistanceToMove.QuadPart;
+       break;
+     default:
+        SetLastError(ERROR_INVALID_PARAMETER);
+       return FALSE;
+   }
+
+   if(FilePosition.CurrentByteOffset.QuadPart < 0)
+   {
+     SetLastError(ERROR_NEGATIVE_SEEK);
+     return FALSE;
+   }
+
    errCode = NtSetInformationFile(hFile,
                                  &IoStatusBlock,
-                                 &FilePosition, 
+                                 &FilePosition,
                                  sizeof(FILE_POSITION_INFORMATION),
                                  FilePositionInformation);
-   if (!NT_SUCCESS(errCode)) 
+   if (!NT_SUCCESS(errCode))
      {
-       SetLastError(RtlNtStatusToDosError(errCode));
-       return -1;
+       SetLastErrorByStatus(errCode);
+       return FALSE;
      }
-   
-   if (lpDistanceToMoveHigh != NULL) 
+
+   if (lpNewFilePointer)
      {
-       *lpDistanceToMoveHigh = GET_LARGE_INTEGER_HIGH_PART(
-                                                           FilePosition.CurrentByteOffset);
+       *lpNewFilePointer = FilePosition.CurrentByteOffset;
      }
-   return GET_LARGE_INTEGER_LOW_PART(FilePosition.CurrentByteOffset);
+   return TRUE;
 }
 
-DWORD STDCALL GetFileType(HANDLE hFile)
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetFileType(HANDLE hFile)
 {
-       return FILE_TYPE_UNKNOWN;
+  FILE_FS_DEVICE_INFORMATION DeviceInfo;
+  IO_STATUS_BLOCK StatusBlock;
+  NTSTATUS Status;
+
+  /* Get real handle */
+  switch ((ULONG)hFile)
+    {
+      case STD_INPUT_HANDLE:
+       hFile = NtCurrentPeb()->ProcessParameters->StandardInput;
+       break;
+
+      case STD_OUTPUT_HANDLE:
+       hFile = NtCurrentPeb()->ProcessParameters->StandardOutput;
+       break;
+
+      case STD_ERROR_HANDLE:
+       hFile = NtCurrentPeb()->ProcessParameters->StandardError;
+       break;
+    }
+
+  /* Check for console handle */
+  if (IsConsoleHandle(hFile))
+    {
+      if (VerifyConsoleIoHandle(hFile))
+       return FILE_TYPE_CHAR;
+    }
+
+  Status = NtQueryVolumeInformationFile(hFile,
+                                       &StatusBlock,
+                                       &DeviceInfo,
+                                       sizeof(FILE_FS_DEVICE_INFORMATION),
+                                       FileFsDeviceInformation);
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return FILE_TYPE_UNKNOWN;
+    }
+
+  switch (DeviceInfo.DeviceType)
+    {
+      case FILE_DEVICE_CD_ROM:
+      case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
+      case FILE_DEVICE_CONTROLLER:
+      case FILE_DEVICE_DATALINK:
+      case FILE_DEVICE_DFS:
+      case FILE_DEVICE_DISK:
+      case FILE_DEVICE_DISK_FILE_SYSTEM:
+      case FILE_DEVICE_VIRTUAL_DISK:
+       return FILE_TYPE_DISK;
+
+      case FILE_DEVICE_KEYBOARD:
+      case FILE_DEVICE_MOUSE:
+      case FILE_DEVICE_NULL:
+      case FILE_DEVICE_PARALLEL_PORT:
+      case FILE_DEVICE_PRINTER:
+      case FILE_DEVICE_SERIAL_PORT:
+      case FILE_DEVICE_SCREEN:
+      case FILE_DEVICE_SOUND:
+      case FILE_DEVICE_MODEM:
+       return FILE_TYPE_CHAR;
+
+      case FILE_DEVICE_NAMED_PIPE:
+       return FILE_TYPE_PIPE;
+    }
+
+  return FILE_TYPE_UNKNOWN;
 }
 
 
-DWORD STDCALL GetFileSize(HANDLE hFile,        
-                         LPDWORD lpFileSizeHigh)
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetFileSize(HANDLE hFile,
+           LPDWORD lpFileSizeHigh)
 {
    NTSTATUS errCode;
    FILE_STANDARD_INFORMATION FileStandard;
    IO_STATUS_BLOCK IoStatusBlock;
-   
 
    errCode = NtQueryInformationFile(hFile,
                                    &IoStatusBlock,
-                                   &FileStandard, 
+                                   &FileStandard,
                                    sizeof(FILE_STANDARD_INFORMATION),
                                    FileStandardInformation);
-   if (!NT_SUCCESS(errCode)) 
+   if (!NT_SUCCESS(errCode))
      {
-       CloseHandle(hFile);
-       SetLastError(RtlNtStatusToDosError(errCode));
-       if ( lpFileSizeHigh == NULL ) 
+       SetLastErrorByStatus(errCode);
+       if ( lpFileSizeHigh == NULL )
          {
             return -1;
          }
@@ -247,370 +633,991 @@ DWORD STDCALL GetFileSize(HANDLE hFile,
          }
      }
    if ( lpFileSizeHigh != NULL )
-     *lpFileSizeHigh = GET_LARGE_INTEGER_HIGH_PART(FileStandard.AllocationSize);
+     *lpFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
 
-   CloseHandle(hFile);
-   return GET_LARGE_INTEGER_LOW_PART(FileStandard.AllocationSize);     
+   return FileStandard.EndOfFile.u.LowPart;
 }
 
-DWORD STDCALL GetCompressedFileSizeA(LPCSTR lpFileName,
-                                    LPDWORD lpFileSizeHigh)
+
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+GetFileSizeEx(
+    HANDLE hFile,
+    PLARGE_INTEGER lpFileSize
+    )
 {
-   WCHAR FileNameW[MAX_PATH];
-   ULONG i;
-   
-   i = 0;
-   while ((*lpFileName)!=0 && i < MAX_PATH)
+   NTSTATUS errCode;
+   FILE_STANDARD_INFORMATION FileStandard;
+   IO_STATUS_BLOCK IoStatusBlock;
+
+   errCode = NtQueryInformationFile(hFile,
+                                   &IoStatusBlock,
+                                   &FileStandard,
+                                   sizeof(FILE_STANDARD_INFORMATION),
+                                   FileStandardInformation);
+   if (!NT_SUCCESS(errCode))
      {
-       FileNameW[i] = *lpFileName;
-       lpFileName++;
-       i++;
+       SetLastErrorByStatus(errCode);
+       return FALSE;
      }
-   FileNameW[i] = 0;
-   
-   return GetCompressedFileSizeW(FileNameW,lpFileSizeHigh);
+   if (lpFileSize)
+     *lpFileSize = FileStandard.EndOfFile;
+
+   return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetCompressedFileSizeA(LPCSTR lpFileName,
+                      LPDWORD lpFileSizeHigh)
+{
+   PWCHAR FileNameW;
+
+   if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
+      return INVALID_FILE_SIZE;
+
+   return GetCompressedFileSizeW(FileNameW, lpFileSizeHigh);
 }
 
-DWORD STDCALL GetCompressedFileSizeW(LPCWSTR lpFileName,
-                                    LPDWORD lpFileSizeHigh)
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetCompressedFileSizeW(LPCWSTR lpFileName,
+                      LPDWORD lpFileSizeHigh)
 {
    FILE_COMPRESSION_INFORMATION FileCompression;
    NTSTATUS errCode;
    IO_STATUS_BLOCK IoStatusBlock;
    HANDLE hFile;
-   
-   hFile = CreateFileW(lpFileName,     
-                      GENERIC_READ,    
-                      FILE_SHARE_READ, 
-                      NULL,    
-                      OPEN_EXISTING,   
-                      FILE_ATTRIBUTE_NORMAL,   
+
+   hFile = CreateFileW(lpFileName,
+                      GENERIC_READ,
+                      FILE_SHARE_READ,
+                      NULL,
+                      OPEN_EXISTING,
+                      FILE_ATTRIBUTE_NORMAL,
                       NULL);
 
+   if (hFile == INVALID_HANDLE_VALUE)
+      return INVALID_FILE_SIZE;
+
    errCode = NtQueryInformationFile(hFile,
                                    &IoStatusBlock,
-                                   &FileCompression, 
+                                   &FileCompression,
                                    sizeof(FILE_COMPRESSION_INFORMATION),
                                    FileCompressionInformation);
-   if (!NT_SUCCESS(errCode)) 
+
+   CloseHandle(hFile);
+
+   if (!NT_SUCCESS(errCode))
      {
-       CloseHandle(hFile);
-       SetLastError(RtlNtStatusToDosError(errCode));
-       return 0;
+       SetLastErrorByStatus(errCode);
+       return INVALID_FILE_SIZE;
      }
-   CloseHandle(hFile);
-   return 0;
-}
 
+   if(lpFileSizeHigh)
+    *lpFileSizeHigh = FileCompression.CompressedFileSize.u.HighPart;
+
+   SetLastError(NO_ERROR);
+   return FileCompression.CompressedFileSize.u.LowPart;
+}
 
 
-WINBOOL STDCALL GetFileInformationByHandle(HANDLE hFile,
-                              LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetFileInformationByHandle(HANDLE hFile,
+                          LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
 {
-   FILE_DIRECTORY_INFORMATION FileDirectory;
+   struct
+   {
+        FILE_FS_VOLUME_INFORMATION FileFsVolume;
+        WCHAR Name[255];
+   }
+   FileFsVolume;
+
+   FILE_BASIC_INFORMATION FileBasic;
    FILE_INTERNAL_INFORMATION FileInternal;
-   FILE_FS_VOLUME_INFORMATION FileFsVolume;
    FILE_STANDARD_INFORMATION FileStandard;
    NTSTATUS errCode;
    IO_STATUS_BLOCK IoStatusBlock;
-   
+
+   if(IsConsoleHandle(hFile))
+   {
+     SetLastError(ERROR_INVALID_HANDLE);
+     return FALSE;
+   }
+
    errCode = NtQueryInformationFile(hFile,
                                    &IoStatusBlock,
-                                   &FileDirectory, 
-                                   sizeof(FILE_DIRECTORY_INFORMATION),
-                                   FileDirectoryInformation);
-   if (!NT_SUCCESS(errCode)) 
+                                   &FileBasic,
+                                   sizeof(FILE_BASIC_INFORMATION),
+                                   FileBasicInformation);
+   if (!NT_SUCCESS(errCode))
      {
-       SetLastError(RtlNtStatusToDosError(errCode));
+       SetLastErrorByStatus(errCode);
        return FALSE;
      }
-   lpFileInformation->dwFileAttributes = (DWORD)FileDirectory.FileAttributes;
-   memcpy(&lpFileInformation->ftCreationTime,&FileDirectory.CreationTime,sizeof(LARGE_INTEGER));
-   memcpy(&lpFileInformation->ftLastAccessTime,&FileDirectory.LastAccessTime,sizeof(LARGE_INTEGER));
-   memcpy(&lpFileInformation->ftLastWriteTime, &FileDirectory.LastWriteTime,sizeof(LARGE_INTEGER)); 
-   lpFileInformation->nFileSizeHigh = GET_LARGE_INTEGER_HIGH_PART(FileDirectory.AllocationSize); 
-   lpFileInformation->nFileSizeLow = GET_LARGE_INTEGER_LOW_PART(FileDirectory.AllocationSize); 
-   
+
+   lpFileInformation->dwFileAttributes = (DWORD)FileBasic.FileAttributes;
+
+   lpFileInformation->ftCreationTime.dwHighDateTime = FileBasic.CreationTime.u.HighPart;
+   lpFileInformation->ftCreationTime.dwLowDateTime = FileBasic.CreationTime.u.LowPart;
+
+   lpFileInformation->ftLastAccessTime.dwHighDateTime = FileBasic.LastAccessTime.u.HighPart;
+   lpFileInformation->ftLastAccessTime.dwLowDateTime = FileBasic.LastAccessTime.u.LowPart;
+
+   lpFileInformation->ftLastWriteTime.dwHighDateTime = FileBasic.LastWriteTime.u.HighPart;
+   lpFileInformation->ftLastWriteTime.dwLowDateTime = FileBasic.LastWriteTime.u.LowPart;
+
    errCode = NtQueryInformationFile(hFile,
                                    &IoStatusBlock,
-                                   &FileInternal, 
+                                   &FileInternal,
                                    sizeof(FILE_INTERNAL_INFORMATION),
                                    FileInternalInformation);
-   if (!NT_SUCCESS(errCode)) 
+   if (!NT_SUCCESS(errCode))
      {
-       SetLastError(RtlNtStatusToDosError(errCode));
+       SetLastErrorByStatus(errCode);
        return FALSE;
      }
-   lpFileInformation->nFileIndexHigh = GET_LARGE_INTEGER_HIGH_PART(FileInternal.IndexNumber);
-   lpFileInformation->nFileIndexLow = GET_LARGE_INTEGER_LOW_PART(FileInternal.IndexNumber);
-   
+
+   lpFileInformation->nFileIndexHigh = FileInternal.IndexNumber.u.HighPart;
+   lpFileInformation->nFileIndexLow = FileInternal.IndexNumber.u.LowPart;
+
    errCode = NtQueryVolumeInformationFile(hFile,
                                          &IoStatusBlock,
-                                         &FileFsVolume, 
-                                         sizeof(FILE_FS_VOLUME_INFORMATION),
+                                         &FileFsVolume,
+                                         sizeof(FileFsVolume),
                                          FileFsVolumeInformation);
-   if (!NT_SUCCESS(errCode)) 
+   if (!NT_SUCCESS(errCode))
      {
-       SetLastError(RtlNtStatusToDosError(errCode));
+       SetLastErrorByStatus(errCode);
        return FALSE;
      }
-   lpFileInformation->dwVolumeSerialNumber = FileFsVolume.VolumeSerialNumber;
-   
+
+   lpFileInformation->dwVolumeSerialNumber = FileFsVolume.FileFsVolume.VolumeSerialNumber;
+
    errCode = NtQueryInformationFile(hFile,
                                    &IoStatusBlock,
-                                   &FileStandard, 
+                                   &FileStandard,
                                    sizeof(FILE_STANDARD_INFORMATION),
                                    FileStandardInformation);
    if (!NT_SUCCESS(errCode))
      {
-       CloseHandle(hFile);
-       SetLastError(RtlNtStatusToDosError(errCode));
+       SetLastErrorByStatus(errCode);
        return FALSE;
      }
+
    lpFileInformation->nNumberOfLinks = FileStandard.NumberOfLinks;
-   CloseHandle(hFile);
-   return TRUE;        
+   lpFileInformation->nFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
+   lpFileInformation->nFileSizeLow = FileStandard.EndOfFile.u.LowPart;
+
+   return TRUE;
 }
 
 
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetFileAttributesExW(LPCWSTR lpFileName,
+                    GET_FILEEX_INFO_LEVELS fInfoLevelId,
+                    LPVOID lpFileInformation)
+{
+  FILE_NETWORK_OPEN_INFORMATION FileInformation;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  IO_STATUS_BLOCK IoStatusBlock;
+  UNICODE_STRING FileName;
+  HANDLE FileHandle;
+  NTSTATUS Status;
+  WIN32_FILE_ATTRIBUTE_DATA* FileAttributeData;
 
+  DPRINT("GetFileAttributesExW(%S) called\n", lpFileName);
 
 
+  if (fInfoLevelId != GetFileExInfoStandard || lpFileInformation == NULL)
+  {
+     SetLastError(ERROR_INVALID_PARAMETER);
+     return FALSE;
+  }
 
-DWORD STDCALL GetFileAttributesA(LPCSTR lpFileName)
+  /* Validate and translate the filename */
+  if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFileName,
+                                    &FileName,
+                                    NULL,
+                                    NULL))
+    {
+      DPRINT1 ("Invalid path\n");
+      SetLastError (ERROR_BAD_PATHNAME);
+      return FALSE;
+    }
+
+  /* build the object attributes */
+  InitializeObjectAttributes (&ObjectAttributes,
+                             &FileName,
+                             OBJ_CASE_INSENSITIVE,
+                             NULL,
+                             NULL);
+
+  /* Open the file */
+  Status = NtOpenFile (&FileHandle,
+                      SYNCHRONIZE | FILE_READ_ATTRIBUTES,
+                      &ObjectAttributes,
+                      &IoStatusBlock,
+                      FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                      FILE_SYNCHRONOUS_IO_NONALERT);
+  RtlFreeUnicodeString (&FileName);
+  if (!NT_SUCCESS (Status))
+    {
+      DPRINT ("NtOpenFile() failed  %x (Status %lx)\n", &ObjectAttributes, Status);
+      SetLastErrorByStatus (Status);
+      return FALSE;
+    }
+
+  /* Get file attributes */
+  Status = NtQueryInformationFile (FileHandle,
+                                  &IoStatusBlock,
+                                  &FileInformation,
+                                  sizeof(FILE_NETWORK_OPEN_INFORMATION),
+                                  FileNetworkOpenInformation);
+  NtClose (FileHandle);
+
+  if (!NT_SUCCESS (Status))
+    {
+      DPRINT1 ("NtQueryInformationFile() failed (Status %lx)\n", Status);
+      SetLastErrorByStatus (Status);
+      return FALSE;
+    }
+
+  FileAttributeData = (WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation;
+  FileAttributeData->dwFileAttributes = FileInformation.FileAttributes;
+  FileAttributeData->ftCreationTime.dwLowDateTime = FileInformation.CreationTime.u.LowPart;
+  FileAttributeData->ftCreationTime.dwHighDateTime = FileInformation.CreationTime.u.HighPart;
+  FileAttributeData->ftLastAccessTime.dwLowDateTime = FileInformation.LastAccessTime.u.LowPart;
+  FileAttributeData->ftLastAccessTime.dwHighDateTime = FileInformation.LastAccessTime.u.HighPart;
+  FileAttributeData->ftLastWriteTime.dwLowDateTime = FileInformation.LastWriteTime.u.LowPart;
+  FileAttributeData->ftLastWriteTime.dwHighDateTime = FileInformation.LastWriteTime.u.HighPart;
+  FileAttributeData->nFileSizeLow = FileInformation.EndOfFile.u.LowPart;
+  FileAttributeData->nFileSizeHigh = FileInformation.EndOfFile.u.HighPart;
+
+  return TRUE;
+}
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetFileAttributesExA(LPCSTR lpFileName,
+                    GET_FILEEX_INFO_LEVELS fInfoLevelId,
+                    LPVOID lpFileInformation)
 {
-   ULONG i;
-   WCHAR FileNameW[MAX_PATH];
-   
-   i = 0;
-   while ((*lpFileName)!=0 && i < MAX_PATH)
-     {
-       FileNameW[i] = *lpFileName;
-       lpFileName++;
-       i++;
-     }
-   FileNameW[i] = 0;
-   return GetFileAttributesW(FileNameW);
+   PWCHAR FileNameW;
+
+   if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
+      return FALSE;
+
+   return GetFileAttributesExW(FileNameW, fInfoLevelId, lpFileInformation);
 }
 
 
-DWORD STDCALL GetFileAttributesW(LPCWSTR lpFileName)
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetFileAttributesA(LPCSTR lpFileName)
 {
-   IO_STATUS_BLOCK IoStatusBlock;
-   FILE_BASIC_INFORMATION FileBasic;
-   HANDLE hFile;
-   NTSTATUS errCode;
+   WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
+   PWSTR FileNameW;
+       BOOL ret;
 
-   hFile = CreateFileW(lpFileName,     
-                      GENERIC_READ,    
-                      FILE_SHARE_READ, 
-                      NULL,    
-                      OPEN_EXISTING,   
-                      FILE_ATTRIBUTE_NORMAL,   
-                      NULL);
-   
-       
-   errCode = NtQueryInformationFile(hFile,
-                                   &IoStatusBlock,
-                                   &FileBasic, 
-                                   sizeof(FILE_BASIC_INFORMATION),
-                                   FileBasicInformation);
-   if (!NT_SUCCESS(errCode)) 
-     {
-       CloseHandle(hFile);
-       SetLastError(RtlNtStatusToDosError(errCode));
-        return 0;
-     }
-   CloseHandle(hFile);
-   return (DWORD)FileBasic.FileAttributes;  
+   if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
+      return INVALID_FILE_ATTRIBUTES;
+
+   ret = GetFileAttributesExW(FileNameW, GetFileExInfoStandard, &FileAttributeData);
+
+   return ret ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
 }
 
-WINBOOL STDCALL SetFileAttributesA(LPCSTR lpFileName,
-                                  DWORD dwFileAttributes)
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetFileAttributesW(LPCWSTR lpFileName)
 {
-       ULONG i;
-       WCHAR FileNameW[MAX_PATH];
-       i = 0;
-       while ((*lpFileName)!=0 && i < MAX_PATH)
-       {
-               FileNameW[i] = *lpFileName;
-               lpFileName++;
-               i++;
-       }
-       FileNameW[i] = 0;
-       return SetFileAttributesW(FileNameW, dwFileAttributes);
+  WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
+  BOOL Result;
+
+  DPRINT ("GetFileAttributeW(%S) called\n", lpFileName);
+
+  Result = GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &FileAttributeData);
+
+  return Result ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
 }
 
 
-WINBOOL STDCALL SetFileAttributesW(LPCWSTR lpFileName,
-                                  DWORD dwFileAttributes)
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetFileAttributesByHandle(IN HANDLE hFile,
+                          OUT LPDWORD dwFileAttributes,
+                          IN DWORD dwFlags)
 {
-   IO_STATUS_BLOCK IoStatusBlock;
-   FILE_BASIC_INFORMATION FileBasic;
-   HANDLE hFile;
-   NTSTATUS errCode;
-   
-   hFile = CreateFileW(lpFileName,     
-                      FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
-                      FILE_SHARE_READ, 
-                      NULL,    
-                      OPEN_EXISTING,   
-                      FILE_ATTRIBUTE_NORMAL,   
-                      NULL);
+    FILE_BASIC_INFORMATION FileBasic;
+    IO_STATUS_BLOCK IoStatusBlock;
+    NTSTATUS Status;
+    
+    UNREFERENCED_PARAMETER(dwFlags);
+    
+    if (IsConsoleHandle(hFile))
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+    
+    Status = NtQueryInformationFile(hFile,
+                                    &IoStatusBlock,
+                                    &FileBasic,
+                                    sizeof(FileBasic),
+                                    FileBasicInformation);
+    if (NT_SUCCESS(Status))
+    {
+        *dwFileAttributes = FileBasic.FileAttributes;
+        return TRUE;
+    }
+    
+    SetLastErrorByStatus(Status);
+    return FALSE;
+}
 
-   errCode = NtQueryInformationFile(hFile,
-                                   &IoStatusBlock,
-                                   &FileBasic, 
-                                   sizeof(FILE_BASIC_INFORMATION),
-                                   FileBasicInformation);
-   if (!NT_SUCCESS(errCode)) 
-     {
-       CloseHandle(hFile);
-       SetLastError(RtlNtStatusToDosError(errCode));
-       return FALSE;
-     }
-   FileBasic.FileAttributes = dwFileAttributes;
-   errCode = NtSetInformationFile(hFile,
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SetFileAttributesByHandle(IN HANDLE hFile,
+                          IN DWORD dwFileAttributes,
+                          IN DWORD dwFlags)
+{
+    FILE_BASIC_INFORMATION FileBasic;
+    IO_STATUS_BLOCK IoStatusBlock;
+    NTSTATUS Status;
+
+    UNREFERENCED_PARAMETER(dwFlags);
+    
+    if (IsConsoleHandle(hFile))
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
+    Status = NtQueryInformationFile(hFile,
+                                    &IoStatusBlock,
+                                    &FileBasic,
+                                    sizeof(FileBasic),
+                                    FileBasicInformation);
+    if (NT_SUCCESS(Status))
+    {
+        FileBasic.FileAttributes = dwFileAttributes;
+        
+        Status = NtSetInformationFile(hFile,
+                                      &IoStatusBlock,
+                                      &FileBasic,
+                                      sizeof(FileBasic),
+                                      FileBasicInformation);
+    }
+
+    if (!NT_SUCCESS(Status))
+    {
+        SetLastErrorByStatus(Status);
+        return FALSE;
+    }
+    
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SetFileAttributesA(
+   LPCSTR lpFileName,
+       DWORD dwFileAttributes)
+{
+   PWCHAR FileNameW;
+
+   if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
+      return FALSE;
+
+   return SetFileAttributesW(FileNameW, dwFileAttributes);
+}
+
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SetFileAttributesW(LPCWSTR lpFileName,
+                  DWORD dwFileAttributes)
+{
+  FILE_BASIC_INFORMATION FileInformation;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  IO_STATUS_BLOCK IoStatusBlock;
+  UNICODE_STRING FileName;
+  HANDLE FileHandle;
+  NTSTATUS Status;
+
+  DPRINT ("SetFileAttributeW(%S, 0x%lx) called\n", lpFileName, dwFileAttributes);
+
+  /* Validate and translate the filename */
+  if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFileName,
+                                    &FileName,
+                                    NULL,
+                                    NULL))
+    {
+      DPRINT ("Invalid path\n");
+      SetLastError (ERROR_BAD_PATHNAME);
+      return FALSE;
+    }
+  DPRINT ("FileName: \'%wZ\'\n", &FileName);
+
+  /* build the object attributes */
+  InitializeObjectAttributes (&ObjectAttributes,
+                             &FileName,
+                             OBJ_CASE_INSENSITIVE,
+                             NULL,
+                             NULL);
+
+  /* Open the file */
+  Status = NtOpenFile (&FileHandle,
+                      SYNCHRONIZE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
+                      &ObjectAttributes,
+                      &IoStatusBlock,
+                      FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                      FILE_SYNCHRONOUS_IO_NONALERT);
+  RtlFreeUnicodeString (&FileName);
+  if (!NT_SUCCESS (Status))
+    {
+      DPRINT ("NtOpenFile() failed (Status %lx)\n", Status);
+      SetLastErrorByStatus (Status);
+      return FALSE;
+    }
+
+  Status = NtQueryInformationFile(FileHandle,
                                  &IoStatusBlock,
-                                 &FileBasic, 
+                                 &FileInformation,
                                  sizeof(FILE_BASIC_INFORMATION),
                                  FileBasicInformation);
-   if (!NT_SUCCESS(errCode)) 
-     {
-       CloseHandle(hFile);
-       SetLastError(RtlNtStatusToDosError(errCode));
-       return FALSE;
-     }
-   CloseHandle(hFile);
-   return TRUE;                
-}
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT ("SetFileAttributes NtQueryInformationFile failed with status 0x%08x\n", Status);
+      NtClose (FileHandle);
+      SetLastErrorByStatus (Status);
+      return FALSE;
+    }
+
+  FileInformation.FileAttributes = dwFileAttributes;
+  Status = NtSetInformationFile(FileHandle,
+                               &IoStatusBlock,
+                               &FileInformation,
+                               sizeof(FILE_BASIC_INFORMATION),
+                               FileBasicInformation);
+  NtClose (FileHandle);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT ("SetFileAttributes NtSetInformationFile failed with status 0x%08x\n", Status);
+      SetLastErrorByStatus (Status);
+      return FALSE;
+    }
 
+  return TRUE;
+}
 
 
 
 
-UINT STDCALL GetTempFileNameA(LPCSTR lpPathName,
-                             LPCSTR lpPrefixString,
-                             UINT uUnique,
-                             LPSTR lpTempFileName)
+/***********************************************************************
+ *           GetTempFileNameA   (KERNEL32.@)
+ */
+UINT WINAPI GetTempFileNameA( LPCSTR path, LPCSTR prefix, UINT unique, LPSTR buffer)
 {
-   HANDLE hFile;
-   UINT unique = uUnique;
-  
-   if (lpPathName == NULL)
-     return 0;
-   
-   if (uUnique == 0)
-     uUnique = GetCurrentTime();
-   /*
-    * sprintf(lpTempFileName,"%s\\%c%.3s%4.4x%s",
-    *      lpPathName,'~',lpPrefixString,uUnique,".tmp");
-    */
-   if (unique)
-     return uUnique;
-   
-   while ((hFile = CreateFileA(lpTempFileName, GENERIC_WRITE, 0, NULL,
-                              CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
-                              0)) == INVALID_HANDLE_VALUE)
-     {
-       //              wsprintfA(lpTempFileName,"%s\\%c%.3s%4.4x%s",
-       //              lpPathName,'~',lpPrefixString,++uUnique,".tmp");
-     }
-   
-   CloseHandle((HANDLE)hFile);
-   return uUnique;
-}
+   WCHAR BufferW[MAX_PATH];
+   PWCHAR PathW;
+   WCHAR PrefixW[3+1];
+   UINT ret;
+
+   if (!(PathW = FilenameA2W(path, FALSE)))
+      return 0;
 
+   if (prefix)
+      FilenameA2W_N(PrefixW, 3+1, prefix, -1);
 
-UINT STDCALL GetTempFileNameW(LPCWSTR lpPathName,
-                             LPCWSTR lpPrefixString,
-                             UINT uUnique,
-                             LPWSTR lpTempFileName)
+   ret = GetTempFileNameW(PathW, prefix ? PrefixW : NULL, unique, BufferW);
+
+   if (ret)
+      FilenameW2A_N(buffer, MAX_PATH, BufferW, -1);
+
+   return ret;
+}
+
+/***********************************************************************
+ *           GetTempFileNameW   (KERNEL32.@)
+ */
+UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique, LPWSTR buffer )
 {
-   HANDLE hFile;
-   UINT unique = uUnique;
-   
-   if (lpPathName == NULL)
-     return 0;
-   
-   if (uUnique == 0)
-     uUnique = GetCurrentTime();
-   
-   //  swprintf(lpTempFileName,L"%s\\%c%.3s%4.4x%s",
-   //    lpPathName,'~',lpPrefixString,uUnique,L".tmp");
-   
-   if (unique)
-     return uUnique;
-  
-   while ((hFile = CreateFileW(lpTempFileName, GENERIC_WRITE, 0, NULL,
-                              CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
-                              0)) == INVALID_HANDLE_VALUE)
-     {
-       //              wsprintfW(lpTempFileName,L"%s\\%c%.3s%4.4x%s",
-       //              lpPathName,'~',lpPrefixString,++uUnique,L".tmp");
-     }
-   
-   CloseHandle((HANDLE)hFile);
-   return uUnique;
+    static const WCHAR formatW[] = L"%x.tmp";
+
+    int i;
+    LPWSTR p;
+
+    if ( !path || !prefix || !buffer )
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return 0;
+    }
+
+    wcscpy( buffer, path );
+    p = buffer + wcslen(buffer);
+
+    /* add a \, if there isn't one  */
+    if ((p == buffer) || (p[-1] != '\\')) *p++ = '\\';
+
+    for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
+
+    unique &= 0xffff;
+
+    if (unique) swprintf( p, formatW, unique );
+    else
+    {
+        /* get a "random" unique number and try to create the file */
+        HANDLE handle;
+        UINT num = GetTickCount() & 0xffff;
+
+        if (!num) num = 1;
+        unique = num;
+        do
+        {
+            swprintf( p, formatW, unique );
+            handle = CreateFileW( buffer, GENERIC_WRITE, 0, NULL,
+                                  CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
+            if (handle != INVALID_HANDLE_VALUE)
+            {  /* We created it */
+                DPRINT("created %S\n", buffer);
+                CloseHandle( handle );
+                break;
+            }
+            if (GetLastError() != ERROR_FILE_EXISTS &&
+                GetLastError() != ERROR_SHARING_VIOLATION)
+                break;  /* No need to go on */
+            if (!(++unique & 0xffff)) unique = 1;
+        } while (unique != num);
+    }
+
+    DPRINT("returning %S\n", buffer);
+    return unique;
 }
 
-WINBOOL STDCALL GetFileTime(HANDLE hFile,
-                           LPFILETIME lpCreationTime,
-                           LPFILETIME lpLastAccessTime,
-                           LPFILETIME lpLastWriteTime)
+
+
+
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetFileTime(HANDLE hFile,
+           LPFILETIME lpCreationTime,
+           LPFILETIME lpLastAccessTime,
+           LPFILETIME lpLastWriteTime)
 {
    IO_STATUS_BLOCK IoStatusBlock;
    FILE_BASIC_INFORMATION FileBasic;
-   NTSTATUS errCode;
-       
-   errCode = NtQueryInformationFile(hFile,
-                                   &IoStatusBlock,
-                                   &FileBasic, 
-                                   sizeof(FILE_BASIC_INFORMATION),
-                                   FileBasicInformation);
-   if (!NT_SUCCESS(errCode)) 
+   NTSTATUS Status;
+
+   if(IsConsoleHandle(hFile))
+   {
+     SetLastError(ERROR_INVALID_HANDLE);
+     return FALSE;
+   }
+
+   Status = NtQueryInformationFile(hFile,
+                                  &IoStatusBlock,
+                                  &FileBasic,
+                                  sizeof(FILE_BASIC_INFORMATION),
+                                  FileBasicInformation);
+   if (!NT_SUCCESS(Status))
      {
-       SetLastError(RtlNtStatusToDosError(errCode));
+       SetLastErrorByStatus(Status);
        return FALSE;
      }
-   memcpy(lpCreationTime,&FileBasic.CreationTime,sizeof(FILETIME));
-   memcpy(lpLastAccessTime,&FileBasic.LastAccessTime,sizeof(FILETIME));
-   memcpy(lpLastWriteTime,&FileBasic.LastWriteTime,sizeof(FILETIME));
+
+   if (lpCreationTime)
+     memcpy(lpCreationTime, &FileBasic.CreationTime, sizeof(FILETIME));
+   if (lpLastAccessTime)
+     memcpy(lpLastAccessTime, &FileBasic.LastAccessTime, sizeof(FILETIME));
+   if (lpLastWriteTime)
+     memcpy(lpLastWriteTime, &FileBasic.LastWriteTime, sizeof(FILETIME));
+
    return TRUE;
 }
 
-WINBOOL STDCALL SetFileTime(HANDLE hFile,
-                           CONST FILETIME *lpCreationTime,
-                           CONST FILETIME *lpLastAccessTime,
-                           CONST FILETIME *lpLastWriteTime)
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SetFileTime(HANDLE hFile,
+           CONST FILETIME *lpCreationTime,
+           CONST FILETIME *lpLastAccessTime,
+           CONST FILETIME *lpLastWriteTime)
 {
    FILE_BASIC_INFORMATION FileBasic;
    IO_STATUS_BLOCK IoStatusBlock;
-   NTSTATUS errCode;
-   
-   memcpy(&FileBasic.CreationTime,lpCreationTime,sizeof(FILETIME));
-   memcpy(&FileBasic.LastAccessTime,lpLastAccessTime,sizeof(FILETIME));
-   memcpy(&FileBasic.LastWriteTime,lpLastWriteTime,sizeof(FILETIME));
-   
-   // shoud i initialize changetime ???
-   
-   errCode = NtSetInformationFile(hFile,
-                                 &IoStatusBlock,
-                                 &FileBasic, 
-                                 sizeof(FILE_BASIC_INFORMATION),
-                                 FileBasicInformation);
-   if (!NT_SUCCESS(errCode)) 
+   NTSTATUS Status;
+
+   if(IsConsoleHandle(hFile))
+   {
+     SetLastError(ERROR_INVALID_HANDLE);
+     return FALSE;
+   }
+
+   Status = NtQueryInformationFile(hFile,
+                                  &IoStatusBlock,
+                                  &FileBasic,
+                                  sizeof(FILE_BASIC_INFORMATION),
+                                  FileBasicInformation);
+   if (!NT_SUCCESS(Status))
      {
-       SetLastError(RtlNtStatusToDosError(errCode));
+       SetLastErrorByStatus(Status);
        return FALSE;
      }
-   
+
+   if (lpCreationTime)
+     memcpy(&FileBasic.CreationTime, lpCreationTime, sizeof(FILETIME));
+   if (lpLastAccessTime)
+     memcpy(&FileBasic.LastAccessTime, lpLastAccessTime, sizeof(FILETIME));
+   if (lpLastWriteTime)
+     memcpy(&FileBasic.LastWriteTime, lpLastWriteTime, sizeof(FILETIME));
+
+   // should i initialize changetime ???
+
+   Status = NtSetInformationFile(hFile,
+                                &IoStatusBlock,
+                                &FileBasic,
+                                sizeof(FILE_BASIC_INFORMATION),
+                                FileBasicInformation);
+   if (!NT_SUCCESS(Status))
+     {
+       SetLastErrorByStatus(Status);
+       return FALSE;
+     }
+
    return TRUE;
 }
 
-WINBOOL STDCALL SetEndOfFile(HANDLE hFile)
+
+/*
+ * The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set.
+ *
+ * @implemented
+ */
+BOOL STDCALL
+SetEndOfFile(HANDLE hFile)
 {
-   int x = -1;
-   DWORD Num;
-   return WriteFile(hFile,&x,1,&Num,NULL);
+       IO_STATUS_BLOCK  IoStatusBlock;
+       FILE_END_OF_FILE_INFORMATION    EndOfFileInfo;
+       FILE_ALLOCATION_INFORMATION             FileAllocationInfo;
+       FILE_POSITION_INFORMATION                FilePosInfo;
+       NTSTATUS Status;
+
+       if(IsConsoleHandle(hFile))
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       //get current position
+       Status = NtQueryInformationFile(
+                                       hFile,
+                                       &IoStatusBlock,
+                                       &FilePosInfo,
+                                       sizeof(FILE_POSITION_INFORMATION),
+                                       FilePositionInformation
+                                       );
+
+       if (!NT_SUCCESS(Status)){
+               SetLastErrorByStatus(Status);
+               return FALSE;
+       }
+
+       EndOfFileInfo.EndOfFile.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
+
+       /*
+       NOTE:
+       This call is not supposed to free up any space after the eof marker
+       if the file gets truncated. We have to deallocate the space explicitly afterwards.
+       But...most file systems dispatch both FileEndOfFileInformation
+       and FileAllocationInformation as they were the same     command.
+
+       */
+       Status = NtSetInformationFile(
+                                               hFile,
+                                               &IoStatusBlock,  //out
+                                               &EndOfFileInfo,
+                                               sizeof(FILE_END_OF_FILE_INFORMATION),
+                                               FileEndOfFileInformation
+                                               );
+
+       if (!NT_SUCCESS(Status)){
+               SetLastErrorByStatus(Status);
+               return FALSE;
+       }
+
+       FileAllocationInfo.AllocationSize.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
+
+
+       Status = NtSetInformationFile(
+                                               hFile,
+                                               &IoStatusBlock,  //out
+                                               &FileAllocationInfo,
+                                               sizeof(FILE_ALLOCATION_INFORMATION),
+                                               FileAllocationInformation
+                                               );
+
+       if (!NT_SUCCESS(Status)){
+               SetLastErrorByStatus(Status);
+               return FALSE;
+       }
+
+       return TRUE;
+
 }
+
+
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+SetFileValidData(
+    HANDLE hFile,
+    LONGLONG ValidDataLength
+    )
+{
+       IO_STATUS_BLOCK IoStatusBlock;
+       FILE_VALID_DATA_LENGTH_INFORMATION ValidDataLengthInformation;
+       NTSTATUS Status;
+
+       ValidDataLengthInformation.ValidDataLength.QuadPart = ValidDataLength;
+
+       Status = NtSetInformationFile(
+                                               hFile,
+                                               &IoStatusBlock,  //out
+                                               &ValidDataLengthInformation,
+                                               sizeof(FILE_VALID_DATA_LENGTH_INFORMATION),
+                                               FileValidDataLengthInformation
+                                               );
+
+       if (!NT_SUCCESS(Status)){
+               SetLastErrorByStatus(Status);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+SetFileShortNameW(
+  HANDLE hFile,
+  LPCWSTR lpShortName)
+{
+  NTSTATUS Status;
+  ULONG NeededSize;
+  UNICODE_STRING ShortName;
+  IO_STATUS_BLOCK IoStatusBlock;
+  PFILE_NAME_INFORMATION FileNameInformation;
+
+  if(IsConsoleHandle(hFile))
+  {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return FALSE;
+  }
+
+  if(!lpShortName)
+  {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return FALSE;
+  }
+
+  RtlInitUnicodeString(&ShortName, lpShortName);
+
+  NeededSize = sizeof(FILE_NAME_INFORMATION) + ShortName.Length + sizeof(WCHAR);
+  if(!(FileNameInformation = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, NeededSize)))
+  {
+    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+    return FALSE;
+  }
+
+  FileNameInformation->FileNameLength = ShortName.Length;
+  RtlCopyMemory(FileNameInformation->FileName, ShortName.Buffer, ShortName.Length);
+
+  Status = NtSetInformationFile(hFile,
+                                &IoStatusBlock,         //out
+                                FileNameInformation,
+                                NeededSize,
+                                FileShortNameInformation);
+
+  RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameInformation);
+  if(!NT_SUCCESS(Status))
+  {
+
+    SetLastErrorByStatus(Status);
+  }
+
+  return NT_SUCCESS(Status);
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+SetFileShortNameA(
+    HANDLE hFile,
+    LPCSTR lpShortName
+    )
+{
+  PWCHAR ShortNameW;
+
+  if(IsConsoleHandle(hFile))
+  {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return FALSE;
+  }
+
+  if(!lpShortName)
+  {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return FALSE;
+  }
+
+  if (!(ShortNameW = FilenameA2W(lpShortName, FALSE)))
+     return FALSE;
+
+  return SetFileShortNameW(hFile, ShortNameW);
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+CheckNameLegalDOS8Dot3W(
+    LPCWSTR lpName,
+    LPSTR lpOemName OPTIONAL,
+    DWORD OemNameSize OPTIONAL,
+    PBOOL pbNameContainsSpaces OPTIONAL,
+    PBOOL pbNameLegal
+    )
+{
+    UNICODE_STRING Name;
+    ANSI_STRING AnsiName;
+
+    if(lpName == NULL ||
+       (lpOemName == NULL && OemNameSize != 0) ||
+       pbNameLegal == NULL)
+    {
+      SetLastError(ERROR_INVALID_PARAMETER);
+      return FALSE;
+    }
+
+    if(lpOemName != NULL)
+    {
+      AnsiName.Buffer = lpOemName;
+      AnsiName.MaximumLength = OemNameSize * sizeof(CHAR);
+      AnsiName.Length = 0;
+    }
+
+    RtlInitUnicodeString(&Name, lpName);
+
+    *pbNameLegal = RtlIsNameLegalDOS8Dot3(&Name,
+                                          (lpOemName ? &AnsiName : NULL),
+                                          (BOOLEAN*)pbNameContainsSpaces);
+
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+CheckNameLegalDOS8Dot3A(
+    LPCSTR lpName,
+    LPSTR lpOemName OPTIONAL,
+    DWORD OemNameSize OPTIONAL,
+    PBOOL pbNameContainsSpaces OPTIONAL,
+    PBOOL pbNameLegal
+    )
+{
+    UNICODE_STRING Name;
+    ANSI_STRING AnsiName, AnsiInputName;
+    NTSTATUS Status;
+
+    if(lpName == NULL ||
+       (lpOemName == NULL && OemNameSize != 0) ||
+       pbNameLegal == NULL)
+    {
+      SetLastError(ERROR_INVALID_PARAMETER);
+      return FALSE;
+    }
+
+    if(lpOemName != NULL)
+    {
+      AnsiName.Buffer = lpOemName;
+      AnsiName.MaximumLength = OemNameSize * sizeof(CHAR);
+      AnsiName.Length = 0;
+    }
+
+    RtlInitAnsiString(&AnsiInputName, (LPSTR)lpName);
+    if(bIsFileApiAnsi)
+      Status = RtlAnsiStringToUnicodeString(&Name, &AnsiInputName, TRUE);
+    else
+      Status = RtlOemStringToUnicodeString(&Name, &AnsiInputName, TRUE);
+
+    if(!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return FALSE;
+    }
+
+    *pbNameLegal = RtlIsNameLegalDOS8Dot3(&Name,
+                                          (lpOemName ? &AnsiName : NULL),
+                                          (BOOLEAN*)pbNameContainsSpaces);
+
+    RtlFreeUnicodeString(&Name);
+
+    return TRUE;
+}
+
+/* EOF */