From b6c94018823f0217dcc9e5ecf1f100ba9ef12b96 Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard@winehq.org>
Date: Tue, 5 May 2020 13:10:03 +0200
Subject: [PATCH] kernel32: Move some file functions to kernelbase.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
---
 dlls/kernel32/file.c            | 326 ---------------
 dlls/kernel32/kernel32.spec     |  22 +-
 dlls/kernel32/path.c            | 449 --------------------
 dlls/kernelbase/file.c          | 700 ++++++++++++++++++++++++++++++++
 dlls/kernelbase/kernelbase.spec |  20 +-
 5 files changed, 721 insertions(+), 796 deletions(-)

diff --git a/dlls/kernel32/file.c b/dlls/kernel32/file.c
index 9bd5e0ec7b8..502a4983e8f 100644
--- a/dlls/kernel32/file.c
+++ b/dlls/kernel32/file.c
@@ -415,121 +415,6 @@ BOOL WINAPI KERNEL32_FlushFileBuffers( HANDLE file )
  **************************************************************************/
 
 
-/**************************************************************************
- *           ReplaceFileW   (KERNEL32.@)
- *           ReplaceFile    (KERNEL32.@)
- */
-BOOL WINAPI ReplaceFileW(LPCWSTR lpReplacedFileName, LPCWSTR lpReplacementFileName,
-                         LPCWSTR lpBackupFileName, DWORD dwReplaceFlags,
-                         LPVOID lpExclude, LPVOID lpReserved)
-{
-    UNICODE_STRING nt_replaced_name, nt_replacement_name;
-    HANDLE hReplacement = NULL;
-    NTSTATUS status;
-    IO_STATUS_BLOCK io;
-    OBJECT_ATTRIBUTES attr;
-    FILE_BASIC_INFORMATION info;
-
-    TRACE("%s %s %s 0x%08x %p %p\n", debugstr_w(lpReplacedFileName),
-          debugstr_w(lpReplacementFileName), debugstr_w(lpBackupFileName),
-          dwReplaceFlags, lpExclude, lpReserved);
-
-    if (dwReplaceFlags)
-        FIXME("Ignoring flags %x\n", dwReplaceFlags);
-
-    /* First two arguments are mandatory */
-    if (!lpReplacedFileName || !lpReplacementFileName)
-    {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        return FALSE;
-    }
-
-    attr.Length = sizeof(attr);
-    attr.RootDirectory = 0;
-    attr.Attributes = OBJ_CASE_INSENSITIVE;
-    attr.ObjectName = NULL;
-    attr.SecurityDescriptor = NULL;
-    attr.SecurityQualityOfService = NULL;
-
-    /* Open the "replaced" file for reading */
-    if (!(RtlDosPathNameToNtPathName_U(lpReplacedFileName, &nt_replaced_name, NULL, NULL)))
-    {
-        SetLastError( ERROR_PATH_NOT_FOUND );
-        return FALSE;
-    }
-    attr.ObjectName = &nt_replaced_name;
-
-    /* Replacement should fail if replaced is READ_ONLY */
-    status = NtQueryAttributesFile(&attr, &info);
-    RtlFreeUnicodeString(&nt_replaced_name);
-    if (status != STATUS_SUCCESS)
-        return set_ntstatus( status );
-
-    if (info.FileAttributes & FILE_ATTRIBUTE_READONLY)
-    {
-        SetLastError( ERROR_ACCESS_DENIED );
-        return FALSE;
-    }
-
-    /*
-     * Open the replacement file for reading, writing, and deleting
-     * (writing and deleting are needed when finished)
-     */
-    if (!(RtlDosPathNameToNtPathName_U(lpReplacementFileName, &nt_replacement_name, NULL, NULL)))
-    {
-        SetLastError( ERROR_PATH_NOT_FOUND );
-        return FALSE;
-    }
-    attr.ObjectName = &nt_replacement_name;
-    status = NtOpenFile(&hReplacement,
-                        GENERIC_READ|GENERIC_WRITE|DELETE|WRITE_DAC|SYNCHRONIZE,
-                        &attr, &io, 0,
-                        FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE);
-    RtlFreeUnicodeString(&nt_replacement_name);
-    if (status != STATUS_SUCCESS)
-        return set_ntstatus( status );
-    NtClose( hReplacement );
-
-    /* If the user wants a backup then that needs to be performed first */
-    if (lpBackupFileName)
-    {
-        if (!MoveFileExW( lpReplacedFileName, lpBackupFileName, MOVEFILE_REPLACE_EXISTING ))
-            return FALSE;
-    }
-    else
-    {
-        /* ReplaceFile() can replace an open target. To do this, we need to move
-         * it out of the way first. */
-        static const WCHAR prefixW[] = {'r','f',0};
-        WCHAR temp_path[MAX_PATH], temp_file[MAX_PATH];
-
-        lstrcpynW( temp_path, lpReplacedFileName, ARRAY_SIZE( temp_path ) );
-        PathRemoveFileSpecW( temp_path );
-        if (!GetTempFileNameW( temp_path, prefixW, 0, temp_file )
-                || !MoveFileExW( lpReplacedFileName, temp_file, MOVEFILE_REPLACE_EXISTING ))
-            return FALSE;
-
-        DeleteFileW( temp_file );
-    }
-
-    /*
-     * Now that the backup has been performed (if requested), copy the replacement
-     * into place
-     */
-    if (!MoveFileExW( lpReplacementFileName, lpReplacedFileName, 0 ))
-    {
-        /* on failure we need to indicate whether a backup was made */
-        if (!lpBackupFileName)
-            SetLastError( ERROR_UNABLE_TO_MOVE_REPLACEMENT );
-        else
-            SetLastError( ERROR_UNABLE_TO_MOVE_REPLACEMENT_2 );
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-
 /**************************************************************************
  *           ReplaceFileA (KERNEL32.@)
  */
@@ -865,214 +750,3 @@ DWORD WINAPI K32GetDeviceDriverFileNameW(void *image_base, LPWSTR file_name, DWO
 
     return 0;
 }
-
-/***********************************************************************
- *           GetFinalPathNameByHandleW (KERNEL32.@)
- */
-DWORD WINAPI GetFinalPathNameByHandleW(HANDLE file, LPWSTR path, DWORD charcount, DWORD flags)
-{
-    WCHAR buffer[sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH + 1];
-    OBJECT_NAME_INFORMATION *info = (OBJECT_NAME_INFORMATION*)&buffer;
-    WCHAR drive_part[MAX_PATH];
-    DWORD drive_part_len = 0;
-    NTSTATUS status;
-    DWORD result = 0;
-    ULONG dummy;
-    WCHAR *ptr;
-
-    TRACE( "(%p,%p,%d,%x)\n", file, path, charcount, flags );
-
-    if (flags & ~(FILE_NAME_OPENED | VOLUME_NAME_GUID | VOLUME_NAME_NONE | VOLUME_NAME_NT))
-    {
-        WARN("Unknown flags: %x\n", flags);
-        SetLastError( ERROR_INVALID_PARAMETER );
-        return 0;
-    }
-
-    /* get object name */
-    status = NtQueryObject( file, ObjectNameInformation, &buffer, sizeof(buffer) - sizeof(WCHAR), &dummy );
-    if (status != STATUS_SUCCESS)
-    {
-        SetLastError( RtlNtStatusToDosError( status ) );
-        return 0;
-    }
-    if (!info->Name.Buffer)
-    {
-        SetLastError( ERROR_INVALID_HANDLE );
-        return 0;
-    }
-    if (info->Name.Length < 4 * sizeof(WCHAR) || info->Name.Buffer[0] != '\\' ||
-             info->Name.Buffer[1] != '?' || info->Name.Buffer[2] != '?' || info->Name.Buffer[3] != '\\' )
-    {
-        FIXME("Unexpected object name: %s\n", debugstr_wn(info->Name.Buffer, info->Name.Length / sizeof(WCHAR)));
-        SetLastError( ERROR_GEN_FAILURE );
-        return 0;
-    }
-
-    /* add terminating null character, remove "\\??\\" */
-    info->Name.Buffer[info->Name.Length / sizeof(WCHAR)] = 0;
-    info->Name.Length -= 4 * sizeof(WCHAR);
-    info->Name.Buffer += 4;
-
-    /* FILE_NAME_OPENED is not supported yet, and would require Wineserver changes */
-    if (flags & FILE_NAME_OPENED)
-    {
-        FIXME("FILE_NAME_OPENED not supported\n");
-        flags &= ~FILE_NAME_OPENED;
-    }
-
-    /* Get information required for VOLUME_NAME_NONE, VOLUME_NAME_GUID and VOLUME_NAME_NT */
-    if (flags == VOLUME_NAME_NONE || flags == VOLUME_NAME_GUID || flags == VOLUME_NAME_NT)
-    {
-        if (!GetVolumePathNameW( info->Name.Buffer, drive_part, MAX_PATH ))
-            return 0;
-
-        drive_part_len = strlenW(drive_part);
-        if (!drive_part_len || drive_part_len > strlenW(info->Name.Buffer) ||
-                drive_part[drive_part_len-1] != '\\' ||
-                strncmpiW( info->Name.Buffer, drive_part, drive_part_len ))
-        {
-            FIXME("Path %s returned by GetVolumePathNameW does not match file path %s\n",
-                debugstr_w(drive_part), debugstr_w(info->Name.Buffer));
-            SetLastError( ERROR_GEN_FAILURE );
-            return 0;
-        }
-    }
-
-    if (flags == VOLUME_NAME_NONE)
-    {
-        ptr    = info->Name.Buffer + drive_part_len - 1;
-        result = strlenW(ptr);
-        if (result < charcount)
-            memcpy(path, ptr, (result + 1) * sizeof(WCHAR));
-        else result++;
-    }
-    else if (flags == VOLUME_NAME_GUID)
-    {
-        WCHAR volume_prefix[51];
-
-        /* GetVolumeNameForVolumeMountPointW sets error code on failure */
-        if (!GetVolumeNameForVolumeMountPointW( drive_part, volume_prefix, 50 ))
-            return 0;
-
-        ptr    = info->Name.Buffer + drive_part_len;
-        result = strlenW(volume_prefix) + strlenW(ptr);
-        if (result < charcount)
-        {
-            path[0] = 0;
-            strcatW(path, volume_prefix);
-            strcatW(path, ptr);
-        }
-        else
-        {
-            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-            result++;
-        }
-    }
-    else if (flags == VOLUME_NAME_NT)
-    {
-        WCHAR nt_prefix[MAX_PATH];
-
-        /* QueryDosDeviceW sets error code on failure */
-        drive_part[drive_part_len - 1] = 0;
-        if (!QueryDosDeviceW( drive_part, nt_prefix, MAX_PATH ))
-            return 0;
-
-        ptr    = info->Name.Buffer + drive_part_len - 1;
-        result = strlenW(nt_prefix) + strlenW(ptr);
-        if (result < charcount)
-        {
-            path[0] = 0;
-            strcatW(path, nt_prefix);
-            strcatW(path, ptr);
-        }
-        else
-        {
-            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-            result++;
-        }
-    }
-    else if (flags == VOLUME_NAME_DOS)
-    {
-        static const WCHAR dos_prefix[] = {'\\','\\','?','\\', '\0'};
-
-        result = strlenW(dos_prefix) + strlenW(info->Name.Buffer);
-        if (result < charcount)
-        {
-            path[0] = 0;
-            strcatW(path, dos_prefix);
-            strcatW(path, info->Name.Buffer);
-        }
-        else
-        {
-            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-            result++;
-        }
-    }
-    else
-    {
-        /* Windows crashes here, but we prefer returning ERROR_INVALID_PARAMETER */
-        WARN("Invalid combination of flags: %x\n", flags);
-        SetLastError( ERROR_INVALID_PARAMETER );
-    }
-
-    return result;
-}
-
-/***********************************************************************
- *           GetFinalPathNameByHandleA (KERNEL32.@)
- */
-DWORD WINAPI GetFinalPathNameByHandleA(HANDLE file, LPSTR path, DWORD charcount, DWORD flags)
-{
-    WCHAR *str;
-    DWORD result, len, cp;
-
-    TRACE( "(%p,%p,%d,%x)\n", file, path, charcount, flags);
-
-    len = GetFinalPathNameByHandleW(file, NULL, 0, flags);
-    if (len == 0)
-        return 0;
-
-    str = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
-    if (!str)
-    {
-        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-        return 0;
-    }
-
-    result = GetFinalPathNameByHandleW(file, str, len, flags);
-    if (result != len - 1)
-    {
-        HeapFree(GetProcessHeap(), 0, str);
-        WARN("GetFinalPathNameByHandleW failed unexpectedly: %u\n", result);
-        return 0;
-    }
-
-    cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
-
-    len = WideCharToMultiByte(cp, 0, str, -1, NULL, 0, NULL, NULL);
-    if (!len)
-    {
-        HeapFree(GetProcessHeap(), 0, str);
-        WARN("Failed to get multibyte length\n");
-        return 0;
-    }
-
-    if (charcount < len)
-    {
-        HeapFree(GetProcessHeap(), 0, str);
-        return len - 1;
-    }
-
-    len = WideCharToMultiByte(cp, 0, str, -1, path, charcount, NULL, NULL);
-    if (!len)
-    {
-        HeapFree(GetProcessHeap(), 0, str);
-        WARN("WideCharToMultiByte failed\n");
-        return 0;
-    }
-
-    HeapFree(GetProcessHeap(), 0, str);
-
-    return len - 1;
-}
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index cb3edf384cb..db9d93e52aa 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -258,10 +258,10 @@
 # @ stub CopyContext
 @ stdcall CopyFileA(str str long)
 @ stdcall CopyFileExA (str str ptr ptr ptr long)
-@ stdcall CopyFileExW (wstr wstr ptr ptr ptr long)
+@ stdcall -import CopyFileExW(wstr wstr ptr ptr ptr long)
 # @ stub CopyFileTransactedA
 # @ stub CopyFileTransactedW
-@ stdcall CopyFileW(wstr wstr long)
+@ stdcall -import CopyFileW(wstr wstr long)
 @ stdcall CopyLZFile(long long) LZCopy
 @ stdcall CreateActCtxA(ptr)
 @ stdcall -import CreateActCtxW(ptr)
@@ -287,10 +287,10 @@
 @ stdcall -import CreateFileMappingNumaW(long ptr long long long wstr long)
 @ stdcall -import CreateFileMappingW(long ptr long long long wstr)
 @ stdcall -import CreateFileW(wstr long long ptr long long long)
-@ stdcall CreateHardLinkA(str str ptr)
+@ stdcall -import CreateHardLinkA(str str ptr)
 @ stdcall CreateHardLinkTransactedA(str str ptr ptr)
 @ stdcall CreateHardLinkTransactedW(wstr wstr ptr ptr)
-@ stdcall CreateHardLinkW(wstr wstr ptr)
+@ stdcall -import CreateHardLinkW(wstr wstr ptr)
 @ stdcall -import CreateIoCompletionPort(long long long long)
 @ stdcall CreateJobObjectA(ptr str)
 @ stdcall CreateJobObjectW(ptr wstr)
@@ -326,7 +326,7 @@
 @ stdcall CreateSymbolicLinkA(str str long)
 # @ stub CreateSymbolicLinkTransactedA
 # @ stub CreateSymbolicLinkTransactedW
-@ stdcall CreateSymbolicLinkW(wstr wstr long)
+@ stdcall -import CreateSymbolicLinkW(wstr wstr long)
 @ stdcall CreateTapePartition(long long long long)
 @ stdcall -import CreateThread(ptr long ptr long long ptr)
 @ stdcall -import CreateThreadpool(ptr)
@@ -684,8 +684,8 @@
 @ stdcall -import GetFileSizeEx(long ptr)
 @ stdcall -import GetFileTime(long ptr ptr ptr)
 @ stdcall -import GetFileType(long)
-@ stdcall GetFinalPathNameByHandleA(long ptr long long)
-@ stdcall GetFinalPathNameByHandleW(long ptr long long)
+@ stdcall -import GetFinalPathNameByHandleA(long ptr long long)
+@ stdcall -import GetFinalPathNameByHandleW(long ptr long long)
 @ stdcall GetFirmwareEnvironmentVariableA(str str ptr long)
 @ stdcall GetFirmwareEnvironmentVariableW(wstr wstr ptr long)
 @ stdcall -import GetFullPathNameA(str long ptr ptr)
@@ -1091,12 +1091,12 @@
 @ stdcall Module32NextW(long ptr)
 @ stdcall MoveFileA(str str)
 @ stdcall MoveFileExA(str str long)
-@ stdcall MoveFileExW(wstr wstr long)
+@ stdcall -import MoveFileExW(wstr wstr long)
 @ stdcall MoveFileTransactedA(str str ptr ptr long ptr)
 @ stdcall MoveFileTransactedW(wstr wstr ptr ptr long ptr)
 @ stdcall MoveFileW(wstr wstr)
 @ stdcall MoveFileWithProgressA(str str ptr ptr long)
-@ stdcall MoveFileWithProgressW(wstr wstr ptr ptr long)
+@ stdcall -import MoveFileWithProgressW(wstr wstr ptr ptr long)
 @ stdcall MulDiv(long long long)
 @ stdcall -import MultiByteToWideChar(long long str long ptr long)
 @ stdcall -import NeedCurrentDirectoryForExePathA(str)
@@ -1273,9 +1273,9 @@
 @ stdcall RemoveVectoredContinueHandler(ptr) ntdll.RtlRemoveVectoredContinueHandler
 @ stdcall RemoveVectoredExceptionHandler(ptr) ntdll.RtlRemoveVectoredExceptionHandler
 @ stdcall -import ReOpenFile(ptr long long long) ReOpenFile
-@ stdcall ReplaceFile(wstr wstr wstr long ptr ptr) ReplaceFileW
+@ stdcall -import ReplaceFile(wstr wstr wstr long ptr ptr) ReplaceFileW
 @ stdcall ReplaceFileA(str str str long ptr ptr)
-@ stdcall ReplaceFileW(wstr wstr wstr long ptr ptr)
+@ stdcall -import ReplaceFileW(wstr wstr wstr long ptr ptr)
 # @ stub RemoveDirectoryTransactedA
 # @ stub RemoveDirectoryTransactedW
 @ stdcall -import RemoveDllDirectory(ptr)
diff --git a/dlls/kernel32/path.c b/dlls/kernel32/path.c
index 54dbf5a4f6f..0f075d0af1c 100644
--- a/dlls/kernel32/path.c
+++ b/dlls/kernel32/path.c
@@ -72,153 +72,6 @@ static DWORD copy_filename_WtoA( LPCWSTR nameW, LPSTR buffer, DWORD len )
     return ret;
 }
 
-/***********************************************************************
- *           add_boot_rename_entry
- *
- * Adds an entry to the registry that is loaded when windows boots and
- * checks if there are some files to be removed or renamed/moved.
- * <fn1> has to be valid and <fn2> may be NULL. If both pointers are
- * non-NULL then the file is moved, otherwise it is deleted.  The
- * entry of the registry key is always appended with two zero
- * terminated strings. If <fn2> is NULL then the second entry is
- * simply a single 0-byte. Otherwise the second filename goes
- * there. The entries are prepended with \??\ before the path and the
- * second filename gets also a '!' as the first character if
- * MOVEFILE_REPLACE_EXISTING is set. After the final string another
- * 0-byte follows to indicate the end of the strings.
- * i.e.:
- * \??\D:\test\file1[0]
- * !\??\D:\test\file1_renamed[0]
- * \??\D:\Test|delete[0]
- * [0]                        <- file is to be deleted, second string empty
- * \??\D:\test\file2[0]
- * !\??\D:\test\file2_renamed[0]
- * [0]                        <- indicates end of strings
- *
- * or:
- * \??\D:\test\file1[0]
- * !\??\D:\test\file1_renamed[0]
- * \??\D:\Test|delete[0]
- * [0]                        <- file is to be deleted, second string empty
- * [0]                        <- indicates end of strings
- *
- */
-static BOOL add_boot_rename_entry( LPCWSTR source, LPCWSTR dest, DWORD flags )
-{
-    static const WCHAR ValueName[] = {'P','e','n','d','i','n','g',
-                                      'F','i','l','e','R','e','n','a','m','e',
-                                      'O','p','e','r','a','t','i','o','n','s',0};
-    static const WCHAR SessionW[] = {'\\','R','e','g','i','s','t','r','y','\\',
-                                     'M','a','c','h','i','n','e','\\',
-                                     'S','y','s','t','e','m','\\',
-                                     'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
-                                     'C','o','n','t','r','o','l','\\',
-                                     'S','e','s','s','i','o','n',' ','M','a','n','a','g','e','r',0};
-    static const int info_size = FIELD_OFFSET( KEY_VALUE_PARTIAL_INFORMATION, Data );
-
-    OBJECT_ATTRIBUTES attr;
-    UNICODE_STRING nameW, source_name, dest_name;
-    KEY_VALUE_PARTIAL_INFORMATION *info;
-    BOOL rc = FALSE;
-    HANDLE Reboot = 0;
-    DWORD len1, len2;
-    DWORD DataSize = 0;
-    BYTE *Buffer = NULL;
-    WCHAR *p;
-
-    if (!RtlDosPathNameToNtPathName_U( source, &source_name, NULL, NULL ))
-    {
-        SetLastError( ERROR_PATH_NOT_FOUND );
-        return FALSE;
-    }
-    dest_name.Buffer = NULL;
-    if (dest && !RtlDosPathNameToNtPathName_U( dest, &dest_name, NULL, NULL ))
-    {
-        RtlFreeUnicodeString( &source_name );
-        SetLastError( ERROR_PATH_NOT_FOUND );
-        return FALSE;
-    }
-
-    attr.Length = sizeof(attr);
-    attr.RootDirectory = 0;
-    attr.ObjectName = &nameW;
-    attr.Attributes = 0;
-    attr.SecurityDescriptor = NULL;
-    attr.SecurityQualityOfService = NULL;
-    RtlInitUnicodeString( &nameW, SessionW );
-
-    if (NtCreateKey( &Reboot, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ) != STATUS_SUCCESS)
-    {
-        WARN("Error creating key for reboot management [%s]\n",
-             "SYSTEM\\CurrentControlSet\\Control\\Session Manager");
-        RtlFreeUnicodeString( &source_name );
-        RtlFreeUnicodeString( &dest_name );
-        return FALSE;
-    }
-
-    len1 = source_name.Length + sizeof(WCHAR);
-    if (dest)
-    {
-        len2 = dest_name.Length + sizeof(WCHAR);
-        if (flags & MOVEFILE_REPLACE_EXISTING)
-            len2 += sizeof(WCHAR); /* Plus 1 because of the leading '!' */
-    }
-    else len2 = sizeof(WCHAR); /* minimum is the 0 characters for the empty second string */
-
-    RtlInitUnicodeString( &nameW, ValueName );
-
-    /* First we check if the key exists and if so how many bytes it already contains. */
-    if (NtQueryValueKey( Reboot, &nameW, KeyValuePartialInformation,
-                         NULL, 0, &DataSize ) == STATUS_BUFFER_TOO_SMALL)
-    {
-        if (!(Buffer = HeapAlloc( GetProcessHeap(), 0, DataSize + len1 + len2 + sizeof(WCHAR) )))
-            goto Quit;
-        if (NtQueryValueKey( Reboot, &nameW, KeyValuePartialInformation,
-                             Buffer, DataSize, &DataSize )) goto Quit;
-        info = (KEY_VALUE_PARTIAL_INFORMATION *)Buffer;
-        if (info->Type != REG_MULTI_SZ) goto Quit;
-        if (DataSize > sizeof(info)) DataSize -= sizeof(WCHAR);  /* remove terminating null (will be added back later) */
-    }
-    else
-    {
-        DataSize = info_size;
-        if (!(Buffer = HeapAlloc( GetProcessHeap(), 0, DataSize + len1 + len2 + sizeof(WCHAR) )))
-            goto Quit;
-    }
-
-    memcpy( Buffer + DataSize, source_name.Buffer, len1 );
-    DataSize += len1;
-    p = (WCHAR *)(Buffer + DataSize);
-    if (dest)
-    {
-        if (flags & MOVEFILE_REPLACE_EXISTING)
-            *p++ = '!';
-        memcpy( p, dest_name.Buffer, len2 );
-        DataSize += len2;
-    }
-    else
-    {
-        *p = 0;
-        DataSize += sizeof(WCHAR);
-    }
-
-    /* add final null */
-    p = (WCHAR *)(Buffer + DataSize);
-    *p = 0;
-    DataSize += sizeof(WCHAR);
-
-    rc = !NtSetValueKey(Reboot, &nameW, 0, REG_MULTI_SZ, Buffer + info_size, DataSize - info_size);
-
- Quit:
-    RtlFreeUnicodeString( &source_name );
-    RtlFreeUnicodeString( &dest_name );
-    if (Reboot) NtClose(Reboot);
-    HeapFree( GetProcessHeap(), 0, Buffer );
-    return(rc);
-}
-
-
-
 /***********************************************************************
  *           GetShortPathNameA   (KERNEL32.@)
  */
@@ -244,26 +97,6 @@ DWORD WINAPI GetShortPathNameA( LPCSTR longpath, LPSTR shortpath, DWORD shortlen
 }
 
 
-static BOOL is_same_file(HANDLE h1, HANDLE h2)
-{
-    FILE_ID_INFORMATION id1, id2;
-    IO_STATUS_BLOCK io;
-
-    return !NtQueryInformationFile( h1, &io, &id1, sizeof(id1), FileIdInformation )
-            && !NtQueryInformationFile( h2, &io, &id2, sizeof(id2), FileIdInformation )
-            && !memcmp( &id1, &id2, sizeof(FILE_ID_INFORMATION) );
-}
-
-/**************************************************************************
- *           CopyFileW   (KERNEL32.@)
- */
-BOOL WINAPI CopyFileW( LPCWSTR source, LPCWSTR dest, BOOL fail_if_exists )
-{
-    return CopyFileExW( source, dest, NULL, NULL, NULL,
-                        fail_if_exists ? COPY_FILE_FAIL_IF_EXISTS : 0 );
-}
-
-
 /**************************************************************************
  *           CopyFileA   (KERNEL32.@)
  */
@@ -282,101 +115,6 @@ BOOL WINAPI CopyFileA( LPCSTR source, LPCSTR dest, BOOL fail_if_exists)
 }
 
 
-/**************************************************************************
- *           CopyFileExW   (KERNEL32.@)
- */
-BOOL WINAPI CopyFileExW(LPCWSTR source, LPCWSTR dest,
-                        LPPROGRESS_ROUTINE progress, LPVOID param,
-                        LPBOOL cancel_ptr, DWORD flags)
-{
-    static const int buffer_size = 65536;
-    HANDLE h1, h2;
-    BY_HANDLE_FILE_INFORMATION info;
-    DWORD count;
-    BOOL ret = FALSE;
-    char *buffer;
-
-    if (!source || !dest)
-    {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        return FALSE;
-    }
-    if (!(buffer = HeapAlloc( GetProcessHeap(), 0, buffer_size )))
-    {
-        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-        return FALSE;
-    }
-
-    TRACE("%s -> %s, %x\n", debugstr_w(source), debugstr_w(dest), flags);
-
-    if ((h1 = CreateFileW(source, GENERIC_READ,
-                     FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                     NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
-    {
-        WARN("Unable to open source %s\n", debugstr_w(source));
-        HeapFree( GetProcessHeap(), 0, buffer );
-        return FALSE;
-    }
-
-    if (!GetFileInformationByHandle( h1, &info ))
-    {
-        WARN("GetFileInformationByHandle returned error for %s\n", debugstr_w(source));
-        HeapFree( GetProcessHeap(), 0, buffer );
-        CloseHandle( h1 );
-        return FALSE;
-    }
-
-    if (!(flags & COPY_FILE_FAIL_IF_EXISTS))
-    {
-        BOOL same_file = FALSE;
-        h2 = CreateFileW( dest, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
-                         OPEN_EXISTING, 0, 0);
-        if (h2 != INVALID_HANDLE_VALUE)
-        {
-            same_file = is_same_file( h1, h2 );
-            CloseHandle( h2 );
-        }
-        if (same_file)
-        {
-            HeapFree( GetProcessHeap(), 0, buffer );
-            CloseHandle( h1 );
-            SetLastError( ERROR_SHARING_VIOLATION );
-            return FALSE;
-        }
-    }
-
-    if ((h2 = CreateFileW( dest, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
-                             (flags & COPY_FILE_FAIL_IF_EXISTS) ? CREATE_NEW : CREATE_ALWAYS,
-                             info.dwFileAttributes, h1 )) == INVALID_HANDLE_VALUE)
-    {
-        WARN("Unable to open dest %s\n", debugstr_w(dest));
-        HeapFree( GetProcessHeap(), 0, buffer );
-        CloseHandle( h1 );
-        return FALSE;
-    }
-
-    while (ReadFile( h1, buffer, buffer_size, &count, NULL ) && count)
-    {
-        char *p = buffer;
-        while (count != 0)
-        {
-            DWORD res;
-            if (!WriteFile( h2, p, count, &res, NULL ) || !res) goto done;
-            p += res;
-            count -= res;
-        }
-    }
-    ret =  TRUE;
-done:
-    /* Maintain the timestamp of source file to destination file */
-    SetFileTime(h2, NULL, NULL, &info.ftLastWriteTime);
-    HeapFree( GetProcessHeap(), 0, buffer );
-    CloseHandle( h1 );
-    CloseHandle( h2 );
-    return ret;
-}
-
-
 /**************************************************************************
  *           CopyFileExA   (KERNEL32.@)
  */
@@ -421,95 +159,6 @@ BOOL WINAPI MoveFileTransactedW(const WCHAR *source, const WCHAR *dest, LPPROGRE
     return FALSE;
 }
 
-/**************************************************************************
- *           MoveFileWithProgressW   (KERNEL32.@)
- */
-BOOL WINAPI MoveFileWithProgressW( LPCWSTR source, LPCWSTR dest,
-                                   LPPROGRESS_ROUTINE fnProgress,
-                                   LPVOID param, DWORD flag )
-{
-    FILE_RENAME_INFORMATION *rename_info;
-    FILE_BASIC_INFORMATION info;
-    UNICODE_STRING nt_name;
-    OBJECT_ATTRIBUTES attr;
-    IO_STATUS_BLOCK io;
-    NTSTATUS status;
-    HANDLE source_handle = 0;
-    ULONG size;
-
-    TRACE("(%s,%s,%p,%p,%04x)\n",
-          debugstr_w(source), debugstr_w(dest), fnProgress, param, flag );
-
-    if (flag & MOVEFILE_DELAY_UNTIL_REBOOT)
-        return add_boot_rename_entry( source, dest, flag );
-
-    if (!dest)
-        return DeleteFileW( source );
-
-    /* check if we are allowed to rename the source */
-
-    if (!RtlDosPathNameToNtPathName_U( source, &nt_name, NULL, NULL ))
-    {
-        SetLastError( ERROR_PATH_NOT_FOUND );
-        return FALSE;
-    }
-    attr.Length = sizeof(attr);
-    attr.RootDirectory = 0;
-    attr.Attributes = OBJ_CASE_INSENSITIVE;
-    attr.ObjectName = &nt_name;
-    attr.SecurityDescriptor = NULL;
-    attr.SecurityQualityOfService = NULL;
-
-    status = NtOpenFile( &source_handle, DELETE | SYNCHRONIZE, &attr, &io,
-                         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_NONALERT );
-    RtlFreeUnicodeString( &nt_name );
-    if (status != STATUS_SUCCESS)
-    {
-        SetLastError( RtlNtStatusToDosError(status) );
-        goto error;
-    }
-    status = NtQueryInformationFile( source_handle, &io, &info, sizeof(info), FileBasicInformation );
-    if (status != STATUS_SUCCESS)
-    {
-        SetLastError( RtlNtStatusToDosError(status) );
-        goto error;
-    }
-
-    if (!RtlDosPathNameToNtPathName_U( dest, &nt_name, NULL, NULL ))
-    {
-        SetLastError( ERROR_PATH_NOT_FOUND );
-        goto error;
-    }
-
-    size = offsetof( FILE_RENAME_INFORMATION, FileName ) + nt_name.Length;
-    if (!(rename_info = HeapAlloc( GetProcessHeap(), 0, size )))
-        goto error;
-
-    rename_info->ReplaceIfExists = !!(flag & MOVEFILE_REPLACE_EXISTING);
-    rename_info->RootDirectory = NULL;
-    rename_info->FileNameLength = nt_name.Length;
-    memcpy( rename_info->FileName, nt_name.Buffer, nt_name.Length );
-    RtlFreeUnicodeString( &nt_name );
-    status = NtSetInformationFile( source_handle, &io, rename_info, size, FileRenameInformation );
-    HeapFree( GetProcessHeap(), 0, rename_info );
-    if (status == STATUS_NOT_SAME_DEVICE && (flag & MOVEFILE_COPY_ALLOWED))
-    {
-        NtClose( source_handle );
-        if (!CopyFileExW( source, dest, fnProgress, param, NULL,
-                          flag & MOVEFILE_REPLACE_EXISTING ?
-                          0 : COPY_FILE_FAIL_IF_EXISTS ))
-            return FALSE;
-        return DeleteFileW( source );
-    }
-
-    NtClose( source_handle );
-    return set_ntstatus( status );
-
-error:
-    if (source_handle) NtClose( source_handle );
-    return FALSE;
-}
-
 /**************************************************************************
  *           MoveFileWithProgressA   (KERNEL32.@)
  */
@@ -533,14 +182,6 @@ BOOL WINAPI MoveFileWithProgressA( LPCSTR source, LPCSTR dest,
     return ret;
 }
 
-/**************************************************************************
- *           MoveFileExW   (KERNEL32.@)
- */
-BOOL WINAPI MoveFileExW( LPCWSTR source, LPCWSTR dest, DWORD flag )
-{
-    return MoveFileWithProgressW( source, dest, NULL, NULL, flag );
-}
-
 /**************************************************************************
  *           MoveFileExA   (KERNEL32.@)
  */
@@ -570,87 +211,6 @@ BOOL WINAPI MoveFileA( LPCSTR source, LPCSTR dest )
 }
 
 
-/*************************************************************************
- *           CreateHardLinkW   (KERNEL32.@)
- */
-BOOL WINAPI CreateHardLinkW(LPCWSTR lpFileName, LPCWSTR lpExistingFileName,
-    LPSECURITY_ATTRIBUTES lpSecurityAttributes)
-{
-    UNICODE_STRING ntDest, ntSource;
-    FILE_LINK_INFORMATION *info = NULL;
-    OBJECT_ATTRIBUTES attr;
-    IO_STATUS_BLOCK io;
-    BOOL ret = FALSE;
-    HANDLE file;
-    ULONG size;
-
-    TRACE("(%s, %s, %p)\n", debugstr_w(lpFileName),
-        debugstr_w(lpExistingFileName), lpSecurityAttributes);
-
-    ntDest.Buffer = ntSource.Buffer = NULL;
-    if (!RtlDosPathNameToNtPathName_U( lpFileName, &ntDest, NULL, NULL ) ||
-        !RtlDosPathNameToNtPathName_U( lpExistingFileName, &ntSource, NULL, NULL ))
-    {
-        SetLastError( ERROR_PATH_NOT_FOUND );
-        goto err;
-    }
-
-    size = offsetof( FILE_LINK_INFORMATION, FileName ) + ntDest.Length;
-    if (!(info = HeapAlloc( GetProcessHeap(), 0, size )))
-    {
-        SetLastError( ERROR_OUTOFMEMORY );
-        goto err;
-    }
-
-    InitializeObjectAttributes( &attr, &ntSource, OBJ_CASE_INSENSITIVE, 0, NULL );
-    if (!(ret = set_ntstatus( NtOpenFile( &file, SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
-            FILE_SYNCHRONOUS_IO_NONALERT ) )))
-        goto err;
-
-    info->ReplaceIfExists = FALSE;
-    info->RootDirectory = NULL;
-    info->FileNameLength = ntDest.Length;
-    memcpy( info->FileName, ntDest.Buffer, ntDest.Length );
-    ret = set_ntstatus( NtSetInformationFile( file, &io, info, size, FileLinkInformation ) );
-
-    NtClose( file );
-
-err:
-    RtlFreeUnicodeString( &ntSource );
-    RtlFreeUnicodeString( &ntDest );
-    HeapFree( GetProcessHeap(), 0, info );
-    return ret;
-}
-
-
-/*************************************************************************
- *           CreateHardLinkA   (KERNEL32.@)
- */
-BOOL WINAPI CreateHardLinkA(LPCSTR lpFileName, LPCSTR lpExistingFileName,
-    LPSECURITY_ATTRIBUTES lpSecurityAttributes)
-{
-    WCHAR *sourceW, *destW;
-    BOOL res;
-
-    if (!(sourceW = FILE_name_AtoW( lpExistingFileName, TRUE )))
-    {
-        return FALSE;
-    }
-    if (!(destW = FILE_name_AtoW( lpFileName, TRUE )))
-    {
-        HeapFree( GetProcessHeap(), 0, sourceW );
-        return FALSE;
-    }
-
-    res = CreateHardLinkW( destW, sourceW, lpSecurityAttributes );
-
-    HeapFree( GetProcessHeap(), 0, sourceW );
-    HeapFree( GetProcessHeap(), 0, destW );
-
-    return res;
-}
-
-
 /***********************************************************************
  *           CreateDirectoryExA   (KERNEL32.@)
  */
@@ -820,15 +380,6 @@ WCHAR * CDECL wine_get_dos_file_name( LPCSTR str )
     return nt_name.Buffer;
 }
 
-/*************************************************************************
- *           CreateSymbolicLinkW   (KERNEL32.@)
- */
-BOOLEAN WINAPI CreateSymbolicLinkW(LPCWSTR link, LPCWSTR target, DWORD flags)
-{
-    FIXME("(%s %s %d): stub\n", debugstr_w(link), debugstr_w(target), flags);
-    return TRUE;
-}
-
 /*************************************************************************
  *           CreateSymbolicLinkA   (KERNEL32.@)
  */
diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c
index 9ca184a5d04..f820a067c7f 100644
--- a/dlls/kernelbase/file.c
+++ b/dlls/kernelbase/file.c
@@ -35,6 +35,7 @@
 #include "winioctl.h"
 #include "wincon.h"
 #include "fileapi.h"
+#include "shlwapi.h"
 #include "ddk/ntddk.h"
 #include "ddk/ntddser.h"
 
@@ -111,6 +112,136 @@ static inline BOOL contains_path( const WCHAR *name )
 }
 
 
+/***********************************************************************
+ *      add_boot_rename_entry
+ *
+ * Adds an entry to the registry that is loaded when windows boots and
+ * checks if there are some files to be removed or renamed/moved.
+ * <fn1> has to be valid and <fn2> may be NULL. If both pointers are
+ * non-NULL then the file is moved, otherwise it is deleted.  The
+ * entry of the registry key is always appended with two zero
+ * terminated strings. If <fn2> is NULL then the second entry is
+ * simply a single 0-byte. Otherwise the second filename goes
+ * there. The entries are prepended with \??\ before the path and the
+ * second filename gets also a '!' as the first character if
+ * MOVEFILE_REPLACE_EXISTING is set. After the final string another
+ * 0-byte follows to indicate the end of the strings.
+ * i.e.:
+ * \??\D:\test\file1[0]
+ * !\??\D:\test\file1_renamed[0]
+ * \??\D:\Test|delete[0]
+ * [0]                        <- file is to be deleted, second string empty
+ * \??\D:\test\file2[0]
+ * !\??\D:\test\file2_renamed[0]
+ * [0]                        <- indicates end of strings
+ *
+ * or:
+ * \??\D:\test\file1[0]
+ * !\??\D:\test\file1_renamed[0]
+ * \??\D:\Test|delete[0]
+ * [0]                        <- file is to be deleted, second string empty
+ * [0]                        <- indicates end of strings
+ *
+ */
+static BOOL add_boot_rename_entry( LPCWSTR source, LPCWSTR dest, DWORD flags )
+{
+    static const int info_size = FIELD_OFFSET( KEY_VALUE_PARTIAL_INFORMATION, Data );
+
+    OBJECT_ATTRIBUTES attr;
+    UNICODE_STRING nameW, source_name, dest_name;
+    KEY_VALUE_PARTIAL_INFORMATION *info;
+    BOOL rc = FALSE;
+    HANDLE key = 0;
+    DWORD len1, len2;
+    DWORD size = 0;
+    BYTE *buffer = NULL;
+    WCHAR *p;
+
+    if (!RtlDosPathNameToNtPathName_U( source, &source_name, NULL, NULL ))
+    {
+        SetLastError( ERROR_PATH_NOT_FOUND );
+        return FALSE;
+    }
+    dest_name.Buffer = NULL;
+    if (dest && !RtlDosPathNameToNtPathName_U( dest, &dest_name, NULL, NULL ))
+    {
+        RtlFreeUnicodeString( &source_name );
+        SetLastError( ERROR_PATH_NOT_FOUND );
+        return FALSE;
+    }
+
+    attr.Length = sizeof(attr);
+    attr.RootDirectory = 0;
+    attr.ObjectName = &nameW;
+    attr.Attributes = 0;
+    attr.SecurityDescriptor = NULL;
+    attr.SecurityQualityOfService = NULL;
+    RtlInitUnicodeString( &nameW, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager" );
+
+    if (NtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ) != STATUS_SUCCESS)
+    {
+        RtlFreeUnicodeString( &source_name );
+        RtlFreeUnicodeString( &dest_name );
+        return FALSE;
+    }
+
+    len1 = source_name.Length + sizeof(WCHAR);
+    if (dest)
+    {
+        len2 = dest_name.Length + sizeof(WCHAR);
+        if (flags & MOVEFILE_REPLACE_EXISTING)
+            len2 += sizeof(WCHAR); /* Plus 1 because of the leading '!' */
+    }
+    else len2 = sizeof(WCHAR); /* minimum is the 0 characters for the empty second string */
+
+    RtlInitUnicodeString( &nameW, L"PendingFileRenameOperations" );
+
+    /* First we check if the key exists and if so how many bytes it already contains. */
+    if (NtQueryValueKey( key, &nameW, KeyValuePartialInformation,
+                         NULL, 0, &size ) == STATUS_BUFFER_TOO_SMALL)
+    {
+        if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size + len1 + len2 + sizeof(WCHAR) ))) goto done;
+        if (NtQueryValueKey( key, &nameW, KeyValuePartialInformation, buffer, size, &size )) goto done;
+        info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
+        if (info->Type != REG_MULTI_SZ) goto done;
+        if (size > sizeof(info)) size -= sizeof(WCHAR);  /* remove terminating null (will be added back later) */
+    }
+    else
+    {
+        size = info_size;
+        if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size + len1 + len2 + sizeof(WCHAR) ))) goto done;
+    }
+
+    memcpy( buffer + size, source_name.Buffer, len1 );
+    size += len1;
+    p = (WCHAR *)(buffer + size);
+    if (dest)
+    {
+        if (flags & MOVEFILE_REPLACE_EXISTING) *p++ = '!';
+        memcpy( p, dest_name.Buffer, len2 );
+        size += len2;
+    }
+    else
+    {
+        *p = 0;
+        size += sizeof(WCHAR);
+    }
+
+    /* add final null */
+    p = (WCHAR *)(buffer + size);
+    *p = 0;
+    size += sizeof(WCHAR);
+    rc = !NtSetValueKey( key, &nameW, 0, REG_MULTI_SZ, buffer + info_size, size - info_size );
+
+ done:
+    RtlFreeUnicodeString( &source_name );
+    RtlFreeUnicodeString( &dest_name );
+    if (key) NtClose(key);
+    HeapFree( GetProcessHeap(), 0, buffer );
+    return rc;
+}
+
+
 /***********************************************************************
  *	append_ext
  */
@@ -337,6 +468,20 @@ DWORD file_name_WtoA( LPCWSTR src, INT srclen, LPSTR dest, INT destlen )
 }
 
 
+/***********************************************************************
+ *           is_same_file
+ */
+static BOOL is_same_file( HANDLE h1, HANDLE h2 )
+{
+    FILE_ID_INFORMATION id1, id2;
+    IO_STATUS_BLOCK io;
+
+    return !NtQueryInformationFile( h1, &io, &id1, sizeof(id1), FileIdInformation ) &&
+           !NtQueryInformationFile( h2, &io, &id2, sizeof(id2), FileIdInformation ) &&
+           !memcmp( &id1, &id2, sizeof(FILE_ID_INFORMATION) );
+}
+
+
 /******************************************************************************
  *	AreFileApisANSI   (kernelbase.@)
  */
@@ -346,6 +491,107 @@ BOOL WINAPI DECLSPEC_HOTPATCH AreFileApisANSI(void)
 }
 
 
+/***********************************************************************
+ *	CopyFileExW   (kernelbase.@)
+ */
+BOOL WINAPI CopyFileExW( const WCHAR *source, const WCHAR *dest, LPPROGRESS_ROUTINE progress,
+                         void *param, BOOL *cancel_ptr, DWORD flags )
+{
+    static const int buffer_size = 65536;
+    HANDLE h1, h2;
+    BY_HANDLE_FILE_INFORMATION info;
+    DWORD count;
+    BOOL ret = FALSE;
+    char *buffer;
+
+    if (!source || !dest)
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return FALSE;
+    }
+    if (!(buffer = HeapAlloc( GetProcessHeap(), 0, buffer_size )))
+    {
+        SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+        return FALSE;
+    }
+
+    TRACE("%s -> %s, %x\n", debugstr_w(source), debugstr_w(dest), flags);
+
+    if ((h1 = CreateFileW( source, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                           NULL, OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE)
+    {
+        WARN("Unable to open source %s\n", debugstr_w(source));
+        HeapFree( GetProcessHeap(), 0, buffer );
+        return FALSE;
+    }
+
+    if (!GetFileInformationByHandle( h1, &info ))
+    {
+        WARN("GetFileInformationByHandle returned error for %s\n", debugstr_w(source));
+        HeapFree( GetProcessHeap(), 0, buffer );
+        CloseHandle( h1 );
+        return FALSE;
+    }
+
+    if (!(flags & COPY_FILE_FAIL_IF_EXISTS))
+    {
+        BOOL same_file = FALSE;
+        h2 = CreateFileW( dest, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
+        if (h2 != INVALID_HANDLE_VALUE)
+        {
+            same_file = is_same_file( h1, h2 );
+            CloseHandle( h2 );
+        }
+        if (same_file)
+        {
+            HeapFree( GetProcessHeap(), 0, buffer );
+            CloseHandle( h1 );
+            SetLastError( ERROR_SHARING_VIOLATION );
+            return FALSE;
+        }
+    }
+
+    if ((h2 = CreateFileW( dest, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+                           (flags & COPY_FILE_FAIL_IF_EXISTS) ? CREATE_NEW : CREATE_ALWAYS,
+                           info.dwFileAttributes, h1 )) == INVALID_HANDLE_VALUE)
+    {
+        WARN("Unable to open dest %s\n", debugstr_w(dest));
+        HeapFree( GetProcessHeap(), 0, buffer );
+        CloseHandle( h1 );
+        return FALSE;
+    }
+
+    while (ReadFile( h1, buffer, buffer_size, &count, NULL ) && count)
+    {
+        char *p = buffer;
+        while (count != 0)
+        {
+            DWORD res;
+            if (!WriteFile( h2, p, count, &res, NULL ) || !res) goto done;
+            p += res;
+            count -= res;
+        }
+    }
+    ret =  TRUE;
+done:
+    /* Maintain the timestamp of source file to destination file */
+    SetFileTime( h2, NULL, NULL, &info.ftLastWriteTime );
+    HeapFree( GetProcessHeap(), 0, buffer );
+    CloseHandle( h1 );
+    CloseHandle( h2 );
+    return ret;
+}
+
+
+/**************************************************************************
+ *	CopyFileW   (kernelbase.@)
+ */
+BOOL WINAPI DECLSPEC_HOTPATCH CopyFileW( const WCHAR *source, const WCHAR *dest, BOOL fail_if_exists )
+{
+    return CopyFileExW( source, dest, NULL, NULL, NULL, fail_if_exists ? COPY_FILE_FAIL_IF_EXISTS : 0 );
+}
+
+
 /***********************************************************************
  *	CreateDirectoryA   (kernelbase.@)
  */
@@ -622,6 +868,88 @@ HANDLE WINAPI DECLSPEC_HOTPATCH CreateFileW( LPCWSTR filename, DWORD access, DWO
 }
 
 
+/*************************************************************************
+ *	CreateHardLinkA   (kernelbase.@)
+ */
+BOOL WINAPI DECLSPEC_HOTPATCH CreateHardLinkA( const char *dest, const char *source,
+                                               SECURITY_ATTRIBUTES *attr )
+{
+    WCHAR *sourceW, *destW;
+    BOOL res;
+
+    if (!(sourceW = file_name_AtoW( source, TRUE ))) return FALSE;
+    if (!(destW = file_name_AtoW( dest, TRUE )))
+    {
+        HeapFree( GetProcessHeap(), 0, sourceW );
+        return FALSE;
+    }
+    res = CreateHardLinkW( destW, sourceW, attr );
+    HeapFree( GetProcessHeap(), 0, sourceW );
+    HeapFree( GetProcessHeap(), 0, destW );
+    return res;
+}
+
+
+/*************************************************************************
+ *	CreateHardLinkW   (kernelbase.@)
+ */
+BOOL WINAPI CreateHardLinkW( LPCWSTR dest, LPCWSTR source, SECURITY_ATTRIBUTES *sec_attr )
+{
+    UNICODE_STRING ntDest, ntSource;
+    FILE_LINK_INFORMATION *info = NULL;
+    OBJECT_ATTRIBUTES attr;
+    IO_STATUS_BLOCK io;
+    BOOL ret = FALSE;
+    HANDLE file;
+    ULONG size;
+
+    TRACE( "(%s, %s, %p)\n", debugstr_w(dest), debugstr_w(source), sec_attr );
+
+    ntDest.Buffer = ntSource.Buffer = NULL;
+    if (!RtlDosPathNameToNtPathName_U( dest, &ntDest, NULL, NULL ) ||
+        !RtlDosPathNameToNtPathName_U( source, &ntSource, NULL, NULL ))
+    {
+        SetLastError( ERROR_PATH_NOT_FOUND );
+        goto done;
+    }
+
+    size = offsetof( FILE_LINK_INFORMATION, FileName ) + ntDest.Length;
+    if (!(info = HeapAlloc( GetProcessHeap(), 0, size )))
+    {
+        SetLastError( ERROR_OUTOFMEMORY );
+        goto done;
+    }
+
+    InitializeObjectAttributes( &attr, &ntSource, OBJ_CASE_INSENSITIVE, 0, NULL );
+    if (!(ret = set_ntstatus( NtOpenFile( &file, SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
+            FILE_SYNCHRONOUS_IO_NONALERT ) )))
+        goto done;
+
+    info->ReplaceIfExists = FALSE;
+    info->RootDirectory = NULL;
+    info->FileNameLength = ntDest.Length;
+    memcpy( info->FileName, ntDest.Buffer, ntDest.Length );
+    ret = set_ntstatus( NtSetInformationFile( file, &io, info, size, FileLinkInformation ) );
+    NtClose( file );
+
+done:
+    RtlFreeUnicodeString( &ntSource );
+    RtlFreeUnicodeString( &ntDest );
+    HeapFree( GetProcessHeap(), 0, info );
+    return ret;
+}
+
+
+/*************************************************************************
+ *	CreateSymbolicLinkW   (kernelbase.@)
+ */
+BOOLEAN WINAPI /* DECLSPEC_HOTPATCH */ CreateSymbolicLinkW( LPCWSTR link, LPCWSTR target, DWORD flags )
+{
+    FIXME( "(%s %s %d): stub\n", debugstr_w(link), debugstr_w(target), flags );
+    return TRUE;
+}
+
+
 /***********************************************************************
  *	DeleteFileA   (kernelbase.@)
  */
@@ -1331,6 +1659,185 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetFileAttributesExW( LPCWSTR name, GET_FILEEX_INF
 }
 
 
+/***********************************************************************
+ *	GetFinalPathNameByHandleA   (kernelbase.@)
+ */
+DWORD WINAPI DECLSPEC_HOTPATCH GetFinalPathNameByHandleA( HANDLE file, LPSTR path,
+                                                          DWORD count, DWORD flags )
+{
+    WCHAR *str;
+    DWORD result, len;
+
+    TRACE( "(%p,%p,%d,%x)\n", file, path, count, flags);
+
+    len = GetFinalPathNameByHandleW(file, NULL, 0, flags);
+    if (len == 0) return 0;
+
+    str = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+    if (!str)
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return 0;
+    }
+
+    result = GetFinalPathNameByHandleW(file, str, len, flags);
+    if (result != len - 1)
+    {
+        HeapFree(GetProcessHeap(), 0, str);
+        return 0;
+    }
+
+    len = file_name_WtoA( str, -1, NULL, 0 );
+    if (count < len)
+    {
+        HeapFree(GetProcessHeap(), 0, str);
+        return len - 1;
+    }
+    file_name_WtoA( str, -1, path, count );
+    HeapFree(GetProcessHeap(), 0, str);
+    return len - 1;
+}
+
+
+/***********************************************************************
+ *	GetFinalPathNameByHandleW   (kernelbase.@)
+ */
+DWORD WINAPI DECLSPEC_HOTPATCH GetFinalPathNameByHandleW( HANDLE file, LPWSTR path,
+                                                          DWORD count, DWORD flags )
+{
+    WCHAR buffer[sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH + 1];
+    OBJECT_NAME_INFORMATION *info = (OBJECT_NAME_INFORMATION*)&buffer;
+    WCHAR drive_part[MAX_PATH];
+    DWORD drive_part_len = 0;
+    NTSTATUS status;
+    DWORD result = 0;
+    ULONG dummy;
+    WCHAR *ptr;
+
+    TRACE( "(%p,%p,%d,%x)\n", file, path, count, flags );
+
+    if (flags & ~(FILE_NAME_OPENED | VOLUME_NAME_GUID | VOLUME_NAME_NONE | VOLUME_NAME_NT))
+    {
+        WARN("Unknown flags: %x\n", flags);
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return 0;
+    }
+
+    /* get object name */
+    status = NtQueryObject( file, ObjectNameInformation, &buffer, sizeof(buffer) - sizeof(WCHAR), &dummy );
+    if (!set_ntstatus( status )) return 0;
+
+    if (!info->Name.Buffer)
+    {
+        SetLastError( ERROR_INVALID_HANDLE );
+        return 0;
+    }
+    if (info->Name.Length < 4 * sizeof(WCHAR) || info->Name.Buffer[0] != '\\' ||
+        info->Name.Buffer[1] != '?' || info->Name.Buffer[2] != '?' || info->Name.Buffer[3] != '\\' )
+    {
+        FIXME("Unexpected object name: %s\n", debugstr_wn(info->Name.Buffer, info->Name.Length / sizeof(WCHAR)));
+        SetLastError( ERROR_GEN_FAILURE );
+        return 0;
+    }
+
+    /* add terminating null character, remove "\\??\\" */
+    info->Name.Buffer[info->Name.Length / sizeof(WCHAR)] = 0;
+    info->Name.Length -= 4 * sizeof(WCHAR);
+    info->Name.Buffer += 4;
+
+    /* FILE_NAME_OPENED is not supported yet, and would require Wineserver changes */
+    if (flags & FILE_NAME_OPENED)
+    {
+        FIXME("FILE_NAME_OPENED not supported\n");
+        flags &= ~FILE_NAME_OPENED;
+    }
+
+    /* Get information required for VOLUME_NAME_NONE, VOLUME_NAME_GUID and VOLUME_NAME_NT */
+    if (flags == VOLUME_NAME_NONE || flags == VOLUME_NAME_GUID || flags == VOLUME_NAME_NT)
+    {
+        if (!GetVolumePathNameW( info->Name.Buffer, drive_part, MAX_PATH )) return 0;
+        drive_part_len = lstrlenW(drive_part);
+        if (!drive_part_len || drive_part_len > lstrlenW(info->Name.Buffer) ||
+            drive_part[drive_part_len-1] != '\\' ||
+            CompareStringOrdinal( info->Name.Buffer, drive_part_len, drive_part, drive_part_len, TRUE ) != CSTR_EQUAL)
+        {
+            FIXME( "Path %s returned by GetVolumePathNameW does not match file path %s\n",
+                   debugstr_w(drive_part), debugstr_w(info->Name.Buffer) );
+            SetLastError( ERROR_GEN_FAILURE );
+            return 0;
+        }
+    }
+
+    if (flags == VOLUME_NAME_NONE)
+    {
+        ptr = info->Name.Buffer + drive_part_len - 1;
+        result = lstrlenW(ptr);
+        if (result < count) memcpy(path, ptr, (result + 1) * sizeof(WCHAR));
+        else result++;
+    }
+    else if (flags == VOLUME_NAME_GUID)
+    {
+        WCHAR volume_prefix[51];
+
+        /* GetVolumeNameForVolumeMountPointW sets error code on failure */
+        if (!GetVolumeNameForVolumeMountPointW( drive_part, volume_prefix, 50 )) return 0;
+        ptr = info->Name.Buffer + drive_part_len;
+        result = lstrlenW(volume_prefix) + lstrlenW(ptr);
+        if (result < count)
+        {
+            lstrcpyW(path, volume_prefix);
+            lstrcatW(path, ptr);
+        }
+        else
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            result++;
+        }
+    }
+    else if (flags == VOLUME_NAME_NT)
+    {
+        WCHAR nt_prefix[MAX_PATH];
+
+        /* QueryDosDeviceW sets error code on failure */
+        drive_part[drive_part_len - 1] = 0;
+        if (!QueryDosDeviceW( drive_part, nt_prefix, MAX_PATH )) return 0;
+        ptr = info->Name.Buffer + drive_part_len - 1;
+        result = lstrlenW(nt_prefix) + lstrlenW(ptr);
+        if (result < count)
+        {
+            lstrcpyW(path, nt_prefix);
+            lstrcatW(path, ptr);
+        }
+        else
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            result++;
+        }
+    }
+    else if (flags == VOLUME_NAME_DOS)
+    {
+        result = 4 + lstrlenW(info->Name.Buffer);
+        if (result < count)
+        {
+            lstrcpyW(path, L"\\\\?\\");
+            lstrcatW(path, info->Name.Buffer);
+        }
+        else
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            result++;
+        }
+    }
+    else
+    {
+        /* Windows crashes here, but we prefer returning ERROR_INVALID_PARAMETER */
+        WARN("Invalid combination of flags: %x\n", flags);
+        SetLastError( ERROR_INVALID_PARAMETER );
+    }
+    return result;
+}
+
+
 /***********************************************************************
  *	GetFullPathNameA   (kernelbase.@)
  */
@@ -1891,6 +2398,94 @@ UINT WINAPI DECLSPEC_HOTPATCH GetWindowsDirectoryW( LPWSTR path, UINT count )
 }
 
 
+/**************************************************************************
+ *	MoveFileExW   (kernelbase.@)
+ */
+BOOL WINAPI MoveFileExW( const WCHAR *source, const WCHAR *dest, DWORD flag )
+{
+    return MoveFileWithProgressW( source, dest, NULL, NULL, flag );
+}
+
+
+/**************************************************************************
+ *	MoveFileWithProgressW   (kernelbase.@)
+ */
+BOOL WINAPI DECLSPEC_HOTPATCH MoveFileWithProgressW( const WCHAR *source, const WCHAR *dest,
+                                                     LPPROGRESS_ROUTINE progress,
+                                                     void *param, DWORD flag )
+{
+    FILE_RENAME_INFORMATION *rename_info;
+    FILE_BASIC_INFORMATION info;
+    UNICODE_STRING nt_name;
+    OBJECT_ATTRIBUTES attr;
+    IO_STATUS_BLOCK io;
+    NTSTATUS status;
+    HANDLE source_handle = 0;
+    ULONG size;
+
+    TRACE( "(%s,%s,%p,%p,%04x)\n", debugstr_w(source), debugstr_w(dest), progress, param, flag );
+
+    if (flag & MOVEFILE_DELAY_UNTIL_REBOOT) return add_boot_rename_entry( source, dest, flag );
+
+    if (!dest) return DeleteFileW( source );
+
+    /* check if we are allowed to rename the source */
+
+    if (!RtlDosPathNameToNtPathName_U( source, &nt_name, NULL, NULL ))
+    {
+        SetLastError( ERROR_PATH_NOT_FOUND );
+        return FALSE;
+    }
+    attr.Length = sizeof(attr);
+    attr.RootDirectory = 0;
+    attr.Attributes = OBJ_CASE_INSENSITIVE;
+    attr.ObjectName = &nt_name;
+    attr.SecurityDescriptor = NULL;
+    attr.SecurityQualityOfService = NULL;
+
+    status = NtOpenFile( &source_handle, DELETE | SYNCHRONIZE, &attr, &io,
+                         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                         FILE_SYNCHRONOUS_IO_NONALERT );
+    RtlFreeUnicodeString( &nt_name );
+    if (!set_ntstatus( status )) goto error;
+
+    status = NtQueryInformationFile( source_handle, &io, &info, sizeof(info), FileBasicInformation );
+    if (!set_ntstatus( status )) goto error;
+
+    if (!RtlDosPathNameToNtPathName_U( dest, &nt_name, NULL, NULL ))
+    {
+        SetLastError( ERROR_PATH_NOT_FOUND );
+        goto error;
+    }
+
+    size = offsetof( FILE_RENAME_INFORMATION, FileName ) + nt_name.Length;
+    if (!(rename_info = HeapAlloc( GetProcessHeap(), 0, size ))) goto error;
+
+    rename_info->ReplaceIfExists = !!(flag & MOVEFILE_REPLACE_EXISTING);
+    rename_info->RootDirectory = NULL;
+    rename_info->FileNameLength = nt_name.Length;
+    memcpy( rename_info->FileName, nt_name.Buffer, nt_name.Length );
+    RtlFreeUnicodeString( &nt_name );
+    status = NtSetInformationFile( source_handle, &io, rename_info, size, FileRenameInformation );
+    HeapFree( GetProcessHeap(), 0, rename_info );
+    if (status == STATUS_NOT_SAME_DEVICE && (flag & MOVEFILE_COPY_ALLOWED))
+    {
+        NtClose( source_handle );
+        if (!CopyFileExW( source, dest, progress, param, NULL,
+                          flag & MOVEFILE_REPLACE_EXISTING ? 0 : COPY_FILE_FAIL_IF_EXISTS ))
+            return FALSE;
+        return DeleteFileW( source );
+    }
+
+    NtClose( source_handle );
+    return set_ntstatus( status );
+
+error:
+    if (source_handle) NtClose( source_handle );
+    return FALSE;
+}
+
+
 /***********************************************************************
  *	NeedCurrentDirectoryForExePathA   (kernelbase.@)
  */
@@ -1916,6 +2511,111 @@ BOOL WINAPI DECLSPEC_HOTPATCH NeedCurrentDirectoryForExePathW( LPCWSTR name )
 }
 
 
+/***********************************************************************
+ *	ReplaceFileW   (kernelbase.@)
+ */
+BOOL WINAPI DECLSPEC_HOTPATCH ReplaceFileW( const WCHAR *replaced, const WCHAR *replacement,
+                                            const WCHAR *backup, DWORD flags,
+                                            void *exclude, void *reserved )
+{
+    UNICODE_STRING nt_replaced_name, nt_replacement_name;
+    HANDLE hReplacement = NULL;
+    NTSTATUS status;
+    IO_STATUS_BLOCK io;
+    OBJECT_ATTRIBUTES attr;
+    FILE_BASIC_INFORMATION info;
+
+    TRACE( "%s %s %s 0x%08x %p %p\n", debugstr_w(replaced), debugstr_w(replacement), debugstr_w(backup),
+           flags, exclude, reserved );
+
+    if (flags) FIXME("Ignoring flags %x\n", flags);
+
+    /* First two arguments are mandatory */
+    if (!replaced || !replacement)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    attr.Length = sizeof(attr);
+    attr.RootDirectory = 0;
+    attr.Attributes = OBJ_CASE_INSENSITIVE;
+    attr.ObjectName = NULL;
+    attr.SecurityDescriptor = NULL;
+    attr.SecurityQualityOfService = NULL;
+
+    /* Open the "replaced" file for reading */
+    if (!RtlDosPathNameToNtPathName_U( replaced, &nt_replaced_name, NULL, NULL ))
+    {
+        SetLastError( ERROR_PATH_NOT_FOUND );
+        return FALSE;
+    }
+    attr.ObjectName = &nt_replaced_name;
+
+    /* Replacement should fail if replaced is READ_ONLY */
+    status = NtQueryAttributesFile(&attr, &info);
+    RtlFreeUnicodeString(&nt_replaced_name);
+    if (!set_ntstatus( status )) return FALSE;
+
+    if (info.FileAttributes & FILE_ATTRIBUTE_READONLY)
+    {
+        SetLastError( ERROR_ACCESS_DENIED );
+        return FALSE;
+    }
+
+    /*
+     * Open the replacement file for reading, writing, and deleting
+     * (writing and deleting are needed when finished)
+     */
+    if (!RtlDosPathNameToNtPathName_U( replacement, &nt_replacement_name, NULL, NULL ))
+    {
+        SetLastError( ERROR_PATH_NOT_FOUND );
+        return FALSE;
+    }
+    attr.ObjectName = &nt_replacement_name;
+    status = NtOpenFile( &hReplacement, GENERIC_READ | GENERIC_WRITE | DELETE | WRITE_DAC | SYNCHRONIZE,
+                         &attr, &io, 0, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE );
+    RtlFreeUnicodeString(&nt_replacement_name);
+    if (!set_ntstatus( status )) return FALSE;
+    NtClose( hReplacement );
+
+    /* If the user wants a backup then that needs to be performed first */
+    if (backup)
+    {
+        if (!MoveFileExW( replaced, backup, MOVEFILE_REPLACE_EXISTING )) return FALSE;
+    }
+    else
+    {
+        /* ReplaceFile() can replace an open target. To do this, we need to move
+         * it out of the way first. */
+        WCHAR temp_path[MAX_PATH], temp_file[MAX_PATH];
+
+        lstrcpynW( temp_path, replaced, ARRAY_SIZE( temp_path ) );
+        PathRemoveFileSpecW( temp_path );
+        if (!GetTempFileNameW( temp_path, L"rf", 0, temp_file ) ||
+            !MoveFileExW( replaced, temp_file, MOVEFILE_REPLACE_EXISTING ))
+            return FALSE;
+
+        DeleteFileW( temp_file );
+    }
+
+    /*
+     * Now that the backup has been performed (if requested), copy the replacement
+     * into place
+     */
+    if (!MoveFileExW( replacement, replaced, 0 ))
+    {
+        /* on failure we need to indicate whether a backup was made */
+        if (!backup)
+            SetLastError( ERROR_UNABLE_TO_MOVE_REPLACEMENT );
+        else
+            SetLastError( ERROR_UNABLE_TO_MOVE_REPLACEMENT_2 );
+        return FALSE;
+    }
+    return TRUE;
+}
+
+
 /***********************************************************************
  *	SearchPathA   (kernelbase.@)
  */
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec
index a3a208e8fe2..904f1704eb1 100644
--- a/dlls/kernelbase/kernelbase.spec
+++ b/dlls/kernelbase/kernelbase.spec
@@ -166,8 +166,8 @@
 @ stdcall ConvertToAutoInheritPrivateObjectSecurity(ptr ptr ptr ptr long ptr)
 # @ stub CopyContext
 # @ stub CopyFile2
-@ stdcall CopyFileExW(wstr wstr ptr ptr ptr long) kernel32.CopyFileExW
-@ stdcall CopyFileW(wstr wstr long) kernel32.CopyFileW
+@ stdcall CopyFileExW(wstr wstr ptr ptr ptr long)
+@ stdcall CopyFileW(wstr wstr long)
 # @ stub -arch=x86_64 CopyMemoryNonTemporal
 @ stdcall CopySid(long ptr ptr)
 # @ stub CouldMultiUserAppsBehaviorBePossibleForPackage
@@ -191,8 +191,8 @@
 @ stdcall CreateFileMappingNumaW(long ptr long long long wstr long)
 @ stdcall CreateFileMappingW(long ptr long long long wstr)
 @ stdcall CreateFileW(wstr long long ptr long long long)
-@ stdcall CreateHardLinkA(str str ptr) kernel32.CreateHardLinkA
-@ stdcall CreateHardLinkW(wstr wstr ptr) kernel32.CreateHardLinkW
+@ stdcall CreateHardLinkA(str str ptr)
+@ stdcall CreateHardLinkW(wstr wstr ptr)
 @ stdcall CreateIoCompletionPort(long long long long)
 @ stdcall CreateMemoryResourceNotification(long)
 @ stdcall CreateMutexA(ptr long str)
@@ -221,7 +221,7 @@
 # @ stub CreateStateContainer
 # @ stub CreateStateLock
 # @ stub CreateStateSubcontainer
-@ stdcall CreateSymbolicLinkW(wstr wstr long) kernel32.CreateSymbolicLinkW
+@ stdcall CreateSymbolicLinkW(wstr wstr long)
 @ stdcall CreateThread(ptr long ptr long long ptr)
 @ stdcall CreateThreadpool(ptr)
 @ stdcall CreateThreadpoolCleanupGroup()
@@ -524,8 +524,8 @@
 @ stdcall GetFileVersionInfoSizeExW(long wstr ptr)
 @ stdcall GetFileVersionInfoSizeW(wstr ptr)
 @ stdcall GetFileVersionInfoW(wstr long long ptr)
-@ stdcall GetFinalPathNameByHandleA(long ptr long long) kernel32.GetFinalPathNameByHandleA
-@ stdcall GetFinalPathNameByHandleW(long ptr long long) kernel32.GetFinalPathNameByHandleW
+@ stdcall GetFinalPathNameByHandleA(long ptr long long)
+@ stdcall GetFinalPathNameByHandleW(long ptr long long)
 @ stdcall GetFullPathNameA(str long ptr ptr)
 @ stdcall GetFullPathNameW(wstr long ptr ptr)
 # @ stub GetGPOListInternalA
@@ -953,9 +953,9 @@
 @ stdcall MapViewOfFileEx(long long long long long ptr)
 @ stdcall MapViewOfFileExNuma(long long long long long ptr long)
 # @ stub MapViewOfFileFromApp
-@ stdcall MoveFileExW(wstr wstr long) kernel32.MoveFileExW
+@ stdcall MoveFileExW(wstr wstr long)
 # @ stub MoveFileWithProgressTransactedW
-@ stdcall MoveFileWithProgressW(wstr wstr ptr ptr long) kernel32.MoveFileWithProgressW
+@ stdcall MoveFileWithProgressW(wstr wstr ptr ptr long)
 @ stdcall MulDiv(long long long) kernel32.MulDiv
 @ stdcall MultiByteToWideChar(long long str long ptr long)
 # @ stub NamedPipeEventEnum
@@ -1339,7 +1339,7 @@
 @ stdcall RemoveVectoredContinueHandler(ptr) ntdll.RtlRemoveVectoredContinueHandler
 @ stdcall RemoveVectoredExceptionHandler(ptr) ntdll.RtlRemoveVectoredExceptionHandler
 # @ stub ReplaceFileExInternal
-@ stdcall ReplaceFileW(wstr wstr wstr long ptr ptr) kernel32.ReplaceFileW
+@ stdcall ReplaceFileW(wstr wstr wstr long ptr ptr)
 @ stdcall ResetEvent(long)
 # @ stub ResetState
 @ stdcall ResetWriteWatch(ptr long)
-- 
GitLab