ReactOS  0.4.15-dev-5126-g3bb451b
files.c
Go to the documentation of this file.
1 /*
2  * Implementation of the Microsoft Installer (msi.dll)
3  *
4  * Copyright 2005 Aric Stewart for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 /*
22  * Actions dealing with files:
23  *
24  * InstallFiles
25  * DuplicateFiles
26  * MoveFiles
27  * PatchFiles
28  * RemoveDuplicateFiles
29  * RemoveFiles
30  */
31 
32 #include <stdarg.h>
33 
34 #define COBJMACROS
35 
36 #include "windef.h"
37 #include "winbase.h"
38 #include "winerror.h"
39 #include "fdi.h"
40 #include "msi.h"
41 #include "msidefs.h"
42 #include "msipriv.h"
43 #include "winuser.h"
44 #include "winreg.h"
45 #include "shlwapi.h"
46 #include "patchapi.h"
47 #include "wine/debug.h"
48 
50 
52  DWORD flags )
53 {
54  HANDLE handle;
55  msi_disable_fs_redirection( package );
56  handle = CreateFileW( filename, access, sharing, NULL, creation, flags, NULL );
57  msi_revert_fs_redirection( package );
58  return handle;
59 }
60 
61 static BOOL msi_copy_file( MSIPACKAGE *package, const WCHAR *src, const WCHAR *dst, BOOL fail_if_exists )
62 {
63  BOOL ret;
64  msi_disable_fs_redirection( package );
65  ret = CopyFileW( src, dst, fail_if_exists );
66  msi_revert_fs_redirection( package );
67  return ret;
68 }
69 
71 {
72  BOOL ret;
73  msi_disable_fs_redirection( package );
75  msi_revert_fs_redirection( package );
76  return ret;
77 }
78 
79 static BOOL msi_create_directory( MSIPACKAGE *package, const WCHAR *path )
80 {
81  BOOL ret;
82  msi_disable_fs_redirection( package );
84  msi_revert_fs_redirection( package );
85  return ret;
86 }
87 
89 {
90  BOOL ret;
91  msi_disable_fs_redirection( package );
93  msi_revert_fs_redirection( package );
94  return ret;
95 }
96 
98 {
99  BOOL ret;
100  msi_disable_fs_redirection( package );
101  ret = SetFileAttributesW( filename, attrs );
102  msi_revert_fs_redirection( package );
103  return ret;
104 }
105 
107 {
108  DWORD attrs;
109  msi_disable_fs_redirection( package );
110  attrs = GetFileAttributesW( path );
111  msi_revert_fs_redirection( package );
112  return attrs;
113 }
114 
116 {
117  HANDLE handle;
118  msi_disable_fs_redirection( package );
120  msi_revert_fs_redirection( package );
121  return handle;
122 }
123 
125 {
126  BOOL ret;
127  msi_disable_fs_redirection( package );
129  msi_revert_fs_redirection( package );
130  return ret;
131 }
132 
133 BOOL msi_move_file( MSIPACKAGE *package, const WCHAR *from, const WCHAR *to, DWORD flags )
134 {
135  BOOL ret;
136  msi_disable_fs_redirection( package );
137  ret = MoveFileExW( from, to, flags );
138  msi_revert_fs_redirection( package );
139  return ret;
140 }
141 
142 static BOOL msi_apply_filepatch( MSIPACKAGE *package, const WCHAR *patch, const WCHAR *old, const WCHAR *new )
143 {
144  BOOL ret;
145  msi_disable_fs_redirection( package );
146  ret = ApplyPatchToFileW( patch, old, new, 0 );
147  msi_revert_fs_redirection( package );
148  return ret;
149 }
150 
152 {
153  DWORD size, handle;
154  msi_disable_fs_redirection( package );
155  if (buffer) size = GetFileVersionInfoW( path, 0, buflen, buffer );
157  msi_revert_fs_redirection( package );
158  return size;
159 }
160 
162 {
164  DWORD version_size;
165  UINT size;
166  void *version;
167 
168  if (!(version_size = msi_get_file_version_info( package, filename, 0, NULL ))) return NULL;
169  if (!(version = msi_alloc( version_size ))) return NULL;
170 
171  msi_get_file_version_info( package, filename, version_size, version );
172 
173  if (!VerQueryValueW( version, L"\\", (void **)&ptr, &size ))
174  {
175  msi_free( version );
176  return NULL;
177  }
178 
179  if (!(ret = msi_alloc( size )))
180  {
181  msi_free( version );
182  return NULL;
183  }
184 
185  memcpy( ret, ptr, size );
186  msi_free( version );
187  return ret;
188 }
189 
191 {
192  DWORD size;
193  HANDLE file;
196  size = GetFileSize( file, NULL );
197  CloseHandle( file );
198  return size;
199 }
200 
201 /* Recursively create all directories in the path. */
203 {
204  BOOL ret = TRUE;
205  WCHAR *new_path;
206  int len;
207 
208  if (!(new_path = msi_alloc( (lstrlenW( path ) + 1) * sizeof(WCHAR) ))) return FALSE;
209  lstrcpyW( new_path, path );
210 
211  while ((len = lstrlenW( new_path )) && new_path[len - 1] == '\\')
212  new_path[len - 1] = 0;
213 
214  while (!msi_create_directory( package, new_path ))
215  {
216  WCHAR *slash;
218  if (last_error == ERROR_ALREADY_EXISTS) break;
220  {
221  ret = FALSE;
222  break;
223  }
224  if (!(slash = wcsrchr( new_path, '\\' )))
225  {
226  ret = FALSE;
227  break;
228  }
229  len = slash - new_path;
230  new_path[len] = 0;
231  if (!msi_create_full_path( package, new_path ))
232  {
233  ret = FALSE;
234  break;
235  }
236  new_path[len] = '\\';
237  }
238  msi_free( new_path );
239  return ret;
240 }
241 
242 static void msi_file_update_ui( MSIPACKAGE *package, MSIFILE *f, const WCHAR *action )
243 {
244  MSIRECORD *uirow;
245 
246  uirow = MSI_CreateRecord( 9 );
247  MSI_RecordSetStringW( uirow, 1, f->FileName );
248  MSI_RecordSetStringW( uirow, 9, f->Component->Directory );
249  MSI_RecordSetInteger( uirow, 6, f->FileSize );
251  msiobj_release( &uirow->hdr );
252  msi_ui_progress( package, 2, f->FileSize, 0, 0 );
253 }
254 
255 static BOOL is_registered_patch_media( MSIPACKAGE *package, UINT disk_id )
256 {
257  MSIPATCHINFO *patch;
258 
259  LIST_FOR_EACH_ENTRY( patch, &package->patches, MSIPATCHINFO, entry )
260  {
261  if (patch->disk_id == disk_id && patch->registered) return TRUE;
262  }
263  return FALSE;
264 }
265 
267 {
268  if (!list_empty( &package->patches ) && file->disk_id < MSI_INITIAL_MEDIA_TRANSFORM_DISKID)
269  {
270  if (!msi_get_property_int( package->db, L"Installed", 0 )) return FALSE;
271  return TRUE;
272  }
273  if (is_registered_patch_media( package, file->disk_id )) return TRUE;
274  return FALSE;
275 }
276 
278 {
279  UINT r;
281 
282  hash.dwFileHashInfoSize = sizeof(hash);
283  r = msi_get_filehash( package, file->TargetPath, &hash );
284  if (r != ERROR_SUCCESS)
285  return FALSE;
286 
287  return !memcmp( &hash, &file->hash, sizeof(hash) );
288 }
289 
291 {
292  MSICOMPONENT *comp = file->Component;
293  VS_FIXEDFILEINFO *file_version;
294  WCHAR *font_version;
296  DWORD size;
297 
298  comp->Action = msi_get_component_action( package, comp );
299  if (!comp->Enabled || comp->Action != INSTALLSTATE_LOCAL || (comp->assembly && comp->assembly->installed))
300  {
301  TRACE("skipping %s (not scheduled for install)\n", debugstr_w(file->File));
302  return msifs_skipped;
303  }
304  if (is_obsoleted_by_patch( package, file ))
305  {
306  TRACE("skipping %s (obsoleted by patch)\n", debugstr_w(file->File));
307  return msifs_skipped;
308  }
309  if ((msi_is_global_assembly( comp ) && !comp->assembly->installed) ||
310  msi_get_file_attributes( package, file->TargetPath ) == INVALID_FILE_ATTRIBUTES)
311  {
312  TRACE("installing %s (missing)\n", debugstr_w(file->File));
313  return msifs_missing;
314  }
315  if (file->Version)
316  {
317  if ((file_version = msi_get_disk_file_version( package, file->TargetPath )))
318  {
319  if (msi_compare_file_versions( file_version, file->Version ) < 0)
320  {
321  TRACE("overwriting %s (new version %s old version %u.%u.%u.%u)\n",
322  debugstr_w(file->File), debugstr_w(file->Version),
323  HIWORD(file_version->dwFileVersionMS), LOWORD(file_version->dwFileVersionMS),
324  HIWORD(file_version->dwFileVersionLS), LOWORD(file_version->dwFileVersionLS));
326  }
327  else
328  {
329  TRACE("keeping %s (new version %s old version %u.%u.%u.%u)\n",
330  debugstr_w(file->File), debugstr_w(file->Version),
331  HIWORD(file_version->dwFileVersionMS), LOWORD(file_version->dwFileVersionMS),
332  HIWORD(file_version->dwFileVersionLS), LOWORD(file_version->dwFileVersionLS));
334  }
335  msi_free( file_version );
336  return state;
337  }
338  else if ((font_version = msi_get_font_file_version( package, file->TargetPath )))
339  {
340  if (msi_compare_font_versions( font_version, file->Version ) < 0)
341  {
342  TRACE("overwriting %s (new version %s old version %s)\n",
343  debugstr_w(file->File), debugstr_w(file->Version), debugstr_w(font_version));
345  }
346  else
347  {
348  TRACE("keeping %s (new version %s old version %s)\n",
349  debugstr_w(file->File), debugstr_w(file->Version), debugstr_w(font_version));
351  }
352  msi_free( font_version );
353  return state;
354  }
355  }
356  if ((size = msi_get_disk_file_size( package, file->TargetPath )) != file->FileSize)
357  {
358  TRACE("overwriting %s (old size %lu new size %d)\n", debugstr_w(file->File), size, file->FileSize);
359  return msifs_overwrite;
360  }
361  if (file->hash.dwFileHashInfoSize)
362  {
363  if (file_hash_matches( package, file ))
364  {
365  TRACE("keeping %s (hash match)\n", debugstr_w(file->File));
366  return msifs_hashmatch;
367  }
368  else
369  {
370  TRACE("overwriting %s (hash mismatch)\n", debugstr_w(file->File));
371  return msifs_overwrite;
372  }
373  }
374  /* assume present */
375  TRACE("keeping %s\n", debugstr_w(file->File));
376  return msifs_present;
377 }
378 
379 static void schedule_install_files(MSIPACKAGE *package)
380 {
381  MSIFILE *file;
382 
384  {
385  MSICOMPONENT *comp = file->Component;
386 
387  file->state = calculate_install_state( package, file );
389  {
390  TRACE("not overwriting %s\n", debugstr_w(file->TargetPath));
391  file->state = msifs_skipped;
392  }
393  }
394 }
395 
397 {
398  BOOL ret;
399 
400  ret = msi_copy_file( package, source, file->TargetPath, FALSE );
401  if (!ret)
402  return GetLastError();
403 
404  msi_set_file_attributes( package, file->TargetPath, FILE_ATTRIBUTE_NORMAL );
405  return ERROR_SUCCESS;
406 }
407 
409 {
410  UINT gle;
411 
412  TRACE("Copying %s to %s\n", debugstr_w(source), debugstr_w(file->TargetPath));
413 
414  gle = copy_file( package, file, source );
415  if (gle == ERROR_SUCCESS)
416  return gle;
417 
418  if (gle == ERROR_ALREADY_EXISTS && file->state == msifs_overwrite)
419  {
420  TRACE("overwriting existing file\n");
421  return ERROR_SUCCESS;
422  }
423  else if (gle == ERROR_ACCESS_DENIED)
424  {
425  msi_set_file_attributes( package, file->TargetPath, FILE_ATTRIBUTE_NORMAL );
426 
427  gle = copy_file( package, file, source );
428  TRACE("Overwriting existing file: %d\n", gle);
429  }
430  if (gle == ERROR_SHARING_VIOLATION || gle == ERROR_USER_MAPPED_FILE)
431  {
432  WCHAR *tmpfileW, *pathW, *p;
433  DWORD len;
434 
435  TRACE("file in use, scheduling rename operation\n");
436 
437  if (!(pathW = strdupW( file->TargetPath ))) return ERROR_OUTOFMEMORY;
438  if ((p = wcsrchr(pathW, '\\'))) *p = 0;
439  len = lstrlenW( pathW ) + 16;
440  if (!(tmpfileW = msi_alloc(len * sizeof(WCHAR))))
441  {
442  msi_free( pathW );
443  return ERROR_OUTOFMEMORY;
444  }
445  if (!GetTempFileNameW( pathW, L"msi", 0, tmpfileW )) tmpfileW[0] = 0;
446  msi_free( pathW );
447 
448  if (msi_copy_file( package, source, tmpfileW, FALSE ) &&
449  msi_move_file( package, file->TargetPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT ) &&
450  msi_move_file( package, tmpfileW, file->TargetPath, MOVEFILE_DELAY_UNTIL_REBOOT ))
451  {
452  package->need_reboot_at_end = 1;
453  gle = ERROR_SUCCESS;
454  }
455  else
456  {
457  gle = GetLastError();
458  WARN("failed to schedule rename operation: %d)\n", gle);
459  DeleteFileW( tmpfileW );
460  }
461  msi_free(tmpfileW);
462  }
463 
464  return gle;
465 }
466 
467 static UINT create_directory( MSIPACKAGE *package, const WCHAR *dir )
468 {
469  MSIFOLDER *folder;
470  const WCHAR *install_path;
471 
472  install_path = msi_get_target_folder( package, dir );
473  if (!install_path) return ERROR_FUNCTION_FAILED;
474 
475  folder = msi_get_loaded_folder( package, dir );
476  if (folder->State == FOLDER_STATE_UNINITIALIZED)
477  {
478  msi_create_full_path( package, install_path );
479  folder->State = FOLDER_STATE_CREATED;
480  }
481  return ERROR_SUCCESS;
482 }
483 
484 static MSIFILE *find_file( MSIPACKAGE *package, UINT disk_id, const WCHAR *filename )
485 {
486  MSIFILE *file;
487 
488  LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
489  {
490  if (file->disk_id == disk_id &&
491  file->state != msifs_installed &&
492  !wcsicmp( filename, file->File )) return file;
493  }
494  return NULL;
495 }
496 
498  LPWSTR *path, DWORD *attrs, PVOID user)
499 {
500  MSIFILE *file = *(MSIFILE **)user;
501 
503  {
504  if (!(file = find_file( package, file->disk_id, filename )))
505  {
506  TRACE("unknown file in cabinet (%s)\n", debugstr_w(filename));
507  return FALSE;
508  }
509  if (file->state != msifs_missing && file->state != msifs_overwrite)
510  return FALSE;
511 
512  if (!msi_is_global_assembly( file->Component ))
513  {
514  create_directory( package, file->Component->Directory );
515  }
516  *path = strdupW( file->TargetPath );
517  *attrs = file->Attributes;
518  *(MSIFILE **)user = file;
519  }
521  {
522  if (!msi_is_global_assembly( file->Component )) file->state = msifs_installed;
523  }
524 
525  return TRUE;
526 }
527 
529 {
530  WCHAR *p, *path;
531 
532  TRACE("Working to resolve source of file %s\n", debugstr_w(file->File));
533 
534  if (file->IsCompressed) return NULL;
535 
536  p = msi_resolve_source_folder( package, file->Component->Directory, NULL );
537  path = msi_build_directory_name( 2, p, file->ShortName );
538 
539  if (file->LongName && msi_get_file_attributes( package, path ) == INVALID_FILE_ATTRIBUTES)
540  {
541  msi_free( path );
542  path = msi_build_directory_name( 2, p, file->LongName );
543  }
544  msi_free( p );
545  TRACE("file %s source resolves to %s\n", debugstr_w(file->File), debugstr_w(path));
546  return path;
547 }
548 
549 /*
550  * ACTION_InstallFiles()
551  *
552  * For efficiency, this is done in two passes:
553  * 1) Correct all the TargetPaths and determine what files are to be installed.
554  * 2) Extract Cabinets and copy files.
555  */
557 {
558  MSIMEDIAINFO *mi;
559  UINT rc = ERROR_SUCCESS;
560  MSIFILE *file;
561 
562  msi_set_sourcedir_props(package, FALSE);
563 
564  if (package->script == SCRIPT_NONE)
565  return msi_schedule_action(package, SCRIPT_INSTALL, L"InstallFiles");
566 
567  schedule_install_files(package);
568  mi = msi_alloc_zero( sizeof(MSIMEDIAINFO) );
569 
570  LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
571  {
572  BOOL is_global_assembly = msi_is_global_assembly( file->Component );
573 
574  msi_file_update_ui( package, file, L"InstallFiles" );
575 
576  rc = msi_load_media_info( package, file->Sequence, mi );
577  if (rc != ERROR_SUCCESS)
578  {
579  ERR("Unable to load media info for %s (%u)\n", debugstr_w(file->File), rc);
581  goto done;
582  }
583 
584  if (file->state != msifs_hashmatch &&
585  file->state != msifs_skipped &&
586  (file->state != msifs_present || !msi_get_property_int( package->db, L"Installed", 0 )) &&
587  (rc = ready_media( package, file->IsCompressed, mi )))
588  {
589  ERR("Failed to ready media for %s\n", debugstr_w(file->File));
590  goto done;
591  }
592 
593  if (file->state != msifs_missing && !mi->is_continuous && file->state != msifs_overwrite)
594  continue;
595 
596  if (file->Sequence > mi->last_sequence || mi->is_continuous ||
597  (file->IsCompressed && !mi->is_extracted))
598  {
600  MSIFILE *cursor = file;
601 
602  data.mi = mi;
603  data.package = package;
604  data.cb = installfiles_cb;
605  data.user = &cursor;
606 
607  if (file->IsCompressed && !msi_cabextract(package, mi, &data))
608  {
609  ERR("Failed to extract cabinet: %s\n", debugstr_w(mi->cabinet));
611  goto done;
612  }
613  }
614 
615  if (!file->IsCompressed)
616  {
618 
619  TRACE("copying %s to %s\n", debugstr_w(source), debugstr_w(file->TargetPath));
620 
621  if (!is_global_assembly)
622  {
623  create_directory(package, file->Component->Directory);
624  }
625  rc = copy_install_file(package, file, source);
626  if (rc != ERROR_SUCCESS)
627  {
628  ERR("Failed to copy %s to %s (%u)\n", debugstr_w(source), debugstr_w(file->TargetPath), rc);
630  msi_free(source);
631  goto done;
632  }
633  if (!is_global_assembly) file->state = msifs_installed;
634  msi_free(source);
635  }
636  else if (!is_global_assembly && file->state != msifs_installed &&
637  !(file->Attributes & msidbFileAttributesPatchAdded))
638  {
639  ERR("compressed file wasn't installed (%s)\n", debugstr_w(file->File));
641  goto done;
642  }
643  }
644  LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
645  {
646  MSICOMPONENT *comp = file->Component;
647 
648  if (!msi_is_global_assembly( comp ) || comp->assembly->installed ||
649  (file->state != msifs_missing && file->state != msifs_overwrite)) continue;
650 
651  rc = msi_install_assembly( package, comp );
652  if (rc != ERROR_SUCCESS)
653  {
654  ERR("Failed to install assembly\n");
656  break;
657  }
658  file->state = msifs_installed;
659  }
660 
661 done:
663  return rc;
664 }
665 
666 static MSIFILEPATCH *find_filepatch( MSIPACKAGE *package, UINT disk_id, const WCHAR *key )
667 {
668  MSIFILEPATCH *patch;
669 
670  LIST_FOR_EACH_ENTRY( patch, &package->filepatches, MSIFILEPATCH, entry )
671  {
672  if (!patch->extracted && patch->disk_id == disk_id && !wcscmp( key, patch->File->File ))
673  return patch;
674  }
675  return NULL;
676 }
677 
679  LPWSTR *path, DWORD *attrs, PVOID user)
680 {
681  MSIFILEPATCH *patch = *(MSIFILEPATCH **)user;
682 
684  {
685  MSICOMPONENT *comp;
686 
687  if (is_registered_patch_media( package, patch->disk_id ) ||
688  !(patch = find_filepatch( package, patch->disk_id, file ))) return FALSE;
689 
690  comp = patch->File->Component;
691  comp->Action = msi_get_component_action( package, comp );
692  if (!comp->Enabled || comp->Action != INSTALLSTATE_LOCAL)
693  {
694  TRACE("file %s component %s not installed or disabled\n",
695  debugstr_w(patch->File->File), debugstr_w(comp->Component));
696  return FALSE;
697  }
698 
699  patch->path = msi_create_temp_file( package->db );
700  *path = strdupW( patch->path );
701  *attrs = patch->File->Attributes;
702  *(MSIFILEPATCH **)user = patch;
703  }
705  {
706  patch->extracted = TRUE;
707  }
708 
709  return TRUE;
710 }
711 
712 static UINT patch_file( MSIPACKAGE *package, MSIFILEPATCH *patch )
713 {
714  UINT r = ERROR_SUCCESS;
715  WCHAR *tmpfile = msi_create_temp_file( package->db );
716 
717  if (!tmpfile) return ERROR_INSTALL_FAILURE;
718  if (msi_apply_filepatch( package, patch->path, patch->File->TargetPath, tmpfile ))
719  {
720  msi_delete_file( package, patch->File->TargetPath );
721  msi_move_file( package, tmpfile, patch->File->TargetPath, 0 );
722  }
723  else
724  {
725  WARN( "failed to patch %s: %#lx\n", debugstr_w(patch->File->TargetPath), GetLastError() );
727  }
728  DeleteFileW( patch->path );
729  DeleteFileW( tmpfile );
730  msi_free( tmpfile );
731  return r;
732 }
733 
735 {
738  IAssemblyEnum *iter;
739 
740  if (!(iter = msi_create_assembly_enum( package, assembly->display_name )))
741  return ERROR_FUNCTION_FAILED;
742 
743  while ((IAssemblyEnum_GetNextAssembly( iter, NULL, &name, 0 ) == S_OK))
744  {
745  WCHAR *displayname, *path;
746  DWORD len = 0;
747  HRESULT hr;
748 
749  hr = IAssemblyName_GetDisplayName( name, NULL, &len, 0 );
750  if (hr != E_NOT_SUFFICIENT_BUFFER || !(displayname = msi_alloc( len * sizeof(WCHAR) )))
751  break;
752 
753  hr = IAssemblyName_GetDisplayName( name, displayname, &len, 0 );
754  if (FAILED( hr ))
755  {
756  msi_free( displayname );
757  break;
758  }
759 
760  if ((path = msi_get_assembly_path( package, displayname )))
761  {
762  if (!msi_copy_file( package, path, patch->File->TargetPath, FALSE ))
763  {
764  ERR( "failed to copy file %s -> %s (%lu)\n", debugstr_w(path),
765  debugstr_w(patch->File->TargetPath), GetLastError() );
766  msi_free( path );
767  msi_free( displayname );
768  IAssemblyName_Release( name );
769  break;
770  }
771  r = patch_file( package, patch );
772  msi_free( path );
773  }
774 
775  msi_free( displayname );
776  IAssemblyName_Release( name );
777  if (r == ERROR_SUCCESS) break;
778  }
779 
780  IAssemblyEnum_Release( iter );
781  return r;
782 }
783 
785 {
786  MSIFILEPATCH *patch;
787  MSIMEDIAINFO *mi;
788  UINT rc = ERROR_SUCCESS;
789 
790  TRACE("%p\n", package);
791 
792  if (package->script == SCRIPT_NONE)
793  return msi_schedule_action(package, SCRIPT_INSTALL, L"PatchFiles");
794 
795  mi = msi_alloc_zero( sizeof(MSIMEDIAINFO) );
796 
797  TRACE("extracting files\n");
798 
799  LIST_FOR_EACH_ENTRY( patch, &package->filepatches, MSIFILEPATCH, entry )
800  {
801  MSIFILE *file = patch->File;
802  MSICOMPONENT *comp = file->Component;
803 
804  rc = msi_load_media_info( package, patch->Sequence, mi );
805  if (rc != ERROR_SUCCESS)
806  {
807  ERR("Unable to load media info for %s (%u)\n", debugstr_w(file->File), rc);
809  goto done;
810  }
811  comp->Action = msi_get_component_action( package, comp );
812  if (!comp->Enabled || comp->Action != INSTALLSTATE_LOCAL) continue;
813 
814  if (!patch->extracted)
815  {
817  MSIFILEPATCH *cursor = patch;
818 
819  rc = ready_media( package, TRUE, mi );
820  if (rc != ERROR_SUCCESS)
821  {
822  ERR("Failed to ready media for %s\n", debugstr_w(file->File));
823  goto done;
824  }
825  data.mi = mi;
826  data.package = package;
827  data.cb = patchfiles_cb;
828  data.user = &cursor;
829 
830  if (!msi_cabextract( package, mi, &data ))
831  {
832  ERR("Failed to extract cabinet: %s\n", debugstr_w(mi->cabinet));
834  goto done;
835  }
836  }
837  }
838 
839  TRACE("applying patches\n");
840 
841  LIST_FOR_EACH_ENTRY( patch, &package->filepatches, MSIFILEPATCH, entry )
842  {
843  MSICOMPONENT *comp = patch->File->Component;
844 
845  if (!patch->path) continue;
846 
847  if (msi_is_global_assembly( comp ))
848  rc = patch_assembly( package, comp->assembly, patch );
849  else
850  rc = patch_file( package, patch );
851 
852  if (rc && !(patch->Attributes & msidbPatchAttributesNonVital))
853  {
854  ERR("Failed to apply patch to file: %s\n", debugstr_w(patch->File->File));
855  break;
856  }
857 
858  if (msi_is_global_assembly( comp ))
859  {
860  if ((rc = msi_install_assembly( package, comp )))
861  {
862  ERR("Failed to install patched assembly\n");
863  break;
864  }
865  }
866  }
867 
868 done:
870  return rc;
871 }
872 
873 #define is_dot_dir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))))
874 
875 typedef struct
876 {
877  struct list entry;
882 } FILE_LIST;
883 
884 static BOOL move_file( MSIPACKAGE *package, const WCHAR *source, const WCHAR *dest, int options )
885 {
886  BOOL ret;
887 
890  {
891  WARN("Source or dest is directory, not moving\n");
892  return FALSE;
893  }
894 
896  {
897  TRACE("moving %s -> %s\n", debugstr_w(source), debugstr_w(dest));
899  if (!ret)
900  {
901  WARN( "msi_move_file failed: %lu\n", GetLastError() );
902  return FALSE;
903  }
904  }
905  else
906  {
907  TRACE("copying %s -> %s\n", debugstr_w(source), debugstr_w(dest));
908  ret = msi_copy_file( package, source, dest, FALSE );
909  if (!ret)
910  {
911  WARN( "msi_copy_file failed: %lu\n", GetLastError() );
912  return FALSE;
913  }
914  }
915 
916  return TRUE;
917 }
918 
919 static WCHAR *wildcard_to_file( const WCHAR *wildcard, const WCHAR *filename )
920 {
921  const WCHAR *ptr;
922  WCHAR *path;
923  DWORD dirlen, pathlen;
924 
925  ptr = wcsrchr(wildcard, '\\');
926  dirlen = ptr - wildcard + 1;
927 
928  pathlen = dirlen + lstrlenW(filename) + 1;
929  if (!(path = msi_alloc(pathlen * sizeof(WCHAR)))) return NULL;
930 
931  lstrcpynW(path, wildcard, dirlen + 1);
933 
934  return path;
935 }
936 
938 {
939  msi_free(file->source);
940  msi_free(file->dest);
941  msi_free(file);
942 }
943 
944 static void free_list(FILE_LIST *list)
945 {
946  while (!list_empty(&list->entry))
947  {
949 
952  }
953 }
954 
955 static BOOL add_wildcard( FILE_LIST *files, const WCHAR *source, WCHAR *dest )
956 {
957  FILE_LIST *new, *file;
958  WCHAR *ptr, *filename;
959  DWORD size;
960 
961  new = msi_alloc_zero(sizeof(FILE_LIST));
962  if (!new)
963  return FALSE;
964 
965  new->source = strdupW(source);
966  ptr = wcsrchr(dest, '\\') + 1;
967  filename = wcsrchr(new->source, '\\') + 1;
968 
969  new->sourcename = filename;
970 
971  if (*ptr)
972  new->destname = ptr;
973  else
974  new->destname = new->sourcename;
975 
976  size = (ptr - dest) + lstrlenW(filename) + 1;
977  new->dest = msi_alloc(size * sizeof(WCHAR));
978  if (!new->dest)
979  {
980  free_file_entry(new);
981  return FALSE;
982  }
983 
984  lstrcpynW(new->dest, dest, ptr - dest + 1);
985  lstrcatW(new->dest, filename);
986 
987  if (list_empty(&files->entry))
988  {
989  list_add_head(&files->entry, &new->entry);
990  return TRUE;
991  }
992 
994  {
995  if (wcscmp( source, file->source ) < 0)
996  {
997  list_add_before(&file->entry, &new->entry);
998  return TRUE;
999  }
1000  }
1001 
1002  list_add_after(&file->entry, &new->entry);
1003  return TRUE;
1004 }
1005 
1007 {
1008  WIN32_FIND_DATAW wfd;
1009  HANDLE hfile;
1010  LPWSTR path;
1011  BOOL res;
1012  FILE_LIST files, *file;
1013  DWORD size;
1014 
1015  hfile = msi_find_first_file( package, source, &wfd );
1016  if (hfile == INVALID_HANDLE_VALUE) return FALSE;
1017 
1018  list_init(&files.entry);
1019 
1020  for (res = TRUE; res; res = msi_find_next_file( package, hfile, &wfd ))
1021  {
1022  if (is_dot_dir(wfd.cFileName)) continue;
1023 
1024  path = wildcard_to_file( source, wfd.cFileName );
1025  if (!path)
1026  {
1027  res = FALSE;
1028  goto done;
1029  }
1030 
1031  add_wildcard(&files, path, dest);
1032  msi_free(path);
1033  }
1034 
1035  /* no files match the wildcard */
1036  if (list_empty(&files.entry))
1037  goto done;
1038 
1039  /* only the first wildcard match gets renamed to dest */
1041  size = (wcsrchr(file->dest, '\\') - file->dest) + lstrlenW(file->destname) + 2;
1042  file->dest = msi_realloc(file->dest, size * sizeof(WCHAR));
1043  if (!file->dest)
1044  {
1045  res = FALSE;
1046  goto done;
1047  }
1048 
1049  /* file->dest may be shorter after the reallocation, so add a NULL
1050  * terminator. This is needed for the call to wcsrchr, as there will no
1051  * longer be a NULL terminator within the bounds of the allocation in this case.
1052  */
1053  file->dest[size - 1] = '\0';
1054  lstrcpyW(wcsrchr(file->dest, '\\') + 1, file->destname);
1055 
1056  while (!list_empty(&files.entry))
1057  {
1059 
1060  move_file( package, file->source, file->dest, options );
1061 
1062  list_remove(&file->entry);
1064  }
1065 
1066  res = TRUE;
1067 
1068 done:
1069  free_list(&files);
1070  FindClose(hfile);
1071  return res;
1072 }
1073 
1075 {
1076  WCHAR *p = wcschr( filename, '|' );
1077  if (p) memmove( filename, p + 1, (lstrlenW( p + 1 ) + 1) * sizeof(WCHAR) );
1078 }
1079 
1081 {
1082  MSIPACKAGE *package = param;
1083  MSIRECORD *uirow;
1084  MSICOMPONENT *comp;
1085  LPCWSTR sourcename, component;
1086  LPWSTR sourcedir, destname = NULL, destdir = NULL, source = NULL, dest = NULL;
1087  int options;
1088  DWORD size;
1089  BOOL wildcards;
1090 
1091  component = MSI_RecordGetString(rec, 2);
1092  comp = msi_get_loaded_component(package, component);
1093  if (!comp)
1094  return ERROR_SUCCESS;
1095 
1096  comp->Action = msi_get_component_action( package, comp );
1097  if (comp->Action != INSTALLSTATE_LOCAL)
1098  {
1099  TRACE("component not scheduled for installation %s\n", debugstr_w(component));
1100  return ERROR_SUCCESS;
1101  }
1102 
1103  sourcename = MSI_RecordGetString(rec, 3);
1104  options = MSI_RecordGetInteger(rec, 7);
1105 
1106  sourcedir = msi_dup_property(package->db, MSI_RecordGetString(rec, 5));
1107  if (!sourcedir)
1108  goto done;
1109 
1110  destdir = msi_dup_property(package->db, MSI_RecordGetString(rec, 6));
1111  if (!destdir)
1112  goto done;
1113 
1114  if (!sourcename)
1115  {
1116  if (msi_get_file_attributes( package, sourcedir ) == INVALID_FILE_ATTRIBUTES)
1117  goto done;
1118 
1119  source = strdupW(sourcedir);
1120  if (!source)
1121  goto done;
1122  }
1123  else
1124  {
1125  size = lstrlenW(sourcedir) + lstrlenW(sourcename) + 2;
1126  source = msi_alloc(size * sizeof(WCHAR));
1127  if (!source)
1128  goto done;
1129 
1130  lstrcpyW(source, sourcedir);
1131  if (source[lstrlenW(source) - 1] != '\\')
1132  lstrcatW(source, L"\\");
1133  lstrcatW(source, sourcename);
1134  }
1135 
1136  wildcards = wcschr(source, '*') || wcschr(source, '?');
1137 
1138  if (MSI_RecordIsNull(rec, 4))
1139  {
1140  if (!wildcards)
1141  {
1142  WCHAR *p;
1143  if (sourcename)
1144  destname = strdupW(sourcename);
1145  else if ((p = wcsrchr(sourcedir, '\\')))
1146  destname = strdupW(p + 1);
1147  else
1148  destname = strdupW(sourcedir);
1149  if (!destname)
1150  goto done;
1151  }
1152  }
1153  else
1154  {
1155  destname = strdupW(MSI_RecordGetString(rec, 4));
1156  if (destname) msi_reduce_to_long_filename(destname);
1157  }
1158 
1159  size = 0;
1160  if (destname)
1161  size = lstrlenW(destname);
1162 
1163  size += lstrlenW(destdir) + 2;
1164  dest = msi_alloc(size * sizeof(WCHAR));
1165  if (!dest)
1166  goto done;
1167 
1168  lstrcpyW(dest, destdir);
1169  if (dest[lstrlenW(dest) - 1] != '\\')
1170  lstrcatW(dest, L"\\");
1171 
1172  if (destname)
1173  lstrcatW(dest, destname);
1174 
1175  if (msi_get_file_attributes( package, destdir ) == INVALID_FILE_ATTRIBUTES)
1176  {
1177  if (!msi_create_full_path( package, destdir ))
1178  {
1179  WARN( "failed to create directory %lu\n", GetLastError() );
1180  goto done;
1181  }
1182  }
1183 
1184  if (!wildcards)
1185  move_file( package, source, dest, options );
1186  else
1187  move_files_wildcard( package, source, dest, options );
1188 
1189 done:
1190  uirow = MSI_CreateRecord( 9 );
1191  MSI_RecordSetStringW( uirow, 1, MSI_RecordGetString(rec, 1) );
1192  MSI_RecordSetInteger( uirow, 6, 1 ); /* FIXME */
1193  MSI_RecordSetStringW( uirow, 9, destdir );
1195  msiobj_release( &uirow->hdr );
1196 
1197  msi_free(sourcedir);
1198  msi_free(destdir);
1199  msi_free(destname);
1200  msi_free(source);
1201  msi_free(dest);
1202 
1203  return ERROR_SUCCESS;
1204 }
1205 
1207 {
1208  MSIQUERY *view;
1209  UINT rc;
1210 
1211  if (package->script == SCRIPT_NONE)
1212  return msi_schedule_action(package, SCRIPT_INSTALL, L"MoveFiles");
1213 
1214  rc = MSI_DatabaseOpenViewW(package->db, L"SELECT * FROM `MoveFile`", &view);
1215  if (rc != ERROR_SUCCESS)
1216  return ERROR_SUCCESS;
1217 
1218  rc = MSI_IterateRecords(view, NULL, ITERATE_MoveFiles, package);
1219  msiobj_release(&view->hdr);
1220  return rc;
1221 }
1222 
1223 static WCHAR *get_duplicate_filename( MSIPACKAGE *package, MSIRECORD *row, const WCHAR *file_key, const WCHAR *src )
1224 {
1225  DWORD len;
1226  WCHAR *dst_name, *dst_path, *dst;
1227 
1228  if (MSI_RecordIsNull( row, 4 ))
1229  {
1230  len = lstrlenW( src ) + 1;
1231  if (!(dst_name = msi_alloc( len * sizeof(WCHAR)))) return NULL;
1232  lstrcpyW( dst_name, wcsrchr( src, '\\' ) + 1 );
1233  }
1234  else
1235  {
1236  MSI_RecordGetStringW( row, 4, NULL, &len );
1237  if (!(dst_name = msi_alloc( ++len * sizeof(WCHAR) ))) return NULL;
1238  MSI_RecordGetStringW( row, 4, dst_name, &len );
1239  msi_reduce_to_long_filename( dst_name );
1240  }
1241 
1242  if (MSI_RecordIsNull( row, 5 ))
1243  {
1244  WCHAR *p;
1245  dst_path = strdupW( src );
1246  p = wcsrchr( dst_path, '\\' );
1247  if (p) *p = 0;
1248  }
1249  else
1250  {
1251  const WCHAR *dst_key = MSI_RecordGetString( row, 5 );
1252 
1253  dst_path = strdupW( msi_get_target_folder( package, dst_key ) );
1254  if (!dst_path)
1255  {
1256  /* try a property */
1257  dst_path = msi_dup_property( package->db, dst_key );
1258  if (!dst_path)
1259  {
1260  FIXME("Unable to get destination folder, try AppSearch properties\n");
1261  msi_free( dst_name );
1262  return NULL;
1263  }
1264  }
1265  }
1266 
1267  dst = msi_build_directory_name( 2, dst_path, dst_name );
1268  msi_create_full_path( package, dst_path );
1269 
1270  msi_free( dst_name );
1271  msi_free( dst_path );
1272  return dst;
1273 }
1274 
1276 {
1277  MSIPACKAGE *package = param;
1278  LPWSTR dest;
1279  LPCWSTR file_key, component;
1280  MSICOMPONENT *comp;
1281  MSIRECORD *uirow;
1282  MSIFILE *file;
1283 
1284  component = MSI_RecordGetString(row,2);
1285  comp = msi_get_loaded_component(package, component);
1286  if (!comp)
1287  return ERROR_SUCCESS;
1288 
1289  comp->Action = msi_get_component_action( package, comp );
1290  if (comp->Action != INSTALLSTATE_LOCAL)
1291  {
1292  TRACE("component not scheduled for installation %s\n", debugstr_w(component));
1293  return ERROR_SUCCESS;
1294  }
1295 
1296  file_key = MSI_RecordGetString(row,3);
1297  if (!file_key)
1298  {
1299  ERR("Unable to get file key\n");
1300  return ERROR_FUNCTION_FAILED;
1301  }
1302 
1303  file = msi_get_loaded_file( package, file_key );
1304  if (!file)
1305  {
1306  ERR("Original file unknown %s\n", debugstr_w(file_key));
1307  return ERROR_SUCCESS;
1308  }
1309 
1310  dest = get_duplicate_filename( package, row, file_key, file->TargetPath );
1311  if (!dest)
1312  {
1313  WARN("Unable to get duplicate filename\n");
1314  return ERROR_SUCCESS;
1315  }
1316 
1317  TRACE("Duplicating file %s to %s\n", debugstr_w(file->TargetPath), debugstr_w(dest));
1318  if (!msi_copy_file( package, file->TargetPath, dest, TRUE ))
1319  {
1320  WARN( "failed to copy file %s -> %s (%lu)\n",
1321  debugstr_w(file->TargetPath), debugstr_w(dest), GetLastError() );
1322  }
1323  FIXME("We should track these duplicate files as well\n");
1324 
1325  uirow = MSI_CreateRecord( 9 );
1326  MSI_RecordSetStringW( uirow, 1, MSI_RecordGetString( row, 1 ) );
1327  MSI_RecordSetInteger( uirow, 6, file->FileSize );
1328  MSI_RecordSetStringW( uirow, 9, MSI_RecordGetString( row, 5 ) );
1330  msiobj_release( &uirow->hdr );
1331 
1332  msi_free(dest);
1333  return ERROR_SUCCESS;
1334 }
1335 
1337 {
1338  MSIQUERY *view;
1339  UINT rc;
1340 
1341  if (package->script == SCRIPT_NONE)
1342  return msi_schedule_action(package, SCRIPT_INSTALL, L"DuplicateFiles");
1343 
1344  rc = MSI_DatabaseOpenViewW(package->db, L"SELECT * FROM `DuplicateFile`", &view);
1345  if (rc != ERROR_SUCCESS)
1346  return ERROR_SUCCESS;
1347 
1349  msiobj_release(&view->hdr);
1350  return rc;
1351 }
1352 
1354 {
1355  MSIPACKAGE *package = param;
1356  LPWSTR dest;
1357  LPCWSTR file_key, component;
1358  MSICOMPONENT *comp;
1359  MSIRECORD *uirow;
1360  MSIFILE *file;
1361 
1362  component = MSI_RecordGetString( row, 2 );
1363  comp = msi_get_loaded_component( package, component );
1364  if (!comp)
1365  return ERROR_SUCCESS;
1366 
1367  comp->Action = msi_get_component_action( package, comp );
1368  if (comp->Action != INSTALLSTATE_ABSENT)
1369  {
1370  TRACE("component not scheduled for removal %s\n", debugstr_w(component));
1371  return ERROR_SUCCESS;
1372  }
1373 
1374  file_key = MSI_RecordGetString( row, 3 );
1375  if (!file_key)
1376  {
1377  ERR("Unable to get file key\n");
1378  return ERROR_FUNCTION_FAILED;
1379  }
1380 
1381  file = msi_get_loaded_file( package, file_key );
1382  if (!file)
1383  {
1384  ERR("Original file unknown %s\n", debugstr_w(file_key));
1385  return ERROR_SUCCESS;
1386  }
1387 
1388  dest = get_duplicate_filename( package, row, file_key, file->TargetPath );
1389  if (!dest)
1390  {
1391  WARN("Unable to get duplicate filename\n");
1392  return ERROR_SUCCESS;
1393  }
1394 
1395  TRACE("Removing duplicate %s of %s\n", debugstr_w(dest), debugstr_w(file->TargetPath));
1396  if (!msi_delete_file( package, dest ))
1397  {
1398  WARN( "failed to delete duplicate file %s (%lu)\n", debugstr_w(dest), GetLastError() );
1399  }
1400 
1401  uirow = MSI_CreateRecord( 9 );
1402  MSI_RecordSetStringW( uirow, 1, MSI_RecordGetString( row, 1 ) );
1403  MSI_RecordSetStringW( uirow, 9, MSI_RecordGetString( row, 5 ) );
1405  msiobj_release( &uirow->hdr );
1406 
1407  msi_free(dest);
1408  return ERROR_SUCCESS;
1409 }
1410 
1412 {
1413  MSIQUERY *view;
1414  UINT rc;
1415 
1416  if (package->script == SCRIPT_NONE)
1417  return msi_schedule_action(package, SCRIPT_INSTALL, L"RemoveDuplicateFiles");
1418 
1419  rc = MSI_DatabaseOpenViewW( package->db, L"SELECT * FROM `DuplicateFile`", &view );
1420  if (rc != ERROR_SUCCESS)
1421  return ERROR_SUCCESS;
1422 
1424  msiobj_release( &view->hdr );
1425  return rc;
1426 }
1427 
1428 static BOOL verify_comp_for_removal(MSICOMPONENT *comp, UINT install_mode)
1429 {
1430  /* special case */
1431  if (comp->Action != INSTALLSTATE_SOURCE &&
1433  (install_mode == msidbRemoveFileInstallModeOnRemove ||
1434  install_mode == msidbRemoveFileInstallModeOnBoth)) return TRUE;
1435 
1436  switch (comp->Action)
1437  {
1438  case INSTALLSTATE_LOCAL:
1439  case INSTALLSTATE_SOURCE:
1440  if (install_mode == msidbRemoveFileInstallModeOnInstall ||
1441  install_mode == msidbRemoveFileInstallModeOnBoth) return TRUE;
1442  break;
1443  case INSTALLSTATE_ABSENT:
1444  if (install_mode == msidbRemoveFileInstallModeOnRemove ||
1445  install_mode == msidbRemoveFileInstallModeOnBoth) return TRUE;
1446  break;
1447  default: break;
1448  }
1449  return FALSE;
1450 }
1451 
1453 {
1454  MSIPACKAGE *package = param;
1455  MSICOMPONENT *comp;
1456  MSIRECORD *uirow;
1457  LPCWSTR component, dirprop;
1458  UINT install_mode;
1459  LPWSTR dir = NULL, path = NULL, filename = NULL;
1460  DWORD size;
1462 
1463  component = MSI_RecordGetString(row, 2);
1464  dirprop = MSI_RecordGetString(row, 4);
1465  install_mode = MSI_RecordGetInteger(row, 5);
1466 
1467  comp = msi_get_loaded_component(package, component);
1468  if (!comp)
1469  return ERROR_SUCCESS;
1470 
1471  comp->Action = msi_get_component_action( package, comp );
1472  if (!verify_comp_for_removal(comp, install_mode))
1473  {
1474  TRACE("Skipping removal due to install mode\n");
1475  return ERROR_SUCCESS;
1476  }
1477  if (comp->assembly && !comp->assembly->application)
1478  {
1479  return ERROR_SUCCESS;
1480  }
1481  if (comp->Attributes & msidbComponentAttributesPermanent)
1482  {
1483  TRACE("permanent component, not removing file\n");
1484  return ERROR_SUCCESS;
1485  }
1486 
1487  dir = msi_dup_property(package->db, dirprop);
1488  if (!dir)
1489  {
1490  WARN("directory property has no value\n");
1491  return ERROR_SUCCESS;
1492  }
1493  size = 0;
1494  if ((filename = strdupW( MSI_RecordGetString(row, 3) )))
1495  {
1497  size = lstrlenW( filename );
1498  }
1499  size += lstrlenW(dir) + 2;
1500  path = msi_alloc(size * sizeof(WCHAR));
1501  if (!path)
1502  {
1504  goto done;
1505  }
1506 
1507  if (filename)
1508  {
1509  lstrcpyW(path, dir);
1512 
1513  TRACE("Deleting misc file: %s\n", debugstr_w(path));
1514  msi_delete_file( package, path );
1515  }
1516  else
1517  {
1518  TRACE("Removing misc directory: %s\n", debugstr_w(dir));
1519  msi_remove_directory( package, dir );
1520  }
1521 
1522 done:
1523  uirow = MSI_CreateRecord( 9 );
1524  MSI_RecordSetStringW( uirow, 1, MSI_RecordGetString(row, 1) );
1525  MSI_RecordSetStringW( uirow, 9, dir );
1527  msiobj_release( &uirow->hdr );
1528 
1529  msi_free(filename);
1530  msi_free(path);
1531  msi_free(dir);
1532  return ret;
1533 }
1534 
1536 {
1537  FolderList *fl;
1538 
1539  LIST_FOR_EACH_ENTRY( fl, &folder->children, FolderList, entry )
1540  {
1541  remove_folder( fl->folder );
1542  }
1543  if (!folder->persistent && folder->State != FOLDER_STATE_REMOVED)
1544  {
1545  if (RemoveDirectoryW( folder->ResolvedTarget )) folder->State = FOLDER_STATE_REMOVED;
1546  }
1547 }
1548 
1550 {
1551  MSIQUERY *view;
1552  MSICOMPONENT *comp;
1553  MSIFILE *file;
1554  UINT r;
1555 
1556  if (package->script == SCRIPT_NONE)
1557  return msi_schedule_action(package, SCRIPT_INSTALL, L"RemoveFiles");
1558 
1559  r = MSI_DatabaseOpenViewW(package->db, L"SELECT * FROM `RemoveFile`", &view);
1560  if (r == ERROR_SUCCESS)
1561  {
1563  msiobj_release(&view->hdr);
1564  if (r != ERROR_SUCCESS)
1565  return r;
1566  }
1567 
1568  LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
1569  {
1570  MSIRECORD *uirow;
1571  VS_FIXEDFILEINFO *ver;
1572 
1573  comp = file->Component;
1574  msi_file_update_ui( package, file, L"RemoveFiles" );
1575 
1576  comp->Action = msi_get_component_action( package, comp );
1577  if (comp->Action != INSTALLSTATE_ABSENT || comp->Installed == INSTALLSTATE_SOURCE)
1578  continue;
1579 
1580  if (comp->assembly && !comp->assembly->application)
1581  continue;
1582 
1584  {
1585  TRACE("permanent component, not removing file\n");
1586  continue;
1587  }
1588 
1589  if (file->Version)
1590  {
1591  ver = msi_get_disk_file_version( package, file->TargetPath );
1592  if (ver && msi_compare_file_versions( ver, file->Version ) > 0)
1593  {
1594  TRACE("newer version detected, not removing file\n");
1595  msi_free( ver );
1596  continue;
1597  }
1598  msi_free( ver );
1599  }
1600 
1601  if (file->state == msifs_installed)
1602  WARN("removing installed file %s\n", debugstr_w(file->TargetPath));
1603 
1604  TRACE("removing %s\n", debugstr_w(file->File) );
1605 
1606  msi_set_file_attributes( package, file->TargetPath, FILE_ATTRIBUTE_NORMAL );
1607  if (!msi_delete_file( package, file->TargetPath ))
1608  {
1609  WARN( "failed to delete %s (%lu)\n", debugstr_w(file->TargetPath), GetLastError() );
1610  }
1611  file->state = msifs_missing;
1612 
1613  uirow = MSI_CreateRecord( 9 );
1614  MSI_RecordSetStringW( uirow, 1, file->FileName );
1615  MSI_RecordSetStringW( uirow, 9, comp->Directory );
1617  msiobj_release( &uirow->hdr );
1618  }
1619 
1620  LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
1621  {
1622  comp->Action = msi_get_component_action( package, comp );
1623  if (comp->Action != INSTALLSTATE_ABSENT) continue;
1624 
1626  {
1627  TRACE("permanent component, not removing directory\n");
1628  continue;
1629  }
1630  if (comp->assembly && !comp->assembly->application)
1631  msi_uninstall_assembly( package, comp );
1632  else
1633  {
1634  MSIFOLDER *folder = msi_get_loaded_folder( package, comp->Directory );
1635  if (folder) remove_folder( folder );
1636  }
1637  }
1638  return ERROR_SUCCESS;
1639 }
BOOL WINAPI SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
Definition: fileinfo.c:794
#define ERROR_USER_MAPPED_FILE
Definition: winerror.h:727
LPWSTR dest
Definition: files.c:881
BOOL WINAPI CreateDirectoryW(IN LPCWSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:90
BOOL WINAPI FindNextFileW(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:382
enum _msi_file_state msi_file_state
static ULONG POBJECT_ATTRIBUTES PIO_STATUS_BLOCK ULONG sharing
Definition: pipe.c:68
static void schedule_install_files(MSIPACKAGE *package)
Definition: files.c:379
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
static BOOL msi_copy_file(MSIPACKAGE *package, const WCHAR *src, const WCHAR *dst, BOOL fail_if_exists)
Definition: files.c:61
static BOOL msi_apply_filepatch(MSIPACKAGE *package, const WCHAR *patch, const WCHAR *old, const WCHAR *new)
Definition: files.c:142
UINT msi_load_media_info(MSIPACKAGE *package, UINT Sequence, MSIMEDIAINFO *mi)
Definition: media.c:689
UINT MSI_RecordSetStringW(MSIRECORD *, UINT, LPCWSTR) DECLSPEC_HIDDEN
Definition: record.c:597
#define CloseHandle
Definition: compat.h:598
Definition: fci.c:115
enum script script
Definition: msipriv.h:432
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
BOOL extracted
Definition: msipriv.h:630
#define ERROR_SUCCESS
Definition: deptool.c:10
BOOL msi_create_full_path(MSIPACKAGE *package, const WCHAR *path)
Definition: files.c:202
HRESULT hr
Definition: shlfolder.c:183
#define new(TYPE, numElems)
Definition: treelist.c:54
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define MSI_INITIAL_MEDIA_TRANSFORM_DISKID
Definition: msipriv.h:84
MSIASSEMBLY * assembly
Definition: msipriv.h:540
#define MOVEFILE_REPLACE_EXISTING
Definition: filesup.h:28
static void msi_revert_fs_redirection(MSIPACKAGE *package)
Definition: msipriv.h:1072
#define TRUE
Definition: types.h:120
GLsizei const GLchar ** path
Definition: glext.h:7234
static WCHAR * strdupW(const WCHAR *src)
Definition: main.c:92
MSIOBJECTHDR hdr
Definition: msipriv.h:151
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
int msi_get_property_int(MSIDATABASE *package, LPCWSTR prop, int def) DECLSPEC_HIDDEN
Definition: package.c:2305
__WINE_SERVER_LIST_INLINE void list_add_after(struct list *elem, struct list *to_add)
Definition: list.h:78
static void free_list(FILE_LIST *list)
Definition: files.c:944
#define WARN(fmt,...)
Definition: debug.h:112
UINT msi_set_sourcedir_props(MSIPACKAGE *package, BOOL replace)
Definition: action.c:354
UINT MSI_RecordGetStringW(MSIRECORD *, UINT, LPWSTR, LPDWORD) DECLSPEC_HIDDEN
BOOL msi_is_global_assembly(MSICOMPONENT *comp)
Definition: action.c:2037
LPWSTR sourcename
Definition: files.c:878
DWORD dwFileVersionLS
Definition: compat.h:762
__WINE_SERVER_LIST_INLINE void list_add_head(struct list *list, struct list *elem)
Definition: list.h:96
static UINT ITERATE_DuplicateFiles(MSIRECORD *row, LPVOID param)
Definition: files.c:1275
DWORD msi_get_disk_file_size(MSIPACKAGE *package, const WCHAR *filename)
Definition: files.c:190
#define INVALID_HANDLE_VALUE
Definition: compat.h:590
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1040
void msi_ui_progress(MSIPACKAGE *package, int a, int b, int c, int d)
Definition: action.c:596
GLuint buffer
Definition: glext.h:5915
LPWSTR File
Definition: msipriv.h:606
WCHAR * msi_get_assembly_path(MSIPACKAGE *package, const WCHAR *displayname)
Definition: assembly.c:240
static MONITORINFO mi
Definition: win.c:7338
static void msi_free(void *mem)
Definition: msipriv.h:1159
#define INVALID_FILE_SIZE
Definition: winbase.h:545
INSTALLSTATE Action
Definition: msipriv.h:533
INSTALLSTATE msi_get_component_action(MSIPACKAGE *package, MSICOMPONENT *comp)
Definition: action.c:611
WCHAR * msi_resolve_source_folder(MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder)
Definition: install.c:364
UINT ACTION_PatchFiles(MSIPACKAGE *package)
Definition: files.c:784
const char * filename
Definition: ioapi.h:135
UINT ready_media(MSIPACKAGE *package, BOOL compressed, MSIMEDIAINFO *mi)
Definition: media.c:850
#define lstrlenW
Definition: compat.h:609
static BOOL msi_create_directory(MSIPACKAGE *package, const WCHAR *path)
Definition: files.c:79
struct list files
Definition: msipriv.h:403
static void * msi_realloc(void *mem, size_t len) __WINE_ALLOC_SIZE(2)
Definition: msipriv.h:1154
MSIFILE * File
Definition: msipriv.h:626
#define FILE_SHARE_READ
Definition: compat.h:136
static void * msi_alloc_zero(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1148
#define lstrcpynW
Definition: compat.h:597
LPWSTR destname
Definition: files.c:879
static UINT create_directory(MSIPACKAGE *package, const WCHAR *dir)
Definition: files.c:467
__WINE_SERVER_LIST_INLINE struct list * list_head(const struct list *list)
Definition: list.h:131
static BOOL patchfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action, LPWSTR *path, DWORD *attrs, PVOID user)
Definition: files.c:678
BOOL msi_delete_file(MSIPACKAGE *package, const WCHAR *filename)
Definition: files.c:70
WCHAR *WINAPIV msi_build_directory_name(DWORD count,...)
Definition: action.c:2008
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
BOOL registered
Definition: msipriv.h:209
#define L(x)
Definition: ntvdm.h:50
UINT MSI_RecordSetInteger(MSIRECORD *, UINT, int) DECLSPEC_HIDDEN
Definition: record.c:280
BOOL msi_set_file_attributes(MSIPACKAGE *package, const WCHAR *filename, DWORD attrs)
Definition: files.c:97
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985
_In_ FLONG fl
Definition: winddi.h:1279
#define FALSE
Definition: types.h:117
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
int hash
Definition: main.c:58
LPWSTR WINAPI PathAddBackslashW(LPWSTR lpszPath)
Definition: path.c:294
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOL MSI_RecordIsNull(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:321
static BOOL is_obsoleted_by_patch(MSIPACKAGE *package, MSIFILE *file)
Definition: files.c:266
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:652
#define debugstr_w
Definition: kernel32.h:32
INT MSI_ProcessMessage(MSIPACKAGE *, INSTALLMESSAGE, MSIRECORD *) DECLSPEC_HIDDEN
Definition: package.c:1914
#define FIXME(fmt,...)
Definition: debug.h:111
UINT ACTION_InstallFiles(MSIPACKAGE *package)
Definition: files.c:556
static PVOID ptr
Definition: dispmode.c:27
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
VS_FIXEDFILEINFO * msi_get_disk_file_version(MSIPACKAGE *package, const WCHAR *filename)
Definition: files.c:161
WCHAR * path
Definition: msipriv.h:632
IAssemblyEnum * msi_create_assembly_enum(MSIPACKAGE *package, const WCHAR *displayname)
Definition: assembly.c:265
static const WCHAR version[]
Definition: asmname.c:66
DWORD msi_get_file_version_info(MSIPACKAGE *package, const WCHAR *path, DWORD buflen, BYTE *buffer)
Definition: files.c:151
#define MOVEFILE_DELAY_UNTIL_REBOOT
Definition: winbase.h:397
#define is_dot_dir(x)
Definition: files.c:873
const WCHAR * MSI_RecordGetString(const MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:433
unsigned int dir
Definition: maze.c:112
struct CFFOLDER folder
Definition: fdi.c:102
static void remove_folder(MSIFOLDER *folder)
Definition: files.c:1535
BOOL WINAPI RemoveDirectoryW(IN LPCWSTR lpPathName)
Definition: dir.c:732
WCHAR * msi_get_font_file_version(MSIPACKAGE *package, const WCHAR *filename)
Definition: font.c:186
UINT ACTION_RemoveDuplicateFiles(MSIPACKAGE *package)
Definition: files.c:1411
int options
Definition: main.c:106
#define OPEN_EXISTING
Definition: compat.h:634
UINT ACTION_MoveFiles(MSIPACKAGE *package)
Definition: files.c:1206
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
_Check_return_ _CRTIMP FILE *__cdecl tmpfile(void)
Definition: file.c:3912
MSIFILE * msi_get_loaded_file(MSIPACKAGE *package, const WCHAR *key)
Definition: action.c:574
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
static MSIFILE * find_file(MSIPACKAGE *package, UINT disk_id, const WCHAR *filename)
Definition: files.c:484
HANDLE msi_create_file(MSIPACKAGE *package, const WCHAR *filename, DWORD access, DWORD sharing, DWORD creation, DWORD flags)
Definition: files.c:51
GLfloat f
Definition: glext.h:7540
BOOL msi_find_next_file(MSIPACKAGE *package, HANDLE handle, WIN32_FIND_DATAW *data)
Definition: files.c:124
#define TRACE(s)
Definition: solgame.cpp:4
#define MSICABEXTRACT_FILEEXTRACTED
Definition: msipriv.h:1096
GLsizeiptr size
Definition: glext.h:5919
LPWSTR Directory
Definition: msipriv.h:527
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
BOOL msi_move_file(MSIPACKAGE *package, const WCHAR *from, const WCHAR *to, DWORD flags)
Definition: files.c:133
__wchar_t WCHAR
Definition: xmlstorage.h:180
static msi_file_state calculate_install_state(MSIPACKAGE *package, MSIFILE *file)
Definition: files.c:290
LONG HRESULT
Definition: typedefs.h:79
BOOL WINAPI CopyFileW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN BOOL bFailIfExists)
Definition: copy.c:439
static WCHAR * wildcard_to_file(const WCHAR *wildcard, const WCHAR *filename)
Definition: files.c:919
#define ERROR_INSTALL_FAILURE
Definition: winerror.h:961
GLfloat param
Definition: glext.h:5796
const char file[]
Definition: icontest.c:11
UINT WINAPI GetTempFileNameW(IN LPCWSTR lpPathName, IN LPCWSTR lpPrefixString, IN UINT uUnique, OUT LPWSTR lpTempFileName)
Definition: filename.c:84
BOOL WINAPI ApplyPatchToFileW(LPCWSTR patch_file, LPCWSTR old_file, LPCWSTR new_file, ULONG apply_flags)
unsigned long DWORD
Definition: ntddk_ex.h:95
DWORD dwFileVersionMS
Definition: compat.h:761
MSIDATABASE * db
Definition: msipriv.h:394
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
static BOOL move_file(MSIPACKAGE *package, const WCHAR *source, const WCHAR *dest, int options)
Definition: files.c:884
MSIFOLDER * msi_get_loaded_folder(MSIPACKAGE *package, const WCHAR *dir)
Definition: action.c:585
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
static void msi_disable_fs_redirection(MSIPACKAGE *package)
Definition: msipriv.h:1068
GLbitfield flags
Definition: glext.h:7161
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:241
LPWSTR Component
Definition: msipriv.h:525
MSICOMPONENT * msi_get_loaded_component(MSIPACKAGE *package, const WCHAR *Component)
Definition: action.c:552
struct list components
Definition: msipriv.h:401
static void msi_file_update_ui(MSIPACKAGE *package, MSIFILE *f, const WCHAR *action)
Definition: files.c:242
#define wcsicmp
Definition: compat.h:15
int ret
MSIRECORD * MSI_CreateRecord(UINT) DECLSPEC_HIDDEN
Definition: record.c:76
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
UINT msi_install_assembly(MSIPACKAGE *package, MSICOMPONENT *comp)
Definition: assembly.c:411
DWORD msi_get_file_attributes(MSIPACKAGE *package, const WCHAR *path)
Definition: files.c:106
BOOL installed
Definition: msipriv.h:518
DWORD WINAPI GetFileVersionInfoSizeW(LPCWSTR filename, LPDWORD handle)
Definition: version.c:611
int msi_compare_font_versions(const WCHAR *ver1, const WCHAR *ver2)
Definition: action.c:1943
static int state
Definition: maze.c:121
static BOOL file_hash_matches(MSIPACKAGE *package, MSIFILE *file)
Definition: files.c:277
uint32_t entry
Definition: isohybrid.c:63
static BOOL is_registered_patch_media(MSIPACKAGE *package, UINT disk_id)
Definition: files.c:255
BOOL msi_remove_directory(MSIPACKAGE *package, const WCHAR *path)
Definition: files.c:88
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
Definition: _list.h:228
#define GENERIC_READ
Definition: compat.h:135
#define ERROR_SHARING_VIOLATION
Definition: winerror.h:135
GLenum src
Definition: glext.h:6340
UINT msi_uninstall_assembly(MSIPACKAGE *package, MSICOMPONENT *comp)
Definition: assembly.c:456
#define wcsrchr
Definition: compat.h:16
LPWSTR source
Definition: files.c:880
#define E_NOT_SUFFICIENT_BUFFER
Definition: winerror.h:2345
unsigned char BYTE
Definition: xxhash.c:193
const WCHAR * msi_get_target_folder(MSIPACKAGE *package, const WCHAR *name)
Definition: install.c:232
int MSI_RecordGetInteger(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:213
#define ERR(fmt,...)
Definition: debug.h:110
UINT ACTION_RemoveFiles(MSIPACKAGE *package)
Definition: files.c:1549
void msi_reduce_to_long_filename(WCHAR *filename)
Definition: files.c:1074
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
LPWSTR application
Definition: msipriv.h:514
__WINE_SERVER_LIST_INLINE int list_empty(const struct list *list)
Definition: list.h:143
UINT msi_get_filehash(MSIPACKAGE *package, const WCHAR *path, MSIFILEHASHINFO *hash)
Definition: msi.c:4024
#define S_OK
Definition: intsafe.h:52
MSICOMPONENT * Component
Definition: msipriv.h:607
const WCHAR * action
Definition: action.c:7479
const char cursor[]
Definition: icontest.c:13
#define lstrcpyW
Definition: compat.h:608
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
UINT ACTION_DuplicateFiles(MSIPACKAGE *package)
Definition: files.c:1336
GLenum GLenum dst
Definition: glext.h:6340
int msi_compare_file_versions(VS_FIXEDFILEINFO *fi, const WCHAR *version)
Definition: action.c:1930
#define MSICABEXTRACT_BEGINEXTRACT
Definition: msipriv.h:1095
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
struct list entry
Definition: files.c:877
static WCHAR * get_duplicate_filename(MSIPACKAGE *package, MSIRECORD *row, const WCHAR *file_key, const WCHAR *src)
Definition: files.c:1223
WCHAR * msi_resolve_file_source(MSIPACKAGE *package, MSIFILE *file)
Definition: files.c:528
__WINE_SERVER_LIST_INLINE void list_add_before(struct list *elem, struct list *to_add)
Definition: list.h:87
struct list entry
Definition: fci.c:128
BOOL WINAPI GetFileVersionInfoW(LPCWSTR filename, DWORD handle, DWORD datasize, LPVOID data)
Definition: version.c:845
#define CreateFileW
Definition: compat.h:600
INSTALLSTATE Installed
Definition: msipriv.h:531
static UINT copy_install_file(MSIPACKAGE *package, MSIFILE *file, LPWSTR source)
Definition: files.c:408
BOOL msi_cabextract(MSIPACKAGE *package, MSIMEDIAINFO *mi, LPVOID data)
Definition: media.c:652
WCHAR * msi_create_temp_file(MSIDATABASE *db)
Definition: custom.c:215
Definition: name.c:38
static MSIFILEPATCH * find_filepatch(MSIPACKAGE *package, UINT disk_id, const WCHAR *key)
Definition: files.c:666
GLuint res
Definition: glext.h:9613
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
static void * msi_alloc(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1142
static UINT ITERATE_MoveFiles(MSIRECORD *rec, LPVOID param)
Definition: files.c:1080
#define HIWORD(l)
Definition: typedefs.h:247
static void free_file_entry(FILE_LIST *file)
Definition: files.c:937
static IOleDocumentView * view
Definition: activex.c:1749
BOOL WINAPI MoveFileExW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName OPTIONAL, IN DWORD dwFlags)
Definition: move.c:1060
static UINT ITERATE_RemoveFiles(MSIRECORD *row, LPVOID param)
Definition: files.c:1452
static char * dest
Definition: rtl.c:135
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
void msi_free_media_info(MSIMEDIAINFO *mi)
Definition: media.c:661
#define ERROR_ALREADY_EXISTS
Definition: disk.h:80
WINE_DEFAULT_DEBUG_CHANNEL(advpack)
INT Attributes
Definition: msipriv.h:614
GLfloat GLfloat p
Definition: glext.h:8902
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define LIST_ENTRY(type)
Definition: queue.h:175
CardRegion * from
Definition: spigame.cpp:19
UINT MSI_IterateRecords(MSIQUERY *, LPDWORD, record_func, LPVOID) DECLSPEC_HIDDEN
Definition: msiquery.c:163
struct list filepatches
Definition: msipriv.h:404
Definition: _hash_fun.h:40
static UINT ITERATE_RemoveDuplicateFiles(MSIRECORD *row, LPVOID param)
Definition: files.c:1353
LPWSTR TargetPath
Definition: msipriv.h:617
void user(int argc, const char *argv[])
Definition: cmds.c:1350
#define LOWORD(l)
Definition: pedump.c:82
static UINT patch_assembly(MSIPACKAGE *package, MSIASSEMBLY *assembly, MSIFILEPATCH *patch)
Definition: files.c:734
static UINT copy_file(MSIPACKAGE *package, MSIFILE *file, WCHAR *source)
Definition: files.c:396
HANDLE msi_find_first_file(MSIPACKAGE *package, const WCHAR *filename, WIN32_FIND_DATAW *data)
Definition: files.c:115
struct list patches
Definition: msipriv.h:400
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
UINT msi_schedule_action(MSIPACKAGE *package, UINT script, const WCHAR *action)
Definition: custom.c:90
struct png_info_def *typedef unsigned char **typedef struct png_info_def *typedef struct png_info_def *typedef struct png_info_def *typedef unsigned char ** row
Definition: typeof.h:78
static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR filename, DWORD action, LPWSTR *path, DWORD *attrs, PVOID user)
Definition: files.c:497
static BOOL add_wildcard(FILE_LIST *files, const WCHAR *source, WCHAR *dest)
Definition: files.c:955
Definition: copy.c:22
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
BOOL WINAPI VerQueryValueW(LPCVOID pBlock, LPCWSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen)
Definition: version.c:1049
static BOOL move_files_wildcard(MSIPACKAGE *package, const WCHAR *source, WCHAR *dest, int options)
Definition: files.c:1006
static BOOL verify_comp_for_removal(MSICOMPONENT *comp, UINT install_mode)
Definition: files.c:1428
Definition: fci.c:126
unsigned char need_reboot_at_end
Definition: msipriv.h:469
LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop) DECLSPEC_HIDDEN
Definition: package.c:2283
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
static UINT patch_file(MSIPACKAGE *package, MSIFILEPATCH *patch)
Definition: files.c:712
UINT MSI_DatabaseOpenViewW(MSIDATABASE *, LPCWSTR, MSIQUERY **) DECLSPEC_HIDDEN
GLuint const GLchar * name
Definition: glext.h:6031