Manually applying Gunnars patch because it's easier this way - and a good chance...
[reactos.git] / reactos / lib / kernel32 / file / file.c
index bb42e50..ec70fca 100644 (file)
@@ -1,4 +1,5 @@
-/*
+/* $Id: file.c,v 1.38 2002/11/07 02:52:37 robd Exp $
+ *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
  * FILE:            lib/kernel32/file/file.c
 
 /* INCLUDES *****************************************************************/
 
-#include <windows.h>
 #include <ddk/ntddk.h>
+#include <windows.h>
 #include <wchar.h>
 #include <string.h>
 
 #define NDEBUG
 #include <kernel32/kernel32.h>
+#include <kernel32/error.h>
 
 #define LPPROGRESS_ROUTINE void*
 
+
 /* GLOBALS ******************************************************************/
 
-static BOOLEAN  bIsFileApiAnsi; // set the file api to ansi or oem
+WINBOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem
+
 
 /* FUNCTIONS ****************************************************************/
 
-VOID STDCALL SetFileApisToOEM(VOID)
+VOID STDCALL
+SetFileApisToOEM(VOID)
 {
-   bIsFileApiAnsi = FALSE;     
+   bIsFileApiAnsi = FALSE;
 }
 
 
-VOID STDCALL SetFileApisToANSI(VOID)
+VOID STDCALL
+SetFileApisToANSI(VOID)
 {
    bIsFileApiAnsi = TRUE;
 }
 
 
-WINBOOL STDCALL AreFileApisANSI(VOID)
+WINBOOL STDCALL
+AreFileApisANSI(VOID)
 {
-   return(bIsFileApiAnsi);
+   return bIsFileApiAnsi;
 }
 
 
-HFILE STDCALL OpenFile(LPCSTR lpFileName,
-                      LPOFSTRUCT lpReOpenBuff,
-                      UINT uStyle)
+HFILE STDCALL
+OpenFile(LPCSTR lpFileName,
+        LPOFSTRUCT lpReOpenBuff,
+        UINT uStyle)
 {
-   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;
+       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;
+       }
+
+       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,FileNameW,NULL,MAX_PATH,PathNameW,&FilePart);
-   if ( Len == 0 )
-     return (HFILE)NULL;
+       Len = SearchPathW (NULL,
+                          FileNameU.Buffer,
+                          NULL,
+                          OFS_MAXPATHNAME,
+                          PathNameW,
+                          &FilePart);
 
-   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;
+       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;
+       }
+
+       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)
+       {
+               RtlFreeUnicodeString(&FileNameString);
+               return (HFILE)NULL;
+       }
+
+       errCode = NtOpenFile (&FileHandle,
+                             GENERIC_READ|SYNCHRONIZE,
+                             &ObjectAttributes,
+                             &IoStatusBlock,
+                             FILE_SHARE_READ,
+                             FILE_NON_DIRECTORY_FILE);
+
+       RtlFreeUnicodeString(&FileNameString);
+
+       lpReOpenBuff->nErrCode = RtlNtStatusToDosError(errCode);
+
+       if (!NT_SUCCESS(errCode))
+       {
+               SetLastErrorByStatus (errCode);
+               return (HFILE)INVALID_HANDLE_VALUE;
+       }
+
+       return (HFILE)FileHandle;
 }
 
 
-WINBOOL STDCALL FlushFileBuffers(HANDLE hFile)
+WINBOOL 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)
+DWORD STDCALL
+SetFilePointer(HANDLE hFile,
+              LONG lDistanceToMove,
+              PLONG lpDistanceToMoveHigh,
+              DWORD dwMoveMethod)
 {
    FILE_POSITION_INFORMATION FilePosition;
-   FILE_END_OF_FILE_INFORMATION FileEndOfFile;
+   FILE_STANDARD_INFORMATION FileStandart;
    NTSTATUS errCode;
    IO_STATUS_BLOCK IoStatusBlock;
    LARGE_INTEGER Distance;
@@ -148,44 +192,55 @@ DWORD STDCALL SetFilePointer(HANDLE hFile,
          hFile,lDistanceToMove,dwMoveMethod);
 
    Distance.u.LowPart = lDistanceToMove;
-   Distance.u.HighPart = (lpDistanceToMoveHigh) ? *lpDistanceToMoveHigh : 0;
-
-   if (dwMoveMethod == FILE_CURRENT) 
+   if (lpDistanceToMoveHigh)
+   {
+      Distance.u.HighPart = *lpDistanceToMoveHigh;
+   }
+   else if (lDistanceToMove >= 0)
+   {
+      Distance.u.HighPart = 0;
+   }
+   else
+   {
+      Distance.u.HighPart = -1;
+   }
+
+   if (dwMoveMethod == FILE_CURRENT)
      {
        NtQueryInformationFile(hFile,
                               &IoStatusBlock,
-                              &FilePosition, 
+                              &FilePosition,
                               sizeof(FILE_POSITION_INFORMATION),
                               FilePositionInformation);
-        FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart;
+       FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart;
      }
-   else if (dwMoveMethod == FILE_END) 
+   else if (dwMoveMethod == FILE_END)
      {
        NtQueryInformationFile(hFile,
                                &IoStatusBlock,
-                               &FileEndOfFile,
-                               sizeof(FILE_END_OF_FILE_INFORMATION),
-                               FileEndOfFileInformation);
+                               &FileStandart,
+                               sizeof(FILE_STANDARD_INFORMATION),
+                               FileStandardInformation);
         FilePosition.CurrentByteOffset.QuadPart =
-                FileEndOfFile.EndOfFile.QuadPart - Distance.QuadPart;
+                  FileStandart.EndOfFile.QuadPart + Distance.QuadPart;
      }
-   else if ( dwMoveMethod == FILE_BEGIN ) 
+   else if ( dwMoveMethod == FILE_BEGIN )
      {
         FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart;
      }
    
    errCode = NtSetInformationFile(hFile,
                                  &IoStatusBlock,
-                                 &FilePosition, 
+                                 &FilePosition,
                                  sizeof(FILE_POSITION_INFORMATION),
                                  FilePositionInformation);
-   if (!NT_SUCCESS(errCode)) 
+   if (!NT_SUCCESS(errCode))
      {
-       SetLastError(RtlNtStatusToDosError(errCode));
+       SetLastErrorByStatus(errCode);
        return -1;
      }
    
-   if (lpDistanceToMoveHigh != NULL) 
+   if (lpDistanceToMoveHigh != NULL)
      {
         *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
      }
@@ -193,14 +248,84 @@ DWORD STDCALL SetFilePointer(HANDLE hFile,
 }
 
 
-DWORD STDCALL GetFileType(HANDLE hFile)
+DWORD STDCALL
+GetFileType(HANDLE hFile)
 {
+   FILE_FS_DEVICE_INFORMATION DeviceInfo;
+   IO_STATUS_BLOCK StatusBlock;
+   NTSTATUS Status;
+
+   /* get real handle */
+   switch ((ULONG)hFile)
+     {
+       case STD_INPUT_HANDLE:
+         hFile = NtCurrentPeb()->ProcessParameters->hStdInput;
+
+         break;
+
+       case STD_OUTPUT_HANDLE:
+         hFile = NtCurrentPeb()->ProcessParameters->hStdOutput;
+
+         break;
+
+       case STD_ERROR_HANDLE:
+         hFile = NtCurrentPeb()->ProcessParameters->hStdError;
+
+         break;
+     }
+
+   /* check console handles */
+   if (IsConsoleHandle(hFile))
+     {
+//     if (VerifyConsoleHandle(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)
+DWORD STDCALL
+GetFileSize(HANDLE hFile,
+           LPDWORD lpFileSizeHigh)
 {
    NTSTATUS errCode;
    FILE_STANDARD_INFORMATION FileStandard;
@@ -208,13 +333,13 @@ DWORD STDCALL GetFileSize(HANDLE hFile,
 
    errCode = NtQueryInformationFile(hFile,
                                    &IoStatusBlock,
-                                   &FileStandard, 
+                                   &FileStandard,
                                    sizeof(FILE_STANDARD_INFORMATION),
                                    FileStandardInformation);
-   if (!NT_SUCCESS(errCode)) 
+   if (!NT_SUCCESS(errCode))
      {
-       SetLastError(RtlNtStatusToDosError(errCode));
-       if ( lpFileSizeHigh == NULL ) 
+       SetLastErrorByStatus(errCode);
+       if ( lpFileSizeHigh == NULL )
          {
             return -1;
          }
@@ -224,56 +349,68 @@ DWORD STDCALL GetFileSize(HANDLE hFile,
          }
      }
    if ( lpFileSizeHigh != NULL )
-     *lpFileSizeHigh = FileStandard.AllocationSize.u.HighPart;
+     *lpFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
 
-   return FileStandard.AllocationSize.u.LowPart;
+   return FileStandard.EndOfFile.u.LowPart;
 }
 
 
-DWORD STDCALL GetCompressedFileSizeA(LPCSTR lpFileName,
-                                    LPDWORD lpFileSizeHigh)
+DWORD STDCALL
+GetCompressedFileSizeA(LPCSTR lpFileName,
+                      LPDWORD lpFileSizeHigh)
 {
-   WCHAR FileNameW[MAX_PATH];
-   ULONG i;
-   
-   i = 0;
-   while ((*lpFileName)!=0 && i < MAX_PATH)
-     {
-       FileNameW[i] = *lpFileName;
-       lpFileName++;
-       i++;
-     }
-   FileNameW[i] = 0;
-   
-   return GetCompressedFileSizeW(FileNameW,lpFileSizeHigh);
+   UNICODE_STRING FileNameU;
+   ANSI_STRING FileName;
+   DWORD Size;
+
+   RtlInitAnsiString(&FileName,
+                    (LPSTR)lpFileName);
+
+   /* convert ansi (or oem) string to unicode */
+   if (bIsFileApiAnsi)
+     RtlAnsiStringToUnicodeString(&FileNameU,
+                                 &FileName,
+                                 TRUE);
+   else
+     RtlOemStringToUnicodeString(&FileNameU,
+                                &FileName,
+                                TRUE);
+
+   Size = GetCompressedFileSizeW(FileNameU.Buffer,
+                                lpFileSizeHigh);
+
+   RtlFreeUnicodeString (&FileNameU);
+
+   return Size;
 }
 
 
-DWORD STDCALL GetCompressedFileSizeW(LPCWSTR lpFileName,
-                                    LPDWORD lpFileSizeHigh)
+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);
 
    errCode = NtQueryInformationFile(hFile,
                                    &IoStatusBlock,
-                                   &FileCompression, 
+                                   &FileCompression,
                                    sizeof(FILE_COMPRESSION_INFORMATION),
                                    FileCompressionInformation);
-   if (!NT_SUCCESS(errCode)) 
+   if (!NT_SUCCESS(errCode))
      {
        CloseHandle(hFile);
-       SetLastError(RtlNtStatusToDosError(errCode));
+       SetLastErrorByStatus(errCode);
        return 0;
      }
    CloseHandle(hFile);
@@ -281,237 +418,295 @@ DWORD STDCALL GetCompressedFileSizeW(LPCWSTR lpFileName,
 }
 
 
-WINBOOL STDCALL GetFileInformationByHandle(HANDLE hFile,
-                              LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
+WINBOOL 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;
-   
+
    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 = FileDirectory.AllocationSize.u.HighPart;
-   lpFileInformation->nFileSizeLow = FileDirectory.AllocationSize.u.LowPart;
-   
+   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));
+
    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 = 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))
      {
-       SetLastError(RtlNtStatusToDosError(errCode));
+       SetLastErrorByStatus(errCode);
        return FALSE;
      }
 
    lpFileInformation->nNumberOfLinks = FileStandard.NumberOfLinks;
+   lpFileInformation->nFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
+   lpFileInformation->nFileSizeLow = FileStandard.EndOfFile.u.LowPart;
 
    return TRUE;
 }
 
 
-DWORD STDCALL GetFileAttributesA(LPCSTR lpFileName)
+DWORD STDCALL
+GetFileAttributesA(LPCSTR lpFileName)
 {
-   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);
+       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);
+
+       Result = GetFileAttributesW (FileNameU.Buffer);
+
+       RtlFreeUnicodeString (&FileNameU);
+
+       return Result;
 }
 
 
-DWORD STDCALL GetFileAttributesW(LPCWSTR lpFileName)
+DWORD STDCALL
+GetFileAttributesW(LPCWSTR lpFileName)
 {
    IO_STATUS_BLOCK IoStatusBlock;
    FILE_BASIC_INFORMATION FileBasic;
    HANDLE hFile;
    NTSTATUS errCode;
 
-   hFile = CreateFileW(lpFileName,     
-                       FILE_READ_ATTRIBUTES,
-                      FILE_SHARE_READ, 
-                      NULL,    
-                      OPEN_EXISTING,   
-                      FILE_ATTRIBUTE_NORMAL,   
+   hFile = CreateFileW(lpFileName,
+                      FILE_READ_ATTRIBUTES,
+                      FILE_SHARE_READ,
+                      NULL,
+                      OPEN_EXISTING,
+                      FILE_ATTRIBUTE_NORMAL,
                       NULL);
-   
-       
+   if (hFile == INVALID_HANDLE_VALUE)
+     {
+       return 0xFFFFFFFF;
+     }
+
    errCode = NtQueryInformationFile(hFile,
                                    &IoStatusBlock,
-                                   &FileBasic, 
+                                   &FileBasic,
                                    sizeof(FILE_BASIC_INFORMATION),
                                    FileBasicInformation);
-   if (!NT_SUCCESS(errCode)) 
+   if (!NT_SUCCESS(errCode))
      {
        CloseHandle(hFile);
-       SetLastError(RtlNtStatusToDosError(errCode));
-        return 0xFFFFFFFF;
+       SetLastErrorByStatus(errCode);
+       return 0xFFFFFFFF;
      }
    CloseHandle(hFile);
-   return (DWORD)FileBasic.FileAttributes;  
+   return (DWORD)FileBasic.FileAttributes;
 }
 
 
-WINBOOL STDCALL SetFileAttributesA(LPCSTR lpFileName,
-                                  DWORD dwFileAttributes)
+WINBOOL STDCALL
+SetFileAttributesA(LPCSTR lpFileName,
+                  DWORD dwFileAttributes)
 {
-       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);
+   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);
+
+   Result = SetFileAttributesW(FileNameU.Buffer,
+                              dwFileAttributes);
+
+   RtlFreeUnicodeString(&FileNameU);
+
+   return Result;
 }
 
 
-WINBOOL STDCALL SetFileAttributesW(LPCWSTR lpFileName,
-                                  DWORD dwFileAttributes)
+WINBOOL STDCALL
+SetFileAttributesW(LPCWSTR lpFileName,
+                  DWORD dwFileAttributes)
 {
    IO_STATUS_BLOCK IoStatusBlock;
    FILE_BASIC_INFORMATION FileBasic;
    HANDLE hFile;
    NTSTATUS errCode;
    
-   hFile = CreateFileW(lpFileName,     
+   hFile = CreateFileW(lpFileName,
                       FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
-                      FILE_SHARE_READ, 
-                      NULL,    
-                      OPEN_EXISTING,   
-                      FILE_ATTRIBUTE_NORMAL,   
+                      FILE_SHARE_READ,
+                      NULL,
+                      OPEN_EXISTING,
+                      FILE_ATTRIBUTE_NORMAL,
                       NULL);
 
    errCode = NtQueryInformationFile(hFile,
                                    &IoStatusBlock,
-                                   &FileBasic, 
+                                   &FileBasic,
                                    sizeof(FILE_BASIC_INFORMATION),
                                    FileBasicInformation);
-   if (!NT_SUCCESS(errCode)) 
+   if (!NT_SUCCESS(errCode))
      {
        CloseHandle(hFile);
-       SetLastError(RtlNtStatusToDosError(errCode));
+       SetLastErrorByStatus(errCode);
        return FALSE;
      }
    FileBasic.FileAttributes = dwFileAttributes;
    errCode = NtSetInformationFile(hFile,
                                  &IoStatusBlock,
-                                 &FileBasic, 
+                                 &FileBasic,
                                  sizeof(FILE_BASIC_INFORMATION),
                                  FileBasicInformation);
-   if (!NT_SUCCESS(errCode)) 
+   if (!NT_SUCCESS(errCode))
      {
        CloseHandle(hFile);
-       SetLastError(RtlNtStatusToDosError(errCode));
+       SetLastErrorByStatus(errCode);
        return FALSE;
      }
    CloseHandle(hFile);
-   return TRUE;                
+   return TRUE;
 }
 
 
-UINT STDCALL GetTempFileNameA(LPCSTR lpPathName,
-                             LPCSTR lpPrefixString,
-                             UINT uUnique,
-                             LPSTR lpTempFileName)
+UINT STDCALL
+GetTempFileNameA(LPCSTR lpPathName,
+                LPCSTR lpPrefixString,
+                UINT uUnique,
+                LPSTR lpTempFileName)
 {
    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,"%s\\%c%.3s%4.4x%s",
-    *      lpPathName,'~',lpPrefixString,uUnique,".tmp");
-    */
+   
+   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)
-     {
-       //              wsprintfA(lpTempFileName,"%s\\%c%.3s%4.4x%s",
-       //              lpPathName,'~',lpPrefixString,++uUnique,".tmp");
-     }
-   
-   CloseHandle((HANDLE)hFile);
+   {
+      if (GetLastError() != ERROR_ALREADY_EXISTS)
+      {
+         return 0;
+      }
+      sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
+   }
+   CloseHandle(hFile);
    return uUnique;
 }
 
 
-UINT STDCALL GetTempFileNameW(LPCWSTR lpPathName,
-                             LPCWSTR lpPrefixString,
-                             UINT uUnique,
-                             LPWSTR lpTempFileName)
+UINT STDCALL
+GetTempFileNameW(LPCWSTR lpPathName,
+                LPCWSTR lpPrefixString,
+                UINT uUnique,
+                LPWSTR lpTempFileName)
 {
    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,L"%s\\%c%.3s%4.4x%s",
-   //    lpPathName,'~',lpPrefixString,uUnique,L".tmp");
+   swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique);
    
    if (unique)
      return uUnique;
@@ -519,67 +714,88 @@ UINT STDCALL GetTempFileNameW(LPCWSTR lpPathName,
    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);
+   {
+      if (GetLastError() != ERROR_ALREADY_EXISTS)
+      {
+         return 0;
+      }
+      swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique);
+   }
+   CloseHandle(hFile);
    return uUnique;
 }
 
 
-WINBOOL STDCALL GetFileTime(HANDLE hFile,
-                           LPFILETIME lpCreationTime,
-                           LPFILETIME lpLastAccessTime,
-                           LPFILETIME lpLastWriteTime)
+WINBOOL 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;
+
+   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)
+WINBOOL 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;
+
+   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;
      }
    
@@ -587,9 +803,73 @@ WINBOOL STDCALL SetFileTime(HANDLE hFile,
 }
 
 
-WINBOOL STDCALL SetEndOfFile(HANDLE hFile)
+/*
+The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set.
+*/
+WINBOOL 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;
+
+       //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;
+
 }
+
+/* EOF */