ReactOS  0.4.12-dev-916-gffc4e30
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 /*
23  * Actions dealing with files:
24  *
25  * InstallFiles
26  * DuplicateFiles
27  * MoveFiles
28  * PatchFiles
29  * RemoveDuplicateFiles
30  * RemoveFiles
31  */
32 
33 #include <stdarg.h>
34 
35 #define COBJMACROS
36 
37 #include "windef.h"
38 #include "winbase.h"
39 #include "winerror.h"
40 #include "wine/debug.h"
41 #include "fdi.h"
42 #include "msi.h"
43 #include "msidefs.h"
44 #include "msipriv.h"
45 #include "winuser.h"
46 #include "winreg.h"
47 #include "shlwapi.h"
48 #include "patchapi.h"
49 #include "wine/unicode.h"
50 
52 
53 static void msi_file_update_ui( MSIPACKAGE *package, MSIFILE *f, const WCHAR *action )
54 {
55  MSIRECORD *uirow;
56 
57  uirow = MSI_CreateRecord( 9 );
58  MSI_RecordSetStringW( uirow, 1, f->FileName );
59  MSI_RecordSetStringW( uirow, 9, f->Component->Directory );
60  MSI_RecordSetInteger( uirow, 6, f->FileSize );
62  msiobj_release( &uirow->hdr );
63  msi_ui_progress( package, 2, f->FileSize, 0, 0 );
64 }
65 
66 static BOOL is_registered_patch_media( MSIPACKAGE *package, UINT disk_id )
67 {
68  MSIPATCHINFO *patch;
69 
70  LIST_FOR_EACH_ENTRY( patch, &package->patches, MSIPATCHINFO, entry )
71  {
72  if (patch->disk_id == disk_id && patch->registered) return TRUE;
73  }
74  return FALSE;
75 }
76 
78 {
79  if (!list_empty( &package->patches ) && file->disk_id < MSI_INITIAL_MEDIA_TRANSFORM_DISKID)
80  {
81  if (!msi_get_property_int( package->db, szInstalled, 0 )) return FALSE;
82  return TRUE;
83  }
84  if (is_registered_patch_media( package, file->disk_id )) return TRUE;
85  return FALSE;
86 }
87 
89 {
90  MSICOMPONENT *comp = file->Component;
91  VS_FIXEDFILEINFO *file_version;
92  WCHAR *font_version;
94  DWORD size;
95 
96  comp->Action = msi_get_component_action( package, comp );
97  if (!comp->Enabled || comp->Action != INSTALLSTATE_LOCAL || (comp->assembly && comp->assembly->installed))
98  {
99  TRACE("skipping %s (not scheduled for install)\n", debugstr_w(file->File));
100  return msifs_skipped;
101  }
102  if (is_obsoleted_by_patch( package, file ))
103  {
104  TRACE("skipping %s (obsoleted by patch)\n", debugstr_w(file->File));
105  return msifs_skipped;
106  }
107  if ((msi_is_global_assembly( comp ) && !comp->assembly->installed) ||
109  {
110  TRACE("installing %s (missing)\n", debugstr_w(file->File));
111  return msifs_missing;
112  }
113  if (file->Version)
114  {
115  if ((file_version = msi_get_disk_file_version( file->TargetPath )))
116  {
117  if (msi_compare_file_versions( file_version, file->Version ) < 0)
118  {
119  TRACE("overwriting %s (new version %s old version %u.%u.%u.%u)\n",
120  debugstr_w(file->File), debugstr_w(file->Version),
121  HIWORD(file_version->dwFileVersionMS), LOWORD(file_version->dwFileVersionMS),
122  HIWORD(file_version->dwFileVersionLS), LOWORD(file_version->dwFileVersionLS));
124  }
125  else
126  {
127  TRACE("keeping %s (new version %s old version %u.%u.%u.%u)\n",
128  debugstr_w(file->File), debugstr_w(file->Version),
129  HIWORD(file_version->dwFileVersionMS), LOWORD(file_version->dwFileVersionMS),
130  HIWORD(file_version->dwFileVersionLS), LOWORD(file_version->dwFileVersionLS));
132  }
133  msi_free( file_version );
134  return state;
135  }
136  else if ((font_version = msi_font_version_from_file( file->TargetPath )))
137  {
138  if (msi_compare_font_versions( font_version, file->Version ) < 0)
139  {
140  TRACE("overwriting %s (new version %s old version %s)\n",
141  debugstr_w(file->File), debugstr_w(file->Version), debugstr_w(font_version));
143  }
144  else
145  {
146  TRACE("keeping %s (new version %s old version %s)\n",
147  debugstr_w(file->File), debugstr_w(file->Version), debugstr_w(font_version));
149  }
150  msi_free( font_version );
151  return state;
152  }
153  }
154  if ((size = msi_get_disk_file_size( file->TargetPath )) != file->FileSize)
155  {
156  TRACE("overwriting %s (old size %u new size %u)\n", debugstr_w(file->File), size, file->FileSize);
157  return msifs_overwrite;
158  }
159  if (file->hash.dwFileHashInfoSize)
160  {
162  {
163  TRACE("keeping %s (hash match)\n", debugstr_w(file->File));
164  return msifs_hashmatch;
165  }
166  else
167  {
168  TRACE("overwriting %s (hash mismatch)\n", debugstr_w(file->File));
169  return msifs_overwrite;
170  }
171  }
172  /* assume present */
173  TRACE("keeping %s\n", debugstr_w(file->File));
174  return msifs_present;
175 }
176 
177 static void schedule_install_files(MSIPACKAGE *package)
178 {
179  MSIFILE *file;
180 
182  {
183  MSICOMPONENT *comp = file->Component;
184 
185  file->state = calculate_install_state( package, file );
187  {
188  TRACE("not overwriting %s\n", debugstr_w(file->TargetPath));
189  file->state = msifs_skipped;
190  }
191  }
192 }
193 
195 {
196  BOOL ret;
197 
198  ret = CopyFileW(source, file->TargetPath, FALSE);
199  if (!ret)
200  return GetLastError();
201 
203  return ERROR_SUCCESS;
204 }
205 
207 {
208  UINT gle;
209 
210  TRACE("Copying %s to %s\n", debugstr_w(source), debugstr_w(file->TargetPath));
211 
212  gle = copy_file(file, source);
213  if (gle == ERROR_SUCCESS)
214  return gle;
215 
216  if (gle == ERROR_ALREADY_EXISTS && file->state == msifs_overwrite)
217  {
218  TRACE("overwriting existing file\n");
219  return ERROR_SUCCESS;
220  }
221  else if (gle == ERROR_ACCESS_DENIED)
222  {
224 
225  gle = copy_file(file, source);
226  TRACE("Overwriting existing file: %d\n", gle);
227  }
228  if (gle == ERROR_SHARING_VIOLATION || gle == ERROR_USER_MAPPED_FILE)
229  {
230  WCHAR *tmpfileW, *pathW, *p;
231  DWORD len;
232 
233  TRACE("file in use, scheduling rename operation\n");
234 
235  if (!(pathW = strdupW( file->TargetPath ))) return ERROR_OUTOFMEMORY;
236  if ((p = strrchrW(pathW, '\\'))) *p = 0;
237  len = strlenW( pathW ) + 16;
238  if (!(tmpfileW = msi_alloc(len * sizeof(WCHAR))))
239  {
240  msi_free( pathW );
241  return ERROR_OUTOFMEMORY;
242  }
243  if (!GetTempFileNameW( pathW, szMsi, 0, tmpfileW )) tmpfileW[0] = 0;
244  msi_free( pathW );
245 
246  if (CopyFileW(source, tmpfileW, FALSE) &&
248  MoveFileExW(tmpfileW, file->TargetPath, MOVEFILE_DELAY_UNTIL_REBOOT))
249  {
250  package->need_reboot_at_end = 1;
251  gle = ERROR_SUCCESS;
252  }
253  else
254  {
255  gle = GetLastError();
256  WARN("failed to schedule rename operation: %d)\n", gle);
257  DeleteFileW( tmpfileW );
258  }
259  msi_free(tmpfileW);
260  }
261 
262  return gle;
263 }
264 
265 static UINT msi_create_directory( MSIPACKAGE *package, const WCHAR *dir )
266 {
267  MSIFOLDER *folder;
268  const WCHAR *install_path;
269 
270  install_path = msi_get_target_folder( package, dir );
271  if (!install_path) return ERROR_FUNCTION_FAILED;
272 
273  folder = msi_get_loaded_folder( package, dir );
274  if (folder->State == FOLDER_STATE_UNINITIALIZED)
275  {
276  msi_create_full_path( install_path );
277  folder->State = FOLDER_STATE_CREATED;
278  }
279  return ERROR_SUCCESS;
280 }
281 
282 static MSIFILE *find_file( MSIPACKAGE *package, UINT disk_id, const WCHAR *filename )
283 {
284  MSIFILE *file;
285 
286  LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
287  {
288  if (file->disk_id == disk_id &&
289  file->state != msifs_installed &&
290  !strcmpiW( filename, file->File )) return file;
291  }
292  return NULL;
293 }
294 
296  LPWSTR *path, DWORD *attrs, PVOID user)
297 {
298  MSIFILE *file = *(MSIFILE **)user;
299 
301  {
302  if (!(file = find_file( package, file->disk_id, filename )))
303  {
304  TRACE("unknown file in cabinet (%s)\n", debugstr_w(filename));
305  return FALSE;
306  }
307  if (file->state != msifs_missing && file->state != msifs_overwrite)
308  return FALSE;
309 
310  if (!msi_is_global_assembly( file->Component ))
311  {
312  msi_create_directory( package, file->Component->Directory );
313  }
314  *path = strdupW( file->TargetPath );
315  *attrs = file->Attributes;
316  *(MSIFILE **)user = file;
317  }
319  {
320  if (!msi_is_global_assembly( file->Component )) file->state = msifs_installed;
321  }
322 
323  return TRUE;
324 }
325 
327 {
328  WCHAR *p, *path;
329 
330  TRACE("Working to resolve source of file %s\n", debugstr_w(file->File));
331 
332  if (file->IsCompressed) return NULL;
333 
334  p = msi_resolve_source_folder( package, file->Component->Directory, NULL );
335  path = msi_build_directory_name( 2, p, file->ShortName );
336 
337  if (file->LongName && GetFileAttributesW( path ) == INVALID_FILE_ATTRIBUTES)
338  {
339  msi_free( path );
340  path = msi_build_directory_name( 2, p, file->LongName );
341  }
342  msi_free( p );
343  TRACE("file %s source resolves to %s\n", debugstr_w(file->File), debugstr_w(path));
344  return path;
345 }
346 
347 /*
348  * ACTION_InstallFiles()
349  *
350  * For efficiency, this is done in two passes:
351  * 1) Correct all the TargetPaths and determine what files are to be installed.
352  * 2) Extract Cabinets and copy files.
353  */
355 {
356  MSIMEDIAINFO *mi;
357  UINT rc = ERROR_SUCCESS;
358  MSIFILE *file;
359 
360  schedule_install_files(package);
361  mi = msi_alloc_zero( sizeof(MSIMEDIAINFO) );
362 
363  LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
364  {
365  BOOL is_global_assembly = msi_is_global_assembly( file->Component );
366 
368 
369  rc = msi_load_media_info( package, file->Sequence, mi );
370  if (rc != ERROR_SUCCESS)
371  {
372  ERR("Unable to load media info for %s (%u)\n", debugstr_w(file->File), rc);
374  goto done;
375  }
376 
377  if (file->state != msifs_hashmatch &&
378  file->state != msifs_skipped &&
379  (file->state != msifs_present || !msi_get_property_int( package->db, szInstalled, 0 )) &&
380  (rc = ready_media( package, file->IsCompressed, mi )))
381  {
382  ERR("Failed to ready media for %s\n", debugstr_w(file->File));
383  goto done;
384  }
385 
386  if (file->state != msifs_missing && !mi->is_continuous && file->state != msifs_overwrite)
387  continue;
388 
389  if (file->Sequence > mi->last_sequence || mi->is_continuous ||
390  (file->IsCompressed && !mi->is_extracted))
391  {
393  MSIFILE *cursor = file;
394 
395  data.mi = mi;
396  data.package = package;
397  data.cb = installfiles_cb;
398  data.user = &cursor;
399 
400  if (file->IsCompressed && !msi_cabextract(package, mi, &data))
401  {
402  ERR("Failed to extract cabinet: %s\n", debugstr_w(mi->cabinet));
404  goto done;
405  }
406  }
407 
408  if (!file->IsCompressed)
409  {
411 
412  TRACE("copying %s to %s\n", debugstr_w(source), debugstr_w(file->TargetPath));
413 
414  if (!is_global_assembly)
415  {
416  msi_create_directory(package, file->Component->Directory);
417  }
418  rc = copy_install_file(package, file, source);
419  if (rc != ERROR_SUCCESS)
420  {
421  ERR("Failed to copy %s to %s (%u)\n", debugstr_w(source), debugstr_w(file->TargetPath), rc);
423  msi_free(source);
424  goto done;
425  }
426  if (!is_global_assembly) file->state = msifs_installed;
427  msi_free(source);
428  }
429  else if (!is_global_assembly && file->state != msifs_installed &&
430  !(file->Attributes & msidbFileAttributesPatchAdded))
431  {
432  ERR("compressed file wasn't installed (%s)\n", debugstr_w(file->File));
434  goto done;
435  }
436  }
437  LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
438  {
439  MSICOMPONENT *comp = file->Component;
440 
441  if (!msi_is_global_assembly( comp ) || comp->assembly->installed ||
442  (file->state != msifs_missing && file->state != msifs_overwrite)) continue;
443 
444  rc = msi_install_assembly( package, comp );
445  if (rc != ERROR_SUCCESS)
446  {
447  ERR("Failed to install assembly\n");
449  break;
450  }
451  file->state = msifs_installed;
452  }
453 
454 done:
456  return rc;
457 }
458 
459 static MSIFILEPATCH *find_filepatch( MSIPACKAGE *package, UINT disk_id, const WCHAR *key )
460 {
461  MSIFILEPATCH *patch;
462 
463  LIST_FOR_EACH_ENTRY( patch, &package->filepatches, MSIFILEPATCH, entry )
464  {
465  if (!patch->extracted && patch->disk_id == disk_id && !strcmpW( key, patch->File->File ))
466  return patch;
467  }
468  return NULL;
469 }
470 
472  LPWSTR *path, DWORD *attrs, PVOID user)
473 {
474  MSIFILEPATCH *patch = *(MSIFILEPATCH **)user;
475 
477  {
478  MSICOMPONENT *comp;
479 
480  if (is_registered_patch_media( package, patch->disk_id ) ||
481  !(patch = find_filepatch( package, patch->disk_id, file ))) return FALSE;
482 
483  comp = patch->File->Component;
484  comp->Action = msi_get_component_action( package, comp );
485  if (!comp->Enabled || comp->Action != INSTALLSTATE_LOCAL)
486  {
487  TRACE("file %s component %s not installed or disabled\n",
488  debugstr_w(patch->File->File), debugstr_w(comp->Component));
489  return FALSE;
490  }
491 
492  patch->path = msi_create_temp_file( package->db );
493  *path = strdupW( patch->path );
494  *attrs = patch->File->Attributes;
495  *(MSIFILEPATCH **)user = patch;
496  }
498  {
499  patch->extracted = TRUE;
500  }
501 
502  return TRUE;
503 }
504 
505 static UINT patch_file( MSIPACKAGE *package, MSIFILEPATCH *patch )
506 {
507  UINT r = ERROR_SUCCESS;
508  WCHAR *tmpfile = msi_create_temp_file( package->db );
509 
510  if (!tmpfile) return ERROR_INSTALL_FAILURE;
511  if (ApplyPatchToFileW( patch->path, patch->File->TargetPath, tmpfile, 0 ))
512  {
513  DeleteFileW( patch->File->TargetPath );
514  MoveFileW( tmpfile, patch->File->TargetPath );
515  }
516  else
517  {
518  WARN("failed to patch %s: %08x\n", debugstr_w(patch->File->TargetPath), GetLastError());
520  }
521  DeleteFileW( patch->path );
522  DeleteFileW( tmpfile );
523  msi_free( tmpfile );
524  return r;
525 }
526 
528 {
531  IAssemblyEnum *iter;
532 
533  if (!(iter = msi_create_assembly_enum( package, assembly->display_name )))
534  return ERROR_FUNCTION_FAILED;
535 
536  while ((IAssemblyEnum_GetNextAssembly( iter, NULL, &name, 0 ) == S_OK))
537  {
538  WCHAR *displayname, *path;
539  UINT len = 0;
540  HRESULT hr;
541 
542  hr = IAssemblyName_GetDisplayName( name, NULL, &len, 0 );
543  if (hr != E_NOT_SUFFICIENT_BUFFER || !(displayname = msi_alloc( len * sizeof(WCHAR) )))
544  break;
545 
546  hr = IAssemblyName_GetDisplayName( name, displayname, &len, 0 );
547  if (FAILED( hr ))
548  {
549  msi_free( displayname );
550  break;
551  }
552 
553  if ((path = msi_get_assembly_path( package, displayname )))
554  {
555  if (!CopyFileW( path, patch->File->TargetPath, FALSE ))
556  {
557  ERR("Failed to copy file %s -> %s (%u)\n", debugstr_w(path),
558  debugstr_w(patch->File->TargetPath), GetLastError() );
559  msi_free( path );
560  msi_free( displayname );
561  IAssemblyName_Release( name );
562  break;
563  }
564  r = patch_file( package, patch );
565  msi_free( path );
566  }
567 
568  msi_free( displayname );
569  IAssemblyName_Release( name );
570  if (r == ERROR_SUCCESS) break;
571  }
572 
573  IAssemblyEnum_Release( iter );
574  return r;
575 }
576 
578 {
579  MSIFILEPATCH *patch;
580  MSIMEDIAINFO *mi;
581  UINT rc = ERROR_SUCCESS;
582 
583  TRACE("%p\n", package);
584 
585  mi = msi_alloc_zero( sizeof(MSIMEDIAINFO) );
586 
587  TRACE("extracting files\n");
588 
589  LIST_FOR_EACH_ENTRY( patch, &package->filepatches, MSIFILEPATCH, entry )
590  {
591  MSIFILE *file = patch->File;
592  MSICOMPONENT *comp = file->Component;
593 
594  rc = msi_load_media_info( package, patch->Sequence, mi );
595  if (rc != ERROR_SUCCESS)
596  {
597  ERR("Unable to load media info for %s (%u)\n", debugstr_w(file->File), rc);
599  goto done;
600  }
601  comp->Action = msi_get_component_action( package, comp );
602  if (!comp->Enabled || comp->Action != INSTALLSTATE_LOCAL) continue;
603 
604  if (!patch->extracted)
605  {
607  MSIFILEPATCH *cursor = patch;
608 
609  rc = ready_media( package, TRUE, mi );
610  if (rc != ERROR_SUCCESS)
611  {
612  ERR("Failed to ready media for %s\n", debugstr_w(file->File));
613  goto done;
614  }
615  data.mi = mi;
616  data.package = package;
617  data.cb = patchfiles_cb;
618  data.user = &cursor;
619 
620  if (!msi_cabextract( package, mi, &data ))
621  {
622  ERR("Failed to extract cabinet: %s\n", debugstr_w(mi->cabinet));
624  goto done;
625  }
626  }
627  }
628 
629  TRACE("applying patches\n");
630 
631  LIST_FOR_EACH_ENTRY( patch, &package->filepatches, MSIFILEPATCH, entry )
632  {
633  MSICOMPONENT *comp = patch->File->Component;
634 
635  if (!patch->path) continue;
636 
637  if (msi_is_global_assembly( comp ))
638  rc = patch_assembly( package, comp->assembly, patch );
639  else
640  rc = patch_file( package, patch );
641 
642  if (rc && !(patch->Attributes & msidbPatchAttributesNonVital))
643  {
644  ERR("Failed to apply patch to file: %s\n", debugstr_w(patch->File->File));
645  break;
646  }
647 
648  if (msi_is_global_assembly( comp ))
649  {
650  if ((rc = msi_install_assembly( package, comp )))
651  {
652  ERR("Failed to install patched assembly\n");
653  break;
654  }
655  }
656  }
657 
658 done:
660  return rc;
661 }
662 
663 #define is_dot_dir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))))
664 
665 typedef struct
666 {
667  struct list entry;
672 } FILE_LIST;
673 
675 {
676  BOOL ret;
677 
680  {
681  WARN("Source or dest is directory, not moving\n");
682  return FALSE;
683  }
684 
686  {
687  TRACE("moving %s -> %s\n", debugstr_w(source), debugstr_w(dest));
689  if (!ret)
690  {
691  WARN("MoveFile failed: %d\n", GetLastError());
692  return FALSE;
693  }
694  }
695  else
696  {
697  TRACE("copying %s -> %s\n", debugstr_w(source), debugstr_w(dest));
699  if (!ret)
700  {
701  WARN("CopyFile failed: %d\n", GetLastError());
702  return FALSE;
703  }
704  }
705 
706  return TRUE;
707 }
708 
710 {
711  LPWSTR path, ptr;
712  DWORD dirlen, pathlen;
713 
714  ptr = strrchrW(wildcard, '\\');
715  dirlen = ptr - wildcard + 1;
716 
717  pathlen = dirlen + lstrlenW(filename) + 1;
718  path = msi_alloc(pathlen * sizeof(WCHAR));
719 
720  lstrcpynW(path, wildcard, dirlen + 1);
722 
723  return path;
724 }
725 
727 {
728  msi_free(file->source);
729  msi_free(file->dest);
730  msi_free(file);
731 }
732 
733 static void free_list(FILE_LIST *list)
734 {
735  while (!list_empty(&list->entry))
736  {
738 
741  }
742 }
743 
745 {
746  FILE_LIST *new, *file;
748  DWORD size;
749 
750  new = msi_alloc_zero(sizeof(FILE_LIST));
751  if (!new)
752  return FALSE;
753 
754  new->source = strdupW(source);
755  ptr = strrchrW(dest, '\\') + 1;
756  filename = strrchrW(new->source, '\\') + 1;
757 
758  new->sourcename = filename;
759 
760  if (*ptr)
761  new->destname = ptr;
762  else
763  new->destname = new->sourcename;
764 
765  size = (ptr - dest) + lstrlenW(filename) + 1;
766  new->dest = msi_alloc(size * sizeof(WCHAR));
767  if (!new->dest)
768  {
769  free_file_entry(new);
770  return FALSE;
771  }
772 
773  lstrcpynW(new->dest, dest, ptr - dest + 1);
774  lstrcatW(new->dest, filename);
775 
776  if (list_empty(&files->entry))
777  {
778  list_add_head(&files->entry, &new->entry);
779  return TRUE;
780  }
781 
783  {
784  if (strcmpW( source, file->source ) < 0)
785  {
786  list_add_before(&file->entry, &new->entry);
787  return TRUE;
788  }
789  }
790 
791  list_add_after(&file->entry, &new->entry);
792  return TRUE;
793 }
794 
796 {
797  WIN32_FIND_DATAW wfd;
798  HANDLE hfile;
799  LPWSTR path;
800  BOOL res;
801  FILE_LIST files, *file;
802  DWORD size;
803 
804  hfile = FindFirstFileW(source, &wfd);
805  if (hfile == INVALID_HANDLE_VALUE) return FALSE;
806 
807  list_init(&files.entry);
808 
809  for (res = TRUE; res; res = FindNextFileW(hfile, &wfd))
810  {
811  if (is_dot_dir(wfd.cFileName)) continue;
812 
813  path = wildcard_to_file(source, wfd.cFileName);
814  if (!path)
815  {
816  res = FALSE;
817  goto done;
818  }
819 
820  add_wildcard(&files, path, dest);
821  msi_free(path);
822  }
823 
824  /* no files match the wildcard */
825  if (list_empty(&files.entry))
826  goto done;
827 
828  /* only the first wildcard match gets renamed to dest */
830  size = (strrchrW(file->dest, '\\') - file->dest) + lstrlenW(file->destname) + 2;
831  file->dest = msi_realloc(file->dest, size * sizeof(WCHAR));
832  if (!file->dest)
833  {
834  res = FALSE;
835  goto done;
836  }
837 
838  /* file->dest may be shorter after the reallocation, so add a NULL
839  * terminator. This is needed for the call to strrchrW, as there will no
840  * longer be a NULL terminator within the bounds of the allocation in this case.
841  */
842  file->dest[size - 1] = '\0';
843  lstrcpyW(strrchrW(file->dest, '\\') + 1, file->destname);
844 
845  while (!list_empty(&files.entry))
846  {
848 
849  msi_move_file(file->source, file->dest, options);
850 
853  }
854 
855  res = TRUE;
856 
857 done:
858  free_list(&files);
859  FindClose(hfile);
860  return res;
861 }
862 
864 {
865  WCHAR *p = strchrW( filename, '|' );
866  if (p) memmove( filename, p + 1, (strlenW( p + 1 ) + 1) * sizeof(WCHAR) );
867 }
868 
870 {
871  MSIPACKAGE *package = param;
872  MSIRECORD *uirow;
873  MSICOMPONENT *comp;
874  LPCWSTR sourcename, component;
875  LPWSTR sourcedir, destname = NULL, destdir = NULL, source = NULL, dest = NULL;
876  int options;
877  DWORD size;
878  BOOL wildcards;
879 
880  component = MSI_RecordGetString(rec, 2);
881  comp = msi_get_loaded_component(package, component);
882  if (!comp)
883  return ERROR_SUCCESS;
884 
885  comp->Action = msi_get_component_action( package, comp );
886  if (comp->Action != INSTALLSTATE_LOCAL)
887  {
888  TRACE("component not scheduled for installation %s\n", debugstr_w(component));
889  return ERROR_SUCCESS;
890  }
891 
892  sourcename = MSI_RecordGetString(rec, 3);
893  options = MSI_RecordGetInteger(rec, 7);
894 
895  sourcedir = msi_dup_property(package->db, MSI_RecordGetString(rec, 5));
896  if (!sourcedir)
897  goto done;
898 
899  destdir = msi_dup_property(package->db, MSI_RecordGetString(rec, 6));
900  if (!destdir)
901  goto done;
902 
903  if (!sourcename)
904  {
906  goto done;
907 
908  source = strdupW(sourcedir);
909  if (!source)
910  goto done;
911  }
912  else
913  {
914  size = lstrlenW(sourcedir) + lstrlenW(sourcename) + 2;
915  source = msi_alloc(size * sizeof(WCHAR));
916  if (!source)
917  goto done;
918 
919  lstrcpyW(source, sourcedir);
920  if (source[lstrlenW(source) - 1] != '\\')
922  lstrcatW(source, sourcename);
923  }
924 
925  wildcards = strchrW(source, '*') || strchrW(source, '?');
926 
927  if (MSI_RecordIsNull(rec, 4))
928  {
929  if (!wildcards)
930  {
931  WCHAR *p;
932  if (sourcename)
933  destname = strdupW(sourcename);
934  else if ((p = strrchrW(sourcedir, '\\')))
935  destname = strdupW(p + 1);
936  else
937  destname = strdupW(sourcedir);
938  if (!destname)
939  goto done;
940  }
941  }
942  else
943  {
944  destname = strdupW(MSI_RecordGetString(rec, 4));
945  if (destname) msi_reduce_to_long_filename(destname);
946  }
947 
948  size = 0;
949  if (destname)
950  size = lstrlenW(destname);
951 
952  size += lstrlenW(destdir) + 2;
953  dest = msi_alloc(size * sizeof(WCHAR));
954  if (!dest)
955  goto done;
956 
957  lstrcpyW(dest, destdir);
958  if (dest[lstrlenW(dest) - 1] != '\\')
960 
961  if (destname)
962  lstrcatW(dest, destname);
963 
965  {
966  if (!msi_create_full_path(destdir))
967  {
968  WARN("failed to create directory %u\n", GetLastError());
969  goto done;
970  }
971  }
972 
973  if (!wildcards)
975  else
977 
978 done:
979  uirow = MSI_CreateRecord( 9 );
980  MSI_RecordSetStringW( uirow, 1, MSI_RecordGetString(rec, 1) );
981  MSI_RecordSetInteger( uirow, 6, 1 ); /* FIXME */
982  MSI_RecordSetStringW( uirow, 9, destdir );
984  msiobj_release( &uirow->hdr );
985 
986  msi_free(sourcedir);
987  msi_free(destdir);
988  msi_free(destname);
989  msi_free(source);
990  msi_free(dest);
991 
992  return ERROR_SUCCESS;
993 }
994 
996 {
997  static const WCHAR query[] = {
998  'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
999  '`','M','o','v','e','F','i','l','e','`',0};
1000  MSIQUERY *view;
1001  UINT rc;
1002 
1003  rc = MSI_DatabaseOpenViewW(package->db, query, &view);
1004  if (rc != ERROR_SUCCESS)
1005  return ERROR_SUCCESS;
1006 
1007  rc = MSI_IterateRecords(view, NULL, ITERATE_MoveFiles, package);
1008  msiobj_release(&view->hdr);
1009  return rc;
1010 }
1011 
1012 static WCHAR *get_duplicate_filename( MSIPACKAGE *package, MSIRECORD *row, const WCHAR *file_key, const WCHAR *src )
1013 {
1014  DWORD len;
1015  WCHAR *dst_name, *dst_path, *dst;
1016 
1017  if (MSI_RecordIsNull( row, 4 ))
1018  {
1019  len = strlenW( src ) + 1;
1020  if (!(dst_name = msi_alloc( len * sizeof(WCHAR)))) return NULL;
1021  strcpyW( dst_name, strrchrW( src, '\\' ) + 1 );
1022  }
1023  else
1024  {
1025  MSI_RecordGetStringW( row, 4, NULL, &len );
1026  if (!(dst_name = msi_alloc( ++len * sizeof(WCHAR) ))) return NULL;
1027  MSI_RecordGetStringW( row, 4, dst_name, &len );
1028  msi_reduce_to_long_filename( dst_name );
1029  }
1030 
1031  if (MSI_RecordIsNull( row, 5 ))
1032  {
1033  WCHAR *p;
1034  dst_path = strdupW( src );
1035  p = strrchrW( dst_path, '\\' );
1036  if (p) *p = 0;
1037  }
1038  else
1039  {
1040  const WCHAR *dst_key = MSI_RecordGetString( row, 5 );
1041 
1042  dst_path = strdupW( msi_get_target_folder( package, dst_key ) );
1043  if (!dst_path)
1044  {
1045  /* try a property */
1046  dst_path = msi_dup_property( package->db, dst_key );
1047  if (!dst_path)
1048  {
1049  FIXME("Unable to get destination folder, try AppSearch properties\n");
1050  msi_free( dst_name );
1051  return NULL;
1052  }
1053  }
1054  }
1055 
1056  dst = msi_build_directory_name( 2, dst_path, dst_name );
1057  msi_create_full_path( dst_path );
1058 
1059  msi_free( dst_name );
1060  msi_free( dst_path );
1061  return dst;
1062 }
1063 
1065 {
1066  MSIPACKAGE *package = param;
1067  LPWSTR dest;
1068  LPCWSTR file_key, component;
1069  MSICOMPONENT *comp;
1070  MSIRECORD *uirow;
1071  MSIFILE *file;
1072 
1073  component = MSI_RecordGetString(row,2);
1074  comp = msi_get_loaded_component(package, component);
1075  if (!comp)
1076  return ERROR_SUCCESS;
1077 
1078  comp->Action = msi_get_component_action( package, comp );
1079  if (comp->Action != INSTALLSTATE_LOCAL)
1080  {
1081  TRACE("component not scheduled for installation %s\n", debugstr_w(component));
1082  return ERROR_SUCCESS;
1083  }
1084 
1085  file_key = MSI_RecordGetString(row,3);
1086  if (!file_key)
1087  {
1088  ERR("Unable to get file key\n");
1089  return ERROR_FUNCTION_FAILED;
1090  }
1091 
1092  file = msi_get_loaded_file( package, file_key );
1093  if (!file)
1094  {
1095  ERR("Original file unknown %s\n", debugstr_w(file_key));
1096  return ERROR_SUCCESS;
1097  }
1098 
1099  dest = get_duplicate_filename( package, row, file_key, file->TargetPath );
1100  if (!dest)
1101  {
1102  WARN("Unable to get duplicate filename\n");
1103  return ERROR_SUCCESS;
1104  }
1105 
1106  TRACE("Duplicating file %s to %s\n", debugstr_w(file->TargetPath), debugstr_w(dest));
1107 
1108  if (!CopyFileW( file->TargetPath, dest, TRUE ))
1109  {
1110  WARN("Failed to copy file %s -> %s (%u)\n",
1111  debugstr_w(file->TargetPath), debugstr_w(dest), GetLastError());
1112  }
1113 
1114  FIXME("We should track these duplicate files as well\n");
1115 
1116  uirow = MSI_CreateRecord( 9 );
1117  MSI_RecordSetStringW( uirow, 1, MSI_RecordGetString( row, 1 ) );
1118  MSI_RecordSetInteger( uirow, 6, file->FileSize );
1119  MSI_RecordSetStringW( uirow, 9, MSI_RecordGetString( row, 5 ) );
1121  msiobj_release( &uirow->hdr );
1122 
1123  msi_free(dest);
1124  return ERROR_SUCCESS;
1125 }
1126 
1128 {
1129  static const WCHAR query[] = {
1130  'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
1131  '`','D','u','p','l','i','c','a','t','e','F','i','l','e','`',0};
1132  MSIQUERY *view;
1133  UINT rc;
1134 
1135  rc = MSI_DatabaseOpenViewW(package->db, query, &view);
1136  if (rc != ERROR_SUCCESS)
1137  return ERROR_SUCCESS;
1138 
1140  msiobj_release(&view->hdr);
1141  return rc;
1142 }
1143 
1145 {
1146  MSIPACKAGE *package = param;
1147  LPWSTR dest;
1148  LPCWSTR file_key, component;
1149  MSICOMPONENT *comp;
1150  MSIRECORD *uirow;
1151  MSIFILE *file;
1152 
1153  component = MSI_RecordGetString( row, 2 );
1154  comp = msi_get_loaded_component( package, component );
1155  if (!comp)
1156  return ERROR_SUCCESS;
1157 
1158  comp->Action = msi_get_component_action( package, comp );
1159  if (comp->Action != INSTALLSTATE_ABSENT)
1160  {
1161  TRACE("component not scheduled for removal %s\n", debugstr_w(component));
1162  return ERROR_SUCCESS;
1163  }
1164 
1165  file_key = MSI_RecordGetString( row, 3 );
1166  if (!file_key)
1167  {
1168  ERR("Unable to get file key\n");
1169  return ERROR_FUNCTION_FAILED;
1170  }
1171 
1172  file = msi_get_loaded_file( package, file_key );
1173  if (!file)
1174  {
1175  ERR("Original file unknown %s\n", debugstr_w(file_key));
1176  return ERROR_SUCCESS;
1177  }
1178 
1179  dest = get_duplicate_filename( package, row, file_key, file->TargetPath );
1180  if (!dest)
1181  {
1182  WARN("Unable to get duplicate filename\n");
1183  return ERROR_SUCCESS;
1184  }
1185 
1186  TRACE("Removing duplicate %s of %s\n", debugstr_w(dest), debugstr_w(file->TargetPath));
1187 
1188  if (!DeleteFileW( dest ))
1189  {
1190  WARN("Failed to delete duplicate file %s (%u)\n", debugstr_w(dest), GetLastError());
1191  }
1192 
1193  uirow = MSI_CreateRecord( 9 );
1194  MSI_RecordSetStringW( uirow, 1, MSI_RecordGetString( row, 1 ) );
1195  MSI_RecordSetStringW( uirow, 9, MSI_RecordGetString( row, 5 ) );
1197  msiobj_release( &uirow->hdr );
1198 
1199  msi_free(dest);
1200  return ERROR_SUCCESS;
1201 }
1202 
1204 {
1205  static const WCHAR query[] = {
1206  'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
1207  '`','D','u','p','l','i','c','a','t','e','F','i','l','e','`',0};
1208  MSIQUERY *view;
1209  UINT rc;
1210 
1211  rc = MSI_DatabaseOpenViewW( package->db, query, &view );
1212  if (rc != ERROR_SUCCESS)
1213  return ERROR_SUCCESS;
1214 
1216  msiobj_release( &view->hdr );
1217  return rc;
1218 }
1219 
1220 static BOOL verify_comp_for_removal(MSICOMPONENT *comp, UINT install_mode)
1221 {
1222  /* special case */
1223  if (comp->Action != INSTALLSTATE_SOURCE &&
1225  (install_mode == msidbRemoveFileInstallModeOnRemove ||
1226  install_mode == msidbRemoveFileInstallModeOnBoth)) return TRUE;
1227 
1228  switch (comp->Action)
1229  {
1230  case INSTALLSTATE_LOCAL:
1231  case INSTALLSTATE_SOURCE:
1232  if (install_mode == msidbRemoveFileInstallModeOnInstall ||
1233  install_mode == msidbRemoveFileInstallModeOnBoth) return TRUE;
1234  break;
1235  case INSTALLSTATE_ABSENT:
1236  if (install_mode == msidbRemoveFileInstallModeOnRemove ||
1237  install_mode == msidbRemoveFileInstallModeOnBoth) return TRUE;
1238  break;
1239  default: break;
1240  }
1241  return FALSE;
1242 }
1243 
1245 {
1246  MSIPACKAGE *package = param;
1247  MSICOMPONENT *comp;
1248  MSIRECORD *uirow;
1249  LPCWSTR component, dirprop;
1250  UINT install_mode;
1251  LPWSTR dir = NULL, path = NULL, filename = NULL;
1252  DWORD size;
1254 
1255  component = MSI_RecordGetString(row, 2);
1256  dirprop = MSI_RecordGetString(row, 4);
1257  install_mode = MSI_RecordGetInteger(row, 5);
1258 
1259  comp = msi_get_loaded_component(package, component);
1260  if (!comp)
1261  return ERROR_SUCCESS;
1262 
1263  comp->Action = msi_get_component_action( package, comp );
1264  if (!verify_comp_for_removal(comp, install_mode))
1265  {
1266  TRACE("Skipping removal due to install mode\n");
1267  return ERROR_SUCCESS;
1268  }
1269  if (comp->assembly && !comp->assembly->application)
1270  {
1271  return ERROR_SUCCESS;
1272  }
1273  if (comp->Attributes & msidbComponentAttributesPermanent)
1274  {
1275  TRACE("permanent component, not removing file\n");
1276  return ERROR_SUCCESS;
1277  }
1278 
1279  dir = msi_dup_property(package->db, dirprop);
1280  if (!dir)
1281  {
1282  WARN("directory property has no value\n");
1283  return ERROR_SUCCESS;
1284  }
1285  size = 0;
1286  if ((filename = strdupW( MSI_RecordGetString(row, 3) )))
1287  {
1289  size = lstrlenW( filename );
1290  }
1291  size += lstrlenW(dir) + 2;
1292  path = msi_alloc(size * sizeof(WCHAR));
1293  if (!path)
1294  {
1296  goto done;
1297  }
1298 
1299  if (filename)
1300  {
1301  lstrcpyW(path, dir);
1304 
1305  TRACE("Deleting misc file: %s\n", debugstr_w(path));
1306  DeleteFileW(path);
1307  }
1308  else
1309  {
1310  TRACE("Removing misc directory: %s\n", debugstr_w(dir));
1312  }
1313 
1314 done:
1315  uirow = MSI_CreateRecord( 9 );
1316  MSI_RecordSetStringW( uirow, 1, MSI_RecordGetString(row, 1) );
1317  MSI_RecordSetStringW( uirow, 9, dir );
1319  msiobj_release( &uirow->hdr );
1320 
1321  msi_free(filename);
1322  msi_free(path);
1323  msi_free(dir);
1324  return ret;
1325 }
1326 
1328 {
1329  FolderList *fl;
1330 
1331  LIST_FOR_EACH_ENTRY( fl, &folder->children, FolderList, entry )
1332  {
1333  remove_folder( fl->folder );
1334  }
1335  if (!folder->persistent && folder->State != FOLDER_STATE_REMOVED)
1336  {
1337  if (RemoveDirectoryW( folder->ResolvedTarget )) folder->State = FOLDER_STATE_REMOVED;
1338  }
1339 }
1340 
1342 {
1343  static const WCHAR query[] = {
1344  'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
1345  '`','R','e','m','o','v','e','F','i','l','e','`',0};
1346  MSIQUERY *view;
1347  MSICOMPONENT *comp;
1348  MSIFILE *file;
1349  UINT r;
1350 
1351  r = MSI_DatabaseOpenViewW(package->db, query, &view);
1352  if (r == ERROR_SUCCESS)
1353  {
1355  msiobj_release(&view->hdr);
1356  if (r != ERROR_SUCCESS)
1357  return r;
1358  }
1359 
1360  LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
1361  {
1362  MSIRECORD *uirow;
1363  VS_FIXEDFILEINFO *ver;
1364 
1365  comp = file->Component;
1366  msi_file_update_ui( package, file, szRemoveFiles );
1367 
1368  comp->Action = msi_get_component_action( package, comp );
1369  if (comp->Action != INSTALLSTATE_ABSENT || comp->Installed == INSTALLSTATE_SOURCE)
1370  continue;
1371 
1372  if (comp->assembly && !comp->assembly->application)
1373  continue;
1374 
1376  {
1377  TRACE("permanent component, not removing file\n");
1378  continue;
1379  }
1380 
1381  if (file->Version)
1382  {
1383  ver = msi_get_disk_file_version( file->TargetPath );
1384  if (ver && msi_compare_file_versions( ver, file->Version ) > 0)
1385  {
1386  TRACE("newer version detected, not removing file\n");
1387  msi_free( ver );
1388  continue;
1389  }
1390  msi_free( ver );
1391  }
1392 
1393  if (file->state == msifs_installed)
1394  WARN("removing installed file %s\n", debugstr_w(file->TargetPath));
1395 
1396  TRACE("removing %s\n", debugstr_w(file->File) );
1397 
1399  if (!DeleteFileW( file->TargetPath ))
1400  {
1401  WARN("failed to delete %s (%u)\n", debugstr_w(file->TargetPath), GetLastError());
1402  }
1403  file->state = msifs_missing;
1404 
1405  uirow = MSI_CreateRecord( 9 );
1406  MSI_RecordSetStringW( uirow, 1, file->FileName );
1407  MSI_RecordSetStringW( uirow, 9, comp->Directory );
1409  msiobj_release( &uirow->hdr );
1410  }
1411 
1412  LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
1413  {
1414  comp->Action = msi_get_component_action( package, comp );
1415  if (comp->Action != INSTALLSTATE_ABSENT) continue;
1416 
1418  {
1419  TRACE("permanent component, not removing directory\n");
1420  continue;
1421  }
1422  if (comp->assembly && !comp->assembly->application)
1423  msi_uninstall_assembly( package, comp );
1424  else
1425  {
1426  MSIFOLDER *folder = msi_get_loaded_folder( package, comp->Directory );
1427  remove_folder( folder );
1428  }
1429  }
1430  return ERROR_SUCCESS;
1431 }
BOOL WINAPI SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
Definition: fileinfo.c:944
#define ERROR_USER_MAPPED_FILE
Definition: winerror.h:727
LPWSTR dest
Definition: files.c:671
BOOL WINAPI FindNextFileW(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:382
enum _msi_file_state msi_file_state
static void schedule_install_files(MSIPACKAGE *package)
Definition: files.c:177
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define TRUE
Definition: types.h:120
UINT msi_load_media_info(MSIPACKAGE *package, UINT Sequence, MSIMEDIAINFO *mi)
Definition: media.c:681
UINT MSI_RecordSetStringW(MSIRECORD *, UINT, LPCWSTR) DECLSPEC_HIDDEN
Definition: record.c:649
Definition: fci.c:115
BOOL extracted
Definition: msipriv.h:607
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
#define ERROR_SUCCESS
Definition: deptool.c:10
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:81
MSIASSEMBLY * assembly
Definition: msipriv.h:517
#define MOVEFILE_REPLACE_EXISTING
Definition: filesup.h:28
GLsizei const GLchar ** path
Definition: glext.h:7234
static WCHAR * strdupW(const WCHAR *src)
Definition: main.c:92
MSIOBJECTHDR hdr
Definition: msipriv.h:141
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
WINE_UNICODE_INLINE WCHAR * strchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:248
int msi_get_property_int(MSIDATABASE *package, LPCWSTR prop, int def) DECLSPEC_HIDDEN
Definition: package.c:2392
__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:733
uint8_t entry
Definition: isohybrid.c:63
#define WARN(fmt,...)
Definition: debug.h:111
UINT MSI_RecordGetStringW(MSIRECORD *, UINT, LPWSTR, LPDWORD) DECLSPEC_HIDDEN
Definition: record.c:487
BOOL msi_is_global_assembly(MSICOMPONENT *comp)
Definition: action.c:2193
LPWSTR sourcename
Definition: files.c:668
DWORD dwFileVersionLS
Definition: compat.h:552
__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:1064
static BOOL msi_move_file(LPCWSTR source, LPCWSTR dest, int options)
Definition: files.c:674
static const WCHAR szRemoveFiles[]
Definition: msipriv.h:1136
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
void msi_ui_progress(MSIPACKAGE *package, int a, int b, int c, int d)
Definition: action.c:740
LPWSTR File
Definition: msipriv.h:583
WCHAR * msi_get_assembly_path(MSIPACKAGE *package, const WCHAR *displayname)
Definition: assembly.c:267
static MONITORINFO mi
Definition: win.c:7331
INSTALLSTATE Action
Definition: msipriv.h:510
BOOL msi_create_full_path(const WCHAR *path)
Definition: action.c:700
INSTALLSTATE msi_get_component_action(MSIPACKAGE *package, MSICOMPONENT *comp)
Definition: action.c:755
WCHAR * msi_resolve_source_folder(MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder)
Definition: install.c:351
UINT ACTION_PatchFiles(MSIPACKAGE *package)
Definition: files.c:577
static const WCHAR szInstallFiles[]
Definition: msipriv.h:1134
const char * filename
Definition: ioapi.h:135
UINT ready_media(MSIPACKAGE *package, BOOL compressed, MSIMEDIAINFO *mi)
Definition: media.c:844
#define lstrlenW
Definition: compat.h:407
WCHAR * msi_font_version_from_file(const WCHAR *filename)
Definition: font.c:199
struct list files
Definition: msipriv.h:394
static void * msi_realloc(void *mem, size_t len) __WINE_ALLOC_SIZE(2)
Definition: msipriv.h:1216
MSIFILE * File
Definition: msipriv.h:603
static void * msi_alloc_zero(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1210
#define lstrcpynW
Definition: compat.h:397
LPWSTR destname
Definition: files.c:669
__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:471
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
BOOL registered
Definition: msipriv.h:197
UINT MSI_RecordSetInteger(MSIRECORD *, UINT, int) DECLSPEC_HIDDEN
Definition: record.c:328
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985
_In_ FLONG fl
Definition: winddi.h:1279
#define ERROR_ACCESS_DENIED
Definition: compat.h:87
LPWSTR WINAPI PathAddBackslashW(LPWSTR lpszPath)
Definition: path.c:289
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOL MSI_RecordIsNull(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:369
static BOOL is_obsoleted_by_patch(MSIPACKAGE *package, MSIFILE *file)
Definition: files.c:77
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:802
#define debugstr_w
Definition: kernel32.h:32
INT MSI_ProcessMessage(MSIPACKAGE *, INSTALLMESSAGE, MSIRECORD *) DECLSPEC_HIDDEN
Definition: package.c:1946
#define FIXME(fmt,...)
Definition: debug.h:110
BOOL WINAPI MoveFileW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName)
Definition: move.c:1044
UINT ACTION_InstallFiles(MSIPACKAGE *package)
Definition: files.c:354
static PVOID ptr
Definition: dispmode.c:27
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
WCHAR * path
Definition: msipriv.h:609
IAssemblyEnum * msi_create_assembly_enum(MSIPACKAGE *package, const WCHAR *displayname)
Definition: assembly.c:292
smooth NULL
Definition: ftsmooth.c:416
#define MOVEFILE_DELAY_UNTIL_REBOOT
Definition: winbase.h:381
#define is_dot_dir(x)
Definition: files.c:663
const WCHAR * MSI_RecordGetString(const MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:482
unsigned int dir
Definition: maze.c:112
static BOOL add_wildcard(FILE_LIST *files, LPWSTR source, LPWSTR dest)
Definition: files.c:744
struct CFFOLDER folder
Definition: fdi.c:110
static void remove_folder(MSIFOLDER *folder)
Definition: files.c:1327
BOOL WINAPI RemoveDirectoryW(IN LPCWSTR lpPathName)
Definition: dir.c:732
UINT ACTION_RemoveDuplicateFiles(MSIPACKAGE *package)
Definition: files.c:1203
int options
Definition: main.c:106
UINT ACTION_MoveFiles(MSIPACKAGE *package)
Definition: files.c:995
#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:674
__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:282
GLfloat f
Definition: glext.h:7540
#define TRACE(s)
Definition: solgame.cpp:4
#define MSICABEXTRACT_FILEEXTRACTED
Definition: msipriv.h:1055
GLsizeiptr size
Definition: glext.h:5919
LPWSTR Directory
Definition: msipriv.h:504
static LPWSTR wildcard_to_file(LPWSTR wildcard, LPWSTR filename)
Definition: files.c:709
__wchar_t WCHAR
Definition: xmlstorage.h:180
static msi_file_state calculate_install_state(MSIPACKAGE *package, MSIFILE *file)
Definition: files.c:88
LONG HRESULT
Definition: typedefs.h:77
BOOL WINAPI CopyFileW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN BOOL bFailIfExists)
Definition: copy.c:439
#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:551
MSIDATABASE * db
Definition: msipriv.h:386
MSIFOLDER * msi_get_loaded_folder(MSIPACKAGE *package, const WCHAR *dir)
Definition: action.c:685
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
static const WCHAR szMsi[]
Definition: msipriv.h:1119
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:242
BOOL msi_file_hash_matches(MSIFILE *file)
Definition: action.c:2098
LPWSTR Component
Definition: msipriv.h:502
MSICOMPONENT * msi_get_loaded_component(MSIPACKAGE *package, const WCHAR *Component)
Definition: action.c:652
struct list components
Definition: msipriv.h:392
static void msi_file_update_ui(MSIPACKAGE *package, MSIFILE *f, const WCHAR *action)
Definition: files.c:53
int ret
MSIRECORD * MSI_CreateRecord(UINT) DECLSPEC_HIDDEN
Definition: record.c:79
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
UINT msi_install_assembly(MSIPACKAGE *package, MSICOMPONENT *comp)
Definition: assembly.c:444
BOOL installed
Definition: msipriv.h:495
int msi_compare_font_versions(const WCHAR *ver1, const WCHAR *ver2)
Definition: action.c:2072
static int state
Definition: maze.c:121
static BOOL is_registered_patch_media(MSIPACKAGE *package, UINT disk_id)
Definition: files.c:66
static BOOL move_files_wildcard(LPWSTR source, LPWSTR dest, int options)
Definition: files.c:795
GLenum GLsizei len
Definition: glext.h:6722
Definition: _list.h:228
#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:489
LPWSTR source
Definition: files.c:670
#define E_NOT_SUFFICIENT_BUFFER
Definition: winerror.h:2345
#define strcmpiW(s1, s2)
Definition: unicode.h:39
WINE_UNICODE_INLINE WCHAR * strrchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:254
const WCHAR * msi_get_target_folder(MSIPACKAGE *package, const WCHAR *name)
Definition: install.c:209
int MSI_RecordGetInteger(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:245
#define ERR(fmt,...)
Definition: debug.h:109
UINT ACTION_RemoveFiles(MSIPACKAGE *package)
Definition: files.c:1341
void msi_reduce_to_long_filename(WCHAR *filename)
Definition: files.c:863
LPWSTR application
Definition: msipriv.h:491
__WINE_SERVER_LIST_INLINE int list_empty(const struct list *list)
Definition: list.h:143
#define S_OK
Definition: intsafe.h:59
WINE_UNICODE_INLINE WCHAR * strcpyW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:219
MSICOMPONENT * Component
Definition: msipriv.h:584
const WCHAR * action
Definition: action.c:7783
const char cursor[]
Definition: icontest.c:13
#define lstrcpyW
Definition: compat.h:406
VS_FIXEDFILEINFO * msi_get_disk_file_version(LPCWSTR filename)
Definition: action.c:2028
UINT ACTION_DuplicateFiles(MSIPACKAGE *package)
Definition: files.c:1127
Definition: services.c:325
GLenum GLenum dst
Definition: glext.h:6340
static UINT copy_file(MSIFILE *file, LPWSTR source)
Definition: files.c:194
int msi_compare_file_versions(VS_FIXEDFILEINFO *fi, const WCHAR *version)
Definition: action.c:2059
#define MSICABEXTRACT_BEGINEXTRACT
Definition: msipriv.h:1054
unsigned int UINT
Definition: ndis.h:50
struct list entry
Definition: files.c:667
static WCHAR * get_duplicate_filename(MSIPACKAGE *package, MSIRECORD *row, const WCHAR *file_key, const WCHAR *src)
Definition: files.c:1012
static const WCHAR szBackSlash[]
Definition: msipriv.h:1111
WCHAR * msi_resolve_file_source(MSIPACKAGE *package, MSIFILE *file)
Definition: files.c:326
__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
INSTALLSTATE Installed
Definition: msipriv.h:508
static UINT copy_install_file(MSIPACKAGE *package, MSIFILE *file, LPWSTR source)
Definition: files.c:206
BOOL msi_cabextract(MSIPACKAGE *package, MSIMEDIAINFO *mi, LPVOID data)
Definition: media.c:653
static BOOL msi_free(void *mem)
Definition: msipriv.h:1227
WCHAR * msi_create_temp_file(MSIDATABASE *db)
Definition: custom.c:201
Definition: name.c:36
WINE_UNICODE_INLINE int strcmpW(const WCHAR *str1, const WCHAR *str2)
Definition: unicode.h:229
static MSIFILEPATCH * find_filepatch(MSIPACKAGE *package, UINT disk_id, const WCHAR *key)
Definition: files.c:459
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:1204
static UINT ITERATE_MoveFiles(MSIRECORD *rec, LPVOID param)
Definition: files.c:869
#define HIWORD(l)
Definition: typedefs.h:246
static void free_file_entry(FILE_LIST *file)
Definition: files.c:726
static IOleDocumentView * view
Definition: activex.c:1749
WCHAR * msi_build_directory_name(DWORD count,...)
Definition: action.c:2164
BOOL WINAPI MoveFileExW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName OPTIONAL, IN DWORD dwFlags)
Definition: move.c:1060
DWORD msi_get_disk_file_size(LPCWSTR filename)
Definition: action.c:2084
static UINT ITERATE_RemoveFiles(MSIRECORD *row, LPVOID param)
Definition: files.c:1244
static char * dest
Definition: rtl.c:135
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
void msi_free_media_info(MSIMEDIAINFO *mi)
Definition: media.c:662
#define ERROR_ALREADY_EXISTS
Definition: disk.h:80
WINE_DEFAULT_DEBUG_CHANNEL(advpack)
INT Attributes
Definition: msipriv.h:591
GLfloat GLfloat p
Definition: glext.h:8902
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define LIST_ENTRY(type)
Definition: queue.h:175
UINT MSI_IterateRecords(MSIQUERY *, LPDWORD, record_func, LPVOID) DECLSPEC_HIDDEN
Definition: msiquery.c:168
struct list filepatches
Definition: msipriv.h:395
static UINT ITERATE_RemoveDuplicateFiles(MSIRECORD *row, LPVOID param)
Definition: files.c:1144
LPWSTR TargetPath
Definition: msipriv.h:594
static const WCHAR szInstalled[]
Definition: msipriv.h:1122
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:527
struct list patches
Definition: msipriv.h:391
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
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:295
Definition: path.c:42
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
static BOOL verify_comp_for_removal(MSICOMPONENT *comp, UINT install_mode)
Definition: files.c:1220
Definition: fci.c:126
unsigned char need_reboot_at_end
Definition: msipriv.h:447
LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop) DECLSPEC_HIDDEN
Definition: package.c:2370
static UINT msi_create_directory(MSIPACKAGE *package, const WCHAR *dir)
Definition: files.c:265
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
static UINT patch_file(MSIPACKAGE *package, MSIFILEPATCH *patch)
Definition: files.c:505
UINT MSI_DatabaseOpenViewW(MSIDATABASE *, LPCWSTR, MSIQUERY **) DECLSPEC_HIDDEN
Definition: msiquery.c:111
GLuint const GLchar * name
Definition: glext.h:6031