sync msi to wine 1.1.31
[reactos.git] / reactos / dll / win32 / msi / files.c
index 01a80b7..d9cc0ff 100644 (file)
@@ -139,7 +139,7 @@ static UINT copy_file(MSIFILE *file, LPWSTR source)
     return ERROR_SUCCESS;
 }
 
-static UINT copy_install_file(MSIFILE *file, LPWSTR source)
+static UINT copy_install_file(MSIPACKAGE *package, MSIFILE *file, LPWSTR source)
 {
     UINT gle;
 
@@ -153,7 +153,7 @@ static UINT copy_install_file(MSIFILE *file, LPWSTR source)
     if (gle == ERROR_ALREADY_EXISTS && file->state == msifs_overwrite)
     {
         TRACE("overwriting existing file\n");
-        gle = ERROR_SUCCESS;
+        return ERROR_SUCCESS;
     }
     else if (gle == ERROR_ACCESS_DENIED)
     {
@@ -162,6 +162,39 @@ static UINT copy_install_file(MSIFILE *file, LPWSTR source)
         gle = copy_file(file, source);
         TRACE("Overwriting existing file: %d\n", gle);
     }
+    if (gle == ERROR_SHARING_VIOLATION)
+    {
+        static const WCHAR msiW[] = {'m','s','i',0};
+        static const WCHAR slashW[] = {'\\',0};
+        WCHAR tmpfileW[MAX_PATH], *pathW, *p;
+        DWORD len;
+
+        TRACE("file in use, scheduling rename operation\n");
+
+        GetTempFileNameW(slashW, msiW, 0, tmpfileW);
+        len = strlenW(file->TargetPath) + strlenW(tmpfileW) + 1;
+        if (!(pathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))))
+            return ERROR_OUTOFMEMORY;
+
+        strcpyW(pathW, file->TargetPath);
+        if ((p = strrchrW(pathW, '\\'))) *p = 0;
+        strcatW(pathW, tmpfileW);
+
+        if (CopyFileW(source, pathW, FALSE) &&
+            MoveFileExW(file->TargetPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT) &&
+            MoveFileExW(pathW, file->TargetPath, MOVEFILE_DELAY_UNTIL_REBOOT))
+        {
+            file->state = msifs_installed;
+            package->need_reboot = 1;
+            gle = ERROR_SUCCESS;
+        }
+        else
+        {
+            gle = GetLastError();
+            WARN("failed to schedule rename operation: %d)\n", gle);
+        }
+        HeapFree(GetProcessHeap(), 0, pathW);
+    }
 
     return gle;
 }
@@ -296,7 +329,7 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
                   debugstr_w(file->TargetPath));
 
             msi_file_update_ui(package, file, szInstallFiles);
-            rc = copy_install_file(file, source);
+            rc = copy_install_file(package, file, source);
             if (rc != ERROR_SUCCESS)
             {
                 ERR("Failed to copy %s to %s (%d)\n", debugstr_w(source),