check for console handles in Get/SetFileAttributesByHandle()
[reactos.git] / reactos / lib / kernel32 / file / file.c
index 5922ac6..9256f15 100644 (file)
 
 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;
 }
 
 
@@ -110,7 +269,7 @@ OpenFile(LPCSTR lpFileName,
                RtlAnsiStringToUnicodeString (&FileNameU, &FileName, TRUE);
        else
                RtlOemStringToUnicodeString (&FileNameU, &FileName, TRUE);
-                       
+
        Len = SearchPathW (NULL,
                           FileNameU.Buffer,
                           NULL,
@@ -221,7 +380,7 @@ SetFilePointer(HANDLE hFile,
    NTSTATUS errCode;
    IO_STATUS_BLOCK IoStatusBlock;
    LARGE_INTEGER Distance;
-   
+
    DPRINT("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
          hFile,lDistanceToMove,dwMoveMethod);
 
@@ -244,7 +403,7 @@ SetFilePointer(HANDLE hFile,
    {
       Distance.u.HighPart = -1;
    }
-   
+
    switch(dwMoveMethod)
    {
      case FILE_CURRENT:
@@ -271,13 +430,13 @@ SetFilePointer(HANDLE hFile,
         SetLastError(ERROR_INVALID_PARAMETER);
        return -1;
    }
-   
+
    if(FilePosition.CurrentByteOffset.QuadPart < 0)
    {
      SetLastError(ERROR_NEGATIVE_SEEK);
      return -1;
    }
-   
+
    errCode = NtSetInformationFile(hFile,
                                  &IoStatusBlock,
                                  &FilePosition,
@@ -288,7 +447,7 @@ SetFilePointer(HANDLE hFile,
        SetLastErrorByStatus(errCode);
        return -1;
      }
-   
+
    if (lpDistanceToMoveHigh != NULL)
      {
         *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
@@ -344,13 +503,13 @@ SetFilePointerEx(HANDLE hFile,
         SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }
-   
+
    if(FilePosition.CurrentByteOffset.QuadPart < 0)
    {
      SetLastError(ERROR_NEGATIVE_SEEK);
      return FALSE;
    }
-   
+
    errCode = NtSetInformationFile(hFile,
                                  &IoStatusBlock,
                                  &FilePosition,
@@ -361,7 +520,7 @@ SetFilePointerEx(HANDLE hFile,
        SetLastErrorByStatus(errCode);
        return FALSE;
      }
-   
+
    if (lpNewFilePointer)
      {
        *lpNewFilePointer = FilePosition.CurrentByteOffset;
@@ -384,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;
     }
 
@@ -518,29 +677,12 @@ DWORD STDCALL
 GetCompressedFileSizeA(LPCSTR lpFileName,
                       LPDWORD lpFileSizeHigh)
 {
-   UNICODE_STRING FileNameU;
-   ANSI_STRING FileName;
-   DWORD Size;
+   PWCHAR FileNameW;
 
-   RtlInitAnsiString(&FileName,
-                    (LPSTR)lpFileName);
+   if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
+      return INVALID_FILE_SIZE;
 
-   /* 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;
+   return GetCompressedFileSizeW(FileNameW, lpFileSizeHigh);
 }
 
 
@@ -555,7 +697,7 @@ GetCompressedFileSizeW(LPCWSTR lpFileName,
    NTSTATUS errCode;
    IO_STATUS_BLOCK IoStatusBlock;
    HANDLE hFile;
-   
+
    hFile = CreateFileW(lpFileName,
                       GENERIC_READ,
                       FILE_SHARE_READ,
@@ -564,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;
 }
 
@@ -622,13 +769,13 @@ GetFileInformationByHandle(HANDLE hFile,
      }
 
    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;
 
@@ -682,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;
@@ -731,7 +878,7 @@ GetFileAttributesExW(LPCWSTR lpFileName,
   RtlFreeUnicodeString (&FileName);
   if (!NT_SUCCESS (Status))
     {
-      DPRINT1 ("NtOpenFile() failed  %x (Status %lx)\n", &ObjectAttributes, Status);
+      DPRINT ("NtOpenFile() failed  %x (Status %lx)\n", &ObjectAttributes, Status);
       SetLastErrorByStatus (Status);
       return FALSE;
     }
@@ -770,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);
 }
 
 
@@ -803,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;
 }
 
 
@@ -842,36 +961,106 @@ GetFileAttributesW(LPCWSTR lpFileName)
 
   Result = GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &FileAttributeData);
 
-  return Result ? FileAttributeData.dwFileAttributes : 0xffffffff;
+  return Result ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
 }
 
+
+/*
+ * @implemented
+ */
 BOOL STDCALL
-SetFileAttributesA(LPCSTR lpFileName,
-                  DWORD dwFileAttributes)
+GetFileAttributesByHandle(IN HANDLE hFile,
+                          OUT LPDWORD dwFileAttributes,
+                          IN DWORD dwFlags)
 {
-  UNICODE_STRING FileNameU;
-  ANSI_STRING FileName;
-  BOOL Result;
+    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;
+}
 
-  RtlInitAnsiString (&FileName,
-                    (LPSTR)lpFileName);
 
-  /* convert ansi (or oem) string to unicode */
-  if (bIsFileApiAnsi)
-    RtlAnsiStringToUnicodeString (&FileNameU,
-                                 &FileName,
-                                 TRUE);
-   else
-    RtlOemStringToUnicodeString (&FileNameU,
-                                &FileName,
-                                TRUE);
+/*
+ * @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;
+}
 
-  Result = SetFileAttributesW (FileNameU.Buffer,
-                              dwFileAttributes);
 
-  RtlFreeUnicodeString (&FileNameU);
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SetFileAttributesA(
+   LPCSTR lpFileName,
+       DWORD dwFileAttributes)
+{
+   PWCHAR FileNameW;
+
+   if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
+      return FALSE;
 
-  return Result;
+   return SetFileAttributesW(FileNameW, dwFileAttributes);
 }
 
 
@@ -956,102 +1145,93 @@ 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_FILE_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_FILE_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
  */
@@ -1142,7 +1322,7 @@ SetFileTime(HANDLE hFile,
        SetLastErrorByStatus(Status);
        return FALSE;
      }
-   
+
    return TRUE;
 }
 
@@ -1184,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.
 
        */
@@ -1219,7 +1399,7 @@ SetEndOfFile(HANDLE hFile)
                SetLastErrorByStatus(Status);
                return FALSE;
        }
-       
+
        return TRUE;
 
 }
@@ -1238,9 +1418,9 @@ SetFileValidData(
        IO_STATUS_BLOCK IoStatusBlock;
        FILE_VALID_DATA_LENGTH_INFORMATION ValidDataLengthInformation;
        NTSTATUS Status;
-       
+
        ValidDataLengthInformation.ValidDataLength.QuadPart = ValidDataLength;
-       
+
        Status = NtSetInformationFile(
                                                hFile,
                                                &IoStatusBlock,  //out
@@ -1248,16 +1428,17 @@ SetFileValidData(
                                                sizeof(FILE_VALID_DATA_LENGTH_INFORMATION),
                                                FileValidDataLengthInformation
                                                );
-  
+
        if (!NT_SUCCESS(Status)){
                SetLastErrorByStatus(Status);
                return FALSE;
        }
-       
+
        return TRUE;
 }
 
 
+
 /*
  * @implemented
  */
@@ -1272,44 +1453,44 @@ SetFileShortNameW(
   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);
 }
 
@@ -1324,39 +1505,24 @@ SetFileShortNameA(
     LPCSTR lpShortName
     )
 {
-  NTSTATUS Status;
-  BOOL Ret;
-  ANSI_STRING ShortNameA;
-  UNICODE_STRING ShortName;
-  
+  PWCHAR ShortNameW;
+
   if(IsConsoleHandle(hFile))
   {
     SetLastError(ERROR_INVALID_HANDLE);
     return FALSE;
   }
-  
+
   if(!lpShortName)
   {
     SetLastError(ERROR_INVALID_PARAMETER);
     return FALSE;
   }
-  
-  RtlInitAnsiString(&ShortNameA, (LPSTR)lpShortName);
-  
-  if(bIsFileApiAnsi)
-    Status = RtlAnsiStringToUnicodeString(&ShortName, &ShortNameA, TRUE);
-  else
-    Status = RtlOemStringToUnicodeString(&ShortName, &ShortNameA, TRUE);
-  if(!NT_SUCCESS(Status))
-  {
-    SetLastErrorByStatus(Status);
-    return FALSE;
-  }
-  
-  Ret = SetFileShortNameW(hFile, ShortName.Buffer);
-  
-  RtlFreeUnicodeString(&ShortName);
-  return Ret;
+
+  if (!(ShortNameW = FilenameA2W(lpShortName, FALSE)))
+     return FALSE;
+
+  return SetFileShortNameW(hFile, ShortNameW);
 }