ReactOS 0.4.15-dev-7712-gbbbcd8e
media.c
Go to the documentation of this file.
1/*
2 * Implementation of the Microsoft Installer (msi.dll)
3 *
4 * Copyright 2008 James Hawkins
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#include <stdarg.h>
22
23#define COBJMACROS
24
25#include "windef.h"
26#include "winerror.h"
27#include "wine/debug.h"
28#include "fdi.h"
29#include "msipriv.h"
30#include "winuser.h"
31#include "winreg.h"
32#include "shlwapi.h"
33#include "objidl.h"
34#include "resource.h"
35
37
38/* from msvcrt/fcntl.h */
39#define _O_RDONLY 0
40#define _O_WRONLY 1
41#define _O_RDWR 2
42#define _O_ACCMODE (_O_RDONLY|_O_WRONLY|_O_RDWR)
43#define _O_APPEND 0x0008
44#define _O_RANDOM 0x0010
45#define _O_SEQUENTIAL 0x0020
46#define _O_TEMPORARY 0x0040
47#define _O_NOINHERIT 0x0080
48#define _O_CREAT 0x0100
49#define _O_TRUNC 0x0200
50#define _O_EXCL 0x0400
51#define _O_SHORT_LIVED 0x1000
52#define _O_TEXT 0x4000
53#define _O_BINARY 0x8000
54
56{
58 const WCHAR *p;
59 int len, len2;
60
61 lstrcpyW(root, source_root);
64
66 {
67 WARN( "failed to get volume information for %s (%lu)\n", debugstr_w(root), GetLastError() );
68 return FALSE;
69 }
70
72 len2 = lstrlenW( mi->volume_label );
73 if (len2 > len) return FALSE;
74 p = volume_name + len - len2;
75
76 return !wcsicmp( mi->volume_label, p );
77}
78
80{
82 LPWSTR source_dir;
83 UINT r = IDRETRY;
84
85 source_dir = msi_dup_property(package->db, L"SourceDir");
87
88 while (r == IDRETRY && !source_matches_volume(mi, source_dir))
89 {
92 MSI_RecordSetStringW(record, 2, mi->disk_prompt);
94 }
95
97 msi_free(source_dir);
98
100}
101
103{
104 MSICABINETSTREAM *cab;
105
107 {
108 if (cab->disk_id == disk_id) return cab;
109 }
110 return NULL;
111}
112
114{
115 return msi_alloc(cb);
116}
117
118static void CDECL cabinet_free(void *pv)
119{
120 msi_free(pv);
121}
122
123static INT_PTR CDECL cabinet_open(char *pszFile, int oflag, int pmode)
124{
125 DWORD dwAccess = 0;
126 DWORD dwShareMode = 0;
127 DWORD dwCreateDisposition = OPEN_EXISTING;
128
129 switch (oflag & _O_ACCMODE)
130 {
131 case _O_RDONLY:
132 dwAccess = GENERIC_READ;
133 dwShareMode = FILE_SHARE_READ | FILE_SHARE_DELETE;
134 break;
135 case _O_WRONLY:
136 dwAccess = GENERIC_WRITE;
138 break;
139 case _O_RDWR:
140 dwAccess = GENERIC_READ | GENERIC_WRITE;
142 break;
143 }
144
145 if ((oflag & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL))
146 dwCreateDisposition = CREATE_NEW;
147 else if (oflag & _O_CREAT)
148 dwCreateDisposition = CREATE_ALWAYS;
149
150 return (INT_PTR)CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
151 dwCreateDisposition, 0, NULL);
152}
153
154static UINT CDECL cabinet_read(INT_PTR hf, void *pv, UINT cb)
155{
156 HANDLE handle = (HANDLE)hf;
157 DWORD read;
158
159 if (ReadFile(handle, pv, cb, &read, NULL))
160 return read;
161
162 return 0;
163}
164
165static UINT CDECL cabinet_write(INT_PTR hf, void *pv, UINT cb)
166{
167 HANDLE handle = (HANDLE)hf;
168 DWORD written;
169
170 if (WriteFile(handle, pv, cb, &written, NULL))
171 return written;
172
173 return 0;
174}
175
177{
178 HANDLE handle = (HANDLE)hf;
179 return CloseHandle(handle) ? 0 : -1;
180}
181
182static LONG CDECL cabinet_seek(INT_PTR hf, LONG dist, int seektype)
183{
184 HANDLE handle = (HANDLE)hf;
185 /* flags are compatible and so are passed straight through */
186 return SetFilePointer(handle, dist, NULL, seektype);
187}
188
190{
193};
194
196
197static INT_PTR CDECL cabinet_open_stream( char *pszFile, int oflag, int pmode )
198{
199 MSICABINETSTREAM *cab;
201
203 {
204 WARN("failed to get cabinet stream\n");
205 return -1;
206 }
207 if (cab->storage == package_disk.package->db->storage)
208 {
210 if (r != ERROR_SUCCESS)
211 {
212 WARN("failed to get stream %u\n", r);
213 return -1;
214 }
215 }
216 else /* patch storage */
217 {
218 HRESULT hr;
219 WCHAR *encoded;
220
221 if (!(encoded = encode_streamname( FALSE, cab->stream + 1 )))
222 {
223 WARN("failed to encode stream name\n");
224 return -1;
225 }
226 hr = IStorage_OpenStream( cab->storage, encoded, NULL, STGM_READ|STGM_SHARE_EXCLUSIVE, 0, &stream );
227 msi_free( encoded );
228 if (FAILED(hr))
229 {
230 WARN( "failed to open stream %#lx\n", hr );
231 return -1;
232 }
233 }
234 return (INT_PTR)stream;
235}
236
238{
239 IStream *stm = (IStream *)hf;
240 DWORD read;
241 HRESULT hr;
242
243 hr = IStream_Read( stm, pv, cb, &read );
244 if (hr == S_OK || hr == S_FALSE)
245 return read;
246
247 return 0;
248}
249
251{
252 IStream *stm = (IStream *)hf;
253 IStream_Release( stm );
254 return 0;
255}
256
257static LONG CDECL cabinet_seek_stream( INT_PTR hf, LONG dist, int seektype )
258{
259 IStream *stm = (IStream *)hf;
260 LARGE_INTEGER move;
261 ULARGE_INTEGER newpos;
262 HRESULT hr;
263
264 move.QuadPart = dist;
265 hr = IStream_Seek( stm, move, seektype, &newpos );
266 if (SUCCEEDED(hr))
267 {
268 if (newpos.QuadPart <= MAXLONG) return newpos.QuadPart;
269 ERR("Too big!\n");
270 }
271 return -1;
272}
273
275{
276 MSIRECORD *row;
277
278 row = MSI_QueryGetRecord(package->db, L"SELECT * FROM `Media` WHERE `DiskId` = %d", mi->disk_id);
279 if (!row)
280 {
281 TRACE("Unable to query row\n");
283 }
284
285 mi->disk_prompt = strdupW(MSI_RecordGetString(row, 3));
286 mi->cabinet = strdupW(MSI_RecordGetString(row, 4));
287 mi->volume_label = strdupW(MSI_RecordGetString(row, 5));
288
289 msiobj_release(&row->hdr);
290 return ERROR_SUCCESS;
291}
292
294 PFDINOTIFICATION pfdin)
295{
296 MSICABDATA *data = pfdin->pv;
297 data->mi->is_continuous = FALSE;
298 return 0;
299}
300
302{
303 int len;
304 WCHAR *ret;
305
306 len = lstrlenW(mi->sourcedir) + lstrlenW(mi->cabinet) + 1;
307 if (!(ret = msi_alloc(len * sizeof(WCHAR)))) return NULL;
308 lstrcpyW(ret, mi->sourcedir);
309 lstrcatW(ret, mi->cabinet);
310 return ret;
311}
312
314 PFDINOTIFICATION pfdin)
315{
316 MSICABDATA *data = pfdin->pv;
317 MSIMEDIAINFO *mi = data->mi;
318 LPWSTR cabinet_file = NULL, cab = strdupAtoW(pfdin->psz1);
319 INT_PTR res = -1;
320 UINT rc;
321
322 msi_free(mi->disk_prompt);
323 msi_free(mi->cabinet);
324 msi_free(mi->volume_label);
325 mi->disk_prompt = NULL;
326 mi->cabinet = NULL;
327 mi->volume_label = NULL;
328
329 mi->disk_id++;
330 mi->is_continuous = TRUE;
331
332 rc = msi_media_get_disk_info(data->package, mi);
333 if (rc != ERROR_SUCCESS)
334 {
335 ERR("Failed to get next cabinet information: %d\n", rc);
336 goto done;
337 }
338
339 if (wcsicmp( mi->cabinet, cab ))
340 {
341 char *next_cab;
343
344 WARN("Continuous cabinet %s does not match the next cabinet %s in the media table => use latter one\n", debugstr_w(cab), debugstr_w(mi->cabinet));
345
346 /* Use cabinet name from the media table */
347 next_cab = strdupWtoA(mi->cabinet);
348 /* Modify path to cabinet file with full filename (psz3 points to a 256 bytes buffer that can be modified contrary to psz1 and psz2) */
349 length = strlen(pfdin->psz3) + 1 + strlen(next_cab) + 1;
350 if (length > 256)
351 {
352 WARN( "cannot update next cabinet filename with a string size %lu > 256\n", length );
353 msi_free(next_cab);
354 goto done;
355 }
356 else
357 {
358 strcat(pfdin->psz3, "\\");
359 strcat(pfdin->psz3, next_cab);
360 }
361 /* Path psz3 and cabinet psz1 are concatenated by FDI so just reset psz1 */
362 *pfdin->psz1 = 0;
363 msi_free(next_cab);
364 }
365
366 if (!(cabinet_file = get_cabinet_filename(mi)))
367 goto done;
368
369 TRACE("Searching for %s\n", debugstr_w(cabinet_file));
370
371 res = 0;
372 if (GetFileAttributesW(cabinet_file) == INVALID_FILE_ATTRIBUTES)
373 {
374 if (msi_change_media(data->package, mi) != ERROR_SUCCESS)
375 res = -1;
376 }
377
378done:
379 msi_free(cab);
380 msi_free(cabinet_file);
381 return res;
382}
383
385 PFDINOTIFICATION pfdin )
386{
387 MSICABDATA *data = pfdin->pv;
388 MSIMEDIAINFO *mi = data->mi;
389 UINT rc;
390
391 msi_free( mi->disk_prompt );
392 msi_free( mi->cabinet );
393 msi_free( mi->volume_label );
394 mi->disk_prompt = NULL;
395 mi->cabinet = NULL;
396 mi->volume_label = NULL;
397
398 mi->disk_id++;
399 mi->is_continuous = TRUE;
400
401 rc = msi_media_get_disk_info( data->package, mi );
402 if (rc != ERROR_SUCCESS)
403 {
404 ERR("Failed to get next cabinet information: %u\n", rc);
405 return -1;
406 }
407 package_disk.id = mi->disk_id;
408
409 TRACE("next cabinet is %s disk id %u\n", debugstr_w(mi->cabinet), mi->disk_id);
410 return 0;
411}
412
414 PFDINOTIFICATION pfdin)
415{
416 MSICABDATA *data = pfdin->pv;
417 HANDLE handle = 0;
418 LPWSTR path = NULL;
419 DWORD attrs;
420
421 data->curfile = strdupAtoW(pfdin->psz1);
422 if (!data->cb(data->package, data->curfile, MSICABEXTRACT_BEGINEXTRACT, &path,
423 &attrs, data->user))
424 {
425 /* We're not extracting this file, so free the filename. */
426 msi_free(data->curfile);
427 data->curfile = NULL;
428 goto done;
429 }
430
431 TRACE("extracting %s -> %s\n", debugstr_w(data->curfile), debugstr_w(path));
432
434 if (!attrs) attrs = FILE_ATTRIBUTE_NORMAL;
435
438 {
440 DWORD attrs2 = msi_get_file_attributes( data->package, path );
441
442 if (attrs2 == INVALID_FILE_ATTRIBUTES)
443 {
444 ERR( "failed to create %s (error %lu)\n", debugstr_w(path), err );
445 goto done;
446 }
447 else if (err == ERROR_ACCESS_DENIED && (attrs2 & FILE_ATTRIBUTE_READONLY))
448 {
449 TRACE("removing read-only attribute on %s\n", debugstr_w(path));
452
453 if (handle != INVALID_HANDLE_VALUE) goto done;
454 err = GetLastError();
455 }
457 {
458 WCHAR *tmpfileW, *tmppathW, *p;
459 DWORD len;
460
461 TRACE("file in use, scheduling rename operation\n");
462
463 if (!(tmppathW = strdupW( path ))) return ERROR_OUTOFMEMORY;
464 if ((p = wcsrchr(tmppathW, '\\'))) *p = 0;
465 len = lstrlenW( tmppathW ) + 16;
466 if (!(tmpfileW = msi_alloc(len * sizeof(WCHAR))))
467 {
468 msi_free( tmppathW );
469 return ERROR_OUTOFMEMORY;
470 }
471 if (!GetTempFileNameW(tmppathW, L"msi", 0, tmpfileW)) tmpfileW[0] = 0;
472 msi_free( tmppathW );
473
475
478 msi_move_file( data->package, tmpfileW, path, MOVEFILE_DELAY_UNTIL_REBOOT ))
479 {
480 data->package->need_reboot_at_end = 1;
481 }
482 else
483 {
484 WARN( "failed to schedule rename operation %s (error %lu)\n", debugstr_w(path), GetLastError() );
485 DeleteFileW( tmpfileW );
486 }
487 msi_free(tmpfileW);
488 }
489 else WARN( "failed to create %s (error %lu)\n", debugstr_w(path), err );
490 }
491
492done:
493 msi_free(path);
494
495 return (INT_PTR)handle;
496}
497
499 PFDINOTIFICATION pfdin)
500{
501 MSICABDATA *data = pfdin->pv;
502 FILETIME ft;
503 FILETIME ftLocal;
504 HANDLE handle = (HANDLE)pfdin->hf;
505
506 data->mi->is_continuous = FALSE;
507
508 if (!DosDateTimeToFileTime(pfdin->date, pfdin->time, &ft))
509 {
511 return -1;
512 }
513 if (!LocalFileTimeToFileTime(&ft, &ftLocal))
514 {
516 return -1;
517 }
518 if (!SetFileTime(handle, &ftLocal, 0, &ftLocal))
519 {
521 return -1;
522 }
523
525 data->cb(data->package, data->curfile, MSICABEXTRACT_FILEEXTRACTED, NULL, NULL, data->user);
526
527 msi_free(data->curfile);
528 data->curfile = NULL;
529
530 return 1;
531}
532
534{
535 switch (fdint)
536 {
538 return cabinet_partial_file(fdint, pfdin);
539
541 return cabinet_next_cabinet(fdint, pfdin);
542
543 case fdintCOPY_FILE:
544 return cabinet_copy_file(fdint, pfdin);
545
547 return cabinet_close_file_info(fdint, pfdin);
548
549 default:
550 return 0;
551 }
552}
553
555{
556 switch (fdint)
557 {
559 return cabinet_partial_file( fdint, pfdin );
560
562 return cabinet_next_cabinet_stream( fdint, pfdin );
563
564 case fdintCOPY_FILE:
565 return cabinet_copy_file( fdint, pfdin );
566
568 return cabinet_close_file_info( fdint, pfdin );
569
571 return 0;
572
573 default:
574 ERR("Unexpected notification %d\n", fdint);
575 return 0;
576 }
577}
578
580{
581 LPSTR cabinet, cab_path = NULL;
582 HFDI hfdi;
583 ERF erf;
584 BOOL ret = FALSE;
585
586 TRACE("extracting %s disk id %u\n", debugstr_w(mi->cabinet), mi->disk_id);
587
590 if (!hfdi)
591 {
592 ERR("FDICreate failed\n");
593 return FALSE;
594 }
595
596 cabinet = strdupWtoA( mi->cabinet );
597 if (!cabinet)
598 goto done;
599
600 cab_path = strdupWtoA( mi->sourcedir );
601 if (!cab_path)
602 goto done;
603
604 ret = FDICopy( hfdi, cabinet, cab_path, 0, cabinet_notify, NULL, data );
605 if (!ret)
606 ERR("FDICopy failed\n");
607
608done:
609 FDIDestroy( hfdi );
611 msi_free( cab_path );
612
613 if (ret)
614 mi->is_extracted = TRUE;
615
616 return ret;
617}
618
620{
621 static char filename[] = {'<','S','T','R','E','A','M','>',0};
622 HFDI hfdi;
623 ERF erf;
624 BOOL ret = FALSE;
625
626 TRACE("extracting %s disk id %u\n", debugstr_w(mi->cabinet), mi->disk_id);
627
630 if (!hfdi)
631 {
632 ERR("FDICreate failed\n");
633 return FALSE;
634 }
635
637 package_disk.id = mi->disk_id;
638
640 if (!ret) ERR("FDICopy failed\n");
641
642 FDIDestroy( hfdi );
643 if (ret) mi->is_extracted = TRUE;
644 return ret;
645}
646
647/***********************************************************************
648 * msi_cabextract
649 *
650 * Extract files from a cabinet file or stream.
651 */
653{
654 if (mi->cabinet[0] == '#')
655 {
657 }
658 return extract_cabinet( package, mi, data );
659}
660
662{
663 msi_free(mi->disk_prompt);
664 msi_free(mi->cabinet);
665 msi_free(mi->volume_label);
666 msi_free(mi->last_volume);
667 msi_free(mi);
668}
669
671{
672 WCHAR root[MAX_PATH + 1];
673
677
678 return GetDriveTypeW(root);
679}
680
682{
683 WCHAR *p, *ret = NULL, *orig_db = msi_dup_property( db, L"OriginalDatabase" );
684 if (UrlIsW( orig_db, URLIS_URL ) && (ret = strdupW( orig_db )) && (p = wcsrchr( ret, '/'))) p[1] = 0;
685 msi_free( orig_db );
686 return ret;
687}
688
690{
691 MSIRECORD *row;
692 WCHAR *source_dir, *source, *base_url = NULL;
694
695 if (Sequence <= mi->last_sequence) /* already loaded */
696 return ERROR_SUCCESS;
697
698 row = MSI_QueryGetRecord(package->db, L"SELECT * FROM `Media` WHERE `LastSequence` >= %d ORDER BY `DiskId`", Sequence);
699 if (!row)
700 {
701 TRACE("Unable to query row\n");
703 }
704
705 mi->is_extracted = FALSE;
706 mi->disk_id = MSI_RecordGetInteger(row, 1);
707 mi->last_sequence = MSI_RecordGetInteger(row, 2);
708 msi_free(mi->disk_prompt);
709 mi->disk_prompt = strdupW(MSI_RecordGetString(row, 3));
710 msi_free(mi->cabinet);
711 mi->cabinet = strdupW(MSI_RecordGetString(row, 4));
712 msi_free(mi->volume_label);
713 mi->volume_label = strdupW(MSI_RecordGetString(row, 5));
714 msiobj_release(&row->hdr);
715
717 source_dir = msi_dup_property(package->db, L"SourceDir");
718 lstrcpyW(mi->sourcedir, source_dir);
719 PathAddBackslashW(mi->sourcedir);
720 mi->type = get_drive_type(source_dir);
721
723 if (mi->type == DRIVE_CDROM || mi->type == DRIVE_REMOVABLE)
724 {
725 source = source_dir;
727 }
728 else if ((base_url = get_base_url(package->db)))
729 {
732 }
733 else
734 {
735 source = mi->sourcedir;
737 }
738
740 MSICODE_PRODUCT, mi->disk_id,
741 mi->volume_label, mi->disk_prompt);
742
745
746 TRACE("sequence %u -> cabinet %s disk id %u\n", Sequence, debugstr_w(mi->cabinet), mi->disk_id);
747
749 msi_free(source_dir);
750 return ERROR_SUCCESS;
751}
752
753/* FIXME: search URL sources as well */
755{
758 WCHAR prompt[MAX_PATH];
759 DWORD volumesz, promptsz;
760 DWORD index, size, id;
761 WCHAR last_type[2];
762 UINT r;
763
764 size = 2;
768 if (r != ERROR_SUCCESS)
769 return r;
770
771 size = MAX_PATH;
775 if (r != ERROR_SUCCESS)
776 return r;
777
778 if (last_type[0] == 'n')
779 {
780 WCHAR cabinet_file[MAX_PATH];
781 BOOL check_all = FALSE;
782
783 while(TRUE)
784 {
785 index = 0;
786 volumesz = MAX_PATH;
790 volume, &volumesz) == ERROR_SUCCESS)
791 {
792 if (check_all || !wcsnicmp(source, volume, lstrlenW(source)))
793 {
794 lstrcpyW(cabinet_file, volume);
795 PathAddBackslashW(cabinet_file);
796 lstrcatW(cabinet_file, mi->cabinet);
797
798 if (GetFileAttributesW(cabinet_file) == INVALID_FILE_ATTRIBUTES)
799 {
800 volumesz = MAX_PATH;
801 if(!check_all)
802 break;
803 continue;
804 }
805
806 lstrcpyW(mi->sourcedir, volume);
807 PathAddBackslashW(mi->sourcedir);
808 TRACE("Found network source %s\n", debugstr_w(mi->sourcedir));
809 return ERROR_SUCCESS;
810 }
811 }
812
813 if (!check_all)
814 check_all = TRUE;
815 else
816 break;
817 }
818 }
819
820 index = 0;
821 volumesz = MAX_PATH;
822 promptsz = MAX_PATH;
825 MSICODE_PRODUCT, index++, &id,
826 volume, &volumesz, prompt, &promptsz) == ERROR_SUCCESS)
827 {
828 mi->disk_id = id;
829 msi_free( mi->volume_label );
830 if (!(mi->volume_label = msi_alloc( ++volumesz * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY;
831 lstrcpyW( mi->volume_label, volume );
832
833 msi_free( mi->disk_prompt );
834 if (!(mi->disk_prompt = msi_alloc( ++promptsz * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY;
835 lstrcpyW( mi->disk_prompt, prompt );
836
838 {
839 /* FIXME: what about SourceDir */
840 lstrcpyW(mi->sourcedir, source);
841 PathAddBackslashW(mi->sourcedir);
842 TRACE("Found disk source %s\n", debugstr_w(mi->sourcedir));
843 return ERROR_SUCCESS;
844 }
845 }
846
848}
849
851{
852 UINT rc;
853 WCHAR *cabinet_file = NULL;
854
855 /* media info for continuous cabinet is already loaded */
856 if (mi->is_continuous) return ERROR_SUCCESS;
857
858 if (mi->cabinet)
859 {
861
862 /* cabinet is internal, no checks needed */
863 if (mi->cabinet[0] == '#') return ERROR_SUCCESS;
864
865 if (!(cabinet_file = get_cabinet_filename( mi ))) return ERROR_OUTOFMEMORY;
866
867 /* package should be downloaded */
868 if (compressed && GetFileAttributesW( cabinet_file ) == INVALID_FILE_ATTRIBUTES &&
870 {
871 WCHAR temppath[MAX_PATH], *p, *url;
872
873 msi_free( cabinet_file );
874 if (!(url = msi_alloc( (lstrlenW( base_url ) + lstrlenW( mi->cabinet ) + 1) * sizeof(WCHAR) )))
875 {
876 return ERROR_OUTOFMEMORY;
877 }
879 lstrcatW( url, mi->cabinet );
880 if ((rc = msi_download_file( url, temppath )) != ERROR_SUCCESS)
881 {
882 ERR("failed to download %s (%u)\n", debugstr_w(url), rc);
883 msi_free( url );
884 return rc;
885 }
886 if ((p = wcsrchr( temppath, '\\' ))) *p = 0;
887 lstrcpyW( mi->sourcedir, temppath );
888 PathAddBackslashW( mi->sourcedir );
889 msi_free( mi->cabinet );
890 mi->cabinet = strdupW( p + 1 );
891
892 msi_free( url );
893 return ERROR_SUCCESS;
894 }
895 }
896 /* check volume matches, change media if not */
897 if (mi->volume_label)
898 {
899 /* assume first volume is in the drive */
900 if (mi->last_volume && wcsicmp( mi->last_volume, mi->volume_label ))
901 {
902 WCHAR *source = msi_dup_property( package->db, L"SourceDir" );
904 msi_free( source );
905
906 if (!match && (mi->type == DRIVE_CDROM || mi->type == DRIVE_REMOVABLE))
907 {
908 if ((rc = msi_change_media( package, mi )) != ERROR_SUCCESS)
909 {
910 msi_free( cabinet_file );
911 return rc;
912 }
913 }
914 }
915
916 msi_free(mi->last_volume);
917 mi->last_volume = strdupW(mi->volume_label);
918 }
919 if (mi->cabinet)
920 {
921 if (compressed && GetFileAttributesW( cabinet_file ) == INVALID_FILE_ATTRIBUTES)
922 {
924 {
925 ERR("cabinet not found: %s\n", debugstr_w(cabinet_file));
926 msi_free( cabinet_file );
928 }
929 }
930 }
931 msi_free( cabinet_file );
932 return ERROR_SUCCESS;
933}
934
936{
937 MSICABINETSTREAM *cab, *item;
938
939 TRACE("%p, %u, %p, %s\n", package, disk_id, storage, debugstr_w(name));
940
942 {
943 if (item->disk_id == disk_id)
944 {
945 TRACE("duplicate disk id %u\n", disk_id);
947 }
948 }
949 if (!(cab = msi_alloc( sizeof(*cab) ))) return ERROR_OUTOFMEMORY;
950 if (!(cab->stream = msi_alloc( (lstrlenW( name ) + 1) * sizeof(WCHAR ) )))
951 {
952 msi_free( cab );
953 return ERROR_OUTOFMEMORY;
954 }
955 lstrcpyW( cab->stream, name );
956 cab->disk_id = disk_id;
957 cab->storage = storage;
958 IStorage_AddRef( storage );
960
961 return ERROR_SUCCESS;
962}
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define read
Definition: acwin.h:96
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
static WCHAR * strdupW(const WCHAR *src)
Definition: main.c:92
#define index(s, c)
Definition: various.h:29
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
#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
HFDI __cdecl FDICreate(PFNALLOC pfnalloc, PFNFREE pfnfree, PFNOPEN pfnopen, PFNREAD pfnread, PFNWRITE pfnwrite, PFNCLOSE pfnclose, PFNSEEK pfnseek, int cpuType, PERF perf)
Definition: fdi.c:412
BOOL __cdecl FDICopy(HFDI hfdi, char *pszCabinet, char *pszCabPath, int flags, PFNFDINOTIFY pfnfdin, PFNFDIDECRYPT pfnfdid, void *pvUser)
Definition: fdi.c:2431
BOOL __cdecl FDIDestroy(HFDI hfdi)
Definition: fdi.c:2831
static WCHAR * strdupAtoW(const char *str)
Definition: main.c:65
#define CDECL
Definition: compat.h:29
#define CloseHandle
Definition: compat.h:739
#define wcsnicmp
Definition: compat.h:14
#define wcsrchr
Definition: compat.h:16
#define OPEN_EXISTING
Definition: compat.h:775
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define SetFilePointer
Definition: compat.h:743
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#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 lstrlenW
Definition: compat.h:750
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
UINT WINAPI GetDriveTypeW(IN LPCWSTR lpRootPathName)
Definition: disk.c:497
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:652
BOOL WINAPI SetFileTime(IN HANDLE hFile, CONST FILETIME *lpCreationTime OPTIONAL, CONST FILETIME *lpLastAccessTime OPTIONAL, CONST FILETIME *lpLastWriteTime OPTIONAL)
Definition: fileinfo.c:948
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
BOOL WINAPI GetVolumeInformationW(IN LPCWSTR lpRootPathName, IN LPWSTR lpVolumeNameBuffer, IN DWORD nVolumeNameSize, OUT LPDWORD lpVolumeSerialNumber OPTIONAL, OUT LPDWORD lpMaximumComponentLength OPTIONAL, OUT LPDWORD lpFileSystemFlags OPTIONAL, OUT LPWSTR lpFileSystemNameBuffer OPTIONAL, IN DWORD nFileSystemNameSize)
Definition: volume.c:226
BOOL WINAPI DosDateTimeToFileTime(IN WORD wFatDate, IN WORD wFatTime, OUT LPFILETIME lpFileTime)
Definition: time.c:75
BOOL WINAPI LocalFileTimeToFileTime(IN CONST FILETIME *lpLocalFileTime, OUT LPFILETIME lpFileTime)
Definition: time.c:253
UINT msi_set_sourcedir_props(MSIPACKAGE *package, BOOL replace)
Definition: action.c:354
BOOL msi_set_file_attributes(MSIPACKAGE *package, const WCHAR *filename, DWORD attrs)
Definition: files.c:97
HANDLE msi_create_file(MSIPACKAGE *package, const WCHAR *filename, DWORD access, DWORD sharing, DWORD creation, DWORD flags)
Definition: files.c:51
BOOL msi_move_file(MSIPACKAGE *package, const WCHAR *from, const WCHAR *to, DWORD flags)
Definition: files.c:133
DWORD msi_get_file_attributes(MSIPACKAGE *package, const WCHAR *path)
Definition: files.c:106
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:241
#define _O_RDWR
Definition: media.c:41
static UINT CDECL cabinet_read(INT_PTR hf, void *pv, UINT cb)
Definition: media.c:154
static UINT msi_media_get_disk_info(MSIPACKAGE *package, MSIMEDIAINFO *mi)
Definition: media.c:274
static int CDECL cabinet_close_stream(INT_PTR hf)
Definition: media.c:250
static void CDECL cabinet_free(void *pv)
Definition: media.c:118
static INT_PTR CDECL cabinet_open(char *pszFile, int oflag, int pmode)
Definition: media.c:123
static BOOL extract_cabinet(MSIPACKAGE *package, MSIMEDIAINFO *mi, LPVOID data)
Definition: media.c:579
#define _O_ACCMODE
Definition: media.c:42
static INT_PTR CDECL cabinet_notify_stream(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
Definition: media.c:554
static WCHAR * get_cabinet_filename(MSIMEDIAINFO *mi)
Definition: media.c:301
UINT msi_add_cabinet_stream(MSIPACKAGE *package, UINT disk_id, IStorage *storage, const WCHAR *name)
Definition: media.c:935
static BOOL source_matches_volume(MSIMEDIAINFO *mi, LPCWSTR source_root)
Definition: media.c:55
static void *CDECL cabinet_alloc(ULONG cb)
Definition: media.c:113
UINT ready_media(MSIPACKAGE *package, BOOL compressed, MSIMEDIAINFO *mi)
Definition: media.c:850
#define _O_RDONLY
Definition: media.c:39
static WCHAR * get_base_url(MSIDATABASE *db)
Definition: media.c:681
static INT_PTR CDECL cabinet_open_stream(char *pszFile, int oflag, int pmode)
Definition: media.c:197
static int CDECL cabinet_close(INT_PTR hf)
Definition: media.c:176
static INT_PTR cabinet_partial_file(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
Definition: media.c:293
static INT_PTR cabinet_next_cabinet_stream(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
Definition: media.c:384
static BOOL extract_cabinet_stream(MSIPACKAGE *package, MSIMEDIAINFO *mi, LPVOID data)
Definition: media.c:619
static INT_PTR cabinet_close_file_info(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
Definition: media.c:498
static LONG CDECL cabinet_seek_stream(INT_PTR hf, LONG dist, int seektype)
Definition: media.c:257
#define _O_CREAT
Definition: media.c:48
#define _O_EXCL
Definition: media.c:50
static LONG CDECL cabinet_seek(INT_PTR hf, LONG dist, int seektype)
Definition: media.c:182
static MSICABINETSTREAM * msi_get_cabinet_stream(MSIPACKAGE *package, UINT disk_id)
Definition: media.c:102
void msi_free_media_info(MSIMEDIAINFO *mi)
Definition: media.c:661
static UINT msi_change_media(MSIPACKAGE *package, MSIMEDIAINFO *mi)
Definition: media.c:79
static UINT CDECL cabinet_read_stream(INT_PTR hf, void *pv, UINT cb)
Definition: media.c:237
static UINT get_drive_type(const WCHAR *path)
Definition: media.c:670
static UINT find_published_source(MSIPACKAGE *package, MSIMEDIAINFO *mi)
Definition: media.c:754
static INT_PTR cabinet_copy_file(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
Definition: media.c:413
#define _O_WRONLY
Definition: media.c:40
static UINT CDECL cabinet_write(INT_PTR hf, void *pv, UINT cb)
Definition: media.c:165
static INT_PTR CDECL cabinet_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
Definition: media.c:533
static INT_PTR cabinet_next_cabinet(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
Definition: media.c:313
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
#define MSIERR_CABNOTFOUND
Definition: resource.h:31
UINT WINAPI MsiSourceListEnumMediaDisksW(const WCHAR *szProductCodeOrPatchCode, const WCHAR *szUserSid, MSIINSTALLCONTEXT dwContext, DWORD dwOptions, DWORD dwIndex, DWORD *pdwDiskId, WCHAR *szVolumeLabel, DWORD *pcchVolumeLabel, WCHAR *szDiskPrompt, DWORD *pcchDiskPrompt)
Definition: source.c:198
UINT WINAPI MsiSourceListGetInfoW(LPCWSTR szProduct, LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext, DWORD dwOptions, LPCWSTR szProperty, LPWSTR szValue, LPDWORD pcchValue)
Definition: source.c:523
UINT WINAPI MsiSourceListEnumSourcesW(const WCHAR *szProductCodeOrPatch, const WCHAR *szUserSid, MSIINSTALLCONTEXT dwContext, DWORD dwOptions, DWORD dwIndex, WCHAR *szSource, DWORD *pcchSource)
Definition: source.c:398
BOOL WINAPI PathStripToRootW(LPWSTR lpszPath)
Definition: path.c:733
BOOL WINAPI UrlIsW(LPCWSTR pszUrl, URLIS Urlis)
Definition: url.c:1933
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
FDINOTIFICATIONTYPE
Definition: fdi.h:246
@ fdintCABINET_INFO
Definition: fdi.h:247
@ fdintCOPY_FILE
Definition: fdi.h:249
@ fdintPARTIAL_FILE
Definition: fdi.h:248
@ fdintCLOSE_FILE_INFO
Definition: fdi.h:250
@ fdintNEXT_CABINET
Definition: fdi.h:251
UINT WINAPI GetTempFileNameW(IN LPCWSTR lpPathName, IN LPCWSTR lpPrefixString, IN UINT uUnique, OUT LPWSTR lpTempFileName)
Definition: filename.c:84
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
GLuint index
Definition: glext.h:6031
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLuint id
Definition: glext.h:5910
static LPSTR strdupWtoA(LPCWSTR str)
Definition: hhctrl.h:299
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#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
if(dx< 0)
Definition: linetemp.h:194
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
#define DRIVE_CDROM
Definition: machpc98.h:119
double __cdecl erf(double)
static char volume_name[]
Definition: mkdosfs.c:526
#define CREATE_ALWAYS
Definition: disk.h:72
#define CREATE_NEW
Definition: disk.h:69
static const WCHAR url[]
Definition: encode.c:1432
const char * base_url
Definition: mimeole.c:1466
static HMODULE MODULEINFO DWORD cb
Definition: module.c:33
static ATOM item
Definition: dde.c:856
static const WCHAR INSTALLPROPERTY_LASTUSEDTYPEW[]
Definition: msi.h:409
@ MSICODE_PRODUCT
Definition: msi.h:215
@ MSISOURCETYPE_URL
Definition: msi.h:209
@ MSISOURCETYPE_NETWORK
Definition: msi.h:208
@ MSISOURCETYPE_MEDIA
Definition: msi.h:210
static const WCHAR INSTALLPROPERTY_LASTUSEDSOURCEW[]
Definition: msi.h:405
@ INSTALLMESSAGE_ERROR
Definition: msi.h:95
UINT msi_package_add_info(MSIPACKAGE *, DWORD, DWORD, LPCWSTR, LPWSTR) DECLSPEC_HIDDEN
Definition: package.c:2625
UINT msi_get_stream(MSIDATABASE *, const WCHAR *, IStream **) DECLSPEC_HIDDEN
Definition: streams.c:499
MSIRECORD *WINAPIV MSI_QueryGetRecord(MSIDATABASE *db, LPCWSTR query,...) DECLSPEC_HIDDEN
Definition: msiquery.c:201
LPWSTR encode_streamname(BOOL bTable, LPCWSTR in) DECLSPEC_HIDDEN
Definition: table.c:119
static void msi_free(void *mem)
Definition: msipriv.h:1159
int MSI_RecordGetInteger(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:213
UINT msi_download_file(LPCWSTR szUrl, LPWSTR filename) DECLSPEC_HIDDEN
Definition: package.c:1027
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
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
LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop) DECLSPEC_HIDDEN
Definition: package.c:2283
#define MSICABEXTRACT_FILEEXTRACTED
Definition: msipriv.h:1096
UINT msi_package_add_media_disk(MSIPACKAGE *, DWORD, DWORD, DWORD, LPWSTR, LPWSTR) DECLSPEC_HIDDEN
Definition: package.c:2648
UINT MSI_RecordSetStringW(MSIRECORD *, UINT, LPCWSTR) DECLSPEC_HIDDEN
Definition: record.c:597
unsigned int UINT
Definition: ndis.h:50
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define GENERIC_WRITE
Definition: nt_native.h:90
#define L(x)
Definition: ntvdm.h:50
#define STGM_SHARE_EXCLUSIVE
Definition: objbase.h:923
#define STGM_READ
Definition: objbase.h:917
#define PathAddBackslashW
Definition: pathcch.h:301
long LONG
Definition: pedump.c:60
#define err(...)
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
HRESULT hr
Definition: shlfolder.c:183
@ URLIS_URL
Definition: shlwapi.h:1191
#define TRACE(s)
Definition: solgame.cpp:4
Definition: fci.h:44
char * psz3
Definition: fdi.h:230
USHORT time
Definition: fdi.h:236
void * pv
Definition: fdi.h:231
INT_PTR hf
Definition: fdi.h:233
char * psz1
Definition: fdi.h:228
USHORT date
Definition: fdi.h:235
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
Definition: match.c:28
Definition: name.c:39
MSIPACKAGE * package
Definition: media.c:191
UINT id
Definition: media.c:192
Definition: parse.h:23
struct list entry
Definition: msipriv.h:192
IStorage * storage
Definition: msipriv.h:194
IStorage * storage
Definition: msipriv.h:109
MSIDATABASE * db
Definition: msipriv.h:394
struct list cabinet_streams
Definition: msipriv.h:408
LPWSTR ProductCode
Definition: msipriv.h:448
UINT Context
Definition: msipriv.h:459
int32_t INT_PTR
Definition: typedefs.h:64
PVOID HANDLE
Definition: typedefs.h:73
uint32_t ULONG
Definition: typedefs.h:59
#define MAXLONG
Definition: umtypes.h:116
LONGLONG QuadPart
Definition: typedefs.h:114
#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 MOVEFILE_DELAY_UNTIL_REBOOT
Definition: winbase.h:400
#define DRIVE_REMOVABLE
Definition: winbase.h:251
#define S_FALSE
Definition: winerror.h:2357
#define ERROR_INSTALL_FAILURE
Definition: winerror.h:961
#define ERROR_SHARING_VIOLATION
Definition: winerror.h:135
#define ERROR_INSTALL_SOURCE_ABSENT
Definition: winerror.h:970
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985
#define ERROR_USER_MAPPED_FILE
Definition: winerror.h:727
#define MB_RETRYCANCEL
Definition: winuser.h:804
#define IDRETRY
Definition: winuser.h:832
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185