Piotr Caban : scrrun: Add IFileSystem3::CopyFolder implementation.
Alexandre Julliard
julliard at winehq.org
Tue Jul 30 14:14:21 CDT 2013
Module: wine
Branch: master
Commit: a20c9738eee5836e86372be9e56208c9d46ca3ec
URL: http://source.winehq.org/git/wine.git/?a=commit;h=a20c9738eee5836e86372be9e56208c9d46ca3ec
Author: Piotr Caban <piotr at 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,
More information about the wine-cvs
mailing list