[KERNEL32] ReplaceFileW:
[reactos.git] / reactos / dll / win32 / kernel32 / file / file.c
index 111601a..cdbafd0 100644 (file)
@@ -239,7 +239,6 @@ OpenFile(LPCSTR lpFileName,
                return HFILE_ERROR;
        }
 
-    lpReOpenBuff->cBytes = sizeof(OFSTRUCT);
     lpReOpenBuff->nErrCode = 0;
 
        if (uStyle & OF_REOPEN) lpFileName = lpReOpenBuff->szPathName;
@@ -265,6 +264,28 @@ OpenFile(LPCSTR lpFileName,
         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;
@@ -371,7 +392,7 @@ OpenFile(LPCSTR lpFileName,
        if (uStyle & OF_EXIST)
        {
                NtClose(FileHandle);
-               return TRUE;
+               return (HFILE)1;
        }
 
        return (HFILE)FileHandle;
@@ -513,7 +534,7 @@ SetFilePointer(HANDLE hFile,
         *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
      }
 
-   if (FilePosition.CurrentByteOffset.u.LowPart == -1U)
+   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
@@ -975,9 +996,9 @@ 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);
@@ -1884,13 +1905,15 @@ ReplaceFileW(
     LPVOID  lpReserved
     )
 {
-    HANDLE hReplaced = NULL, hReplacement = NULL, hBackup = NULL;
-    UNICODE_STRING NtReplacedName, NtReplacementName;
+    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);
@@ -1902,6 +1925,16 @@ ReplaceFileW(
         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)))
     {
@@ -1916,7 +1949,7 @@ ReplaceFileW(
                                NULL);
 
     Status = NtOpenFile(&hReplaced,
-                        GENERIC_READ | GENERIC_WRITE | DELETE | SYNCHRONIZE,
+                        GENERIC_READ | GENERIC_WRITE | DELETE | SYNCHRONIZE | WRITE_DAC,
                         &ObjectAttributes,
                         &IoStatusBlock,
                         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
@@ -1931,9 +1964,12 @@ ReplaceFileW(
         goto Cleanup;
     }
 
+    /* Blank it */
+    SetEndOfFile(hReplaced) ;
+
     /*
      * Open the replacement file for reading, writing, and deleting
-     * (writing and deleting are needed when finished)
+     * (deleting is needed when finished)
      */
     if (!(RtlDosPathNameToNtPathName_U(lpReplacementFileName, &NtReplacementName, NULL, NULL)))
     {
@@ -1948,11 +1984,11 @@ ReplaceFileW(
                                NULL);
 
     Status = NtOpenFile(&hReplacement,
-                        GENERIC_READ | GENERIC_WRITE | DELETE | WRITE_DAC | SYNCHRONIZE,
+                        GENERIC_READ | DELETE | SYNCHRONIZE,
                         &ObjectAttributes,
                         &IoStatusBlock,
                         0,
-                        FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
+                        FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE);
 
     if (!NT_SUCCESS(Status))
     {
@@ -1960,18 +1996,44 @@ ReplaceFileW(
         goto Cleanup;
     }
 
-    /* Not success :( */
-    FIXME("ReplaceFileW not implemented, but it is returned TRUE!\n");
+    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 (hBackup) NtClose(hBackup);
     if (hReplaced) NtClose(hReplaced);
     if (hReplacement) NtClose(hReplacement);
+    if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
 
-    RtlFreeUnicodeString(&NtReplacementName);
-    RtlFreeUnicodeString(&NtReplacedName);
+    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)