Respect the version SP_COPY flags when installing files.

Make GenInstall16 only copy files if the version is new or same.
This commit is contained in:
Aric Stewart 2003-05-19 18:52:16 +00:00 committed by Alexandre Julliard
parent 1048ebb37e
commit b5d318460d
3 changed files with 133 additions and 5 deletions

View file

@ -4,7 +4,7 @@ TOPOBJDIR = ../..
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = setupapi.dll
IMPORTS = user32 advapi32 kernel32 ntdll
IMPORTS = user32 version advapi32 kernel32 ntdll
ALTNAMES = setupx.dll
EXTRALIBS = $(LIBUNICODE)

View file

@ -183,8 +183,9 @@ RETERR16 WINAPI GenInstall16( HINF16 hinf16, LPCSTR section, WORD genflags )
if (genflags & GENINSTALL_DO_PERUSER) FIXME( "unsupported flag: GENINSTALL_DO_PERUSER\n" );
context = SetupInitDefaultQueueCallback( 0 );
if (!SetupInstallFromInfSectionA( 0, hinf, section, flags, 0, NULL, 0,
SetupDefaultQueueCallbackA, context, 0, 0 ))
if (!SetupInstallFromInfSectionA( 0, hinf, section, flags, 0, NULL,
SP_COPY_NEWER_OR_SAME, SetupDefaultQueueCallbackA,
context, 0, 0 ))
ret = get_last_error();
SetupTermDefaultQueueCallback( context );

View file

@ -25,6 +25,7 @@
#include "setupapi.h"
#include "wine/unicode.h"
#include "setupapi_private.h"
#include "ver.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
@ -937,6 +938,132 @@ static BOOL create_full_pathW(const WCHAR *path)
return ret;
}
BOOL static 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 existance 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(source,&zero);
VersionSizeTarget = GetFileVersionInfoSizeW(target,&zero);
}
TRACE("SizeTarget %li ... SizeSource %li\n",VersionSizeTarget,
VersionSizeSource);
if (VersionSizeSource && VersionSizeTarget)
{
LPVOID VersionSource;
LPVOID VersionTarget;
VS_FIXEDFILEINFO *TargetInfo;
VS_FIXEDFILEINFO *SourceInfo;
INT length;
WCHAR SubBlock[2]={'\\',0};
DWORD ret;
VersionSource = HeapAlloc(GetProcessHeap(),0,VersionSizeSource);
VersionTarget = HeapAlloc(GetProcessHeap(),0,VersionSizeTarget);
ret = GetFileVersionInfoW(source,0,VersionSizeSource,VersionSource);
if (ret)
ret = GetFileVersionInfoW(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.@)
@ -1035,8 +1162,8 @@ BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBAC
if (op_result == FILEOP_ABORT) goto done;
}
}
if (CopyFileW( op_result == FILEOP_NEWPATH ? newpath : paths.Source,
paths.Target, FALSE /*FIXME*/ )) break; /* success */
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)
{