ReactOS 0.4.16-dev-258-g81860b4
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 <fcntl.h>
22#include <stdarg.h>
23
24#define COBJMACROS
25
26#include "windef.h"
27#include "winerror.h"
28#include "wine/debug.h"
29#include "fdi.h"
30#include "msipriv.h"
31#include "winuser.h"
32#include "winreg.h"
33#include "shlwapi.h"
34#include "objidl.h"
35#include "resource.h"
36
38
40{
42 const WCHAR *p;
43 int len, len2;
44
45 lstrcpyW(root, source_root);
48
50 {
51 WARN( "failed to get volume information for %s (%lu)\n", debugstr_w(root), GetLastError() );
52 return FALSE;
53 }
54
56 len2 = lstrlenW( mi->volume_label );
57 if (len2 > len) return FALSE;
58 p = volume_name + len - len2;
59
60 return !wcsicmp( mi->volume_label, p );
61}
62
64{
66 LPWSTR source_dir;
67 UINT r = IDRETRY;
68
69 source_dir = msi_dup_property(package->db, L"SourceDir");
71
72 while (r == IDRETRY && !source_matches_volume(mi, source_dir))
73 {
76 MSI_RecordSetStringW(record, 2, mi->disk_prompt);
78 }
79
81 free(source_dir);
82
84}
85
87{
89
91 {
92 if (cab->disk_id == disk_id) return cab;
93 }
94 return NULL;
95}
96
98{
99 return malloc(cb);
100}
101
102static void CDECL cabinet_free(void *pv)
103{
104 free(pv);
105}
106
107static INT_PTR CDECL cabinet_open(char *pszFile, int oflag, int pmode)
108{
109 DWORD dwAccess = 0;
110 DWORD dwShareMode = 0;
111 DWORD dwCreateDisposition = OPEN_EXISTING;
113 WCHAR *path;
114
115 switch (oflag & _O_ACCMODE)
116 {
117 case _O_RDONLY:
118 dwAccess = GENERIC_READ;
119 dwShareMode = FILE_SHARE_READ | FILE_SHARE_DELETE;
120 break;
121 case _O_WRONLY:
122 dwAccess = GENERIC_WRITE;
124 break;
125 case _O_RDWR:
126 dwAccess = GENERIC_READ | GENERIC_WRITE;
128 break;
129 }
130
131 if ((oflag & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL))
132 dwCreateDisposition = CREATE_NEW;
133 else if (oflag & _O_CREAT)
134 dwCreateDisposition = CREATE_ALWAYS;
135
136 path = strdupUtoW(pszFile);
137 handle = CreateFileW(path, dwAccess, dwShareMode, NULL, dwCreateDisposition, 0, NULL);
138 free(path);
139 return (INT_PTR)handle;
140}
141
142static UINT CDECL cabinet_read(INT_PTR hf, void *pv, UINT cb)
143{
144 HANDLE handle = (HANDLE)hf;
145 DWORD read;
146
147 if (ReadFile(handle, pv, cb, &read, NULL))
148 return read;
149
150 return 0;
151}
152
153static UINT CDECL cabinet_write(INT_PTR hf, void *pv, UINT cb)
154{
155 HANDLE handle = (HANDLE)hf;
156 DWORD written;
157
158 if (WriteFile(handle, pv, cb, &written, NULL))
159 return written;
160
161 return 0;
162}
163
165{
166 HANDLE handle = (HANDLE)hf;
167 return CloseHandle(handle) ? 0 : -1;
168}
169
170static LONG CDECL cabinet_seek(INT_PTR hf, LONG dist, int seektype)
171{
172 HANDLE handle = (HANDLE)hf;
173 /* flags are compatible and so are passed straight through */
174 return SetFilePointer(handle, dist, NULL, seektype);
175}
176
178{
181};
182
184
185static INT_PTR CDECL cabinet_open_stream( char *pszFile, int oflag, int pmode )
186{
187 MSICABINETSTREAM *cab;
189
191 {
192 WARN("failed to get cabinet stream\n");
193 return -1;
194 }
195 if (cab->storage == package_disk.package->db->storage)
196 {
198 if (r != ERROR_SUCCESS)
199 {
200 WARN("failed to get stream %u\n", r);
201 return -1;
202 }
203 }
204 else /* patch storage */
205 {
206 HRESULT hr;
207 WCHAR *encoded;
208
209 if (!(encoded = encode_streamname( FALSE, cab->stream + 1 )))
210 {
211 WARN("failed to encode stream name\n");
212 return -1;
213 }
214 hr = IStorage_OpenStream( cab->storage, encoded, NULL, STGM_READ|STGM_SHARE_EXCLUSIVE, 0, &stream );
215 free( encoded );
216 if (FAILED(hr))
217 {
218 WARN( "failed to open stream %#lx\n", hr );
219 return -1;
220 }
221 }
222 return (INT_PTR)stream;
223}
224
226{
227 IStream *stm = (IStream *)hf;
228 DWORD read;
229 HRESULT hr;
230
231 hr = IStream_Read( stm, pv, cb, &read );
232 if (hr == S_OK || hr == S_FALSE)
233 return read;
234
235 return 0;
236}
237
239{
240 IStream *stm = (IStream *)hf;
241 IStream_Release( stm );
242 return 0;
243}
244
245static LONG CDECL cabinet_seek_stream( INT_PTR hf, LONG dist, int seektype )
246{
247 IStream *stm = (IStream *)hf;
248 LARGE_INTEGER move;
249 ULARGE_INTEGER newpos;
250 HRESULT hr;
251
252 move.QuadPart = dist;
253 hr = IStream_Seek( stm, move, seektype, &newpos );
254 if (SUCCEEDED(hr))
255 {
256 if (newpos.QuadPart <= MAXLONG) return newpos.QuadPart;
257 ERR("Too big!\n");
258 }
259 return -1;
260}
261
263{
264 MSIRECORD *row;
265
266 row = MSI_QueryGetRecord(package->db, L"SELECT * FROM `Media` WHERE `DiskId` = %d", mi->disk_id);
267 if (!row)
268 {
269 TRACE("Unable to query row\n");
271 }
272
273 mi->disk_prompt = wcsdup(MSI_RecordGetString(row, 3));
274 mi->cabinet = wcsdup(MSI_RecordGetString(row, 4));
275 mi->volume_label = wcsdup(MSI_RecordGetString(row, 5));
276
277 msiobj_release(&row->hdr);
278 return ERROR_SUCCESS;
279}
280
282 PFDINOTIFICATION pfdin)
283{
284 MSICABDATA *data = pfdin->pv;
285 data->mi->is_continuous = FALSE;
286 return 0;
287}
288
290{
291 int len;
292 WCHAR *ret;
293
294 len = lstrlenW(mi->sourcedir) + lstrlenW(mi->cabinet) + 1;
295 if (!(ret = malloc(len * sizeof(WCHAR)))) return NULL;
296 lstrcpyW(ret, mi->sourcedir);
297 lstrcatW(ret, mi->cabinet);
298 return ret;
299}
300
302 PFDINOTIFICATION pfdin)
303{
304 MSICABDATA *data = pfdin->pv;
305 MSIMEDIAINFO *mi = data->mi;
306 LPWSTR cabinet_file = NULL, cab = strdupAtoW(pfdin->psz1);
307 INT_PTR res = -1;
308 UINT rc;
309
310 free(mi->disk_prompt);
311 free(mi->cabinet);
312 free(mi->volume_label);
313 mi->disk_prompt = NULL;
314 mi->cabinet = NULL;
315 mi->volume_label = NULL;
316
317 mi->disk_id++;
318 mi->is_continuous = TRUE;
319
320 rc = media_get_disk_info(data->package, mi);
321 if (rc != ERROR_SUCCESS)
322 {
323 ERR("Failed to get next cabinet information: %d\n", rc);
324 goto done;
325 }
326
327 if (wcsicmp( mi->cabinet, cab ))
328 {
329 char *next_cab;
331
332 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));
333
334 /* Use cabinet name from the media table */
335 next_cab = strdupWtoA(mi->cabinet);
336 /* Modify path to cabinet file with full filename (psz3 points to a 256 bytes buffer that can be modified contrary to psz1 and psz2) */
337 length = strlen(pfdin->psz3) + 1 + strlen(next_cab) + 1;
338 if (length > 256)
339 {
340 WARN( "cannot update next cabinet filename with a string size %lu > 256\n", length );
341 free(next_cab);
342 goto done;
343 }
344 else
345 {
346 strcat(pfdin->psz3, "\\");
347 strcat(pfdin->psz3, next_cab);
348 }
349 /* Path psz3 and cabinet psz1 are concatenated by FDI so just reset psz1 */
350 *pfdin->psz1 = 0;
351 free(next_cab);
352 }
353
354 if (!(cabinet_file = get_cabinet_filename(mi)))
355 goto done;
356
357 TRACE("Searching for %s\n", debugstr_w(cabinet_file));
358
359 res = 0;
360 if (GetFileAttributesW(cabinet_file) == INVALID_FILE_ATTRIBUTES)
361 {
362 if (change_media(data->package, mi) != ERROR_SUCCESS)
363 res = -1;
364 }
365
366done:
367 free(cab);
368 free(cabinet_file);
369 return res;
370}
371
373 PFDINOTIFICATION pfdin )
374{
375 MSICABDATA *data = pfdin->pv;
376 MSIMEDIAINFO *mi = data->mi;
377 UINT rc;
378
379 free( mi->disk_prompt );
380 free( mi->cabinet );
381 free( mi->volume_label );
382 mi->disk_prompt = NULL;
383 mi->cabinet = NULL;
384 mi->volume_label = NULL;
385
386 mi->disk_id++;
387 mi->is_continuous = TRUE;
388
389 rc = media_get_disk_info( data->package, mi );
390 if (rc != ERROR_SUCCESS)
391 {
392 ERR("Failed to get next cabinet information: %u\n", rc);
393 return -1;
394 }
395 package_disk.id = mi->disk_id;
396
397 TRACE("next cabinet is %s disk id %u\n", debugstr_w(mi->cabinet), mi->disk_id);
398 return 0;
399}
400
402 PFDINOTIFICATION pfdin)
403{
404 MSICABDATA *data = pfdin->pv;
405 HANDLE handle = 0;
406 LPWSTR path = NULL;
407 DWORD attrs;
408
409 data->curfile = strdupAtoW(pfdin->psz1);
410 if (!data->cb(data->package, data->curfile, MSICABEXTRACT_BEGINEXTRACT, &path,
411 &attrs, data->user))
412 {
413 /* We're not extracting this file, so free the filename. */
414 free(data->curfile);
415 data->curfile = NULL;
416 goto done;
417 }
418
419 TRACE("extracting %s -> %s\n", debugstr_w(data->curfile), debugstr_w(path));
420
422 if (!attrs) attrs = FILE_ATTRIBUTE_NORMAL;
423
426 {
428 DWORD attrs2 = msi_get_file_attributes( data->package, path );
429
430 if (attrs2 == INVALID_FILE_ATTRIBUTES)
431 {
432 ERR( "failed to create %s (error %lu)\n", debugstr_w(path), err );
433 goto done;
434 }
435 else if (err == ERROR_ACCESS_DENIED && (attrs2 & FILE_ATTRIBUTE_READONLY))
436 {
437 TRACE("removing read-only attribute on %s\n", debugstr_w(path));
440
441 if (handle != INVALID_HANDLE_VALUE) goto done;
442 err = GetLastError();
443 }
445 {
446 WCHAR *tmpfileW, *tmppathW, *p;
447 DWORD len;
448
449 TRACE("file in use, scheduling rename operation\n");
450
451 if (!(tmppathW = wcsdup(path))) return ERROR_OUTOFMEMORY;
452 if ((p = wcsrchr(tmppathW, '\\'))) *p = 0;
453 len = lstrlenW( tmppathW ) + 16;
454 if (!(tmpfileW = malloc(len * sizeof(WCHAR))))
455 {
456 free( tmppathW );
457 return ERROR_OUTOFMEMORY;
458 }
459 if (!msi_get_temp_file_name( data->package, tmppathW, L"msi", tmpfileW )) tmpfileW[0] = 0;
460 free( tmppathW );
461
462 handle = msi_create_file( data->package, tmpfileW, GENERIC_READ | GENERIC_WRITE, 0, CREATE_ALWAYS, attrs );
463
466 msi_move_file( data->package, tmpfileW, path, MOVEFILE_DELAY_UNTIL_REBOOT ))
467 {
468 data->package->need_reboot_at_end = 1;
469 }
470 else
471 {
472 WARN( "failed to schedule rename operation %s (error %lu)\n", debugstr_w(path), GetLastError() );
473 msi_delete_file( data->package, tmpfileW );
474 }
475 free(tmpfileW);
476 }
477 else WARN( "failed to create %s (error %lu)\n", debugstr_w(path), err );
478 }
479
480done:
481 free(path);
482
483 return (INT_PTR)handle;
484}
485
487 PFDINOTIFICATION pfdin)
488{
489 MSICABDATA *data = pfdin->pv;
490 FILETIME ft;
491 FILETIME ftLocal;
492 HANDLE handle = (HANDLE)pfdin->hf;
493
494 data->mi->is_continuous = FALSE;
495
496 if (!DosDateTimeToFileTime(pfdin->date, pfdin->time, &ft))
497 {
499 return -1;
500 }
501 if (!LocalFileTimeToFileTime(&ft, &ftLocal))
502 {
504 return -1;
505 }
506 if (!SetFileTime(handle, &ftLocal, 0, &ftLocal))
507 {
509 return -1;
510 }
511
513 data->cb(data->package, data->curfile, MSICABEXTRACT_FILEEXTRACTED, NULL, NULL, data->user);
514
515 free(data->curfile);
516 data->curfile = NULL;
517
518 return 1;
519}
520
522{
523 switch (fdint)
524 {
526 return cabinet_partial_file(fdint, pfdin);
527
529 return cabinet_next_cabinet(fdint, pfdin);
530
531 case fdintCOPY_FILE:
532 return cabinet_copy_file(fdint, pfdin);
533
535 return cabinet_close_file_info(fdint, pfdin);
536
537 default:
538 return 0;
539 }
540}
541
543{
544 switch (fdint)
545 {
547 return cabinet_partial_file( fdint, pfdin );
548
550 return cabinet_next_cabinet_stream( fdint, pfdin );
551
552 case fdintCOPY_FILE:
553 return cabinet_copy_file( fdint, pfdin );
554
556 return cabinet_close_file_info( fdint, pfdin );
557
559 return 0;
560
561 default:
562 ERR("Unexpected notification %d\n", fdint);
563 return 0;
564 }
565}
566
568{
569 LPSTR cabinet, cab_path = NULL;
570 HFDI hfdi;
571 ERF erf;
572 BOOL ret = FALSE;
573
574 TRACE("extracting %s disk id %u\n", debugstr_w(mi->cabinet), mi->disk_id);
575
578 if (!hfdi)
579 {
580 ERR("FDICreate failed\n");
581 return FALSE;
582 }
583
584 cabinet = strdupWtoU( mi->cabinet );
585 if (!cabinet)
586 goto done;
587
588 cab_path = strdupWtoU( mi->sourcedir );
589 if (!cab_path)
590 goto done;
591
592 ret = FDICopy( hfdi, cabinet, cab_path, 0, cabinet_notify, NULL, data );
593 if (!ret)
594 ERR("FDICopy failed\n");
595
596done:
597 FDIDestroy( hfdi );
598 free( cabinet );
599 free( cab_path );
600
601 if (ret)
602 mi->is_extracted = TRUE;
603
604 return ret;
605}
606
608{
609 static char filename[] = {'<','S','T','R','E','A','M','>',0};
610 HFDI hfdi;
611 ERF erf;
612 BOOL ret = FALSE;
613
614 TRACE("extracting %s disk id %u\n", debugstr_w(mi->cabinet), mi->disk_id);
615
618 if (!hfdi)
619 {
620 ERR("FDICreate failed\n");
621 return FALSE;
622 }
623
625 package_disk.id = mi->disk_id;
626
628 if (!ret) ERR("FDICopy failed\n");
629
630 FDIDestroy( hfdi );
631 if (ret) mi->is_extracted = TRUE;
632 return ret;
633}
634
635/***********************************************************************
636 * msi_cabextract
637 *
638 * Extract files from a cabinet file or stream.
639 */
641{
642 if (mi->cabinet[0] == '#')
643 {
645 }
646 return extract_cabinet( package, mi, data );
647}
648
650{
651 free(mi->disk_prompt);
652 free(mi->cabinet);
653 free(mi->volume_label);
654 free(mi->last_volume);
655 free(mi);
656}
657
659{
660 WCHAR root[MAX_PATH + 1];
661
665
666 return GetDriveTypeW(root);
667}
668
670{
671 WCHAR *p, *ret = NULL, *orig_db = msi_dup_property( db, L"OriginalDatabase" );
672 if (UrlIsW( orig_db, URLIS_URL ) && (ret = wcsdup( orig_db )) && (p = wcsrchr( ret, '/' ))) p[1] = 0;
673 free( orig_db );
674 return ret;
675}
676
678{
679 MSIRECORD *row;
680 WCHAR *source_dir, *source, *base_url = NULL;
682
683 if (Sequence <= mi->last_sequence) /* already loaded */
684 return ERROR_SUCCESS;
685
686 row = MSI_QueryGetRecord(package->db, L"SELECT * FROM `Media` WHERE `LastSequence` >= %d ORDER BY `DiskId`", Sequence);
687 if (!row)
688 {
689 TRACE("Unable to query row\n");
691 }
692
693 mi->is_extracted = FALSE;
694 mi->disk_id = MSI_RecordGetInteger(row, 1);
695 mi->last_sequence = MSI_RecordGetInteger(row, 2);
696 free(mi->disk_prompt);
697 mi->disk_prompt = wcsdup(MSI_RecordGetString(row, 3));
698 free(mi->cabinet);
699 mi->cabinet = wcsdup(MSI_RecordGetString(row, 4));
700 free(mi->volume_label);
701 mi->volume_label = wcsdup(MSI_RecordGetString(row, 5));
702 msiobj_release(&row->hdr);
703
705 source_dir = msi_dup_property(package->db, L"SourceDir");
706 lstrcpyW(mi->sourcedir, source_dir);
707 PathAddBackslashW(mi->sourcedir);
708 mi->type = get_drive_type(source_dir);
709
711 if (mi->type == DRIVE_CDROM || mi->type == DRIVE_REMOVABLE)
712 {
713 source = source_dir;
715 }
716 else if ((base_url = get_base_url(package->db)))
717 {
720 }
721 else
722 {
723 source = mi->sourcedir;
725 }
726
728 MSICODE_PRODUCT, mi->disk_id,
729 mi->volume_label, mi->disk_prompt);
730
733
734 TRACE("sequence %u -> cabinet %s disk id %u\n", Sequence, debugstr_w(mi->cabinet), mi->disk_id);
735
736 free(base_url);
737 free(source_dir);
738 return ERROR_SUCCESS;
739}
740
741/* FIXME: search URL sources as well */
743{
746 WCHAR prompt[MAX_PATH];
747 DWORD volumesz, promptsz;
748 DWORD index, size, id;
749 WCHAR last_type[2];
750 UINT r;
751
752 size = 2;
756 if (r != ERROR_SUCCESS)
757 return r;
758
759 size = MAX_PATH;
763 if (r != ERROR_SUCCESS)
764 return r;
765
766 if (last_type[0] == 'n')
767 {
768 WCHAR cabinet_file[MAX_PATH];
769 BOOL check_all = FALSE;
770
771 while(TRUE)
772 {
773 index = 0;
774 volumesz = MAX_PATH;
778 volume, &volumesz) == ERROR_SUCCESS)
779 {
780 if (check_all || !wcsnicmp(source, volume, lstrlenW(source)))
781 {
782 lstrcpyW(cabinet_file, volume);
783 PathAddBackslashW(cabinet_file);
784 lstrcatW(cabinet_file, mi->cabinet);
785
786 if (GetFileAttributesW(cabinet_file) == INVALID_FILE_ATTRIBUTES)
787 {
788 volumesz = MAX_PATH;
789 if(!check_all)
790 break;
791 continue;
792 }
793
794 lstrcpyW(mi->sourcedir, volume);
795 PathAddBackslashW(mi->sourcedir);
796 TRACE("Found network source %s\n", debugstr_w(mi->sourcedir));
797 return ERROR_SUCCESS;
798 }
799 }
800
801 if (!check_all)
802 check_all = TRUE;
803 else
804 break;
805 }
806 }
807
808 index = 0;
809 volumesz = MAX_PATH;
810 promptsz = MAX_PATH;
813 MSICODE_PRODUCT, index++, &id,
814 volume, &volumesz, prompt, &promptsz) == ERROR_SUCCESS)
815 {
816 mi->disk_id = id;
817 free( mi->volume_label );
818 if (!(mi->volume_label = malloc( ++volumesz * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY;
819 lstrcpyW( mi->volume_label, volume );
820
821 free( mi->disk_prompt );
822 if (!(mi->disk_prompt = malloc( ++promptsz * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY;
823 lstrcpyW( mi->disk_prompt, prompt );
824
826 {
827 /* FIXME: what about SourceDir */
828 lstrcpyW(mi->sourcedir, source);
829 PathAddBackslashW(mi->sourcedir);
830 TRACE("Found disk source %s\n", debugstr_w(mi->sourcedir));
831 return ERROR_SUCCESS;
832 }
833 }
834
836}
837
839{
840 UINT rc;
841 WCHAR *cabinet_file = NULL;
842
843 /* media info for continuous cabinet is already loaded */
844 if (mi->is_continuous) return ERROR_SUCCESS;
845
846 if (mi->cabinet)
847 {
849
850 /* cabinet is internal, no checks needed */
851 if (mi->cabinet[0] == '#') return ERROR_SUCCESS;
852
853 if (!(cabinet_file = get_cabinet_filename( mi ))) return ERROR_OUTOFMEMORY;
854
855 /* package should be downloaded */
856 if (compressed && GetFileAttributesW( cabinet_file ) == INVALID_FILE_ATTRIBUTES &&
858 {
859 WCHAR temppath[MAX_PATH], *p, *url;
860
861 free( cabinet_file );
862 if (!(url = realloc( base_url, (wcslen( base_url ) + wcslen( mi->cabinet ) + 1) * sizeof(WCHAR) )))
863 {
864 free( base_url );
865 return ERROR_OUTOFMEMORY;
866 }
867 lstrcatW( url, mi->cabinet );
868 if ((rc = msi_download_file( url, temppath )) != ERROR_SUCCESS)
869 {
870 ERR("failed to download %s (%u)\n", debugstr_w(url), rc);
871 free( url );
872 return rc;
873 }
874 if ((p = wcsrchr( temppath, '\\' ))) *p = 0;
875 lstrcpyW( mi->sourcedir, temppath );
876 PathAddBackslashW( mi->sourcedir );
877 free( mi->cabinet );
878 mi->cabinet = wcsdup( p + 1 );
879
880 free( url );
881 return ERROR_SUCCESS;
882 }
883 }
884 /* check volume matches, change media if not */
885 if (mi->volume_label)
886 {
887 /* assume first volume is in the drive */
888 if (mi->last_volume && wcsicmp( mi->last_volume, mi->volume_label ))
889 {
890 WCHAR *source = msi_dup_property( package->db, L"SourceDir" );
892 free( source );
893
894 if (!match && (mi->type == DRIVE_CDROM || mi->type == DRIVE_REMOVABLE))
895 {
896 if ((rc = change_media( package, mi )) != ERROR_SUCCESS)
897 {
898 free( cabinet_file );
899 return rc;
900 }
901 }
902 }
903
904 free(mi->last_volume);
905 mi->last_volume = wcsdup(mi->volume_label);
906 }
907 if (mi->cabinet)
908 {
909 if (compressed && GetFileAttributesW( cabinet_file ) == INVALID_FILE_ATTRIBUTES)
910 {
912 {
913 ERR("cabinet not found: %s\n", debugstr_w(cabinet_file));
914 free( cabinet_file );
916 }
917 }
918 }
919 free( cabinet_file );
920 return ERROR_SUCCESS;
921}
922
924{
925 MSICABINETSTREAM *cab, *item;
926
927 TRACE("%p, %u, %p, %s\n", package, disk_id, storage, debugstr_w(name));
928
930 {
931 if (item->disk_id == disk_id)
932 {
933 TRACE("duplicate disk id %u\n", disk_id);
935 }
936 }
937 if (!(cab = malloc( sizeof(*cab) ))) return ERROR_OUTOFMEMORY;
938 if (!(cab->stream = malloc( (wcslen( name ) + 1) * sizeof(WCHAR) )))
939 {
940 free( cab );
941 return ERROR_OUTOFMEMORY;
942 }
943 lstrcpyW( cab->stream, name );
944 cab->disk_id = disk_id;
945 cab->storage = storage;
946 IStorage_AddRef( storage );
948
949 return ERROR_SUCCESS;
950}
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
#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: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#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 _O_RDWR
Definition: cabinet.h:39
#define _O_ACCMODE
Definition: cabinet.h:40
#define _O_RDONLY
Definition: cabinet.h:37
#define _O_CREAT
Definition: cabinet.h:46
#define _O_EXCL
Definition: cabinet.h:48
#define _O_WRONLY
Definition: cabinet.h:38
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 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
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:352
BOOL msi_set_file_attributes(MSIPACKAGE *package, const WCHAR *filename, DWORD attrs)
Definition: files.c:106
HANDLE msi_create_file(MSIPACKAGE *package, const WCHAR *filename, DWORD access, DWORD sharing, DWORD creation, DWORD flags)
Definition: files.c:60
BOOL msi_delete_file(MSIPACKAGE *package, const WCHAR *filename)
Definition: files.c:79
BOOL msi_move_file(MSIPACKAGE *package, const WCHAR *from, const WCHAR *to, DWORD flags)
Definition: files.c:142
DWORD msi_get_file_attributes(MSIPACKAGE *package, const WCHAR *path)
Definition: files.c:115
BOOL msi_get_temp_file_name(MSIPACKAGE *package, const WCHAR *tmp_path, const WCHAR *prefix, WCHAR *tmp_filename)
Definition: files.c:51
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:241
static UINT CDECL cabinet_read(INT_PTR hf, void *pv, UINT cb)
Definition: media.c:142
static UINT change_media(MSIPACKAGE *package, MSIMEDIAINFO *mi)
Definition: media.c:63
static MSICABINETSTREAM * get_cabinet_stream(MSIPACKAGE *package, UINT disk_id)
Definition: media.c:86
static int CDECL cabinet_close_stream(INT_PTR hf)
Definition: media.c:238
static void CDECL cabinet_free(void *pv)
Definition: media.c:102
static INT_PTR CDECL cabinet_open(char *pszFile, int oflag, int pmode)
Definition: media.c:107
static BOOL extract_cabinet(MSIPACKAGE *package, MSIMEDIAINFO *mi, LPVOID data)
Definition: media.c:567
static INT_PTR CDECL cabinet_notify_stream(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
Definition: media.c:542
static WCHAR * get_cabinet_filename(MSIMEDIAINFO *mi)
Definition: media.c:289
UINT msi_add_cabinet_stream(MSIPACKAGE *package, UINT disk_id, IStorage *storage, const WCHAR *name)
Definition: media.c:923
static BOOL source_matches_volume(MSIMEDIAINFO *mi, LPCWSTR source_root)
Definition: media.c:39
static void *CDECL cabinet_alloc(ULONG cb)
Definition: media.c:97
UINT ready_media(MSIPACKAGE *package, BOOL compressed, MSIMEDIAINFO *mi)
Definition: media.c:838
static WCHAR * get_base_url(MSIDATABASE *db)
Definition: media.c:669
static INT_PTR CDECL cabinet_open_stream(char *pszFile, int oflag, int pmode)
Definition: media.c:185
static int CDECL cabinet_close(INT_PTR hf)
Definition: media.c:164
static INT_PTR cabinet_partial_file(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
Definition: media.c:281
static INT_PTR cabinet_next_cabinet_stream(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
Definition: media.c:372
static BOOL extract_cabinet_stream(MSIPACKAGE *package, MSIMEDIAINFO *mi, LPVOID data)
Definition: media.c:607
static INT_PTR cabinet_close_file_info(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
Definition: media.c:486
static LONG CDECL cabinet_seek_stream(INT_PTR hf, LONG dist, int seektype)
Definition: media.c:245
static UINT media_get_disk_info(MSIPACKAGE *package, MSIMEDIAINFO *mi)
Definition: media.c:262
static LONG CDECL cabinet_seek(INT_PTR hf, LONG dist, int seektype)
Definition: media.c:170
void msi_free_media_info(MSIMEDIAINFO *mi)
Definition: media.c:649
static UINT CDECL cabinet_read_stream(INT_PTR hf, void *pv, UINT cb)
Definition: media.c:225
static UINT get_drive_type(const WCHAR *path)
Definition: media.c:658
static UINT find_published_source(MSIPACKAGE *package, MSIMEDIAINFO *mi)
Definition: media.c:742
static INT_PTR cabinet_copy_file(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
Definition: media.c:401
static UINT CDECL cabinet_write(INT_PTR hf, void *pv, UINT cb)
Definition: media.c:153
static INT_PTR CDECL cabinet_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
Definition: media.c:521
static INT_PTR cabinet_next_cabinet(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
Definition: media.c:301
BOOL msi_cabextract(MSIPACKAGE *package, MSIMEDIAINFO *mi, LPVOID data)
Definition: media.c:640
UINT msi_load_media_info(MSIPACKAGE *package, UINT Sequence, MSIMEDIAINFO *mi)
Definition: media.c:677
#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
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
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#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
int MSI_RecordGetInteger(MSIRECORD *, UINT)
Definition: record.c:213
UINT MSI_RecordSetInteger(MSIRECORD *, UINT, int)
Definition: record.c:280
WCHAR * encode_streamname(BOOL is_table, const WCHAR *in)
UINT msi_download_file(LPCWSTR szUrl, LPWSTR filename)
Definition: package.c:1026
UINT msi_package_add_media_disk(MSIPACKAGE *, DWORD, DWORD, DWORD, LPWSTR, LPWSTR)
Definition: package.c:2648
const WCHAR * MSI_RecordGetString(const MSIRECORD *, UINT)
Definition: record.c:433
static char * strdupWtoU(LPCWSTR str)
Definition: msipriv.h:1172
#define MSICABEXTRACT_BEGINEXTRACT
Definition: msipriv.h:1101
MSIRECORD *WINAPIV MSI_QueryGetRecord(MSIDATABASE *db, LPCWSTR query,...)
Definition: msiquery.c:201
WCHAR * msi_dup_property(MSIDATABASE *db, const WCHAR *prop)
INT MSI_ProcessMessage(MSIPACKAGE *, INSTALLMESSAGE, MSIRECORD *)
Definition: package.c:1909
UINT MSI_RecordSetStringW(MSIRECORD *, UINT, LPCWSTR)
Definition: record.c:597
MSIRECORD * MSI_CreateRecord(UINT)
Definition: record.c:76
#define MSICABEXTRACT_FILEEXTRACTED
Definition: msipriv.h:1102
UINT msi_get_stream(MSIDATABASE *, const WCHAR *, IStream **)
Definition: streams.c:499
UINT msi_package_add_info(MSIPACKAGE *, DWORD, DWORD, LPCWSTR, LPWSTR)
Definition: package.c:2625
static LPWSTR strdupUtoW(LPCSTR str)
Definition: msipriv.h:1185
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(...)
_Check_return_ _CRTIMP wchar_t *__cdecl wcsdup(_In_z_ const wchar_t *_Str)
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
HRESULT hr
Definition: shlfolder.c:183
@ URLIS_URL
Definition: shlwapi.h:1217
#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:179
UINT id
Definition: media.c:180
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
MSIINSTALLCONTEXT 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:426
#define DRIVE_REMOVABLE
Definition: winbase.h:277
#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:808
#define IDRETRY
Definition: winuser.h:836
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