setupapi: Implement source media path resolution.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47107 Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
cfe4ce28eb
commit
3e5c9798a8
|
@ -55,6 +55,8 @@ struct source_media
|
|||
{
|
||||
WCHAR root[MAX_PATH];
|
||||
WCHAR *desc, *tag;
|
||||
BOOL resolved;
|
||||
BOOL cabinet;
|
||||
};
|
||||
|
||||
struct file_op
|
||||
|
@ -518,6 +520,8 @@ static struct source_media *get_source_media(struct file_queue *queue,
|
|||
strcpyW(queue->sources[i]->root, root);
|
||||
queue->sources[i]->desc = strdupW(desc);
|
||||
queue->sources[i]->tag = strdupW(tag);
|
||||
queue->sources[i]->resolved = FALSE;
|
||||
queue->sources[i]->cabinet = FALSE;
|
||||
|
||||
return queue->sources[i];
|
||||
}
|
||||
|
@ -1284,7 +1288,10 @@ static BOOL queue_copy_file( const WCHAR *source, const WCHAR *dest,
|
|||
|
||||
/* try to extract it from the cabinet file */
|
||||
if (op->media->tag && extract_cabinet_file(op->media->tag, op->media->root, op->src_file, dest))
|
||||
{
|
||||
op->media->cabinet = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1367,22 +1374,101 @@ BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBAC
|
|||
{
|
||||
WCHAR newpath[MAX_PATH];
|
||||
|
||||
build_filepathsW( op, &paths );
|
||||
op_result = handler( context, SPFILENOTIFY_STARTCOPY, (UINT_PTR)&paths, FILEOP_COPY );
|
||||
if (op_result == FILEOP_ABORT) goto done;
|
||||
if (op_result == FILEOP_NEWPATH) op_result = FILEOP_DOIT;
|
||||
while (op_result == FILEOP_DOIT || op_result == FILEOP_NEWPATH)
|
||||
if (!op->media->resolved)
|
||||
{
|
||||
if (queue_copy_file( op_result == FILEOP_NEWPATH ? newpath : paths.Source,
|
||||
paths.Target, op, handler, context ))
|
||||
break;
|
||||
/* The NEEDMEDIA callback asks for the folder containing the
|
||||
* first file, but that might be in a subdir of the source
|
||||
* disk's root directory. We have to do some contortions to
|
||||
* correct for this. Pretend that the file we're using
|
||||
* actually isn't in a subdirectory, but keep track of what it
|
||||
* was, and then later strip it from the root path that we
|
||||
* ultimately resolve the source disk to. */
|
||||
WCHAR *src_path = op->src_path;
|
||||
|
||||
paths.Win32Error = GetLastError();
|
||||
op_result = handler( context, SPFILENOTIFY_COPYERROR,
|
||||
(UINT_PTR)&paths, (UINT_PTR)newpath );
|
||||
if (op_result == FILEOP_ABORT) goto done;
|
||||
op->src_path = NULL;
|
||||
if (src_path)
|
||||
{
|
||||
strcatW(op->media->root, backslashW);
|
||||
strcatW(op->media->root, src_path);
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
SOURCE_MEDIA_W media;
|
||||
media.Reserved = NULL;
|
||||
media.Tagfile = op->media->tag;
|
||||
media.Description = op->media->desc;
|
||||
media.SourcePath = op->media->root;
|
||||
media.SourceFile = op->src_file;
|
||||
media.Flags = op->style & (SP_COPY_WARNIFSKIP | SP_COPY_NOSKIP | SP_FLAG_CABINETCONTINUATION | SP_COPY_NOBROWSE);
|
||||
|
||||
newpath[0] = 0;
|
||||
op_result = handler( context, SPFILENOTIFY_NEEDMEDIA, (UINT_PTR)&media, (UINT_PTR)newpath );
|
||||
|
||||
if (op_result == FILEOP_ABORT)
|
||||
goto done;
|
||||
else if (op_result == FILEOP_SKIP)
|
||||
break;
|
||||
else if (op_result == FILEOP_NEWPATH)
|
||||
strcpyW(op->media->root, newpath);
|
||||
else if (op_result != FILEOP_DOIT)
|
||||
FIXME("Unhandled return value %#x.\n", op_result);
|
||||
|
||||
build_filepathsW( op, &paths );
|
||||
op_result = handler( context, SPFILENOTIFY_STARTCOPY, (UINT_PTR)&paths, FILEOP_COPY );
|
||||
if (op_result == FILEOP_ABORT)
|
||||
goto done;
|
||||
else if (op_result == FILEOP_SKIP)
|
||||
break;
|
||||
else if (op_result != FILEOP_DOIT)
|
||||
FIXME("Unhandled return value %#x.\n", op_result);
|
||||
|
||||
if (queue_copy_file( paths.Source, paths.Target, op, handler, context ))
|
||||
{
|
||||
if (src_path && !op->media->cabinet)
|
||||
{
|
||||
size_t root_len = strlenW(op->media->root), path_len = strlenW(src_path);
|
||||
if (path_len <= root_len && !strncmpiW(op->media->root + root_len - path_len, src_path, path_len))
|
||||
op->media->root[root_len - path_len - 1] = 0;
|
||||
heap_free( src_path );
|
||||
}
|
||||
op->media->resolved = TRUE;
|
||||
handler( context, SPFILENOTIFY_ENDCOPY, (UINT_PTR)&paths, 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
build_filepathsW( op, &paths );
|
||||
op_result = handler( context, SPFILENOTIFY_STARTCOPY, (UINT_PTR)&paths, FILEOP_COPY );
|
||||
if (op_result == FILEOP_ABORT)
|
||||
goto done;
|
||||
else if (op_result == FILEOP_SKIP)
|
||||
break;
|
||||
else if (op_result != FILEOP_DOIT)
|
||||
FIXME("Unhandled return value %#x.\n", op_result);
|
||||
|
||||
while (op_result == FILEOP_DOIT || op_result == FILEOP_NEWPATH)
|
||||
{
|
||||
if (queue_copy_file( paths.Source, paths.Target, op, handler, context ))
|
||||
break;
|
||||
|
||||
paths.Win32Error = GetLastError();
|
||||
newpath[0] = 0;
|
||||
op_result = handler( context, SPFILENOTIFY_COPYERROR, (UINT_PTR)&paths, (UINT_PTR)newpath );
|
||||
if (op_result == FILEOP_ABORT)
|
||||
goto done;
|
||||
else if (op_result == FILEOP_NEWPATH)
|
||||
{
|
||||
strcpyW(op->media->root, newpath);
|
||||
build_filepathsW(op, &paths);
|
||||
}
|
||||
else if (op_result != FILEOP_SKIP && op_result != FILEOP_DOIT)
|
||||
FIXME("Unhandled return value %#x.\n", op_result);
|
||||
}
|
||||
handler( context, SPFILENOTIFY_ENDCOPY, (UINT_PTR)&paths, 0 );
|
||||
}
|
||||
handler( context, SPFILENOTIFY_ENDCOPY, (UINT_PTR)&paths, 0 );
|
||||
}
|
||||
handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_COPY, 0 );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue