[06/13] msi: Preserve strings with embedded nulls in the record implementation.
Hans Leidekker
hans at codeweavers.com
Mon Oct 29 06:13:54 CDT 2012
---
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:
--
1.7.10.4
More information about the wine-patches
mailing list