Module: wine Branch: master Commit: 32aed6078680bc322fd8a9f34d2a5fae7a791d1e URL: http://source.winehq.org/git/wine.git/?a=commit;h=32aed6078680bc322fd8a9f34d...
Author: Hans Leidekker hans@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: