setupapi: Add an extension to support file copies from module resources.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
354aabd77e
commit
5696c3c23d
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
|
@ -151,8 +152,11 @@ 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->src_file[0] != '@')
|
||||
{
|
||||
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;
|
||||
|
@ -170,7 +174,10 @@ 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;
|
||||
if (op->src_file[0] != '@')
|
||||
concat_W( source, op->media ? op->media->root : NULL, op->src_path, op->src_file );
|
||||
else
|
||||
lstrcpyW( source, op->src_file );
|
||||
concat_W( target, NULL, op->dst_path, op->dst_file );
|
||||
paths->Win32Error = 0;
|
||||
paths->Flags = 0;
|
||||
|
@ -1002,6 +1009,59 @@ static BOOL create_full_pathW(const WCHAR *path)
|
|||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style,
|
||||
PSP_FILE_CALLBACK_W handler, PVOID context )
|
||||
{
|
||||
|
@ -1124,7 +1184,7 @@ static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style,
|
|||
|
||||
if (docopy)
|
||||
{
|
||||
rc = CopyFileW(source,target,FALSE);
|
||||
rc = copy_file( source, target );
|
||||
if (!rc && GetLastError() == ERROR_SHARING_VIOLATION &&
|
||||
(style & SP_COPY_IN_USE_NEEDS_REBOOT))
|
||||
{
|
||||
|
@ -1134,7 +1194,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
|
||||
|
|
Loading…
Reference in New Issue