📄 queue.c
字号:
ret = TRUE;
done:
if (security_descriptor)
MyFree( security_descriptor );
return ret;
}
/***********************************************************************
* SetupQueueDeleteSectionA (SETUPAPI.@)
*/
BOOL WINAPI SetupQueueDeleteSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
{
UNICODE_STRING sectionW;
BOOL ret = FALSE;
if (RtlCreateUnicodeStringFromAsciiz( §ionW, section ))
{
ret = SetupQueueDeleteSectionW( queue, hinf, hlist, sectionW.Buffer );
RtlFreeUnicodeString( §ionW );
}
else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return ret;
}
/***********************************************************************
* SetupQueueDeleteSectionW (SETUPAPI.@)
*/
BOOL WINAPI SetupQueueDeleteSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
{
INFCONTEXT context;
WCHAR *dest_dir;
WCHAR buffer[MAX_PATH];
BOOL ret = FALSE;
INT flags;
TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
if (!hlist) hlist = hinf;
if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
do
{
if (!SetupGetStringFieldW( &context, 1, buffer, sizeof(buffer)/sizeof(WCHAR), NULL ))
goto done;
if (!SetupGetIntField( &context, 4, &flags )) flags = 0;
if (!SetupQueueDeleteW( queue, dest_dir, buffer )) goto done;
} while (SetupFindNextLine( &context, &context ));
ret = TRUE;
done:
HeapFree( GetProcessHeap(), 0, dest_dir );
return ret;
}
/***********************************************************************
* SetupQueueRenameSectionA (SETUPAPI.@)
*/
BOOL WINAPI SetupQueueRenameSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
{
UNICODE_STRING sectionW;
BOOL ret = FALSE;
if (RtlCreateUnicodeStringFromAsciiz( §ionW, section ))
{
ret = SetupQueueRenameSectionW( queue, hinf, hlist, sectionW.Buffer );
RtlFreeUnicodeString( §ionW );
}
else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return ret;
}
/***********************************************************************
* SetupQueueRenameSectionW (SETUPAPI.@)
*/
BOOL WINAPI SetupQueueRenameSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
{
INFCONTEXT context;
WCHAR *dest_dir;
WCHAR src[MAX_PATH], dst[MAX_PATH];
BOOL ret = FALSE;
TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
if (!hlist) hlist = hinf;
if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
do
{
if (!SetupGetStringFieldW( &context, 1, dst, sizeof(dst)/sizeof(WCHAR), NULL ))
goto done;
if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL ))
goto done;
if (!SetupQueueRenameW( queue, dest_dir, src, NULL, dst )) goto done;
} while (SetupFindNextLine( &context, &context ));
ret = TRUE;
done:
HeapFree( GetProcessHeap(), 0, dest_dir );
return ret;
}
/***********************************************************************
* SetupCommitFileQueueA (SETUPAPI.@)
*/
BOOL WINAPI SetupCommitFileQueueA( HWND owner, HSPFILEQ queue, PSP_FILE_CALLBACK_A handler,
PVOID context )
{
struct callback_WtoA_context ctx;
ctx.orig_context = context;
ctx.orig_handler = handler;
return SetupCommitFileQueueW( owner, queue, QUEUE_callback_WtoA, &ctx );
}
/***********************************************************************
* create_full_pathW
*
* Recursively create all directories in the path.
*/
static BOOL create_full_pathW(const WCHAR *path)
{
BOOL ret = TRUE;
int len;
WCHAR *new_path;
new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * sizeof(WCHAR));
strcpyW(new_path, path);
while((len = strlenW(new_path)) && new_path[len - 1] == '\\')
new_path[len - 1] = 0;
while(!CreateDirectoryW(new_path, NULL))
{
WCHAR *slash;
DWORD last_error = GetLastError();
if(last_error == ERROR_ALREADY_EXISTS)
break;
if(last_error != ERROR_PATH_NOT_FOUND)
{
ret = FALSE;
break;
}
if(!(slash = strrchrW(new_path, '\\')))
{
ret = FALSE;
break;
}
len = slash - new_path;
new_path[len] = 0;
if(!create_full_pathW(new_path))
{
ret = FALSE;
break;
}
new_path[len] = '\\';
}
HeapFree(GetProcessHeap(), 0, new_path);
return ret;
}
static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style)
{
BOOL rc = FALSE;
BOOL docopy = TRUE;
TRACE("copy %s to %s style 0x%lx\n",debugstr_w(source),debugstr_w(target),style);
/* before copy processing */
if (style & SP_COPY_REPLACEONLY)
{
if (GetFileAttributesW(target) == INVALID_FILE_ATTRIBUTES)
docopy = FALSE;
}
if (style & (SP_COPY_NEWER_OR_SAME | SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER))
{
DWORD VersionSizeSource=0;
DWORD VersionSizeTarget=0;
DWORD zero=0;
/*
* This is sort of an interesting workaround. You see, calling
* GetVersionInfoSize on a builtin dll loads that dll into memory
* and we do not properly unload builtin dlls.. so we effectively
* lock into memory all the targets we are replacing. This leads
* to problems when we try to register the replaced dlls.
*
* So I will test for the existence of the files first so that
* we just basically unconditionally replace the builtin versions.
*/
if ((GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) &&
(GetFileAttributesW(source) != INVALID_FILE_ATTRIBUTES))
{
VersionSizeSource = GetFileVersionInfoSizeW((LPWSTR)source,&zero);
VersionSizeTarget = GetFileVersionInfoSizeW((LPWSTR)target,&zero);
}
TRACE("SizeTarget %li ... SizeSource %li\n",VersionSizeTarget,
VersionSizeSource);
if (VersionSizeSource && VersionSizeTarget)
{
LPVOID VersionSource;
LPVOID VersionTarget;
VS_FIXEDFILEINFO *TargetInfo;
VS_FIXEDFILEINFO *SourceInfo;
UINT length;
WCHAR SubBlock[2]={'\\',0};
DWORD ret;
VersionSource = HeapAlloc(GetProcessHeap(),0,VersionSizeSource);
VersionTarget = HeapAlloc(GetProcessHeap(),0,VersionSizeTarget);
ret = GetFileVersionInfoW((LPWSTR)source,0,VersionSizeSource,VersionSource);
if (ret)
ret = GetFileVersionInfoW((LPWSTR)target, 0, VersionSizeTarget,
VersionTarget);
if (ret)
{
ret = VerQueryValueW(VersionSource, SubBlock,
(LPVOID*)&SourceInfo, &length);
if (ret)
ret = VerQueryValueW(VersionTarget, SubBlock,
(LPVOID*)&TargetInfo, &length);
if (ret)
{
TRACE("Versions: Source %li.%li target %li.%li\n",
SourceInfo->dwFileVersionMS, SourceInfo->dwFileVersionLS,
TargetInfo->dwFileVersionMS, TargetInfo->dwFileVersionLS);
if (TargetInfo->dwFileVersionMS > SourceInfo->dwFileVersionMS)
{
FIXME("Notify that target version is greater..\n");
docopy = FALSE;
}
else if ((TargetInfo->dwFileVersionMS == SourceInfo->dwFileVersionMS)
&& (TargetInfo->dwFileVersionLS > SourceInfo->dwFileVersionLS))
{
FIXME("Notify that target version is greater..\n");
docopy = FALSE;
}
else if ((style & SP_COPY_NEWER_ONLY) &&
(TargetInfo->dwFileVersionMS ==
SourceInfo->dwFileVersionMS)
&&(TargetInfo->dwFileVersionLS ==
SourceInfo->dwFileVersionLS))
{
FIXME("Notify that target version is greater..\n");
docopy = FALSE;
}
}
}
HeapFree(GetProcessHeap(),0,VersionSource);
HeapFree(GetProcessHeap(),0,VersionTarget);
}
}
if (style & (SP_COPY_NOOVERWRITE | SP_COPY_FORCE_NOOVERWRITE))
{
if (GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES)
{
FIXME("Notify user target file exists\n");
docopy = FALSE;
}
}
if (style & (SP_COPY_NODECOMP | SP_COPY_LANGUAGEAWARE | SP_COPY_FORCE_IN_USE |
SP_COPY_IN_USE_NEEDS_REBOOT | SP_COPY_NOSKIP | SP_COPY_WARNIFSKIP))
{
ERR("Unsupported style(s) 0x%lx\n",style);
}
if (docopy)
{
rc = CopyFileW(source,target,FALSE);
TRACE("Did copy... rc was %i\n",rc);
}
/* after copy processing */
if (style & SP_COPY_DELETESOURCE)
{
if (rc)
DeleteFileW(source);
}
return rc;
}
/***********************************************************************
* SetupCommitFileQueueW (SETUPAPI.@)
*/
BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBACK_W handler,
PVOID context )
{
struct file_queue *queue = handle;
struct file_op *op;
BOOL result = FALSE;
FILEPATHS_W paths;
UINT op_result;
paths.Source = paths.Target = NULL;
if (!queue->copy_queue.count && !queue->delete_queue.count && !queue->rename_queue.count)
return TRUE; /* nothing to do */
if (!handler( context, SPFILENOTIFY_STARTQUEUE, (UINT)owner, 0 )) return FALSE;
/* perform deletes */
if (queue->delete_queue.count)
{
if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_DELETE,
queue->delete_queue.count ))) goto done;
for (op = queue->delete_queue.head; op; op = op->next)
{
build_filepathsW( op, &paths );
op_result = handler( context, SPFILENOTIFY_STARTDELETE, (UINT_PTR)&paths, FILEOP_DELETE);
if (op_result == FILEOP_ABORT) goto done;
while (op_result == FILEOP_DOIT)
{
TRACE( "deleting file %s\n", debugstr_w(paths.Target) );
if (DeleteFileW( paths.Target )) break; /* success */
paths.Win32Error = GetLastError();
op_result = handler( context, SPFILENOTIFY_DELETEERROR, (UINT_PTR)&paths, 0 );
if (op_result == FILEOP_ABORT) goto done;
}
handler( context, SPFILENOTIFY_ENDDELETE, (UINT_PTR)&paths, 0 );
}
handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_DELETE, 0 );
}
/* perform renames */
if (queue->rename_queue.count)
{
if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_RENAME,
queue->rename_queue.count ))) goto done;
for (op = queue->rename_queue.head; op; op = op->next)
{
build_filepathsW( op, &paths );
op_result = handler( context, SPFILENOTIFY_STARTRENAME, (UINT_PTR)&paths, FILEOP_RENAME);
if (op_result == FILEOP_ABORT) goto done;
while (op_result == FILEOP_DOIT)
{
TRACE( "renaming file %s -> %s\n",
debugstr_w(paths.Source), debugstr_w(paths.Target) );
if (MoveFileW( paths.Source, paths.Target )) break; /* success */
paths.Win32Error = GetLastError();
op_result = handler( context, SPFILENOTIFY_RENAMEERROR, (UINT_PTR)&paths, 0 );
if (op_result == FILEOP_ABORT) goto done;
}
handler( context, SPFILENOTIFY_ENDRENAME, (UINT_PTR)&paths, 0 );
}
handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_RENAME, 0 );
}
/* perform copies */
if (queue->copy_queue.count)
{
if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_COPY,
queue->copy_queue.count ))) goto done;
for (op = queue->copy_queue.head; op; op = op->next)
{
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)
{
TRACE( "copying file %s -> %s\n",
debugstr_w( op_result == FILEOP_NEWPATH ? newpath : paths.Source ),
debugstr_w(paths.Target) );
if (op->dst_path)
{
if (!create_full_pathW( op->dst_path ))
{
paths.Win32Error = GetLastError();
op_result = handler( context, SPFILENOTIFY_COPYERROR,
(UINT_PTR)&paths, (UINT_PTR)newpath );
if (op_result == FILEOP_ABORT) goto done;
}
}
if (do_file_copyW( op_result == FILEOP_NEWPATH ? newpath : paths.Source,
paths.Target, op->style )) break; /* success */
/* try to extract it from the cabinet file */
if (op->src_tag)
{
if (extract_cabinet_file( op->src_tag, op->src_root,
paths.Source, paths.Target )) break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -