ReactOS 0.4.15-dev-7788-g1ad9096
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{
58 return handle;
59}
60
61static BOOL msi_copy_file( MSIPACKAGE *package, const WCHAR *src, const WCHAR *dst, BOOL fail_if_exists )
62{
63 BOOL ret;
65 ret = CopyFileW( src, dst, fail_if_exists );
67 return ret;
68}
69
71{
72 BOOL ret;
76 return ret;
77}
78
79static BOOL msi_create_directory( MSIPACKAGE *package, const WCHAR *path )
80{
81 BOOL ret;
85 return ret;
86}
87
89{
90 BOOL ret;
94 return ret;
95}
96
98{
99 BOOL ret;
101 ret = SetFileAttributesW( filename, attrs );
102 msi_revert_fs_redirection( package );
103 return ret;
104}
105
107{
108 DWORD attrs;
110 attrs = GetFileAttributesW( path );
111 msi_revert_fs_redirection( package );
112 return attrs;
113}
114
116{
120 msi_revert_fs_redirection( package );
121 return handle;
122}
123
125{
126 BOOL ret;
129 msi_revert_fs_redirection( package );
130 return ret;
131}
132
133BOOL msi_move_file( MSIPACKAGE *package, const WCHAR *from, const WCHAR *to, DWORD flags )
134{
135 BOOL ret;
137 ret = MoveFileExW( from, to, flags );
138 msi_revert_fs_redirection( package );
139 return ret;
140}
141
142static BOOL msi_apply_filepatch( MSIPACKAGE *package, const WCHAR *patch, const WCHAR *old, const WCHAR *new )
143{
144 BOOL ret;
146 ret = ApplyPatchToFileW( patch, old, new, 0 );
147 msi_revert_fs_redirection( package );
148 return ret;
149}
150
152{
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;
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
242static 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
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
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 }
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
467static UINT create_directory( MSIPACKAGE *package, const WCHAR *dir )
468{
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 );
477 {
478 msi_create_full_path( package, install_path );
480 }
481 return ERROR_SUCCESS;
482}
483
484static MSIFILE *find_file( MSIPACKAGE *package, UINT disk_id, const WCHAR *filename )
485{
486 MSIFILE *file;
487
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{
559 UINT rc = ERROR_SUCCESS;
560 MSIFILE *file;
561
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
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 {
601
602 data.mi = mi;
603 data.package = package;
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);
631 goto done;
632 }
633 if (!is_global_assembly) file->state = msifs_installed;
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 }
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
661done:
663 return rc;
664}
665
666static MSIFILEPATCH *find_filepatch( MSIPACKAGE *package, UINT disk_id, const WCHAR *key )
667{
668 MSIFILEPATCH *patch;
669
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
712static UINT patch_file( MSIPACKAGE *package, MSIFILEPATCH *patch )
713{
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 );
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 )))
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),
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;
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
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
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
868done:
870 return rc;
871}
872
873#define is_dot_dir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))))
874
875typedef struct
876{
877 struct list entry;
882} FILE_LIST;
883
884static 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
919static 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
945{
946 while (!list_empty(&list->entry))
947 {
949
952 }
953}
954
955static 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
1064 }
1065
1066 res = TRUE;
1067
1068done:
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
1189done:
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);
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
1219 msiobj_release(&view->hdr);
1220 return rc;
1221}
1222
1223static 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 {
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
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:
1440 if (install_mode == msidbRemoveFileInstallModeOnInstall ||
1441 install_mode == msidbRemoveFileInstallModeOnBoth) return TRUE;
1442 break;
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;
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
1522done:
1523 uirow = MSI_CreateRecord( 9 );
1525 MSI_RecordSetStringW( uirow, 9, dir );
1527 msiobj_release( &uirow->hdr );
1528
1530 msi_free(path);
1531 msi_free(dir);
1532 return ret;
1533}
1534
1536{
1537 FolderList *fl;
1538
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
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 );
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
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}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
static int state
Definition: maze.c:121
unsigned int dir
Definition: maze.c:112
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
static WCHAR * strdupW(const WCHAR *src)
Definition: main.c:92
void user(int argc, const char *argv[])
Definition: cmds.c:1350
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static int list_empty(struct list_entry *head)
Definition: list.h:58
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
static void list_init(struct list_entry *head)
Definition: list.h:51
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
Definition: list.h:37
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
#define wcschr
Definition: compat.h:17
#define wcsrchr
Definition: compat.h:16
#define OPEN_EXISTING
Definition: compat.h:775
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define GENERIC_READ
Definition: compat.h:135
#define CreateFileW
Definition: compat.h:741
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define lstrcpyW
Definition: compat.h:749
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define FILE_SHARE_READ
Definition: compat.h:136
#define wcsicmp
Definition: compat.h:15
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
static const WCHAR version[]
Definition: asmname.c:66
BOOL WINAPI CopyFileW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN BOOL bFailIfExists)
Definition: copy.c:439
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
BOOL WINAPI CreateDirectoryW(IN LPCWSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:90
BOOL WINAPI RemoveDirectoryW(IN LPCWSTR lpPathName)
Definition: dir.c:732
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:652
BOOL WINAPI SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
Definition: fileinfo.c:794
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
BOOL WINAPI FindNextFileW(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:382
BOOL WINAPI MoveFileExW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName OPTIONAL, IN DWORD dwFlags)
Definition: move.c:1120
INSTALLSTATE msi_get_component_action(MSIPACKAGE *package, MSICOMPONENT *comp)
Definition: action.c:611
int msi_compare_file_versions(VS_FIXEDFILEINFO *fi, const WCHAR *version)
Definition: action.c:1930
const WCHAR * action
Definition: action.c:7479
BOOL msi_is_global_assembly(MSICOMPONENT *comp)
Definition: action.c:2037
UINT msi_set_sourcedir_props(MSIPACKAGE *package, BOOL replace)
Definition: action.c:354
MSIFOLDER * msi_get_loaded_folder(MSIPACKAGE *package, const WCHAR *dir)
Definition: action.c:585
int msi_compare_font_versions(const WCHAR *ver1, const WCHAR *ver2)
Definition: action.c:1943
void msi_ui_progress(MSIPACKAGE *package, int a, int b, int c, int d)
Definition: action.c:596
MSICOMPONENT * msi_get_loaded_component(MSIPACKAGE *package, const WCHAR *Component)
Definition: action.c:552
WCHAR *WINAPIV msi_build_directory_name(DWORD count,...)
Definition: action.c:2008
MSIFILE * msi_get_loaded_file(MSIPACKAGE *package, const WCHAR *key)
Definition: action.c:574
UINT msi_schedule_action(MSIPACKAGE *package, UINT script, const WCHAR *action)
Definition: custom.c:90
WCHAR * msi_create_temp_file(MSIDATABASE *db)
Definition: custom.c:215
static BOOL is_registered_patch_media(MSIPACKAGE *package, UINT disk_id)
Definition: files.c:255
BOOL msi_set_file_attributes(MSIPACKAGE *package, const WCHAR *filename, DWORD attrs)
Definition: files.c:97
BOOL msi_create_full_path(MSIPACKAGE *package, const WCHAR *path)
Definition: files.c:202
BOOL msi_remove_directory(MSIPACKAGE *package, const WCHAR *path)
Definition: files.c:88
HANDLE msi_create_file(MSIPACKAGE *package, const WCHAR *filename, DWORD access, DWORD sharing, DWORD creation, DWORD flags)
Definition: files.c:51
static WCHAR * get_duplicate_filename(MSIPACKAGE *package, MSIRECORD *row, const WCHAR *file_key, const WCHAR *src)
Definition: files.c:1223
DWORD msi_get_file_version_info(MSIPACKAGE *package, const WCHAR *path, DWORD buflen, BYTE *buffer)
Definition: files.c:151
UINT ACTION_InstallFiles(MSIPACKAGE *package)
Definition: files.c:556
UINT ACTION_RemoveFiles(MSIPACKAGE *package)
Definition: files.c:1549
static MSIFILE * find_file(MSIPACKAGE *package, UINT disk_id, const WCHAR *filename)
Definition: files.c:484
static UINT ITERATE_MoveFiles(MSIRECORD *rec, LPVOID param)
Definition: files.c:1080
BOOL msi_delete_file(MSIPACKAGE *package, const WCHAR *filename)
Definition: files.c:70
HANDLE msi_find_first_file(MSIPACKAGE *package, const WCHAR *filename, WIN32_FIND_DATAW *data)
Definition: files.c:115
static void free_file_entry(FILE_LIST *file)
Definition: files.c:937
static UINT patch_assembly(MSIPACKAGE *package, MSIASSEMBLY *assembly, MSIFILEPATCH *patch)
Definition: files.c:734
static void free_list(FILE_LIST *list)
Definition: files.c:944
static UINT ITERATE_RemoveDuplicateFiles(MSIRECORD *row, LPVOID param)
Definition: files.c:1353
WCHAR * msi_resolve_file_source(MSIPACKAGE *package, MSIFILE *file)
Definition: files.c:528
void msi_reduce_to_long_filename(WCHAR *filename)
Definition: files.c:1074
#define is_dot_dir(x)
Definition: files.c:873
static UINT patch_file(MSIPACKAGE *package, MSIFILEPATCH *patch)
Definition: files.c:712
static BOOL msi_apply_filepatch(MSIPACKAGE *package, const WCHAR *patch, const WCHAR *old, const WCHAR *new)
Definition: files.c:142
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
static void msi_file_update_ui(MSIPACKAGE *package, MSIFILE *f, const WCHAR *action)
Definition: files.c:242
static UINT ITERATE_DuplicateFiles(MSIRECORD *row, LPVOID param)
Definition: files.c:1275
static UINT copy_file(MSIPACKAGE *package, MSIFILE *file, WCHAR *source)
Definition: files.c:396
BOOL msi_move_file(MSIPACKAGE *package, const WCHAR *from, const WCHAR *to, DWORD flags)
Definition: files.c:133
static WCHAR * wildcard_to_file(const WCHAR *wildcard, const WCHAR *filename)
Definition: files.c:919
VS_FIXEDFILEINFO * msi_get_disk_file_version(MSIPACKAGE *package, const WCHAR *filename)
Definition: files.c:161
static UINT ITERATE_RemoveFiles(MSIRECORD *row, LPVOID param)
Definition: files.c:1452
static MSIFILEPATCH * find_filepatch(MSIPACKAGE *package, UINT disk_id, const WCHAR *key)
Definition: files.c:666
UINT ACTION_PatchFiles(MSIPACKAGE *package)
Definition: files.c:784
static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR filename, DWORD action, LPWSTR *path, DWORD *attrs, PVOID user)
Definition: files.c:497
DWORD msi_get_file_attributes(MSIPACKAGE *package, const WCHAR *path)
Definition: files.c:106
BOOL msi_find_next_file(MSIPACKAGE *package, HANDLE handle, WIN32_FIND_DATAW *data)
Definition: files.c:124
static UINT create_directory(MSIPACKAGE *package, const WCHAR *dir)
Definition: files.c:467
static BOOL msi_create_directory(MSIPACKAGE *package, const WCHAR *path)
Definition: files.c:79
static void schedule_install_files(MSIPACKAGE *package)
Definition: files.c:379
static BOOL file_hash_matches(MSIPACKAGE *package, MSIFILE *file)
Definition: files.c:277
static BOOL msi_copy_file(MSIPACKAGE *package, const WCHAR *src, const WCHAR *dst, BOOL fail_if_exists)
Definition: files.c:61
UINT ACTION_DuplicateFiles(MSIPACKAGE *package)
Definition: files.c:1336
static BOOL add_wildcard(FILE_LIST *files, const WCHAR *source, WCHAR *dest)
Definition: files.c:955
static BOOL is_obsoleted_by_patch(MSIPACKAGE *package, MSIFILE *file)
Definition: files.c:266
DWORD msi_get_disk_file_size(MSIPACKAGE *package, const WCHAR *filename)
Definition: files.c:190
UINT ACTION_MoveFiles(MSIPACKAGE *package)
Definition: files.c:1206
static BOOL patchfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action, LPWSTR *path, DWORD *attrs, PVOID user)
Definition: files.c:678
static UINT copy_install_file(MSIPACKAGE *package, MSIFILE *file, LPWSTR source)
Definition: files.c:408
static void remove_folder(MSIFOLDER *folder)
Definition: files.c:1535
static msi_file_state calculate_install_state(MSIPACKAGE *package, MSIFILE *file)
Definition: files.c:290
static BOOL move_file(MSIPACKAGE *package, const WCHAR *source, const WCHAR *dest, int options)
Definition: files.c:884
UINT ACTION_RemoveDuplicateFiles(MSIPACKAGE *package)
Definition: files.c:1411
WCHAR * msi_get_font_file_version(MSIPACKAGE *package, const WCHAR *filename)
Definition: font.c:186
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:241
WCHAR * msi_resolve_source_folder(MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder)
Definition: install.c:364
const WCHAR * msi_get_target_folder(MSIPACKAGE *package, const WCHAR *name)
Definition: install.c:232
UINT ready_media(MSIPACKAGE *package, BOOL compressed, MSIMEDIAINFO *mi)
Definition: media.c:850
void msi_free_media_info(MSIMEDIAINFO *mi)
Definition: media.c:661
BOOL msi_cabextract(MSIPACKAGE *package, MSIMEDIAINFO *mi, LPVOID data)
Definition: media.c:652
UINT msi_load_media_info(MSIPACKAGE *package, UINT Sequence, MSIMEDIAINFO *mi)
Definition: media.c:689
UINT msi_get_filehash(MSIPACKAGE *package, const WCHAR *path, MSIFILEHASHINFO *hash)
Definition: msi.c:4024
BOOL WINAPI GetFileVersionInfoW(LPCWSTR filename, DWORD handle, DWORD datasize, LPVOID data)
Definition: version.c:845
BOOL WINAPI VerQueryValueW(LPCVOID pBlock, LPCWSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen)
Definition: version.c:1049
DWORD WINAPI GetFileVersionInfoSizeW(LPCWSTR filename, LPDWORD handle)
Definition: version.c:611
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
UINT WINAPI GetTempFileNameW(IN LPCWSTR lpPathName, IN LPCWSTR lpPrefixString, IN UINT uUnique, OUT LPWSTR lpTempFileName)
Definition: filename.c:84
#define MOVEFILE_REPLACE_EXISTING
Definition: filesup.h:28
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLsizeiptr size
Definition: glext.h:5919
GLuint res
Definition: glext.h:9613
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
GLfloat f
Definition: glext.h:7540
GLenum GLenum dst
Definition: glext.h:6340
GLbitfield flags
Definition: glext.h:7161
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
GLfloat GLfloat p
Definition: glext.h:8902
GLfloat param
Definition: glext.h:5796
GLenum GLsizei len
Definition: glext.h:6722
const char cursor[]
Definition: icontest.c:13
_Check_return_ _CRTIMP FILE *__cdecl tmpfile(void)
Definition: file.c:3914
#define S_OK
Definition: intsafe.h:52
#define FAILED(hr)
Definition: intsafe.h:51
const char * filename
Definition: ioapi.h:137
uint32_t entry
Definition: isohybrid.c:63
#define debugstr_w
Definition: kernel32.h:32
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define ERROR_ALREADY_EXISTS
Definition: disk.h:80
static PVOID ptr
Definition: dispmode.c:27
static ULONG POBJECT_ATTRIBUTES PIO_STATUS_BLOCK ULONG sharing
Definition: pipe.c:70
static char * dest
Definition: rtl.c:135
UINT msi_uninstall_assembly(MSIPACKAGE *package, MSICOMPONENT *comp)
Definition: assembly.c:456
IAssemblyEnum * msi_create_assembly_enum(MSIPACKAGE *package, const WCHAR *displayname)
Definition: assembly.c:265
WCHAR * msi_get_assembly_path(MSIPACKAGE *package, const WCHAR *displayname)
Definition: assembly.c:240
UINT msi_install_assembly(MSIPACKAGE *package, MSICOMPONENT *comp)
Definition: assembly.c:411
@ INSTALLMESSAGE_ACTIONDATA
Definition: msi.h:103
@ INSTALLSTATE_LOCAL
Definition: msi.h:46
@ INSTALLSTATE_ABSENT
Definition: msi.h:45
@ INSTALLSTATE_SOURCE
Definition: msi.h:47
@ msidbComponentAttributesNeverOverwrite
Definition: msidefs.h:167
@ msidbComponentAttributesPermanent
Definition: msidefs.h:164
@ msidbComponentAttributesSourceOnly
Definition: msidefs.h:160
@ msidbMoveFileOptionsMove
Definition: msidefs.h:210
@ msidbPatchAttributesNonVital
Definition: msidefs.h:43
@ msidbFileAttributesPatchAdded
Definition: msidefs.h:37
@ msidbRemoveFileInstallModeOnBoth
Definition: msidefs.h:231
@ msidbRemoveFileInstallModeOnInstall
Definition: msidefs.h:229
@ msidbRemoveFileInstallModeOnRemove
Definition: msidefs.h:230
#define MSI_INITIAL_MEDIA_TRANSFORM_DISKID
Definition: msipriv.h:84
static void * msi_realloc(void *mem, size_t len) __WINE_ALLOC_SIZE(2)
Definition: msipriv.h:1154
static void * msi_alloc_zero(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1148
UINT MSI_IterateRecords(MSIQUERY *, LPDWORD, record_func, LPVOID) DECLSPEC_HIDDEN
Definition: msiquery.c:163
UINT MSI_RecordGetStringW(MSIRECORD *, UINT, LPWSTR, LPDWORD) DECLSPEC_HIDDEN
static void msi_free(void *mem)
Definition: msipriv.h:1159
@ SCRIPT_INSTALL
Definition: msipriv.h:385
@ SCRIPT_NONE
Definition: msipriv.h:384
int MSI_RecordGetInteger(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:213
UINT MSI_RecordSetInteger(MSIRECORD *, UINT, int) DECLSPEC_HIDDEN
Definition: record.c:280
#define MSICABEXTRACT_BEGINEXTRACT
Definition: msipriv.h:1095
const WCHAR * MSI_RecordGetString(const MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:433
@ FOLDER_STATE_UNINITIALIZED
Definition: msipriv.h:565
@ FOLDER_STATE_REMOVED
Definition: msipriv.h:569
@ FOLDER_STATE_CREATED
Definition: msipriv.h:567
INT MSI_ProcessMessage(MSIPACKAGE *, INSTALLMESSAGE, MSIRECORD *) DECLSPEC_HIDDEN
Definition: package.c:1914
static void * msi_alloc(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1142
MSIRECORD * MSI_CreateRecord(UINT) DECLSPEC_HIDDEN
Definition: record.c:76
static void msi_revert_fs_redirection(MSIPACKAGE *package)
Definition: msipriv.h:1072
static void msi_disable_fs_redirection(MSIPACKAGE *package)
Definition: msipriv.h:1068
int msi_get_property_int(MSIDATABASE *package, LPCWSTR prop, int def) DECLSPEC_HIDDEN
Definition: package.c:2305
LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop) DECLSPEC_HIDDEN
Definition: package.c:2283
BOOL MSI_RecordIsNull(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:321
#define MSICABEXTRACT_FILEEXTRACTED
Definition: msipriv.h:1096
enum _msi_file_state msi_file_state
UINT MSI_DatabaseOpenViewW(MSIDATABASE *, LPCWSTR, MSIQUERY **) DECLSPEC_HIDDEN
UINT MSI_RecordSetStringW(MSIRECORD *, UINT, LPCWSTR) DECLSPEC_HIDDEN
Definition: record.c:597
@ msifs_missing
Definition: msipriv.h:595
@ msifs_skipped
Definition: msipriv.h:599
@ msifs_installed
Definition: msipriv.h:598
@ msifs_present
Definition: msipriv.h:597
@ msifs_hashmatch
Definition: msipriv.h:600
@ msifs_overwrite
Definition: msipriv.h:596
BOOL WINAPI ApplyPatchToFileW(LPCWSTR patch_file, LPCWSTR old_file, LPCWSTR new_file, ULONG apply_flags)
unsigned int UINT
Definition: ndis.h:50
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define L(x)
Definition: ntvdm.h:50
#define PathAddBackslashW
Definition: pathcch.h:301
#define LOWORD(l)
Definition: pedump.c:82
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
__WINE_SERVER_LIST_INLINE void list_add_before(struct list *elem, struct list *to_add)
Definition: list.h:87
__WINE_SERVER_LIST_INLINE void list_add_after(struct list *elem, struct list *to_add)
Definition: list.h:78
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
CardRegion * from
Definition: spigame.cpp:19
LPWSTR sourcename
Definition: files.c:878
LPWSTR source
Definition: files.c:880
struct list entry
Definition: files.c:877
LPWSTR destname
Definition: files.c:879
LPWSTR dest
Definition: files.c:881
Definition: fci.c:127
struct list entry
Definition: fci.c:128
Definition: fci.c:116
Definition: _hash_fun.h:40
Definition: copy.c:22
Definition: list.h:15
Definition: name.c:39
BOOL installed
Definition: msipriv.h:518
LPWSTR application
Definition: msipriv.h:514
LPWSTR Component
Definition: msipriv.h:525
INSTALLSTATE Action
Definition: msipriv.h:533
MSIASSEMBLY * assembly
Definition: msipriv.h:540
INSTALLSTATE Installed
Definition: msipriv.h:531
LPWSTR Directory
Definition: msipriv.h:527
MSIFILE * File
Definition: msipriv.h:626
BOOL extracted
Definition: msipriv.h:630
WCHAR * path
Definition: msipriv.h:632
LPWSTR File
Definition: msipriv.h:606
MSICOMPONENT * Component
Definition: msipriv.h:607
LPWSTR TargetPath
Definition: msipriv.h:617
INT Attributes
Definition: msipriv.h:614
struct list files
Definition: msipriv.h:403
MSIDATABASE * db
Definition: msipriv.h:394
struct list components
Definition: msipriv.h:401
enum script script
Definition: msipriv.h:432
struct list filepatches
Definition: msipriv.h:404
unsigned char need_reboot_at_end
Definition: msipriv.h:469
struct list patches
Definition: msipriv.h:400
BOOL registered
Definition: msipriv.h:209
MSIOBJECTHDR hdr
Definition: msipriv.h:151
DWORD dwFileVersionLS
Definition: compat.h:903
DWORD dwFileVersionMS
Definition: compat.h:902
#define LIST_ENTRY(type)
Definition: queue.h:175
#define new(TYPE, numElems)
Definition: treelist.c:54
#define HIWORD(l)
Definition: typedefs.h:247
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
int ret
static MONITORINFO mi
Definition: win.c:7338
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define INVALID_FILE_SIZE
Definition: winbase.h:548
#define MOVEFILE_DELAY_UNTIL_REBOOT
Definition: winbase.h:400
_In_ FLONG fl
Definition: winddi.h:1279
#define ERROR_INSTALL_FAILURE
Definition: winerror.h:961
#define ERROR_SHARING_VIOLATION
Definition: winerror.h:135
#define E_NOT_SUFFICIENT_BUFFER
Definition: winerror.h:2345
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985
#define ERROR_USER_MAPPED_FILE
Definition: winerror.h:727
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
unsigned char BYTE
Definition: xxhash.c:193