msi: Improve handling of short paths.

This commit is contained in:
Mike McCormack 2006-03-21 19:40:36 +09:00 committed by Alexandre Julliard
parent f40f81b6d5
commit c1513be48c
4 changed files with 96 additions and 63 deletions

View File

@ -1269,6 +1269,17 @@ static UINT load_feature(MSIRECORD * row, LPVOID param)
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static LPWSTR folder_split_path(LPWSTR p, WCHAR ch)
{
if (!p)
return p;
p = strchrW(p, ch);
if (!p)
return p;
*p = 0;
return p+1;
}
static UINT load_file(MSIRECORD *row, LPVOID param) static UINT load_file(MSIRECORD *row, LPVOID param)
{ {
MSIPACKAGE* package = (MSIPACKAGE*)param; MSIPACKAGE* package = (MSIPACKAGE*)param;
@ -1293,7 +1304,7 @@ static UINT load_file(MSIRECORD *row, LPVOID param)
reduce_to_longfilename( file->FileName ); reduce_to_longfilename( file->FileName );
file->ShortName = msi_dup_record_field( row, 3 ); file->ShortName = msi_dup_record_field( row, 3 );
reduce_to_shortfilename( file->ShortName ); file->LongName = strdupW( folder_split_path(file->ShortName, '|'));
file->FileSize = MSI_RecordGetInteger( row, 4 ); file->FileSize = MSI_RecordGetInteger( row, 4 );
file->Version = msi_dup_record_field( row, 5 ); file->Version = msi_dup_record_field( row, 5 );
@ -1411,7 +1422,6 @@ static UINT ACTION_FileCost(MSIPACKAGE *package)
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static MSIFOLDER *load_folder( MSIPACKAGE *package, LPCWSTR dir ) static MSIFOLDER *load_folder( MSIPACKAGE *package, LPCWSTR dir )
{ {
static const WCHAR Query[] = static const WCHAR Query[] =
@ -1420,10 +1430,10 @@ static MSIFOLDER *load_folder( MSIPACKAGE *package, LPCWSTR dir )
'W','H','E','R','E',' ', '`', 'D','i','r','e','c','t', 'o','r','y','`', 'W','H','E','R','E',' ', '`', 'D','i','r','e','c','t', 'o','r','y','`',
' ','=',' ','\'','%','s','\'', ' ','=',' ','\'','%','s','\'',
0}; 0};
LPWSTR ptargetdir, targetdir, srcdir; static const WCHAR szDot[] = { '.',0 };
LPWSTR p, tgt_short, tgt_long, src_short, src_long;
LPCWSTR parent; LPCWSTR parent;
LPWSTR shortname = NULL; MSIRECORD *row;
MSIRECORD * row = 0;
MSIFOLDER *folder; MSIFOLDER *folder;
TRACE("Looking for dir %s\n",debugstr_w(dir)); TRACE("Looking for dir %s\n",debugstr_w(dir));
@ -1444,54 +1454,40 @@ static MSIFOLDER *load_folder( MSIPACKAGE *package, LPCWSTR dir )
if (!row) if (!row)
return NULL; return NULL;
ptargetdir = targetdir = msi_dup_record_field(row,3); p = msi_dup_record_field(row, 3);
/* split src and target dir */ /* split src and target dir */
if (strchrW(targetdir,':')) tgt_short = p;
{ src_short = folder_split_path( p, ':' );
srcdir=strchrW(targetdir,':');
*srcdir=0;
srcdir ++;
}
else
srcdir=NULL;
/* for now only pick long filename versions */ /* split the long and short pathes */
if (strchrW(targetdir,'|')) tgt_long = folder_split_path( tgt_short, '|' );
{ src_long = folder_split_path( src_short, '|' );
shortname = targetdir;
targetdir = strchrW(targetdir,'|');
*targetdir = 0;
targetdir ++;
}
/* for the sourcedir pick the short filename */
if (srcdir && strchrW(srcdir,'|'))
{
LPWSTR p = strchrW(srcdir,'|');
*p = 0;
}
/* now check for root dirs */ /* check for root dirs */
if (targetdir[0] == '.' && targetdir[1] == 0) if (!lstrcmpW(szDot, tgt_short))
targetdir = NULL; tgt_short = NULL;
if (!lstrcmpW(szDot, tgt_long))
tgt_long = NULL;
if (targetdir) if (!tgt_long)
{ tgt_long = tgt_short;
TRACE(" TargetDefault = %s\n",debugstr_w(targetdir)); if (!src_short)
msi_free( folder->TargetDefault); src_short = tgt_long;
folder->TargetDefault = strdupW(targetdir); if (!src_long)
} src_long = src_short;
if (srcdir) /* FIXME: use the target short path too */
folder->SourceDefault = strdupW(srcdir); folder->TargetDefault = strdupW(tgt_long);
else if (shortname) folder->SourceShortPath = strdupW(src_long);
folder->SourceDefault = strdupW(shortname); folder->SourceLongPath = strdupW(src_long);
else if (targetdir) msi_free(p);
folder->SourceDefault = strdupW(targetdir);
msi_free(ptargetdir);
TRACE(" SourceDefault = %s\n", debugstr_w( folder->SourceDefault ));
parent = MSI_RecordGetString(row,2); TRACE("TargetDefault = %s\n",debugstr_w( folder->TargetDefault ));
TRACE("SourceLong = %s\n", debugstr_w( folder->SourceLongPath ));
TRACE("SourceShort = %s\n", debugstr_w( folder->SourceShortPath ));
parent = MSI_RecordGetString(row, 2);
if (parent) if (parent)
{ {
folder->Parent = load_folder( package, parent ); folder->Parent = load_folder( package, parent );

View File

@ -78,7 +78,8 @@ typedef struct tagMSIFOLDER
struct list entry; struct list entry;
LPWSTR Directory; LPWSTR Directory;
LPWSTR TargetDefault; LPWSTR TargetDefault;
LPWSTR SourceDefault; LPWSTR SourceLongPath;
LPWSTR SourceShortPath;
LPWSTR ResolvedTarget; LPWSTR ResolvedTarget;
LPWSTR ResolvedSource; LPWSTR ResolvedSource;
@ -109,6 +110,7 @@ typedef struct tagMSIFILE
MSICOMPONENT *Component; MSICOMPONENT *Component;
LPWSTR FileName; LPWSTR FileName;
LPWSTR ShortName; LPWSTR ShortName;
LPWSTR LongName;
INT FileSize; INT FileSize;
LPWSTR Version; LPWSTR Version;
LPWSTR Language; LPWSTR Language;

View File

@ -328,9 +328,15 @@ static VOID set_file_source(MSIPACKAGE* package, MSIFILE* file, MSICOMPONENT*
{ {
if (file->Attributes & msidbFileAttributesNoncompressed) if (file->Attributes & msidbFileAttributesNoncompressed)
{ {
LPWSTR p; LPWSTR p, path;
p = resolve_folder(package, comp->Directory, TRUE, FALSE, NULL); p = resolve_folder(package, comp->Directory, TRUE, FALSE, NULL);
file->SourcePath = build_directory_name(2, p, file->ShortName); path = build_directory_name(2, p, file->ShortName);
if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW( path ))
{
msi_free(path);
path = build_directory_name(2, p, file->LongName);
}
file->SourcePath = path;
msi_free(p); msi_free(p);
} }
else else

View File

@ -355,20 +355,47 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
} }
else else
{ {
if (f->SourceDefault && f->SourceDefault[0]!='.') /* source may be in a few different places ... check each of them */
path = build_directory_name( 3, p, f->SourceDefault, NULL ); path = NULL;
else
path = strdupW(p);
TRACE("source -> %s\n", debugstr_w(path));
/* if the directory doesn't exist, use the root */ /* try the long path directory */
if (f->SourceLongPath)
{
path = build_directory_name( 3, p, f->SourceLongPath, NULL );
if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW( path )) if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW( path ))
{ {
msi_free( path ); msi_free( path );
path = get_source_root( package ); path = NULL;
TRACE("defaulting to %s\n", debugstr_w(path));
} }
else }
/* try the short path directory */
if (!path && f->SourceShortPath)
{
path = build_directory_name( 3, p, f->SourceShortPath, NULL );
if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW( path ))
{
msi_free( path );
path = NULL;
}
}
/* try the parent folder's path */
if (!path)
{
path = strdupW(p);
if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW( path ))
{
msi_free( path );
path = NULL;
}
}
/* try the root of the install */
if (!path)
path = get_source_root( package );
TRACE("source -> %s\n", debugstr_w(path));
f->ResolvedSource = strdupW( path ); f->ResolvedSource = strdupW( path );
} }
msi_free(p); msi_free(p);
@ -508,7 +535,8 @@ void ACTION_free_package_structures( MSIPACKAGE* package)
list_remove( &folder->entry ); list_remove( &folder->entry );
msi_free( folder->Directory ); msi_free( folder->Directory );
msi_free( folder->TargetDefault ); msi_free( folder->TargetDefault );
msi_free( folder->SourceDefault ); msi_free( folder->SourceLongPath );
msi_free( folder->SourceShortPath );
msi_free( folder->ResolvedTarget ); msi_free( folder->ResolvedTarget );
msi_free( folder->ResolvedSource ); msi_free( folder->ResolvedSource );
msi_free( folder->Property ); msi_free( folder->Property );
@ -537,6 +565,7 @@ void ACTION_free_package_structures( MSIPACKAGE* package)
msi_free( file->File ); msi_free( file->File );
msi_free( file->FileName ); msi_free( file->FileName );
msi_free( file->ShortName ); msi_free( file->ShortName );
msi_free( file->LongName );
msi_free( file->Version ); msi_free( file->Version );
msi_free( file->Language ); msi_free( file->Language );
msi_free( file->SourcePath ); msi_free( file->SourcePath );