kernel32: Implement ReplaceFileA/ReplaceFileW

Erich Hoover ehoover at mines.edu
Mon Feb 26 20:23:35 CST 2007


Skipped content of type multipart/alternative-------------- next part --------------
/**************************************************************************
 *           ReplaceFileW   (KERNEL32.@)
 *           ReplaceFile    (KERNEL32.@)
 */
BOOL WINAPI ReplaceFileW(LPCWSTR lpReplacedFileName,LPCWSTR lpReplacementFileName,
                         LPCWSTR lpBackupFileName, DWORD dwReplaceFlags,
                         LPVOID lpExclude, LPVOID lpReserved)
{
    HANDLE hReplaced, hReplacement;
    BOOL skipBackup = FALSE;

    if(dwReplaceFlags)
        FIXME("Ignoring flags %x\n", dwReplaceFlags);
    /* First two arguments are mandatory */
    if(!lpReplacedFileName || !lpReplacementFileName)
    {
        SetLastError( ERROR_INVALID_PARAMETER );
        return FALSE;
    }
    /*
     * Lock the "replacement" file, fail if it does not exist
     */
    if((hReplacement = CreateFileW(lpReplacementFileName, GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
    {
        SetLastError( ERROR_INVALID_PARAMETER );
        return FALSE;
    }
    if(!LockFile( hReplacement, 0, 0, 0, 0 ))
    {
        CloseHandle( hReplacement );
        SetLastError( ERROR_INVALID_PARAMETER );
        return FALSE;
    }
    /*
     * Lock the "replaced" file while we're working.
     */
    if((hReplaced = CreateFileW(lpReplacedFileName, GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
    {
        /* If "replaced" does not exist then create it for the lock, but skip backup */
        if((hReplaced = CreateFileW(lpReplacedFileName, GENERIC_READ,
            FILE_SHARE_READ | FILE_SHARE_WRITE,
            NULL, CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE)
        {
            UnlockFile( hReplacement, 0, 0, 0, 0 );
            CloseHandle( hReplacement );
            SetLastError( ERROR_INVALID_PARAMETER );
            return FALSE;
        }
        skipBackup = TRUE;
    }
    if(!LockFile( hReplaced, 0, 0, 0, 0 ))
    {
        UnlockFile( hReplacement, 0, 0, 0, 0 );
        CloseHandle( hReplacement );
        CloseHandle( hReplaced );
        SetLastError( ERROR_INVALID_PARAMETER );
        return FALSE;
    }
    /*
     * If the user wants a backup then that needs to be performed first
     */
    if( lpBackupFileName && !skipBackup )
    {
        /* If an existing backup exists then copy over it */
        if(!CopyFileW( lpReplacedFileName, lpBackupFileName, FALSE ))
        {
            SetLastError( ERROR_INVALID_PARAMETER );
            goto replace_fail;
        }
    }
    /*
     * Now that the backup has been performed (if requested), copy the replacement
     * into place
     */
    if(!CopyFileW( lpReplacementFileName, lpReplacedFileName, FALSE ))
    {
        /* Assume that all access denied errors are a write problem. */
        if(GetLastError() == ERROR_ACCESS_DENIED)
            SetLastError( ERROR_UNABLE_TO_REMOVE_REPLACED );
        else
            SetLastError( ERROR_UNABLE_TO_MOVE_REPLACEMENT );
        goto replace_fail;
    }
    /* Delete the replacement file */
    if(!DeleteFileW( lpReplacementFileName ))
    {
        SetLastError( ERROR_INVALID_PARAMETER );
        return FALSE;
    }
    /* Unlock the handles */
    UnlockFile( hReplacement, 0, 0, 0, 0 );
    CloseHandle( hReplacement );
    UnlockFile( hReplaced, 0, 0, 0, 0 );
    CloseHandle( hReplaced );
    /* All done, file replacement successful */
    return TRUE;

replace_fail:
    UnlockFile( hReplacement, 0, 0, 0, 0 );
    CloseHandle( hReplacement );
    UnlockFile( hReplaced, 0, 0, 0, 0 );
    CloseHandle( hReplaced );
    return FALSE;
}


More information about the wine-devel mailing list