check for console handles in Get/SetFileAttributesByHandle()
[reactos.git] / reactos / lib / kernel32 / file / file.c
index a612d6a..9256f15 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: file.c,v 1.46 2003/08/07 09:05:43 hbirr Exp $
+/* $Id$
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
 #include <k32.h>
 
 #define NDEBUG
-#include <kernel32/kernel32.h>
+#include "../include/debug.h"
 
 
 /* GLOBALS ******************************************************************/
 
-WINBOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem
-
+BOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem
 
 /* FUNCTIONS ****************************************************************/
 
+
+
+PWCHAR
+FilenameA2W(LPCSTR NameA, BOOL alloc)
+{
+   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;
+}
+
+
+/*
+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
+   )
+{
+   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;
+}
+
+
+/*
+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 */
+   )
+{
+   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);
+}
+
+
+/*
+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 */
+   )
+{
+    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
+VOID
+STDCALL
 SetFileApisToOEM(VOID)
 {
-   bIsFileApiAnsi = FALSE;
+    /* Set the correct Base Api */
+    Basep8BitStringToUnicodeString = RtlOemStringToUnicodeString;
+
+    /* FIXME: Old, deprecated way */
+    bIsFileApiAnsi = FALSE;
 }
 
 
 /*
  * @implemented
  */
-VOID STDCALL
+VOID
+STDCALL
 SetFileApisToANSI(VOID)
 {
-   bIsFileApiAnsi = TRUE;
+    /* Set the correct Base Api */
+    Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
+
+    /* FIXME: Old, deprecated way */
+    bIsFileApiAnsi = TRUE;
 }
 
 
 /*
  * @implemented
  */
-WINBOOL STDCALL
+BOOL STDCALL
 AreFileApisANSI(VOID)
 {
    return bIsFileApiAnsi;
@@ -81,6 +240,28 @@ OpenFile(LPCSTR lpFileName,
                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 */
@@ -91,10 +272,10 @@ OpenFile(LPCSTR lpFileName,
 
        Len = SearchPathW (NULL,
                           FileNameU.Buffer,
-                          NULL,
+                          NULL,
                           OFS_MAXPATHNAME,
                           PathNameW,
-                          &FilePart);
+                          &FilePart);
 
        RtlFreeUnicodeString(&FileNameU);
 
@@ -123,13 +304,6 @@ OpenFile(LPCSTR lpFileName,
                return (HFILE)INVALID_HANDLE_VALUE;
        }
 
-       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
 
@@ -139,12 +313,19 @@ OpenFile(LPCSTR lpFileName,
                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_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT);
 
        RtlFreeUnicodeString(&FileNameString);
 
@@ -163,7 +344,7 @@ OpenFile(LPCSTR lpFileName,
 /*
  * @implemented
  */
-WINBOOL STDCALL
+BOOL STDCALL
 FlushFileBuffers(HANDLE hFile)
 {
    NTSTATUS errCode;
@@ -195,14 +376,20 @@ SetFilePointer(HANDLE hFile,
               DWORD dwMoveMethod)
 {
    FILE_POSITION_INFORMATION FilePosition;
-   FILE_STANDARD_INFORMATION FileStandart;
+   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(IsConsoleHandle(hFile))
+   {
+     SetLastError(ERROR_INVALID_HANDLE);
+     return -1;
+   }
+
    Distance.u.LowPart = lDistanceToMove;
    if (lpDistanceToMoveHigh)
    {
@@ -217,30 +404,39 @@ SetFilePointer(HANDLE hFile,
       Distance.u.HighPart = -1;
    }
 
-   if (dwMoveMethod == FILE_CURRENT)
-     {
+   switch(dwMoveMethod)
+   {
+     case FILE_CURRENT:
        NtQueryInformationFile(hFile,
                               &IoStatusBlock,
                               &FilePosition,
                               sizeof(FILE_POSITION_INFORMATION),
                               FilePositionInformation);
        FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart;
-     }
-   else if (dwMoveMethod == FILE_END)
-     {
+       break;
+     case FILE_END:
        NtQueryInformationFile(hFile,
                                &IoStatusBlock,
-                               &FileStandart,
+                               &FileStandard,
                                sizeof(FILE_STANDARD_INFORMATION),
                                FileStandardInformation);
         FilePosition.CurrentByteOffset.QuadPart =
-                  FileStandart.EndOfFile.QuadPart + Distance.QuadPart;
-     }
-   else if ( dwMoveMethod == FILE_BEGIN )
-     {
+                  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,
@@ -251,7 +447,7 @@ SetFilePointer(HANDLE hFile,
        SetLastErrorByStatus(errCode);
        return -1;
      }
-   
+
    if (lpDistanceToMoveHigh != NULL)
      {
         *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
@@ -260,6 +456,79 @@ SetFilePointer(HANDLE hFile,
 }
 
 
+/*
+ * @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,
+                                 sizeof(FILE_POSITION_INFORMATION),
+                                 FilePositionInformation);
+   if (!NT_SUCCESS(errCode))
+     {
+       SetLastErrorByStatus(errCode);
+       return FALSE;
+     }
+
+   if (lpNewFilePointer)
+     {
+       *lpNewFilePointer = FilePosition.CurrentByteOffset;
+     }
+   return TRUE;
+}
+
+
 /*
  * @implemented
  */
@@ -274,15 +543,15 @@ GetFileType(HANDLE hFile)
   switch ((ULONG)hFile)
     {
       case STD_INPUT_HANDLE:
-       hFile = NtCurrentPeb()->ProcessParameters->hStdInput;
+       hFile = NtCurrentPeb()->ProcessParameters->StandardInput;
        break;
 
       case STD_OUTPUT_HANDLE:
-       hFile = NtCurrentPeb()->ProcessParameters->hStdOutput;
+       hFile = NtCurrentPeb()->ProcessParameters->StandardOutput;
        break;
 
       case STD_ERROR_HANDLE:
-       hFile = NtCurrentPeb()->ProcessParameters->hStdError;
+       hFile = NtCurrentPeb()->ProcessParameters->StandardError;
        break;
     }
 
@@ -373,33 +642,47 @@ GetFileSize(HANDLE hFile,
 /*
  * @implemented
  */
-DWORD STDCALL
-GetCompressedFileSizeA(LPCSTR lpFileName,
-                      LPDWORD lpFileSizeHigh)
+BOOL
+STDCALL
+GetFileSizeEx(
+    HANDLE hFile,
+    PLARGE_INTEGER lpFileSize
+    )
 {
-   UNICODE_STRING FileNameU;
-   ANSI_STRING FileName;
-   DWORD Size;
+   NTSTATUS errCode;
+   FILE_STANDARD_INFORMATION FileStandard;
+   IO_STATUS_BLOCK IoStatusBlock;
 
-   RtlInitAnsiString(&FileName,
-                    (LPSTR)lpFileName);
+   errCode = NtQueryInformationFile(hFile,
+                                   &IoStatusBlock,
+                                   &FileStandard,
+                                   sizeof(FILE_STANDARD_INFORMATION),
+                                   FileStandardInformation);
+   if (!NT_SUCCESS(errCode))
+     {
+       SetLastErrorByStatus(errCode);
+       return FALSE;
+     }
+   if (lpFileSize)
+     *lpFileSize = FileStandard.EndOfFile;
+
+   return TRUE;
+}
 
-   /* convert ansi (or oem) string to unicode */
-   if (bIsFileApiAnsi)
-     RtlAnsiStringToUnicodeString(&FileNameU,
-                                 &FileName,
-                                 TRUE);
-   else
-     RtlOemStringToUnicodeString(&FileNameU,
-                                &FileName,
-                                TRUE);
 
-   Size = GetCompressedFileSizeW(FileNameU.Buffer,
-                                lpFileSizeHigh);
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetCompressedFileSizeA(LPCSTR lpFileName,
+                      LPDWORD lpFileSizeHigh)
+{
+   PWCHAR FileNameW;
 
-   RtlFreeUnicodeString (&FileNameU);
+   if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
+      return INVALID_FILE_SIZE;
 
-   return Size;
+   return GetCompressedFileSizeW(FileNameW, lpFileSizeHigh);
 }
 
 
@@ -414,7 +697,7 @@ GetCompressedFileSizeW(LPCWSTR lpFileName,
    NTSTATUS errCode;
    IO_STATUS_BLOCK IoStatusBlock;
    HANDLE hFile;
-   
+
    hFile = CreateFileW(lpFileName,
                       GENERIC_READ,
                       FILE_SHARE_READ,
@@ -423,22 +706,27 @@ GetCompressedFileSizeW(LPCWSTR lpFileName,
                       FILE_ATTRIBUTE_NORMAL,
                       NULL);
 
+   if (hFile == INVALID_HANDLE_VALUE)
+      return INVALID_FILE_SIZE;
+
    errCode = NtQueryInformationFile(hFile,
                                    &IoStatusBlock,
                                    &FileCompression,
                                    sizeof(FILE_COMPRESSION_INFORMATION),
                                    FileCompressionInformation);
+
+   CloseHandle(hFile);
+
    if (!NT_SUCCESS(errCode))
      {
-       CloseHandle(hFile);
        SetLastErrorByStatus(errCode);
        return INVALID_FILE_SIZE;
      }
-   CloseHandle(hFile);
 
    if(lpFileSizeHigh)
     *lpFileSizeHigh = FileCompression.CompressedFileSize.u.HighPart;
 
+   SetLastError(NO_ERROR);
    return FileCompression.CompressedFileSize.u.LowPart;
 }
 
@@ -446,7 +734,7 @@ GetCompressedFileSizeW(LPCWSTR lpFileName,
 /*
  * @implemented
  */
-WINBOOL STDCALL
+BOOL STDCALL
 GetFileInformationByHandle(HANDLE hFile,
                           LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
 {
@@ -463,6 +751,12 @@ GetFileInformationByHandle(HANDLE hFile,
    NTSTATUS errCode;
    IO_STATUS_BLOCK IoStatusBlock;
 
+   if(IsConsoleHandle(hFile))
+   {
+     SetLastError(ERROR_INVALID_HANDLE);
+     return FALSE;
+   }
+
    errCode = NtQueryInformationFile(hFile,
                                    &IoStatusBlock,
                                    &FileBasic,
@@ -475,9 +769,15 @@ GetFileInformationByHandle(HANDLE hFile,
      }
 
    lpFileInformation->dwFileAttributes = (DWORD)FileBasic.FileAttributes;
-   memcpy(&lpFileInformation->ftCreationTime,&FileBasic.CreationTime,sizeof(LARGE_INTEGER));
-   memcpy(&lpFileInformation->ftLastAccessTime,&FileBasic.LastAccessTime,sizeof(LARGE_INTEGER));
-   memcpy(&lpFileInformation->ftLastWriteTime, &FileBasic.LastWriteTime,sizeof(LARGE_INTEGER));
+
+   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,
@@ -529,8 +829,8 @@ GetFileInformationByHandle(HANDLE hFile,
  * @implemented
  */
 BOOL STDCALL
-GetFileAttributesExW(LPCWSTR lpFileName, 
-                    GET_FILEEX_INFO_LEVELS fInfoLevelId, 
+GetFileAttributesExW(LPCWSTR lpFileName,
+                    GET_FILEEX_INFO_LEVELS fInfoLevelId,
                     LPVOID lpFileInformation)
 {
   FILE_NETWORK_OPEN_INFORMATION FileInformation;
@@ -541,7 +841,7 @@ GetFileAttributesExW(LPCWSTR lpFileName,
   NTSTATUS Status;
   WIN32_FILE_ATTRIBUTE_DATA* FileAttributeData;
 
-  DPRINT ("GetFileAttributesExW(%S) called\n", lpFileName);
+  DPRINT("GetFileAttributesExW(%S) called\n", lpFileName);
 
 
   if (fInfoLevelId != GetFileExInfoStandard || lpFileInformation == NULL)
@@ -556,7 +856,7 @@ GetFileAttributesExW(LPCWSTR lpFileName,
                                     NULL,
                                     NULL))
     {
-      DPRINT ("Invalid path\n");
+      DPRINT1 ("Invalid path\n");
       SetLastError (ERROR_BAD_PATHNAME);
       return FALSE;
     }
@@ -578,7 +878,7 @@ GetFileAttributesExW(LPCWSTR lpFileName,
   RtlFreeUnicodeString (&FileName);
   if (!NT_SUCCESS (Status))
     {
-      DPRINT ("NtOpenFile() failed (Status %lx)\n", Status);
+      DPRINT ("NtOpenFile() failed  %x (Status %lx)\n", &ObjectAttributes, Status);
       SetLastErrorByStatus (Status);
       return FALSE;
     }
@@ -593,7 +893,7 @@ GetFileAttributesExW(LPCWSTR lpFileName,
 
   if (!NT_SUCCESS (Status))
     {
-      DPRINT ("NtQueryInformationFile() failed (Status %lx)\n", Status);
+      DPRINT1 ("NtQueryInformationFile() failed (Status %lx)\n", Status);
       SetLastErrorByStatus (Status);
       return FALSE;
     }
@@ -617,30 +917,15 @@ GetFileAttributesExW(LPCWSTR lpFileName,
  */
 BOOL STDCALL
 GetFileAttributesExA(LPCSTR lpFileName,
-                    GET_FILEEX_INFO_LEVELS fInfoLevelId, 
+                    GET_FILEEX_INFO_LEVELS fInfoLevelId,
                     LPVOID lpFileInformation)
 {
-       UNICODE_STRING FileNameU;
-       ANSI_STRING FileName;
-       BOOL Result;
-       RtlInitAnsiString (&FileName,
-                          (LPSTR)lpFileName);
+   PWCHAR FileNameW;
 
-       /* convert ansi (or oem) string to unicode */
-       if (bIsFileApiAnsi)
-               RtlAnsiStringToUnicodeString (&FileNameU,
-                                             &FileName,
-                                             TRUE);
-       else
-               RtlOemStringToUnicodeString (&FileNameU,
-                                            &FileName,
-                                            TRUE);
-
-        Result = GetFileAttributesExW(FileNameU.Buffer, fInfoLevelId, lpFileInformation);
-
-       RtlFreeUnicodeString (&FileNameU);
+   if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
+      return FALSE;
 
-       return Result;
+   return GetFileAttributesExW(FileNameW, fInfoLevelId, lpFileInformation);
 }
 
 
@@ -650,29 +935,16 @@ GetFileAttributesExA(LPCSTR lpFileName,
 DWORD STDCALL
 GetFileAttributesA(LPCSTR lpFileName)
 {
-        WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
-       UNICODE_STRING FileNameU;
-       ANSI_STRING FileName;
-       BOOL Result;
-
-       RtlInitAnsiString (&FileName,
-                          (LPSTR)lpFileName);
-
-       /* convert ansi (or oem) string to unicode */
-       if (bIsFileApiAnsi)
-               RtlAnsiStringToUnicodeString (&FileNameU,
-                                             &FileName,
-                                             TRUE);
-       else
-               RtlOemStringToUnicodeString (&FileNameU,
-                                            &FileName,
-                                            TRUE);
+   WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
+   PWSTR FileNameW;
+       BOOL ret;
 
-        Result = GetFileAttributesExW(FileNameU.Buffer, GetFileExInfoStandard, &FileAttributeData);
+   if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
+      return INVALID_FILE_ATTRIBUTES;
 
-       RtlFreeUnicodeString (&FileNameU);
+   ret = GetFileAttributesExW(FileNameW, GetFileExInfoStandard, &FileAttributeData);
 
-       return Result ? FileAttributeData.dwFileAttributes : 0xffffffff;
+   return ret ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
 }
 
 
@@ -689,43 +961,113 @@ GetFileAttributesW(LPCWSTR lpFileName)
 
   Result = GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &FileAttributeData);
 
-  return Result ? FileAttributeData.dwFileAttributes : 0xffffffff;
+  return Result ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
 }
 
-WINBOOL STDCALL
-SetFileAttributesA(LPCSTR lpFileName,
-                  DWORD dwFileAttributes)
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetFileAttributesByHandle(IN HANDLE hFile,
+                          OUT LPDWORD dwFileAttributes,
+                          IN DWORD dwFlags)
 {
-  UNICODE_STRING FileNameU;
-  ANSI_STRING FileName;
-  WINBOOL Result;
-
-  RtlInitAnsiString (&FileName,
-                    (LPSTR)lpFileName);
-
-  /* convert ansi (or oem) string to unicode */
-  if (bIsFileApiAnsi)
-    RtlAnsiStringToUnicodeString (&FileNameU,
-                                 &FileName,
-                                 TRUE);
-   else
-    RtlOemStringToUnicodeString (&FileNameU,
-                                &FileName,
-                                TRUE);
+    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;
+}
 
-  Result = SetFileAttributesW (FileNameU.Buffer,
-                              dwFileAttributes);
 
-  RtlFreeUnicodeString (&FileNameU);
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SetFileAttributesByHandle(IN HANDLE hFile,
+                          IN DWORD dwFileAttributes,
+                          IN DWORD dwFlags)
+{
+    FILE_BASIC_INFORMATION FileBasic;
+    IO_STATUS_BLOCK IoStatusBlock;
+    NTSTATUS Status;
 
-  return Result;
+    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
  */
-WINBOOL STDCALL
+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)
 {
@@ -803,106 +1145,97 @@ SetFileAttributesW(LPCWSTR lpFileName,
 }
 
 
-/*
- * @implemented
+
+
+/***********************************************************************
+ *           GetTempFileNameA   (KERNEL32.@)
  */
-UINT STDCALL
-GetTempFileNameA(LPCSTR lpPathName,
-                LPCSTR lpPrefixString,
-                UINT uUnique,
-                LPSTR lpTempFileName)
+UINT WINAPI GetTempFileNameA( LPCSTR path, LPCSTR prefix, UINT unique, LPSTR buffer)
 {
-   HANDLE hFile;
-   UINT unique = uUnique;
-   UINT len;
-   const char *format = "%.*s\\~%.3s%4.4x.TMP";
-
-   DPRINT("GetTempFileNameA(lpPathName %s, lpPrefixString %.*s, "
-         "uUnique %x, lpTempFileName %x)\n", lpPathName, 4, 
-         lpPrefixString, uUnique, lpTempFileName);
-  
-   if (lpPathName == NULL)
-     return 0;
-
-   len = strlen(lpPathName);
-   if (len > 0 && (lpPathName[len-1] == '\\' || lpPathName[len-1] == '/'))
-     len--;
-
-   if (uUnique == 0)
-     uUnique = GetCurrentTime();
-   
-   sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique);
-   
-   if (unique)
-     return uUnique;
-   
-   while ((hFile = CreateFileA(lpTempFileName, GENERIC_WRITE, 0, NULL,
-                              CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
-                              0)) == INVALID_HANDLE_VALUE)
-   {
-      if (GetLastError() != ERROR_ALREADY_EXISTS)
-      {
-         return 0;
-      }
-      sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
-   }
-   CloseHandle(hFile);
-   return uUnique;
-}
+   WCHAR BufferW[MAX_PATH];
+   PWCHAR PathW;
+   WCHAR PrefixW[3+1];
+   UINT ret;
 
+   if (!(PathW = FilenameA2W(path, FALSE)))
+      return 0;
 
-/*
- * @implemented
+   if (prefix)
+      FilenameA2W_N(PrefixW, 3+1, prefix, -1);
+
+   ret = GetTempFileNameW(PathW, prefix ? PrefixW : NULL, unique, BufferW);
+
+   if (ret)
+      FilenameW2A_N(buffer, MAX_PATH, BufferW, -1);
+
+   return ret;
+}
+
+/***********************************************************************
+ *           GetTempFileNameW   (KERNEL32.@)
  */
-UINT STDCALL
-GetTempFileNameW(LPCWSTR lpPathName,
-                LPCWSTR lpPrefixString,
-                UINT uUnique,
-                LPWSTR lpTempFileName)
+UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique, LPWSTR buffer )
 {
-   HANDLE hFile;
-   UINT unique = uUnique;
-   UINT len;
-   const WCHAR *format = L"%.*s\\~%.3s%4.4x.TMP";
-   
-   DPRINT("GetTempFileNameW(lpPathName %S, lpPrefixString %.*S, "
-         "uUnique %x, lpTempFileName %x)\n", lpPathName, 4, 
-         lpPrefixString, uUnique, lpTempFileName);
-
-   if (lpPathName == NULL)
-     return 0;
-
-   len = wcslen(lpPathName);
-   if (len > 0 && (lpPathName[len-1] == L'\\' || lpPathName[len-1] == L'/'))
-     len--;
-   
-   if (uUnique == 0)
-     uUnique = GetCurrentTime();
-   
-   swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique);
-   
-   if (unique)
-     return uUnique;
-  
-   while ((hFile = CreateFileW(lpTempFileName, GENERIC_WRITE, 0, NULL,
-                              CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY,
-                              0)) == INVALID_HANDLE_VALUE)
-   {
-      if (GetLastError() != ERROR_ALREADY_EXISTS)
-      {
-         return 0;
-      }
-      swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
-   }
-   CloseHandle(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;
 }
 
 
+
+
+
 /*
  * @implemented
  */
-WINBOOL STDCALL
+BOOL STDCALL
 GetFileTime(HANDLE hFile,
            LPFILETIME lpCreationTime,
            LPFILETIME lpLastAccessTime,
@@ -912,6 +1245,12 @@ GetFileTime(HANDLE hFile,
    FILE_BASIC_INFORMATION FileBasic;
    NTSTATUS Status;
 
+   if(IsConsoleHandle(hFile))
+   {
+     SetLastError(ERROR_INVALID_HANDLE);
+     return FALSE;
+   }
+
    Status = NtQueryInformationFile(hFile,
                                   &IoStatusBlock,
                                   &FileBasic,
@@ -937,7 +1276,7 @@ GetFileTime(HANDLE hFile,
 /*
  * @implemented
  */
-WINBOOL STDCALL
+BOOL STDCALL
 SetFileTime(HANDLE hFile,
            CONST FILETIME *lpCreationTime,
            CONST FILETIME *lpLastAccessTime,
@@ -947,6 +1286,12 @@ SetFileTime(HANDLE hFile,
    IO_STATUS_BLOCK IoStatusBlock;
    NTSTATUS Status;
 
+   if(IsConsoleHandle(hFile))
+   {
+     SetLastError(ERROR_INVALID_HANDLE);
+     return FALSE;
+   }
+
    Status = NtQueryInformationFile(hFile,
                                   &IoStatusBlock,
                                   &FileBasic,
@@ -977,7 +1322,7 @@ SetFileTime(HANDLE hFile,
        SetLastErrorByStatus(Status);
        return FALSE;
      }
-   
+
    return TRUE;
 }
 
@@ -987,7 +1332,7 @@ SetFileTime(HANDLE hFile,
  *
  * @implemented
  */
-WINBOOL STDCALL
+BOOL STDCALL
 SetEndOfFile(HANDLE hFile)
 {
        IO_STATUS_BLOCK  IoStatusBlock;
@@ -996,6 +1341,12 @@ SetEndOfFile(HANDLE hFile)
        FILE_POSITION_INFORMATION                FilePosInfo;
        NTSTATUS Status;
 
+       if(IsConsoleHandle(hFile))
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
        //get current position
        Status = NtQueryInformationFile(
                                        hFile,
@@ -1013,10 +1364,10 @@ SetEndOfFile(HANDLE hFile)
        EndOfFileInfo.EndOfFile.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
 
        /*
-       NOTE: 
+       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 
+       But...most file systems dispatch both FileEndOfFileInformation
        and FileAllocationInformation as they were the same     command.
 
        */
@@ -1048,9 +1399,225 @@ SetEndOfFile(HANDLE hFile)
                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 */