Respect the version SP_COPY flags when installing files.
Make GenInstall16 only copy files if the version is new or same.

diff --git a/dlls/setupapi/queue.c b/dlls/setupapi/queue.c
index 476fd00..19247a8 100644
--- a/dlls/setupapi/queue.c
+++ b/dlls/setupapi/queue.c
@@ -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 @@
     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 @@
 			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)
                 {