MSI: MsiFormatRecord improvements.

Aric Stewart aric at codeweavers.com
Fri May 27 10:22:51 CDT 2005


restrict deformating of nested index keys [[1]]
introduce the beginning of group deformating {}

-------------- next part --------------
Index: dlls/msi/format.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/format.c,v
retrieving revision 1.13
diff -u -r1.13 format.c
--- dlls/msi/format.c	25 May 2005 17:49:49 -0000	1.13
+++ dlls/msi/format.c	27 May 2005 15:21:21 -0000
@@ -50,6 +50,11 @@
 WINE_DEFAULT_DEBUG_CHANNEL(msi);
 
 
+static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, 
+                                     WCHAR** data, DWORD len, MSIRECORD* record,
+                                     BOOL* in_group);
+
+
 LPWSTR build_default_format(MSIRECORD* record)
 {
     int i;  
@@ -239,6 +244,45 @@
     return value;
 }
 
+/*
+ * Groups cannot be nested. They are just treated as from { to next } 
+ */
+static BOOL find_next_group(LPCWSTR source, DWORD len_remaining,
+                                    LPWSTR *group, LPCWSTR *mark, 
+                                    LPCWSTR* mark2)
+{
+    int i;
+    BOOL found = FALSE;
+
+    *mark = scanW(source,'{',len_remaining);
+    if (!*mark)
+        return FALSE;
+
+    for (i = 1; (*mark - source) + i < len_remaining; i++)
+    {
+        if ((*mark)[i] == '}')
+        {
+            found = TRUE;
+            break;
+        }
+    }
+    if (! found)
+        return FALSE;
+
+    *mark2 = &(*mark)[i]; 
+
+    i = *mark2 - *mark;
+    *group = HeapAlloc(GetProcessHeap(),0,i*sizeof(WCHAR));
+
+    i -= 1;
+    memcpy(*group,&(*mark)[1],i*sizeof(WCHAR));
+    (*group)[i] = 0;
+
+    TRACE("Found group %s\n",debugstr_w(*group));
+    return TRUE;
+}
+
+
 static BOOL find_next_outermost_key(LPCWSTR source, DWORD len_remaining,
                                     LPWSTR *key, LPCWSTR *mark, LPCWSTR* mark2, 
                                     BOOL *nested)
@@ -284,13 +328,71 @@
     return TRUE;
 }
 
+LPWSTR deformat_group(MSIPACKAGE* package, LPWSTR group, DWORD len, 
+                      MSIRECORD* record, DWORD* size)
+{
+    LPWSTR value;
+    LPCWSTR mark, mark2;
+    LPWSTR key;
+    BOOL nested;
+    INT failcount;
+    static const WCHAR fmt[] = {'{','%','s','}',0};
+    UINT sz;
+
+    if (!group || group[0] == 0) 
+    {
+        *size = 0;
+        return NULL;
+    }
+    /* if no [] then group is returned as is */
+
+     if (!find_next_outermost_key(group, len, &key, &mark, &mark2, &nested))
+     {
+         *size = (len+2)*sizeof(WCHAR);
+         value = HeapAlloc(GetProcessHeap(),0,*size);
+         sprintfW(value,fmt,group);
+         /* do not return size of the null at the end */
+         *size = (len+1)*sizeof(WCHAR);
+         return value;
+     }
+
+     HeapFree(GetProcessHeap(),0,key);
+     failcount = 0;
+     sz = deformat_string_internal(package, group, &value, strlenW(group),
+                                     record, &failcount);
+     if (failcount==0)
+     {
+        *size = sz * sizeof(WCHAR);
+        return value;
+     }
+     else if (failcount < 0)
+     {
+         LPWSTR v2;
+
+         v2 = HeapAlloc(GetProcessHeap(),0,(sz+2)*sizeof(WCHAR));
+         v2[0] = '{';
+         memcpy(&v2[1],value,sz*sizeof(WCHAR));
+         v2[sz+1]='}';
+         HeapFree(GetProcessHeap(),0,value);
+
+         *size = (sz+2)*sizeof(WCHAR);
+         return v2;
+     }
+     else
+     {
+         *size = 0;
+         return NULL;
+     }
+}
+
 
 /*
  * len is in WCHARs
  * return is also in WCHARs
  */
 static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, 
-                                     WCHAR** data, DWORD len, MSIRECORD* record)
+                                     WCHAR** data, DWORD len, MSIRECORD* record,
+                                     INT* failcount)
 {
     LPCWSTR mark = NULL;
     LPCWSTR mark2 = NULL;
@@ -313,7 +415,8 @@
     TRACE("Starting with %s\n",debugstr_w(ptr));
 
     /* scan for special characters... fast exit */
-    if (!scanW(ptr,'[',len) || (scanW(ptr,'[',len) && !scanW(ptr,']',len)))
+    if ((!scanW(ptr,'[',len) || (scanW(ptr,'[',len) && !scanW(ptr,']',len))) && 
+        (scanW(ptr,'{',len) && !scanW(ptr,'}',len)))
     {
         /* not formatted */
         *data = HeapAlloc(GetProcessHeap(),0,(len*sizeof(WCHAR)));
@@ -326,9 +429,18 @@
 
     while (progress - ptr < len)
     {
+        /* seek out first group if existing */
+        if (find_next_group(progress, len - (progress - ptr), &key,
+                                &mark, &mark2))
+        {
+            value = deformat_group(package, key, strlenW(key)+1, record, 
+                            &chunk);
+            key = NULL;
+            nested = FALSE;
+        }
         /* formatted string located */
-        if (!find_next_outermost_key(progress, len - (progress - ptr), &key,
-                                     &mark, &mark2, &nested))
+        else if (!find_next_outermost_key(progress, len - (progress - ptr), 
+                                &key, &mark, &mark2, &nested))
         {
             LPBYTE nd2;
 
@@ -368,7 +480,7 @@
         {
             TRACE("Nested key... %s\n",debugstr_w(key));
             deformat_string_internal(package, key, &value, strlenW(key)+1,
-                                     record);
+                                     record, failcount);
 
             HeapFree(GetProcessHeap(),0,key);
             key = value;
@@ -379,22 +491,31 @@
         if (!package)
         {
             /* only deformat number indexs */
-            if (is_key_number(key))
+            if (key && is_key_number(key))
+            {
                 value = deformat_index(record,key,&chunk);  
+                if (!chunk && failcount && *failcount >= 0)
+                    (*failcount)++;
+            }
             else
             {
-                DWORD keylen = strlenW(key);
-                chunk = (keylen + 2)*sizeof(WCHAR);
-                value = HeapAlloc(GetProcessHeap(),0,chunk);
-                value[0] = '[';
-                memcpy(&value[1],key,keylen*sizeof(WCHAR));
-                value[1+keylen] = ']';
+                if (failcount)
+                    *failcount = -1;
+                if(key)
+                {
+                    DWORD keylen = strlenW(key);
+                    chunk = (keylen + 2)*sizeof(WCHAR);
+                    value = HeapAlloc(GetProcessHeap(),0,chunk);
+                    value[0] = '[';
+                    memcpy(&value[1],key,keylen*sizeof(WCHAR));
+                    value[1+keylen] = ']';
+                }
             }
         }
         else
         {
             sz = 0;
-            switch (key[0])
+            if (key) switch (key[0])
             {
                 case '~':
                     value = deformat_NULL(&chunk);
@@ -415,8 +536,17 @@
                     value = deformat_environment(package,&key[1],&chunk);
                 break;
                 default:
+                    /* index keys cannot be nested */
                     if (is_key_number(key))
-                        value = deformat_index(record,key,&chunk);
+                        if (!nested)
+                            value = deformat_index(record,key,&chunk);
+                        else
+                        {
+                            static const WCHAR fmt[] = {'[','%','s',']',0};
+                            value = HeapAlloc(GetProcessHeap(),0,10);
+                            sprintfW(value,fmt,key);
+                            chunk = strlenW(value)*sizeof(WCHAR);
+                        }
                     else
                         value = deformat_property(package,key,&chunk);
                 break;      
@@ -439,6 +569,8 @@
             size+=chunk;   
             HeapFree(GetProcessHeap(),0,value);
         }
+        else if (failcount && *failcount >=0 )
+            (*failcount)++;
 
         progress = mark2+1;
     }
@@ -467,7 +599,7 @@
     TRACE("(%s)\n",debugstr_w(rec));
 
     len = deformat_string_internal(package,rec,&deformated,strlenW(rec),
-                                   record);
+                                   record, NULL);
 
     if (buffer)
     {
@@ -514,7 +646,7 @@
     TRACE("(%s)\n",debugstr_w(rec));
 
     len = deformat_string_internal(package,rec,&deformated,strlenW(rec),
-                                   record);
+                                   record, NULL);
     lenA = WideCharToMultiByte(CP_ACP,0,deformated,len,NULL,0,NULL,NULL);
 
     if (buffer)


More information about the wine-patches mailing list