[KERNEL32] ReplaceFileW:
[reactos.git] / reactos / dll / win32 / kernel32 / file / file.c
index 804d605..cdbafd0 100644 (file)
@@ -177,7 +177,7 @@ FilenameW2A_N(
  * @implemented
  */
 VOID
-STDCALL
+WINAPI
 SetFileApisToOEM(VOID)
 {
     /* Set the correct Base Api */
@@ -192,7 +192,7 @@ SetFileApisToOEM(VOID)
  * @implemented
  */
 VOID
-STDCALL
+WINAPI
 SetFileApisToANSI(VOID)
 {
     /* Set the correct Base Api */
@@ -206,7 +206,7 @@ SetFileApisToANSI(VOID)
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 AreFileApisANSI(VOID)
 {
    return bIsFileApiAnsi;
@@ -216,7 +216,7 @@ AreFileApisANSI(VOID)
 /*
  * @implemented
  */
-HFILE STDCALL
+HFILE WINAPI
 OpenFile(LPCSTR lpFileName,
         LPOFSTRUCT lpReOpenBuff,
         UINT uStyle)
@@ -236,9 +236,56 @@ OpenFile(LPCSTR lpFileName,
 
        if (lpReOpenBuff == NULL)
        {
-               return FALSE;
+               return HFILE_ERROR;
+       }
+
+    lpReOpenBuff->nErrCode = 0;
+
+       if (uStyle & OF_REOPEN) lpFileName = lpReOpenBuff->szPathName;
+
+       if (!lpFileName)
+       {
+               return HFILE_ERROR;
+       }
+
+       if (!GetFullPathNameA(lpFileName,
+                                                 sizeof(lpReOpenBuff->szPathName),
+                                                 lpReOpenBuff->szPathName,
+                                                 NULL))
+       {
+           lpReOpenBuff->nErrCode = GetLastError();
+               return HFILE_ERROR;
        }
 
+    if (uStyle & OF_PARSE)
+    {
+        lpReOpenBuff->fFixedDisk = (GetDriveTypeA(lpReOpenBuff->szPathName) != DRIVE_REMOVABLE);
+        TRACE("(%s): OF_PARSE, res = '%s'\n", lpFileName, lpReOpenBuff->szPathName);
+        return 0;
+    }
+
+    if ((uStyle & OF_EXIST) && !(uStyle & OF_CREATE))
+    {
+        DWORD dwAttributes = GetFileAttributesA(lpReOpenBuff->szPathName);
+
+        switch (dwAttributes)
+        {
+            case 0xFFFFFFFF: /* File does not exist */
+                SetLastError(ERROR_FILE_NOT_FOUND);
+                lpReOpenBuff->nErrCode = (WORD) ERROR_FILE_NOT_FOUND;
+                return -1;
+
+            case FILE_ATTRIBUTE_DIRECTORY:
+                SetLastError(ERROR_ACCESS_DENIED);
+                lpReOpenBuff->nErrCode = (WORD) ERROR_ACCESS_DENIED;
+                return -1;
+
+            default:
+                lpReOpenBuff->cBytes = sizeof(OFSTRUCT);
+                return 1;
+        }
+    }
+    lpReOpenBuff->cBytes = sizeof(OFSTRUCT);
        if ((uStyle & OF_CREATE) == OF_CREATE)
        {
                DWORD Sharing;
@@ -280,9 +327,21 @@ OpenFile(LPCSTR lpFileName,
 
        if (Len == 0 || Len > OFS_MAXPATHNAME)
        {
+               lpReOpenBuff->nErrCode = GetLastError();
                return (HFILE)INVALID_HANDLE_VALUE;
        }
 
+    if (uStyle & OF_DELETE)
+    {
+        if (!DeleteFileW(PathNameW))
+               {
+                       lpReOpenBuff->nErrCode = GetLastError();
+                       return HFILE_ERROR;
+               }
+        TRACE("(%s): OF_DELETE return = OK\n", lpFileName);
+        return TRUE;
+    }
+
        FileName.Buffer = lpReOpenBuff->szPathName;
        FileName.Length = 0;
        FileName.MaximumLength = OFS_MAXPATHNAME;
@@ -306,14 +365,6 @@ OpenFile(LPCSTR lpFileName,
        // FILE_SHARE_READ
        // FILE_NO_INTERMEDIATE_BUFFERING
 
-       if ((uStyle & OF_PARSE) == OF_PARSE)
-       {
-               RtlFreeHeap(RtlGetProcessHeap(),
-                            0,
-                            FileNameString.Buffer);
-               return (HFILE)NULL;
-       }
-
        ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
        ObjectAttributes.RootDirectory = NULL;
        ObjectAttributes.ObjectName = &FileNameString;
@@ -328,11 +379,9 @@ OpenFile(LPCSTR lpFileName,
                              FILE_SHARE_READ,
                              FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT);
 
-       RtlFreeHeap(RtlGetProcessHeap(),
-                    0,
-                    FileNameString.Buffer);
+       RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameString.Buffer);
 
-       lpReOpenBuff->nErrCode = (WORD)RtlNtStatusToDosError(errCode);
+       lpReOpenBuff->nErrCode = RtlNtStatusToDosError(errCode);
 
        if (!NT_SUCCESS(errCode))
        {
@@ -340,6 +389,12 @@ OpenFile(LPCSTR lpFileName,
                return (HFILE)INVALID_HANDLE_VALUE;
        }
 
+       if (uStyle & OF_EXIST)
+       {
+               NtClose(FileHandle);
+               return (HFILE)1;
+       }
+
        return (HFILE)FileHandle;
 }
 
@@ -347,7 +402,7 @@ OpenFile(LPCSTR lpFileName,
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 FlushFileBuffers(HANDLE hFile)
 {
    NTSTATUS errCode;
@@ -374,11 +429,11 @@ FlushFileBuffers(HANDLE hFile)
 /*
  * @implemented
  */
-DWORD STDCALL
+DWORD WINAPI
 SetFilePointer(HANDLE hFile,
-              LONG lDistanceToMove,
-              PLONG lpDistanceToMoveHigh,
-              DWORD dwMoveMethod)
+           LONG lDistanceToMove,
+           PLONG lpDistanceToMoveHigh,
+           DWORD dwMoveMethod)
 {
    FILE_POSITION_INFORMATION FilePosition;
    FILE_STANDARD_INFORMATION FileStandard;
@@ -387,12 +442,12 @@ SetFilePointer(HANDLE hFile,
    LARGE_INTEGER Distance;
 
    TRACE("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
-         hFile,lDistanceToMove,dwMoveMethod);
+      hFile,lDistanceToMove,dwMoveMethod);
 
    if(IsConsoleHandle(hFile))
    {
      SetLastError(ERROR_INVALID_HANDLE);
-     return -1;
+     return INVALID_SET_FILE_POINTER;
    }
 
    if (lpDistanceToMoveHigh)
@@ -408,34 +463,48 @@ SetFilePointer(HANDLE hFile,
    switch(dwMoveMethod)
    {
      case FILE_CURRENT:
-       NtQueryInformationFile(hFile,
-                              &IoStatusBlock,
-                              &FilePosition,
-                              sizeof(FILE_POSITION_INFORMATION),
-                              FilePositionInformation);
-       FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart;
-       break;
+    errCode = NtQueryInformationFile(hFile,
+                   &IoStatusBlock,
+                   &FilePosition,
+                   sizeof(FILE_POSITION_INFORMATION),
+                   FilePositionInformation);
+    FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart;
+    if (!NT_SUCCESS(errCode))
+    {
+      if (lpDistanceToMoveHigh != NULL)
+          *lpDistanceToMoveHigh = -1;
+      SetLastErrorByStatus(errCode);
+      return INVALID_SET_FILE_POINTER;
+    }
+    break;
      case FILE_END:
-       NtQueryInformationFile(hFile,
+    errCode = NtQueryInformationFile(hFile,
                                &IoStatusBlock,
                                &FileStandard,
                                sizeof(FILE_STANDARD_INFORMATION),
                                FileStandardInformation);
-        FilePosition.CurrentByteOffset.QuadPart =
+    FilePosition.CurrentByteOffset.QuadPart =
                   FileStandard.EndOfFile.QuadPart + Distance.QuadPart;
-       break;
+    if (!NT_SUCCESS(errCode))
+    {
+      if (lpDistanceToMoveHigh != NULL)
+          *lpDistanceToMoveHigh = -1;
+      SetLastErrorByStatus(errCode);
+      return INVALID_SET_FILE_POINTER;
+    }
+    break;
      case FILE_BEGIN:
         FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart;
-       break;
+    break;
      default:
         SetLastError(ERROR_INVALID_PARAMETER);
-       return -1;
+    return INVALID_SET_FILE_POINTER;
    }
 
    if(FilePosition.CurrentByteOffset.QuadPart < 0)
    {
      SetLastError(ERROR_NEGATIVE_SEEK);
-     return -1;
+     return INVALID_SET_FILE_POINTER;
    }
 
    if (lpDistanceToMoveHigh == NULL && FilePosition.CurrentByteOffset.HighPart != 0)
@@ -443,21 +512,21 @@ SetFilePointer(HANDLE hFile,
      /* If we're moving the pointer outside of the 32 bit boundaries but
         the application only passed a 32 bit value we need to bail out! */
      SetLastError(ERROR_INVALID_PARAMETER);
-     return -1;
+     return INVALID_SET_FILE_POINTER;
    }
 
    errCode = NtSetInformationFile(hFile,
-                                 &IoStatusBlock,
-                                 &FilePosition,
-                                 sizeof(FILE_POSITION_INFORMATION),
-                                 FilePositionInformation);
+                  &IoStatusBlock,
+                  &FilePosition,
+                  sizeof(FILE_POSITION_INFORMATION),
+                  FilePositionInformation);
    if (!NT_SUCCESS(errCode))
      {
        if (lpDistanceToMoveHigh != NULL)
            *lpDistanceToMoveHigh = -1;
 
        SetLastErrorByStatus(errCode);
-       return -1;
+       return INVALID_SET_FILE_POINTER;
      }
 
    if (lpDistanceToMoveHigh != NULL)
@@ -465,7 +534,7 @@ SetFilePointer(HANDLE hFile,
         *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
      }
 
-   if (FilePosition.CurrentByteOffset.u.LowPart == -1)
+   if (FilePosition.CurrentByteOffset.u.LowPart == MAXDWORD)
      {
        /* The value of -1 is valid here, especially when the new
           file position is greater than 4 GB. Since NtSetInformationFile
@@ -483,7 +552,7 @@ SetFilePointer(HANDLE hFile,
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 SetFilePointerEx(HANDLE hFile,
                 LARGE_INTEGER liDistanceToMove,
                 PLARGE_INTEGER lpNewFilePointer,
@@ -555,7 +624,7 @@ SetFilePointerEx(HANDLE hFile,
 /*
  * @implemented
  */
-DWORD STDCALL
+DWORD WINAPI
 GetFileType(HANDLE hFile)
 {
   FILE_FS_DEVICE_INFORMATION DeviceInfo;
@@ -617,7 +686,7 @@ GetFileType(HANDLE hFile)
 /*
  * @implemented
  */
-DWORD STDCALL
+DWORD WINAPI
 GetFileSize(HANDLE hFile,
            LPDWORD lpFileSizeHigh)
 {
@@ -653,7 +722,7 @@ GetFileSize(HANDLE hFile,
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 GetFileSizeEx(
     HANDLE hFile,
     PLARGE_INTEGER lpFileSize
@@ -683,7 +752,7 @@ GetFileSizeEx(
 /*
  * @implemented
  */
-DWORD STDCALL
+DWORD WINAPI
 GetCompressedFileSizeA(LPCSTR lpFileName,
                       LPDWORD lpFileSizeHigh)
 {
@@ -699,7 +768,7 @@ GetCompressedFileSizeA(LPCSTR lpFileName,
 /*
  * @implemented
  */
-DWORD STDCALL
+DWORD WINAPI
 GetCompressedFileSizeW(LPCWSTR lpFileName,
                       LPDWORD lpFileSizeHigh)
 {
@@ -744,7 +813,7 @@ GetCompressedFileSizeW(LPCWSTR lpFileName,
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 GetFileInformationByHandle(HANDLE hFile,
                           LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
 {
@@ -838,7 +907,7 @@ GetFileInformationByHandle(HANDLE hFile,
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 GetFileAttributesExW(LPCWSTR lpFileName,
                     GET_FILEEX_INFO_LEVELS fInfoLevelId,
                     LPVOID lpFileInformation)
@@ -905,7 +974,7 @@ GetFileAttributesExW(LPCWSTR lpFileName,
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 GetFileAttributesExA(LPCSTR lpFileName,
                     GET_FILEEX_INFO_LEVELS fInfoLevelId,
                     LPVOID lpFileInformation)
@@ -922,14 +991,14 @@ GetFileAttributesExA(LPCSTR lpFileName,
 /*
  * @implemented
  */
-DWORD STDCALL
+DWORD WINAPI
 GetFileAttributesA(LPCSTR lpFileName)
 {
    WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
    PWSTR FileNameW;
-       BOOL ret;
+   BOOL ret;
 
-   if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
+   if (!lpFileName || !(FileNameW = FilenameA2W(lpFileName, FALSE)))
       return INVALID_FILE_ATTRIBUTES;
 
    ret = GetFileAttributesExW(FileNameW, GetFileExInfoStandard, &FileAttributeData);
@@ -941,7 +1010,7 @@ GetFileAttributesA(LPCSTR lpFileName)
 /*
  * @implemented
  */
-DWORD STDCALL
+DWORD WINAPI
 GetFileAttributesW(LPCWSTR lpFileName)
 {
   WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
@@ -958,7 +1027,7 @@ GetFileAttributesW(LPCWSTR lpFileName)
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 GetFileAttributesByHandle(IN HANDLE hFile,
                           OUT LPDWORD dwFileAttributes,
                           IN DWORD dwFlags)
@@ -994,7 +1063,7 @@ GetFileAttributesByHandle(IN HANDLE hFile,
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 SetFileAttributesByHandle(IN HANDLE hFile,
                           IN DWORD dwFileAttributes,
                           IN DWORD dwFlags)
@@ -1040,7 +1109,7 @@ SetFileAttributesByHandle(IN HANDLE hFile,
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 SetFileAttributesA(
    LPCSTR lpFileName,
        DWORD dwFileAttributes)
@@ -1057,7 +1126,7 @@ SetFileAttributesA(
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 SetFileAttributesW(LPCWSTR lpFileName,
                   DWORD dwFileAttributes)
 {
@@ -1226,7 +1295,7 @@ UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique, LPWSTR
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 GetFileTime(HANDLE hFile,
            LPFILETIME lpCreationTime,
            LPFILETIME lpLastAccessTime,
@@ -1267,7 +1336,7 @@ GetFileTime(HANDLE hFile,
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 SetFileTime(HANDLE hFile,
            CONST FILETIME *lpCreationTime,
            CONST FILETIME *lpLastAccessTime,
@@ -1323,7 +1392,7 @@ SetFileTime(HANDLE hFile,
  *
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 SetEndOfFile(HANDLE hFile)
 {
        IO_STATUS_BLOCK  IoStatusBlock;
@@ -1400,7 +1469,7 @@ SetEndOfFile(HANDLE hFile)
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 SetFileValidData(
     HANDLE hFile,
     LONGLONG ValidDataLength
@@ -1434,7 +1503,7 @@ SetFileValidData(
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 SetFileShortNameW(
   HANDLE hFile,
   LPCWSTR lpShortName)
@@ -1490,7 +1559,7 @@ SetFileShortNameW(
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 SetFileShortNameA(
     HANDLE hFile,
     LPCSTR lpShortName
@@ -1521,7 +1590,7 @@ SetFileShortNameA(
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 CheckNameLegalDOS8Dot3W(
     LPCWSTR lpName,
     LPSTR lpOemName OPTIONAL,
@@ -1562,7 +1631,7 @@ CheckNameLegalDOS8Dot3W(
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 CheckNameLegalDOS8Dot3A(
     LPCSTR lpName,
     LPSTR lpOemName OPTIONAL,
@@ -1771,4 +1840,208 @@ OpenFileById(IN HANDLE hFile,
     return INVALID_HANDLE_VALUE;
 }
 
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+ReplaceFileA(
+    LPCSTR  lpReplacedFileName,
+    LPCSTR  lpReplacementFileName,
+    LPCSTR  lpBackupFileName,
+    DWORD   dwReplaceFlags,
+    LPVOID  lpExclude,
+    LPVOID  lpReserved
+    )
+{
+    WCHAR *replacedW, *replacementW, *backupW = NULL;
+    BOOL ret;
+
+    /* This function only makes sense when the first two parameters are defined */
+    if (!lpReplacedFileName || !(replacedW = FilenameA2W(lpReplacedFileName, TRUE)))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if (!lpReplacementFileName || !(replacementW = FilenameA2W(lpReplacementFileName, TRUE)))
+    {
+        HeapFree(GetProcessHeap(), 0, replacedW);
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    /* The backup parameter, however, is optional */
+    if (lpBackupFileName)
+    {
+        if (!(backupW = FilenameA2W(lpBackupFileName, TRUE)))
+        {
+            HeapFree(GetProcessHeap(), 0, replacedW);
+            HeapFree(GetProcessHeap(), 0, replacementW);
+            SetLastError(ERROR_INVALID_PARAMETER);
+            return FALSE;
+        }
+    }
+
+    ret = ReplaceFileW(replacedW, replacementW, backupW, dwReplaceFlags, lpExclude, lpReserved);
+    HeapFree(GetProcessHeap(), 0, replacedW);
+    HeapFree(GetProcessHeap(), 0, replacementW);
+    HeapFree(GetProcessHeap(), 0, backupW);
+
+    return ret;
+}
+
+/*
+ * @unimplemented
+ */
+BOOL
+WINAPI
+ReplaceFileW(
+    LPCWSTR lpReplacedFileName,
+    LPCWSTR lpReplacementFileName,
+    LPCWSTR lpBackupFileName,
+    DWORD   dwReplaceFlags,
+    LPVOID  lpExclude,
+    LPVOID  lpReserved
+    )
+{
+    HANDLE hReplaced = NULL, hReplacement = NULL;
+    UNICODE_STRING NtReplacedName = { 0, 0, NULL };
+    UNICODE_STRING NtReplacementName = { 0, 0, NULL };
+    DWORD Error = ERROR_SUCCESS;
+    NTSTATUS Status;
+    BOOL Ret = FALSE;
+    IO_STATUS_BLOCK IoStatusBlock;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    PVOID Buffer = NULL ;
+
+    if (dwReplaceFlags)
+        FIXME("Ignoring flags %x\n", dwReplaceFlags);
+
+    /* First two arguments are mandatory */
+    if (!lpReplacedFileName || !lpReplacementFileName)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    /* Back it up */
+    if(lpBackupFileName)
+    {
+        if(!CopyFileW(lpReplacedFileName, lpBackupFileName, FALSE))
+        {
+            Error = GetLastError();
+            goto Cleanup ;
+        }
+    }
+
+    /* Open the "replaced" file for reading and writing */
+    if (!(RtlDosPathNameToNtPathName_U(lpReplacedFileName, &NtReplacedName, NULL, NULL)))
+    {
+        Error = ERROR_PATH_NOT_FOUND;
+        goto Cleanup;
+    }
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &NtReplacedName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+
+    Status = NtOpenFile(&hReplaced,
+                        GENERIC_READ | GENERIC_WRITE | DELETE | SYNCHRONIZE | WRITE_DAC,
+                        &ObjectAttributes,
+                        &IoStatusBlock,
+                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                        FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
+
+    if (!NT_SUCCESS(Status))
+    {
+        if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+            Error = ERROR_FILE_NOT_FOUND;
+        else
+            Error = ERROR_UNABLE_TO_REMOVE_REPLACED;
+        goto Cleanup;
+    }
+
+    /* Blank it */
+    SetEndOfFile(hReplaced) ;
+
+    /*
+     * Open the replacement file for reading, writing, and deleting
+     * (deleting is needed when finished)
+     */
+    if (!(RtlDosPathNameToNtPathName_U(lpReplacementFileName, &NtReplacementName, NULL, NULL)))
+    {
+        Error = ERROR_PATH_NOT_FOUND;
+        goto Cleanup;
+    }
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &NtReplacementName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+
+    Status = NtOpenFile(&hReplacement,
+                        GENERIC_READ | DELETE | SYNCHRONIZE,
+                        &ObjectAttributes,
+                        &IoStatusBlock,
+                        0,
+                        FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE);
+
+    if (!NT_SUCCESS(Status))
+    {
+        Error = RtlNtStatusToDosError(Status);
+        goto Cleanup;
+    }
+
+    Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 0x10000) ;
+    if (!Buffer)
+    {
+        Error = ERROR_NOT_ENOUGH_MEMORY;
+        goto Cleanup ;
+    }
+    while (Status != STATUS_END_OF_FILE)
+    {
+        Status = NtReadFile(hReplacement, NULL, NULL, NULL, &IoStatusBlock, Buffer, 0x10000, NULL, NULL) ;
+        if (NT_SUCCESS(Status))
+        {
+            Status = NtWriteFile(hReplaced, NULL, NULL, NULL, &IoStatusBlock, Buffer,
+                    IoStatusBlock.Information, NULL, NULL) ;
+            if (!NT_SUCCESS(Status))
+            {
+                Error = RtlNtStatusToDosError(Status);
+                goto Cleanup;
+            }
+        }
+        else if (Status != STATUS_END_OF_FILE)
+        {
+            Error = RtlNtStatusToDosError(Status);
+            goto Cleanup;
+        }
+    }
+
+    Ret = TRUE;
+
+    /* Perform resource cleanup */
+Cleanup:
+    if (hReplaced) NtClose(hReplaced);
+    if (hReplacement) NtClose(hReplacement);
+    if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
+
+    if (NtReplacementName.Buffer)
+        RtlFreeHeap(GetProcessHeap(), 0, NtReplacementName.Buffer);
+    if (NtReplacedName.Buffer)
+        RtlFreeHeap(GetProcessHeap(), 0, NtReplacedName.Buffer);
+
+    /* If there was an error, set the error code */
+    if(!Ret)
+    {
+        TRACE("ReplaceFileW failed (error=%d)\n", Error);
+        SetLastError(Error);
+    }
+    return Ret;
+}
+
 /* EOF */