⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 queue.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 4 页
字号:
    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( &sectionW, section ))
    {
        ret = SetupQueueDeleteSectionW( queue, hinf, hlist, sectionW.Buffer );
        RtlFreeUnicodeString( &sectionW );
    }
    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( &sectionW, section ))
    {
        ret = SetupQueueRenameSectionW( queue, hinf, hlist, sectionW.Buffer );
        RtlFreeUnicodeString( &sectionW );
    }
    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 + -