Oops, I must have hit the wrong reply button.<br><br>>>> The "right" way would probably to do the copying yourself by<br>>>> read/write.. but I dunno.<br>>> Except that it would ignore the permissions issues that have already
<br>>> been coded into the copy routines (and any updates that may eventually<br>> No, CreateFile (and friends) does the permissions checks (which you<br>> would still have to call).<br>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.
<br><br>>> be made to these routines). Also, it seems to me that MSDN is<br>>> describing the list of function calls that ReplaceFile actually makes.<br>> No it doesn't?<br>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.
<br><br>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.
<br><br>Erich Hoover<br><a href="mailto:ehoover@mines.edu">ehoover@mines.edu</a><br><br><div><span class="gmail_quote">On 2/28/07, <b class="gmail_sendername">Felix Nawothnig</b> <<a href="mailto:flexo@holycrap.org">flexo@holycrap.org
</a>> wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">(CC-ing wine-devel again)<br><br>Erich Hoover wrote:<br>>> The "right" way would probably to do the copying yourself by
<br>>> read/write.. but I dunno.<br>> Except that it would ignore the permissions issues that have already<br>> been coded into the copy routines (and any updates that may eventually<br><br>No, CreateFile (and friends) does the permissions checks (which you
<br>would still have to call).<br><br>> be made to these routines). Also, it seems to me that MSDN is<br>> describing the list of function calls that ReplaceFile actually makes.<br><br>No it doesn't?<br><br>Your other objections were right. Your last version follows for wine-devel.
<br><br>> ------------------------------------------------------------------------<br>><br>> /**************************************************************************<br>> * ReplaceFileW (KERNEL32.@)
<br>> * ReplaceFile (KERNEL32.@)<br>> */<br>> BOOL WINAPI ReplaceFileW(LPCWSTR lpReplacedFileName,LPCWSTR lpReplacementFileName,<br>> LPCWSTR lpBackupFileName, DWORD dwReplaceFlags,
<br>> LPVOID lpExclude, LPVOID lpReserved)<br>> {<br>> HANDLE hReplaced, hReplacement;<br>> BOOL skipBackup = FALSE;<br>><br>> if(dwReplaceFlags)<br>> FIXME("Ignoring flags %x\n", dwReplaceFlags);
<br>> /* First two arguments are mandatory */<br>> if(!lpReplacedFileName || !lpReplacementFileName)<br>> {<br>> SetLastError( ERROR_INVALID_PARAMETER );<br>> return FALSE;<br>> }
<br>> /*<br>> * Lock the "replacement" file, fail if it does not exist<br>> */<br>> if((hReplacement = CreateFileW(lpReplacementFileName, GENERIC_READ,<br>> FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
<br>> NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)<br>> {<br>> return FALSE;<br>> }<br>> if(!LockFile( hReplacement, 0, 0, 0, 0 ))<br>> {<br>> CloseHandle( hReplacement );
<br>> return FALSE;<br>> }<br>> /*<br>> * Lock the "replaced" file while we're working.<br>> */<br>> if((hReplaced = CreateFileW(lpReplacedFileName, GENERIC_READ,
<br>> FILE_SHARE_READ | FILE_SHARE_WRITE,<br>> NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)<br>> {<br>> /* If "replaced" does not exist then create it for the lock, but skip backup */
<br>> if((hReplaced = CreateFileW(lpReplacedFileName, GENERIC_READ,<br>> FILE_SHARE_READ | FILE_SHARE_WRITE,<br>> NULL, CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE)<br>> {
<br>> UnlockFile( hReplacement, 0, 0, 0, 0 );<br>> CloseHandle( hReplacement );<br>> return FALSE;<br>> }<br>> skipBackup = TRUE;<br>> }<br>> if(!LockFile( hReplaced, 0, 0, 0, 0 ))
<br>> {<br>> UnlockFile( hReplacement, 0, 0, 0, 0 );<br>> CloseHandle( hReplacement );<br>> CloseHandle( hReplaced );<br>> return FALSE;<br>> }<br>> /*<br>> * If the user wants a backup then that needs to be performed first
<br>> */<br>> if( lpBackupFileName && !skipBackup )<br>> {<br>> /* If an existing backup exists then copy over it */<br>> if(!CopyFileW( lpReplacedFileName, lpBackupFileName, FALSE ))
<br>> goto replace_fail;<br>> }<br>> /*<br>> * Now that the backup has been performed (if requested), copy the replacement<br>> * into place<br>> */<br>> if(!CopyFileW( lpReplacementFileName, lpReplacedFileName, FALSE ))
<br>> {<br>> /* Assume that all access denied errors are a write problem. */<br>> if(GetLastError() == ERROR_ACCESS_DENIED)<br>> SetLastError( ERROR_UNABLE_TO_REMOVE_REPLACED );
<br>> else<br>> SetLastError( ERROR_UNABLE_TO_MOVE_REPLACEMENT );<br>> goto replace_fail;<br>> }<br>> /* Delete the replacement file */<br>> if(!DeleteFileW( lpReplacementFileName ))
<br>> return FALSE;<br>> /* Unlock the handles */<br>> UnlockFile( hReplacement, 0, 0, 0, 0 );<br>> CloseHandle( hReplacement );<br>> UnlockFile( hReplaced, 0, 0, 0, 0 );<br>> CloseHandle( hReplaced );
<br>> /* All done, file replacement successful */<br>> return TRUE;<br>><br>> replace_fail:<br>> UnlockFile( hReplacement, 0, 0, 0, 0 );<br>> CloseHandle( hReplacement );<br>> UnlockFile( hReplaced, 0, 0, 0, 0 );
<br>> CloseHandle( hReplaced );<br>> return FALSE;<br>> }<br><br></blockquote></div><br>