(CC-ing wine-devel again)

Erich Hoover wrote:
The "right" way would probably to do the copying yourself by
read/write.. but I dunno.
Except that it would ignore the permissions issues that have already been coded into the copy routines (and any updates that may eventually

No, CreateFile (and friends) does the permissions checks (which you would still have to call).

be made to these routines). Also, it seems to me that MSDN is describing the list of function calls that ReplaceFile actually makes.

No it doesn't?

Your other objections were right. Your last version follows for wine-devel.

------------------------------------------------------------------------

/**************************************************************************
 *           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)
    {
        return FALSE;
    }
    if(!LockFile( hReplacement, 0, 0, 0, 0 ))
    {
        CloseHandle( hReplacement );
        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 );
            return FALSE;
        }
        skipBackup = TRUE;
    }
    if(!LockFile( hReplaced, 0, 0, 0, 0 ))
    {
        UnlockFile( hReplacement, 0, 0, 0, 0 );
        CloseHandle( hReplacement );
        CloseHandle( hReplaced );
        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 ))
            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 ))
        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;
}



Reply via email to