Oops, I must have hit the wrong reply button.<br><br>&gt;&gt;&gt; The &quot;right&quot; way would probably to do the copying yourself by<br>&gt;&gt;&gt; read/write.. but I dunno.<br>&gt;&gt; Except that it would ignore the permissions issues that have already
<br>&gt;&gt; been coded into the copy routines (and any updates that may eventually<br>&gt; No, CreateFile (and friends) does the permissions checks (which you<br>&gt; 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.&nbsp; Implementing ReplaceFile as calls to either Copy or Move takes these issues into account.
<br><br>&gt;&gt; be made to these routines).&nbsp;&nbsp;Also, it seems to me that MSDN is<br>&gt;&gt; describing the list of function calls that ReplaceFile actually makes.<br>&gt; No it doesn&#39;t?<br>From my perspective the &quot;remarks&quot; section discusses the implementation of ReplaceFile as calls to existing API functions (as a sort of macro) as a convenience.&nbsp; 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?&nbsp; 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> &lt;<a href="mailto:flexo@holycrap.org">flexo@holycrap.org
</a>&gt; 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>&gt;&gt; The &quot;right&quot; way would probably to do the copying yourself by
<br>&gt;&gt; read/write.. but I dunno.<br>&gt; Except that it would ignore the permissions issues that have already<br>&gt; 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>&gt; be made to these routines).&nbsp;&nbsp;Also, it seems to me that MSDN is<br>&gt; describing the list of function calls that ReplaceFile actually makes.<br><br>No it doesn&#39;t?<br><br>Your other objections were right. Your last version follows for wine-devel.
<br><br>&gt; ------------------------------------------------------------------------<br>&gt;<br>&gt; /**************************************************************************<br>&gt;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ReplaceFileW&nbsp;&nbsp; (KERNEL32.@)
<br>&gt;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ReplaceFile&nbsp;&nbsp;&nbsp;&nbsp;(KERNEL32.@)<br>&gt;&nbsp;&nbsp;*/<br>&gt; BOOL WINAPI ReplaceFileW(LPCWSTR lpReplacedFileName,LPCWSTR lpReplacementFileName,<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LPCWSTR lpBackupFileName, DWORD dwReplaceFlags,
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LPVOID lpExclude, LPVOID lpReserved)<br>&gt; {<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; HANDLE hReplaced, hReplacement;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; BOOL skipBackup = FALSE;<br>&gt;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; if(dwReplaceFlags)<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FIXME(&quot;Ignoring flags %x\n&quot;, dwReplaceFlags);
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; /* First two arguments are mandatory */<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; if(!lpReplacedFileName || !lpReplacementFileName)<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SetLastError( ERROR_INVALID_PARAMETER );<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; }
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; /*<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* Lock the &quot;replacement&quot; file, fail if it does not exist<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; if((hReplacement = CreateFileW(lpReplacementFileName, GENERIC_READ,<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; if(!LockFile( hReplacement, 0, 0, 0, 0 ))<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CloseHandle( hReplacement );
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; /*<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* Lock the &quot;replaced&quot; file while we&#39;re working.<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; if((hReplaced = CreateFileW(lpReplacedFileName, GENERIC_READ,
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FILE_SHARE_READ | FILE_SHARE_WRITE,<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* If &quot;replaced&quot; does not exist then create it for the lock, but skip backup */
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if((hReplaced = CreateFileW(lpReplacedFileName, GENERIC_READ,<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FILE_SHARE_READ | FILE_SHARE_WRITE,<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL, CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE)<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; UnlockFile( hReplacement, 0, 0, 0, 0 );<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CloseHandle( hReplacement );<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; skipBackup = TRUE;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; if(!LockFile( hReplaced, 0, 0, 0, 0 ))
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; UnlockFile( hReplacement, 0, 0, 0, 0 );<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CloseHandle( hReplacement );<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CloseHandle( hReplaced );<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; /*<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* If the user wants a backup then that needs to be performed first
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; if( lpBackupFileName &amp;&amp; !skipBackup )<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* If an existing backup exists then copy over it */<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!CopyFileW( lpReplacedFileName, lpBackupFileName, FALSE ))
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto replace_fail;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; /*<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* Now that the backup has been performed (if requested), copy the replacement<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* into place<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; if(!CopyFileW( lpReplacementFileName, lpReplacedFileName, FALSE ))
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Assume that all access denied errors are a write problem. */<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(GetLastError() == ERROR_ACCESS_DENIED)<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SetLastError( ERROR_UNABLE_TO_REMOVE_REPLACED );
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SetLastError( ERROR_UNABLE_TO_MOVE_REPLACEMENT );<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto replace_fail;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; /* Delete the replacement file */<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; if(!DeleteFileW( lpReplacementFileName ))
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; /* Unlock the handles */<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; UnlockFile( hReplacement, 0, 0, 0, 0 );<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; CloseHandle( hReplacement );<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; UnlockFile( hReplaced, 0, 0, 0, 0 );<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; CloseHandle( hReplaced );
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; /* All done, file replacement successful */<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; return TRUE;<br>&gt;<br>&gt; replace_fail:<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; UnlockFile( hReplacement, 0, 0, 0, 0 );<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; CloseHandle( hReplacement );<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; UnlockFile( hReplaced, 0, 0, 0, 0 );
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; CloseHandle( hReplaced );<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;<br>&gt; }<br><br></blockquote></div><br>