Module: wine Branch: master Commit: a20c9738eee5836e86372be9e56208c9d46ca3ec URL: http://source.winehq.org/git/wine.git/?a=commit;h=a20c9738eee5836e86372be9e5...
Author: Piotr Caban piotr@codeweavers.com Date: Tue Jul 30 11:32:13 2013 +0200
scrrun: Add IFileSystem3::CopyFolder implementation.
---
dlls/scrrun/filesystem.c | 123 +++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 121 insertions(+), 2 deletions(-)
diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c index d03b32d..19e3e23 100644 --- a/dlls/scrrun/filesystem.c +++ b/dlls/scrrun/filesystem.c @@ -82,6 +82,7 @@ static inline HRESULT create_error(DWORD err) case ERROR_PATH_NOT_FOUND: return CTL_E_PATHNOTFOUND; case ERROR_ACCESS_DENIED: return CTL_E_PERMISSIONDENIED; case ERROR_FILE_EXISTS: return CTL_E_FILEALREADYEXISTS; + case ERROR_ALREADY_EXISTS: return CTL_E_FILEALREADYEXISTS; default: FIXME("Unsupported error code: %d\n", err); return E_FAIL; @@ -1589,12 +1590,130 @@ static HRESULT WINAPI filesys_CopyFile(IFileSystem3 *iface, BSTR Source, SysStringLen(Destination), OverWriteFiles); }
+static HRESULT copy_folder(const WCHAR *source, DWORD source_len, const WCHAR *destination, + DWORD destination_len, VARIANT_BOOL overwrite) +{ + DWORD tmp, src_len, dst_len, name_len; + WCHAR src[MAX_PATH], dst[MAX_PATH]; + WIN32_FIND_DATAW ffd; + HANDLE f; + HRESULT hr; + BOOL copied = FALSE; + + if(!source[0] || !destination[0]) + return E_INVALIDARG; + + dst_len = destination_len; + if(dst_len+1 >= MAX_PATH) + return E_FAIL; + memcpy(dst, destination, (dst_len+1)*sizeof(WCHAR)); + + if(dst[dst_len-1]!='\' && dst[dst_len-1]!='/' && + (tmp = GetFileAttributesW(source))!=INVALID_FILE_ATTRIBUTES && + tmp&FILE_ATTRIBUTE_DIRECTORY) { + if(!CreateDirectoryW(dst, NULL)) { + if(overwrite && GetLastError()==ERROR_ALREADY_EXISTS) { + tmp = GetFileAttributesW(dst); + if(tmp==INVALID_FILE_ATTRIBUTES || !(tmp&FILE_ATTRIBUTE_DIRECTORY)) + return CTL_E_FILEALREADYEXISTS; + }else { + return create_error(GetLastError()); + } + } + copied = TRUE; + + src_len = source_len; + if(src_len+2 >= MAX_PATH) + return E_FAIL; + memcpy(src, source, src_len*sizeof(WCHAR)); + src[src_len++] = '\'; + src[src_len] = '*'; + src[src_len+1] = 0; + + hr = copy_file(src, src_len+1, dst, dst_len, overwrite); + if(FAILED(hr) && hr!=CTL_E_FILENOTFOUND) + return create_error(GetLastError()); + + f = FindFirstFileW(src, &ffd); + }else { + src_len = get_parent_folder_name(source, source_len); + if(src_len+2 >= MAX_PATH) + return E_FAIL; + memcpy(src, source, src_len*sizeof(WCHAR)); + if(src_len) + src[src_len++] = '\'; + + f = FindFirstFileW(source, &ffd); + } + if(f == INVALID_HANDLE_VALUE) + return CTL_E_PATHNOTFOUND; + + dst[dst_len++] = '\'; + dst[dst_len] = 0; + + do { + if(!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + continue; + if(ffd.cFileName[0]=='.' && (ffd.cFileName[1]==0 || + (ffd.cFileName[1]=='.' && ffd.cFileName[2]==0))) + continue; + + name_len = strlenW(ffd.cFileName); + if(dst_len+name_len>=MAX_PATH || src_len+name_len+2>=MAX_PATH) { + FindClose(f); + return E_FAIL; + } + memcpy(dst+dst_len, ffd.cFileName, name_len*sizeof(WCHAR)); + dst[dst_len+name_len] = 0; + memcpy(src+src_len, ffd.cFileName, name_len*sizeof(WCHAR)); + src[src_len+name_len] = '\'; + src[src_len+name_len+1] = '*'; + src[src_len+name_len+2] = 0; + + TRACE("copying %s to %s\n", debugstr_w(src), debugstr_w(dst)); + + if(!CreateDirectoryW(dst, NULL)) { + if(overwrite && GetLastError()==ERROR_ALREADY_EXISTS) { + tmp = GetFileAttributesW(dst); + if(tmp==INVALID_FILE_ATTRIBUTES || !(tmp&FILE_ATTRIBUTE_DIRECTORY)) { + FindClose(f); + return CTL_E_FILEALREADYEXISTS; + } + }else { + FindClose(f); + return create_error(GetLastError()); + } + return create_error(GetLastError()); + } + copied = TRUE; + + hr = copy_file(src, src_len+name_len+2, dst, dst_len+name_len, overwrite); + if(FAILED(hr) && hr!=CTL_E_FILENOTFOUND) { + FindClose(f); + return hr; + } + + hr = copy_folder(src, src_len+name_len+2, dst, dst_len+name_len, overwrite); + if(FAILED(hr) && hr!=CTL_E_PATHNOTFOUND) { + FindClose(f); + return hr; + } + } while(FindNextFileW(f, &ffd)); + FindClose(f); + + return copied ? S_OK : CTL_E_PATHNOTFOUND; +} + static HRESULT WINAPI filesys_CopyFolder(IFileSystem3 *iface, BSTR Source, BSTR Destination, VARIANT_BOOL OverWriteFiles) { - FIXME("%p %s %s %d\n", iface, debugstr_w(Source), debugstr_w(Destination), OverWriteFiles); + TRACE("%p %s %s %d\n", iface, debugstr_w(Source), debugstr_w(Destination), OverWriteFiles);
- return E_NOTIMPL; + if(!Source || !Destination) + return E_POINTER; + + return copy_folder(Source, SysStringLen(Source), Destination, + SysStringLen(Destination), OverWriteFiles); }
static HRESULT WINAPI filesys_CreateFolder(IFileSystem3 *iface, BSTR path,