diff --git a/dll/win32/setupapi/queue.c b/dll/win32/setupapi/queue.c index 228934916fa..585d31cd33d 100644 --- a/dll/win32/setupapi/queue.c +++ b/dll/win32/setupapi/queue.c @@ -21,6 +21,10 @@ #include "setupapi_private.h" #include "wine/heap.h" +#ifdef __WINESRC__ +#include +#endif + #ifdef __REACTOS__ #include #endif @@ -146,8 +150,13 @@ static BOOL build_filepathsW( const struct file_op *op, FILEPATHS_W *paths ) unsigned int src_len = 1, dst_len = 1; WCHAR *source = (PWSTR)paths->Source, *target = (PWSTR)paths->Target; - if (op->media) src_len += lstrlenW(op->media->root) + 1; - if (op->src_path) src_len += lstrlenW(op->src_path) + 1; +#ifdef __WINESRC__ + if (op->src_file[0] != '@') +#endif + { + if (op->media) src_len += lstrlenW(op->media->root) + 1; + if (op->src_path) src_len += lstrlenW(op->src_path) + 1; + } if (op->src_file) src_len += lstrlenW(op->src_file) + 1; if (op->dst_path) dst_len += lstrlenW(op->dst_path) + 1; if (op->dst_file) dst_len += lstrlenW(op->dst_file) + 1; @@ -165,7 +174,14 @@ static BOOL build_filepathsW( const struct file_op *op, FILEPATHS_W *paths ) paths->Target = target = HeapAlloc( GetProcessHeap(), 0, dst_len ); } if (!source || !target) return FALSE; - concat_W( source, op->media ? op->media->root : NULL, op->src_path, op->src_file ); +#ifdef __WINESRC__ + if (op->src_file[0] != '@') +#endif + concat_W( source, op->media ? op->media->root : NULL, op->src_path, op->src_file ); +#ifdef __WINESRC__ + else + lstrcpyW( source, op->src_file ); +#endif concat_W( target, NULL, op->dst_path, op->dst_file ); paths->Win32Error = 0; paths->Flags = 0; @@ -1159,6 +1175,61 @@ static BOOL create_full_pathW(const WCHAR *path) return ret; } +#ifdef __WINESRC__ +static BOOL copy_file( LPCWSTR source, LPCWSTR target ) +{ + WCHAR module[MAX_PATH]; + HMODULE mod = NULL; + HRSRC res; + HGLOBAL data; + HANDLE handle; + DWORD size, written; + BOOL ret = FALSE; + int id = 0; + const WCHAR *p; + + TRACE( "%s -> %s\n", debugstr_w(source), debugstr_w(target) ); + + if (source[0] != '@') return CopyFileW( source, target, FALSE ); + + /* Wine extension: when the source of a file copy is in the format "@file.dll,-123" + * the source data is extracted from the corresponding file.dll resource */ + + source++; /* skip '@' */ + p = wcschr( source, ',' ); + if (!p || p - source >= MAX_PATH) + { + SetLastError( ERROR_RESOURCE_DATA_NOT_FOUND ); + return FALSE; + } + memcpy( module, source, (p - source) * sizeof(WCHAR) ); + module[p - source] = 0; + id = -wcstol( p + 1, NULL, 10 ); + if (id <= 0 || id > 0xffff || + !(mod = LoadLibraryExW( module, 0, LOAD_LIBRARY_AS_DATAFILE )) || + !(res = FindResourceW( mod, MAKEINTRESOURCEW(id), L"WINE_DATA_FILE" )) || + !(data = LoadResource( mod, res ))) + { + WARN( "failed to save %s #%d to %s\n", debugstr_w(module), -id, debugstr_w(target) ); + if (mod) FreeLibrary( mod ); + SetLastError( ERROR_RESOURCE_DATA_NOT_FOUND ); + return FALSE; + } + size = SizeofResource( mod, res ); + if ((handle = CreateFileW( target, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + CREATE_ALWAYS, 0, 0 )) == INVALID_HANDLE_VALUE) + { + WARN( "failed to save %s #%d to %s\n", debugstr_w(module), -id, debugstr_w(target) ); + if (mod) FreeLibrary( mod ); + return FALSE; + } + ret = WriteFile( handle, LockResource(data), size, &written, NULL ) && written == size; + CloseHandle( handle ); + if (!ret) DeleteFileW( target ); + return ret; +} +#endif // __WINESRC__ + static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style, PSP_FILE_CALLBACK_W handler, PVOID context ) { @@ -1363,8 +1434,8 @@ static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style, { #ifdef __REACTOS__ rc = MoveFileExW(TempFile,target,MOVEFILE_REPLACE_EXISTING); -#else - rc = CopyFileW(source,target,FALSE); +#else // __WINESRC__ + rc = copy_file( source, target ); #endif if (!rc && GetLastError() == ERROR_SHARING_VIOLATION && (style & SP_COPY_IN_USE_NEEDS_REBOOT)) @@ -1376,7 +1447,7 @@ static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style, if (GetTempPathW(MAX_PATH, temp) && GetTempFileNameW(temp, L"SET", 0, temp_file)) { - rc = CopyFileW(source, temp_file, FALSE); + rc = copy_file( source, temp_file ); if (rc) rc = MoveFileExW(temp_file, target, MOVEFILE_DELAY_UNTIL_REBOOT); else diff --git a/sdk/tools/winesync/setupapi.cfg b/sdk/tools/winesync/setupapi.cfg index b35498cbe0b..e1ad20da48b 100644 --- a/sdk/tools/winesync/setupapi.cfg +++ b/sdk/tools/winesync/setupapi.cfg @@ -10,4 +10,4 @@ files: dlls/setupapi/setupcab.c: dll/win32/setupapi/setupcab.c dlls/setupapi/stringtable.c: dll/win32/setupapi/stringtable_wine.c tags: - wine: 354aabd77e4ff3747446b2402de89d804001bd3f + wine: 5696c3c23d5be9f5ce57ef7e361d88722120da09