kernel32: Implement ReplaceFileA/ReplaceFileW

Erich Hoover ehoover at mines.edu
Wed Feb 28 11:36:44 CST 2007


Oops, I must have hit the wrong reply button.

>>> 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).
That was worded poorly, Copy/Move already handle copying file attributes and
I imagine would eventually implement copying the access control list
information.  Implementing ReplaceFile as calls to either Copy or Move takes
these issues into account.

>> 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?
>From my perspective the "remarks" section discusses the implementation of
ReplaceFile as calls to existing API functions (as a sort of macro) as a
convenience.  Granted, it discusses moving files instead of copying but that
conflicted with the file locking.

Should I make a new patch file with the previously attached changes or would
you prefer that the function be implemented in the read/write manner?
Re-implementing the function in such a fashion would make it possible to do
a more move-like operation while maintaining the file locking, but would
lose out on any future improvements to CopyFile.

Erich Hoover
ehoover at mines.edu

On 2/28/07, Felix Nawothnig <flexo at holycrap.org> wrote:
>
> (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;
> > }
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.winehq.org/pipermail/wine-devel/attachments/20070228/eec44018/attachment.htm


More information about the wine-devel mailing list