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/fil... ============================================================================== --- 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);