diff --git a/dlls/msi/media.c b/dlls/msi/media.c index 5c53027e900..c8a14879a81 100644 --- a/dlls/msi/media.c +++ b/dlls/msi/media.c @@ -264,7 +264,6 @@ static LONG CDECL cabinet_seek_stream( INT_PTR hf, LONG dist, int seektype ) static UINT CDECL msi_media_get_disk_info(MSIPACKAGE *package, MSIMEDIAINFO *mi) { MSIRECORD *row; - LPWSTR ptr; static const WCHAR query[] = { 'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ', @@ -285,10 +284,7 @@ static UINT CDECL msi_media_get_disk_info(MSIPACKAGE *package, MSIMEDIAINFO *mi) if (!mi->first_volume) mi->first_volume = strdupW(mi->volume_label); - ptr = strrchrW(mi->source, '\\') + 1; - lstrcpyW(ptr, mi->cabinet); msiobj_release(&row->hdr); - return ERROR_SUCCESS; } @@ -300,12 +296,24 @@ static INT_PTR cabinet_partial_file(FDINOTIFICATIONTYPE fdint, return 0; } +static WCHAR *get_cabinet_filename(MSIMEDIAINFO *mi) +{ + int len; + WCHAR *ret; + + len = strlenW(mi->sourcedir) + strlenW(mi->cabinet) + 1; + if (!(ret = msi_alloc(len * sizeof(WCHAR)))) return NULL; + strcpyW(ret, mi->sourcedir); + strcatW(ret, mi->cabinet); + return ret; +} + static INT_PTR cabinet_next_cabinet(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin) { MSICABDATA *data = pfdin->pv; MSIMEDIAINFO *mi = data->mi; - LPWSTR cab = strdupAtoW(pfdin->psz1); + LPWSTR cabinet_file = NULL, cab = strdupAtoW(pfdin->psz1); INT_PTR res = -1; UINT rc; @@ -332,10 +340,13 @@ static INT_PTR cabinet_next_cabinet(FDINOTIFICATIONTYPE fdint, goto done; } - TRACE("Searching for %s\n", debugstr_w(mi->source)); + if (!(cabinet_file = get_cabinet_filename(mi))) + goto done; + + TRACE("Searching for %s\n", debugstr_w(cabinet_file)); res = 0; - if (GetFileAttributesW(mi->source) == INVALID_FILE_ATTRIBUTES) + if (GetFileAttributesW(cabinet_file) == INVALID_FILE_ATTRIBUTES) { if (msi_change_media(data->package, mi) != ERROR_SUCCESS) res = -1; @@ -343,6 +354,7 @@ static INT_PTR cabinet_next_cabinet(FDINOTIFICATIONTYPE fdint, done: msi_free(cab); + msi_free(cabinet_file); return res; } @@ -504,12 +516,11 @@ static INT_PTR CDECL cabinet_notify_stream( FDINOTIFICATIONTYPE fdint, PFDINOTIF static BOOL extract_cabinet( MSIPACKAGE* package, MSIMEDIAINFO *mi, LPVOID data ) { LPSTR cabinet, cab_path = NULL; - LPWSTR ptr; HFDI hfdi; ERF erf; BOOL ret = FALSE; - TRACE("Extracting %s\n", debugstr_w(mi->source)); + TRACE("Extracting %s\n", debugstr_w(mi->cabinet)); hfdi = FDICreate( cabinet_alloc, cabinet_free, cabinet_open, cabinet_read, cabinet_write, cabinet_close, cabinet_seek, 0, &erf ); @@ -519,17 +530,14 @@ static BOOL extract_cabinet( MSIPACKAGE* package, MSIMEDIAINFO *mi, LPVOID data return FALSE; } - ptr = strrchrW( mi->source, '\\' ) + 1; - cabinet = strdupWtoA( ptr ); + cabinet = strdupWtoA( mi->cabinet ); if (!cabinet) goto done; - cab_path = strdupWtoA( mi->source ); + cab_path = strdupWtoA( mi->sourcedir ); if (!cab_path) goto done; - cab_path[ptr - mi->source] = '\0'; - ret = FDICopy( hfdi, cabinet, cab_path, 0, cabinet_notify, NULL, data ); if (!ret) ERR("FDICopy failed\n"); @@ -652,12 +660,9 @@ static UINT msi_load_media_info(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO mi->first_volume = strdupW(mi->volume_label); source_dir = msi_dup_property(package, cszSourceDir); - lstrcpyW(mi->source, source_dir); + lstrcpyW(mi->sourcedir, source_dir); mi->type = get_drive_type(source_dir); - if (file->IsCompressed && mi->cabinet && mi->cabinet[0] != '#') - lstrcatW(mi->source, mi->cabinet); - options = MSICODE_PRODUCT; if (mi->type == DRIVE_CDROM || mi->type == DRIVE_REMOVABLE) { @@ -671,7 +676,7 @@ static UINT msi_load_media_info(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO } else { - source = mi->source; + source = mi->sourcedir; options |= MSISOURCETYPE_NETWORK; } @@ -724,9 +729,8 @@ static UINT find_published_source(MSIPACKAGE *package, MSIMEDIAINFO *mi) { if (!strncmpiW(source, volume, strlenW(source))) { - lstrcpyW(mi->source, source); - lstrcatW(mi->source, mi->cabinet); - TRACE("Found network source %s\n", debugstr_w(mi->source)); + lstrcpyW(mi->sourcedir, source); + TRACE("Found network source %s\n", debugstr_w(mi->sourcedir)); return ERROR_SUCCESS; } } @@ -749,8 +753,8 @@ static UINT find_published_source(MSIPACKAGE *package, MSIMEDIAINFO *mi) if (source_matches_volume(mi, source)) { /* FIXME: what about SourceDir */ - lstrcpyW(mi->source, source); - TRACE("Found disk source %s\n", debugstr_w(mi->source)); + lstrcpyW(mi->sourcedir, source); + TRACE("Found disk source %s\n", debugstr_w(mi->sourcedir)); return ERROR_SUCCESS; } } @@ -761,6 +765,7 @@ static UINT find_published_source(MSIPACKAGE *package, MSIMEDIAINFO *mi) UINT ready_media(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO *mi) { UINT rc = ERROR_SUCCESS; + WCHAR *cabinet_file; /* media info for continuous cabinet is already loaded */ if (mi->is_continuous) @@ -777,15 +782,24 @@ UINT ready_media(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO *mi) if (!mi->cabinet || mi->cabinet[0] == '#') return ERROR_SUCCESS; + cabinet_file = get_cabinet_filename(mi); + /* package should be downloaded */ if (file->IsCompressed && - GetFileAttributesW(mi->source) == INVALID_FILE_ATTRIBUTES && + GetFileAttributesW(cabinet_file) == INVALID_FILE_ATTRIBUTES && package->BaseURL && UrlIsW(package->BaseURL, URLIS_URL)) { - WCHAR temppath[MAX_PATH]; + WCHAR temppath[MAX_PATH], *p; - msi_download_file(mi->source, temppath); - lstrcpyW(mi->source, temppath); + msi_download_file(cabinet_file, temppath); + if ((p = strrchrW(temppath, '\\'))) *p = 0; + + msi_free(mi->sourcedir); + strcpyW(mi->sourcedir, temppath); + msi_free(mi->cabinet); + strcpyW(mi->cabinet, p + 1); + + msi_free(cabinet_file); return ERROR_SUCCESS; } @@ -803,20 +817,25 @@ UINT ready_media(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO *mi) { rc = msi_change_media(package, mi); if (rc != ERROR_SUCCESS) + { + msi_free(cabinet_file); return rc; + } } } if (file->IsCompressed && - GetFileAttributesW(mi->source) == INVALID_FILE_ATTRIBUTES) + GetFileAttributesW(cabinet_file) == INVALID_FILE_ATTRIBUTES) { rc = find_published_source(package, mi); if (rc != ERROR_SUCCESS) { - ERR("Cabinet not found: %s\n", debugstr_w(mi->source)); + ERR("Cabinet not found: %s\n", debugstr_w(cabinet_file)); + msi_free(cabinet_file); return ERROR_INSTALL_FAILURE; } } + msi_free(cabinet_file); return ERROR_SUCCESS; } diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 4546f5c419e..f13f5b94eff 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -143,7 +143,7 @@ typedef struct tagMSIMEDIAINFO LPWSTR volume_label; BOOL is_continuous; BOOL is_extracted; - WCHAR source[MAX_PATH]; + WCHAR sourcedir[MAX_PATH]; } MSIMEDIAINFO; typedef struct tagMSIPATCHINFO