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

This commit is contained in:
Hans Leidekker 2012-10-29 12:13:54 +01:00 committed by Alexandre Julliard
parent 8d28cc0ac7
commit 32aed60786
2 changed files with 44 additions and 36 deletions

View File

@ -823,6 +823,7 @@ extern MSIRECORD *MSI_CloneRecord( MSIRECORD * ) DECLSPEC_HIDDEN;
extern BOOL MSI_RecordsAreEqual( MSIRECORD *, MSIRECORD * ) DECLSPEC_HIDDEN; extern BOOL MSI_RecordsAreEqual( MSIRECORD *, MSIRECORD * ) DECLSPEC_HIDDEN;
extern BOOL MSI_RecordsAreFieldsEqual(MSIRECORD *a, MSIRECORD *b, UINT field) 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 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 */ /* stream internals */
extern void enum_stream_names( IStorage *stg ) DECLSPEC_HIDDEN; extern void enum_stream_names( IStorage *stg ) DECLSPEC_HIDDEN;

View File

@ -156,6 +156,17 @@ static BOOL string2intW( LPCWSTR str, int *out )
return TRUE; 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, UINT MSI_RecordCopyField( MSIRECORD *in_rec, UINT in_n,
MSIRECORD *out_rec, UINT out_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; out->u.pVal = in->u.pVal;
break; break;
case MSIFIELD_WSTR: case MSIFIELD_WSTR:
str = strdupW( in->u.szwVal ); if ((str = msi_strdupW( in->u.szwVal, in->len )))
if ( !str ) {
r = ERROR_OUTOFMEMORY;
else
out->u.szwVal = str; out->u.szwVal = str;
out->len = in->len;
}
else r = ERROR_OUTOFMEMORY;
break; break;
case MSIFIELD_STREAM: case MSIFIELD_STREAM:
IStream_AddRef( in->u.stream ); IStream_AddRef( in->u.stream );
@ -202,7 +214,6 @@ UINT MSI_RecordCopyField( MSIRECORD *in_rec, UINT in_n,
} }
msiobj_unlock( &in_rec->hdr ); msiobj_unlock( &in_rec->hdr );
return r; return r;
} }
@ -380,7 +391,7 @@ BOOL WINAPI MsiRecordIsNull( MSIHANDLE handle, UINT iField )
UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField, UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField,
LPSTR szValue, LPDWORD pcchValue) LPSTR szValue, LPDWORD pcchValue)
{ {
UINT len=0, ret; UINT len = 0, ret = ERROR_SUCCESS;
CHAR buffer[16]; CHAR buffer[16];
TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue); TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue);
@ -394,7 +405,6 @@ UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField,
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
ret = ERROR_SUCCESS;
switch( rec->fields[iField].type ) switch( rec->fields[iField].type )
{ {
case MSIFIELD_INT: case MSIFIELD_INT:
@ -404,11 +414,11 @@ UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField,
lstrcpynA(szValue, buffer, *pcchValue); lstrcpynA(szValue, buffer, *pcchValue);
break; break;
case MSIFIELD_WSTR: case MSIFIELD_WSTR:
len = WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, -1, len = WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal,
NULL, 0 , NULL, NULL); rec->fields[iField].len + 1, NULL, 0 , NULL, NULL );
if (szValue) if (szValue)
WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, -1, WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal,
szValue, *pcchValue, NULL, NULL); rec->fields[iField].len + 1, szValue, *pcchValue, NULL, NULL );
if( szValue && *pcchValue && len>*pcchValue ) if( szValue && *pcchValue && len>*pcchValue )
szValue[*pcchValue-1] = 0; szValue[*pcchValue-1] = 0;
if( len ) if( len )
@ -448,23 +458,30 @@ UINT WINAPI MsiRecordGetStringA(MSIHANDLE handle, UINT iField,
return ret; return ret;
} }
const WCHAR *msi_record_get_string( const MSIRECORD *rec, UINT field, int *len )
{
if (field > rec->count)
return NULL;
if (rec->fields[field].type != MSIFIELD_WSTR)
return NULL;
if (len) *len = rec->fields[field].len;
return rec->fields[field].u.szwVal;
}
const WCHAR *MSI_RecordGetString( const MSIRECORD *rec, UINT iField ) const WCHAR *MSI_RecordGetString( const MSIRECORD *rec, UINT iField )
{ {
if( iField > rec->count ) return msi_record_get_string( rec, iField, NULL );
return NULL;
if( rec->fields[iField].type != MSIFIELD_WSTR )
return NULL;
return rec->fields[iField].u.szwVal;
} }
UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField, UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField,
LPWSTR szValue, LPDWORD pcchValue) LPWSTR szValue, LPDWORD pcchValue)
{ {
UINT len=0, ret; static const WCHAR szFormat[] = {'%','d',0};
UINT len = 0, ret = ERROR_SUCCESS;
WCHAR buffer[16]; WCHAR buffer[16];
static const WCHAR szFormat[] = { '%','d',0 };
TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue); TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue);
@ -477,7 +494,6 @@ UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField,
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
ret = ERROR_SUCCESS;
switch( rec->fields[iField].type ) switch( rec->fields[iField].type )
{ {
case MSIFIELD_INT: case MSIFIELD_INT:
@ -487,9 +503,9 @@ UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField,
lstrcpynW(szValue, buffer, *pcchValue); lstrcpynW(szValue, buffer, *pcchValue);
break; break;
case MSIFIELD_WSTR: case MSIFIELD_WSTR:
len = lstrlenW( rec->fields[iField].u.szwVal ); len = rec->fields[iField].len;
if (szValue) if (szValue)
lstrcpynW(szValue, rec->fields[iField].u.szwVal, *pcchValue); memcpy( szValue, rec->fields[iField].u.szwVal, min(len + 1, *pcchValue) * sizeof(WCHAR) );
break; break;
case MSIFIELD_NULL: case MSIFIELD_NULL:
if( szValue && *pcchValue > 0 ) if( szValue && *pcchValue > 0 )
@ -548,7 +564,7 @@ static UINT MSI_RecordDataSize(MSIRECORD *rec, UINT iField)
case MSIFIELD_INT: case MSIFIELD_INT:
return sizeof (INT); return sizeof (INT);
case MSIFIELD_WSTR: case MSIFIELD_WSTR:
return lstrlenW( rec->fields[iField].u.szwVal ); return rec->fields[iField].len;
case MSIFIELD_NULL: case MSIFIELD_NULL:
break; break;
case MSIFIELD_STREAM: case MSIFIELD_STREAM:
@ -598,16 +614,6 @@ UINT WINAPI MsiRecordSetStringA( MSIHANDLE handle, UINT iField, LPCSTR szValue )
return ret; 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 ) UINT msi_record_set_string( MSIRECORD *rec, UINT field, const WCHAR *value, int len )
{ {
if (field > rec->count) if (field > rec->count)
@ -1008,8 +1014,9 @@ BOOL MSI_RecordsAreFieldsEqual(MSIRECORD *a, MSIRECORD *b, UINT field)
break; break;
case MSIFIELD_WSTR: case MSIFIELD_WSTR:
if (strcmpW(a->fields[field].u.szwVal, b->fields[field].u.szwVal)) if (a->fields[field].len != b->fields[field].len) return FALSE;
return FALSE; if (memcmp( a->fields[field].u.szwVal, b->fields[field].u.szwVal,
a->fields[field].len * sizeof(WCHAR) )) return FALSE;
break; break;
case MSIFIELD_STREAM: case MSIFIELD_STREAM: