Mike McCormack : msi: Improve handling of short paths.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Mar 21 13:21:19 CST 2006


Module: wine
Branch: refs/heads/master
Commit: c1513be48c414f4b862111ca5bd9bda85ab5c94b
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=c1513be48c414f4b862111ca5bd9bda85ab5c94b

Author: Mike McCormack <mike at codeweavers.com>
Date:   Tue Mar 21 19:40:36 2006 +0900

msi: Improve handling of short paths.

---

 dlls/msi/action.c  |   94 +++++++++++++++++++++++++---------------------------
 dlls/msi/action.h  |    4 ++
 dlls/msi/files.c   |   10 ++++--
 dlls/msi/helpers.c |   55 +++++++++++++++++++++++-------
 4 files changed, 98 insertions(+), 65 deletions(-)

diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index 60907a9..6501031 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -1269,6 +1269,17 @@ static UINT load_feature(MSIRECORD * row
     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)
 {
     MSIPACKAGE* package = (MSIPACKAGE*)param;
@@ -1293,7 +1304,7 @@ static UINT load_file(MSIRECORD *row, LP
     reduce_to_longfilename( file->FileName );
 
     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->Version = msi_dup_record_field( row, 5 );
@@ -1411,7 +1422,6 @@ static UINT ACTION_FileCost(MSIPACKAGE *
     return ERROR_SUCCESS;
 }
 
-
 static MSIFOLDER *load_folder( MSIPACKAGE *package, LPCWSTR dir )
 {
     static const WCHAR Query[] =
@@ -1420,10 +1430,10 @@ static MSIFOLDER *load_folder( MSIPACKAG
          'W','H','E','R','E',' ', '`', 'D','i','r','e','c','t', 'o','r','y','`',
          ' ','=',' ','\'','%','s','\'',
          0};
-    LPWSTR ptargetdir, targetdir, srcdir;
+    static const WCHAR szDot[] = { '.',0 };
+    LPWSTR p, tgt_short, tgt_long, src_short, src_long;
     LPCWSTR parent;
-    LPWSTR shortname = NULL;
-    MSIRECORD * row = 0;
+    MSIRECORD *row;
     MSIFOLDER *folder;
 
     TRACE("Looking for dir %s\n",debugstr_w(dir));
@@ -1444,54 +1454,40 @@ static MSIFOLDER *load_folder( MSIPACKAG
     if (!row)
         return NULL;
 
-    ptargetdir = targetdir = msi_dup_record_field(row,3);
+    p = msi_dup_record_field(row, 3);
 
     /* split src and target dir */
-    if (strchrW(targetdir,':'))
-    {
-        srcdir=strchrW(targetdir,':');
-        *srcdir=0;
-        srcdir ++;
-    }
-    else
-        srcdir=NULL;
+    tgt_short = p;
+    src_short = folder_split_path( p, ':' );
 
-    /* for now only pick long filename versions */
-    if (strchrW(targetdir,'|'))
-    {
-        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 */
-    if (targetdir[0] == '.' && targetdir[1] == 0)
-        targetdir = NULL;
-        
-    if (targetdir)
-    {
-        TRACE("   TargetDefault = %s\n",debugstr_w(targetdir));
-        msi_free( folder->TargetDefault);
-        folder->TargetDefault = strdupW(targetdir);
-    }
-
-    if (srcdir)
-        folder->SourceDefault = strdupW(srcdir);
-    else if (shortname)
-        folder->SourceDefault = strdupW(shortname);
-    else if (targetdir)
-        folder->SourceDefault = strdupW(targetdir);
-    msi_free(ptargetdir);
-        TRACE("   SourceDefault = %s\n", debugstr_w( folder->SourceDefault ));
+    /* split the long and short pathes */
+    tgt_long = folder_split_path( tgt_short, '|' );
+    src_long = folder_split_path( src_short, '|' );
+
+    /* check for root dirs */
+    if (!lstrcmpW(szDot, tgt_short))
+        tgt_short = NULL;
+    if (!lstrcmpW(szDot, tgt_long))
+        tgt_long = NULL;
+
+    if (!tgt_long)
+        tgt_long = tgt_short;
+    if (!src_short)
+        src_short = tgt_long;
+    if (!src_long)
+        src_long = src_short;
+
+    /* FIXME: use the target short path too */
+    folder->TargetDefault = strdupW(tgt_long);
+    folder->SourceShortPath = strdupW(src_long);
+    folder->SourceLongPath = strdupW(src_long);
+    msi_free(p);
+
+    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);
+    parent = MSI_RecordGetString(row, 2);
     if (parent) 
     {
         folder->Parent = load_folder( package, parent );
diff --git a/dlls/msi/action.h b/dlls/msi/action.h
index 9b3e58d..be2654c 100644
--- a/dlls/msi/action.h
+++ b/dlls/msi/action.h
@@ -78,7 +78,8 @@ typedef struct tagMSIFOLDER
     struct list entry;
     LPWSTR Directory;
     LPWSTR TargetDefault;
-    LPWSTR SourceDefault;
+    LPWSTR SourceLongPath;
+    LPWSTR SourceShortPath;
 
     LPWSTR ResolvedTarget;
     LPWSTR ResolvedSource;
@@ -109,6 +110,7 @@ typedef struct tagMSIFILE
     MSICOMPONENT *Component;
     LPWSTR FileName;
     LPWSTR ShortName;
+    LPWSTR LongName;
     INT FileSize;
     LPWSTR Version;
     LPWSTR Language;
diff --git a/dlls/msi/files.c b/dlls/msi/files.c
index b5c80ca..aa6f8e6 100644
--- a/dlls/msi/files.c
+++ b/dlls/msi/files.c
@@ -328,9 +328,15 @@ static VOID set_file_source(MSIPACKAGE* 
 {
     if (file->Attributes & msidbFileAttributesNoncompressed)
     {
-        LPWSTR p;
+        LPWSTR p, path;
         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);
     }
     else
diff --git a/dlls/msi/helpers.c b/dlls/msi/helpers.c
index af604a5..ffbde9f 100644
--- a/dlls/msi/helpers.c
+++ b/dlls/msi/helpers.c
@@ -355,21 +355,48 @@ LPWSTR resolve_folder(MSIPACKAGE *packag
         }
         else 
         {
-            if (f->SourceDefault && f->SourceDefault[0]!='.')
-                path = build_directory_name( 3, p, f->SourceDefault, NULL );
-            else
-                path = strdupW(p);
-            TRACE("source -> %s\n", debugstr_w(path));
+            /* source may be in a few different places ... check each of them */
+            path = NULL;
 
-            /* if the directory doesn't exist, use the root */
-            if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW( path ))
+            /* try the long path directory */
+            if (f->SourceLongPath)
             {
-                msi_free( path );
-                path = get_source_root( package );
-                TRACE("defaulting to %s\n", debugstr_w(path));
+                path = build_directory_name( 3, p, f->SourceLongPath, NULL );
+                if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW( path ))
+                {
+                    msi_free( path );
+                    path = NULL;
+                }
             }
-            else
-                f->ResolvedSource = strdupW( path );
+
+            /* 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 );
         }
         msi_free(p);
     }
@@ -508,7 +535,8 @@ void ACTION_free_package_structures( MSI
         list_remove( &folder->entry );
         msi_free( folder->Directory );
         msi_free( folder->TargetDefault );
-        msi_free( folder->SourceDefault );
+        msi_free( folder->SourceLongPath );
+        msi_free( folder->SourceShortPath );
         msi_free( folder->ResolvedTarget );
         msi_free( folder->ResolvedSource );
         msi_free( folder->Property );
@@ -537,6 +565,7 @@ void ACTION_free_package_structures( MSI
         msi_free( file->File );
         msi_free( file->FileName );
         msi_free( file->ShortName );
+        msi_free( file->LongName );
         msi_free( file->Version );
         msi_free( file->Language );
         msi_free( file->SourcePath );




More information about the wine-cvs mailing list