Hans Leidekker : msi: Preserve strings with embedded nulls in the record implementation.

Alexandre Julliard julliard at winehq.org
Mon Oct 29 13:52:52 CDT 2012


Module: wine
Branch: master
Commit: 32aed6078680bc322fd8a9f34d2a5fae7a791d1e
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=32aed6078680bc322fd8a9f34d2a5fae7a791d1e

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Mon Oct 29 12:13:54 2012 +0100

msi: Preserve strings with embedded nulls in the record implementation.

---

 dlls/msi/msipriv.h |    1 +
 dlls/msi/record.c  |   73 ++++++++++++++++++++++++++++-----------------------
 2 files changed, 41 insertions(+), 33 deletions(-)

diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 56c9340..897353e 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -823,6 +823,7 @@ extern MSIRECORD *MSI_CloneRecord( MSIRECORD * ) DECLSPEC_HIDDEN;
 extern BOOL MSI_RecordsAreEqual( MSIRECORD *, MSIRECORD * ) DECLSPEC_HIDDEN;
 extern BOOL MSI_RecordsAreFieldsEqual(MSIRECORD *a, MSIRECORD *b, UINT field) DECLSPEC_HIDDEN;
 extern UINT msi_record_set_string(MSIRECORD *, UINT, const WCHAR *, int) DECLSPEC_HIDDEN;
+extern const WCHAR *msi_record_get_string(const MSIRECORD *, UINT, int *) DECLSPEC_HIDDEN;
 
 /* stream internals */
 extern void enum_stream_names( IStorage *stg ) DECLSPEC_HIDDEN;
diff --git a/dlls/msi/record.c b/dlls/msi/record.c
index 263ea2c..d42dd81 100644
--- a/dlls/msi/record.c
+++ b/dlls/msi/record.c
@@ -156,6 +156,17 @@ static BOOL string2intW( LPCWSTR str, int *out )
     return TRUE;
 }
 
+static WCHAR *msi_strdupW( const WCHAR *value, int len )
+{
+    WCHAR *ret;
+
+    if (!value) return NULL;
+    if (!(ret = msi_alloc( (len + 1) * sizeof(WCHAR) ))) return NULL;
+    memcpy( ret, value, len * sizeof(WCHAR) );
+    ret[len] = 0;
+    return ret;
+}
+
 UINT MSI_RecordCopyField( MSIRECORD *in_rec, UINT in_n,
                           MSIRECORD *out_rec, UINT out_n )
 {
@@ -184,11 +195,12 @@ UINT MSI_RecordCopyField( MSIRECORD *in_rec, UINT in_n,
             out->u.pVal = in->u.pVal;
             break;
         case MSIFIELD_WSTR:
-            str = strdupW( in->u.szwVal );
-            if ( !str )
-                r = ERROR_OUTOFMEMORY;
-            else
+            if ((str = msi_strdupW( in->u.szwVal, in->len )))
+            {
                 out->u.szwVal = str;
+                out->len = in->len;
+            }
+            else r = ERROR_OUTOFMEMORY;
             break;
         case MSIFIELD_STREAM:
             IStream_AddRef( in->u.stream );
@@ -202,7 +214,6 @@ UINT MSI_RecordCopyField( MSIRECORD *in_rec, UINT in_n,
     }
 
     msiobj_unlock( &in_rec->hdr );
-
     return r;
 }
 
@@ -380,7 +391,7 @@ BOOL WINAPI MsiRecordIsNull( MSIHANDLE handle, UINT iField )
 UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField,
                LPSTR szValue, LPDWORD pcchValue)
 {
-    UINT len=0, ret;
+    UINT len = 0, ret = ERROR_SUCCESS;
     CHAR buffer[16];
 
     TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue);
@@ -394,7 +405,6 @@ UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField,
         return ERROR_SUCCESS;
     }
 
-    ret = ERROR_SUCCESS;
     switch( rec->fields[iField].type )
     {
     case MSIFIELD_INT:
@@ -404,11 +414,11 @@ UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField,
             lstrcpynA(szValue, buffer, *pcchValue);
         break;
     case MSIFIELD_WSTR:
-        len = WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, -1,
-                             NULL, 0 , NULL, NULL);
+        len = WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal,
+                                   rec->fields[iField].len + 1, NULL, 0 , NULL, NULL );
         if (szValue)
-            WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, -1,
-                                 szValue, *pcchValue, NULL, NULL);
+            WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal,
+                                 rec->fields[iField].len + 1, szValue, *pcchValue, NULL, NULL );
         if( szValue && *pcchValue && len>*pcchValue )
             szValue[*pcchValue-1] = 0;
         if( len )
@@ -448,23 +458,30 @@ UINT WINAPI MsiRecordGetStringA(MSIHANDLE handle, UINT iField,
     return ret;
 }
 
-const WCHAR *MSI_RecordGetString( const MSIRECORD *rec, UINT iField )
+const WCHAR *msi_record_get_string( const MSIRECORD *rec, UINT field, int *len )
 {
-    if( iField > rec->count )
+    if (field > rec->count)
         return NULL;
 
-    if( rec->fields[iField].type != MSIFIELD_WSTR )
+    if (rec->fields[field].type != MSIFIELD_WSTR)
         return NULL;
 
-    return rec->fields[iField].u.szwVal;
+    if (len) *len = rec->fields[field].len;
+
+    return rec->fields[field].u.szwVal;
+}
+
+const WCHAR *MSI_RecordGetString( const MSIRECORD *rec, UINT iField )
+{
+    return msi_record_get_string( rec, iField, NULL );
 }
 
 UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField,
                LPWSTR szValue, LPDWORD pcchValue)
 {
-    UINT len=0, ret;
+    static const WCHAR szFormat[] = {'%','d',0};
+    UINT len = 0, ret = ERROR_SUCCESS;
     WCHAR buffer[16];
-    static const WCHAR szFormat[] = { '%','d',0 };
 
     TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue);
 
@@ -477,7 +494,6 @@ UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField,
         return ERROR_SUCCESS;
     }
 
-    ret = ERROR_SUCCESS;
     switch( rec->fields[iField].type )
     {
     case MSIFIELD_INT:
@@ -487,9 +503,9 @@ UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField,
             lstrcpynW(szValue, buffer, *pcchValue);
         break;
     case MSIFIELD_WSTR:
-        len = lstrlenW( rec->fields[iField].u.szwVal );
+        len = rec->fields[iField].len;
         if (szValue)
-            lstrcpynW(szValue, rec->fields[iField].u.szwVal, *pcchValue);
+            memcpy( szValue, rec->fields[iField].u.szwVal, min(len + 1, *pcchValue) * sizeof(WCHAR) );
         break;
     case MSIFIELD_NULL:
         if( szValue && *pcchValue > 0 )
@@ -548,7 +564,7 @@ static UINT MSI_RecordDataSize(MSIRECORD *rec, UINT iField)
     case MSIFIELD_INT:
         return sizeof (INT);
     case MSIFIELD_WSTR:
-        return lstrlenW( rec->fields[iField].u.szwVal );
+        return rec->fields[iField].len;
     case MSIFIELD_NULL:
         break;
     case MSIFIELD_STREAM:
@@ -598,16 +614,6 @@ UINT WINAPI MsiRecordSetStringA( MSIHANDLE handle, UINT iField, LPCSTR szValue )
     return ret;
 }
 
-static WCHAR *msi_strdupW( const WCHAR *value, int len )
-{
-    WCHAR *ret;
-
-    if (!(ret = msi_alloc( (len + 1) * sizeof(WCHAR) ))) return NULL;
-    memcpy( ret, value, len * sizeof(WCHAR) );
-    ret[len] = 0;
-    return ret;
-}
-
 UINT msi_record_set_string( MSIRECORD *rec, UINT field, const WCHAR *value, int len )
 {
     if (field > rec->count)
@@ -1008,8 +1014,9 @@ BOOL MSI_RecordsAreFieldsEqual(MSIRECORD *a, MSIRECORD *b, UINT field)
             break;
 
         case MSIFIELD_WSTR:
-            if (strcmpW(a->fields[field].u.szwVal, b->fields[field].u.szwVal))
-                return FALSE;
+            if (a->fields[field].len != b->fields[field].len) return FALSE;
+            if (memcmp( a->fields[field].u.szwVal, b->fields[field].u.szwVal,
+                        a->fields[field].len * sizeof(WCHAR) )) return FALSE;
             break;
 
         case MSIFIELD_STREAM:




More information about the wine-cvs mailing list