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/fi…
==============================================================================
--- 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);