[ros-diffs] [gschneider] 44383: [kernel32] - Jerome Gardou <jerome DOT gardou AT laposte DOT net>: Implement missing ReplaceFileW functionality - Fixes six kernel32 file winetests, bug #4827

gschneider at svn.reactos.org gschneider at svn.reactos.org
Thu Dec 3 19:41:53 CET 2009


Author: gschneider
Date: Thu Dec  3 19:41:53 2009
New Revision: 44383

URL: http://svn.reactos.org/svn/reactos?rev=44383&view=rev
Log:
[kernel32]
- Jerome Gardou <jerome DOT gardou AT laposte DOT net>: Implement missing ReplaceFileW functionality
- Fixes six kernel32 file winetests, bug #4827

Modified:
    trunk/reactos/dll/win32/kernel32/file/file.c

Modified: trunk/reactos/dll/win32/kernel32/file/file.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/file/file.c?rev=44383&r1=44382&r2=44383&view=diff
==============================================================================
--- trunk/reactos/dll/win32/kernel32/file/file.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/file/file.c [iso-8859-1] Thu Dec  3 19:41:53 2009
@@ -1905,13 +1905,14 @@
     LPVOID  lpReserved
     )
 {
-    HANDLE hReplaced = NULL, hReplacement = NULL, hBackup = NULL;
+    HANDLE hReplaced = NULL, hReplacement = NULL;
     UNICODE_STRING NtReplacedName, NtReplacementName;
     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);
@@ -1921,6 +1922,16 @@
     {
         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 */
@@ -1937,7 +1948,7 @@
                                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,
@@ -1952,9 +1963,12 @@
         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)))
     {
@@ -1969,11 +1983,11 @@
                                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))
     {
@@ -1981,15 +1995,39 @@
         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);




More information about the Ros-diffs mailing list