[kernel32]

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

svn path=/trunk/; revision=44383
This commit is contained in:
Gregor Schneider 2009-12-03 18:41:53 +00:00
parent 9b49e5e810
commit 76e69bee97

View file

@ -1905,13 +1905,14 @@ ReplaceFileW(
LPVOID lpReserved LPVOID lpReserved
) )
{ {
HANDLE hReplaced = NULL, hReplacement = NULL, hBackup = NULL; HANDLE hReplaced = NULL, hReplacement = NULL;
UNICODE_STRING NtReplacedName, NtReplacementName; UNICODE_STRING NtReplacedName, NtReplacementName;
DWORD Error = ERROR_SUCCESS; DWORD Error = ERROR_SUCCESS;
NTSTATUS Status; NTSTATUS Status;
BOOL Ret = FALSE; BOOL Ret = FALSE;
IO_STATUS_BLOCK IoStatusBlock; IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
PVOID Buffer = NULL ;
if (dwReplaceFlags) if (dwReplaceFlags)
FIXME("Ignoring flags %x\n", dwReplaceFlags); FIXME("Ignoring flags %x\n", dwReplaceFlags);
@ -1923,6 +1924,16 @@ ReplaceFileW(
return FALSE; return FALSE;
} }
/* Back it up */
if(lpBackupFileName)
{
if(!CopyFileW(lpReplacedFileName, lpBackupFileName, FALSE))
{
Error = GetLastError();
goto Cleanup ;
}
}
/* Open the "replaced" file for reading and writing */ /* Open the "replaced" file for reading and writing */
if (!(RtlDosPathNameToNtPathName_U(lpReplacedFileName, &NtReplacedName, NULL, NULL))) if (!(RtlDosPathNameToNtPathName_U(lpReplacedFileName, &NtReplacedName, NULL, NULL)))
{ {
@ -1937,7 +1948,7 @@ ReplaceFileW(
NULL); NULL);
Status = NtOpenFile(&hReplaced, Status = NtOpenFile(&hReplaced,
GENERIC_READ | GENERIC_WRITE | DELETE | SYNCHRONIZE, GENERIC_READ | GENERIC_WRITE | DELETE | SYNCHRONIZE | WRITE_DAC,
&ObjectAttributes, &ObjectAttributes,
&IoStatusBlock, &IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
@ -1952,9 +1963,12 @@ ReplaceFileW(
goto Cleanup; goto Cleanup;
} }
/* Blank it */
SetEndOfFile(hReplaced) ;
/* /*
* Open the replacement file for reading, writing, and deleting * 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))) if (!(RtlDosPathNameToNtPathName_U(lpReplacementFileName, &NtReplacementName, NULL, NULL)))
{ {
@ -1969,11 +1983,11 @@ ReplaceFileW(
NULL); NULL);
Status = NtOpenFile(&hReplacement, Status = NtOpenFile(&hReplacement,
GENERIC_READ | GENERIC_WRITE | DELETE | WRITE_DAC | SYNCHRONIZE, GENERIC_READ | DELETE | SYNCHRONIZE,
&ObjectAttributes, &ObjectAttributes,
&IoStatusBlock, &IoStatusBlock,
0, 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)) if (!NT_SUCCESS(Status))
{ {
@ -1981,15 +1995,39 @@ ReplaceFileW(
goto Cleanup; goto Cleanup;
} }
/* Not success :( */ Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 0x10000) ;
FIXME("ReplaceFileW not implemented, but it is returned TRUE!\n"); 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; Ret = TRUE;
/* Perform resource cleanup */ /* Perform resource cleanup */
Cleanup: Cleanup:
if (hBackup) NtClose(hBackup);
if (hReplaced) NtClose(hReplaced); if (hReplaced) NtClose(hReplaced);
if (hReplacement) NtClose(hReplacement); if (hReplacement) NtClose(hReplacement);
if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
RtlFreeUnicodeString(&NtReplacementName); RtlFreeUnicodeString(&NtReplacementName);
RtlFreeUnicodeString(&NtReplacedName); RtlFreeUnicodeString(&NtReplacedName);