msi: Preserve strings with embedded nulls in the record implementation.
This commit is contained in:
parent
8d28cc0ac7
commit
32aed60786
|
@ -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;
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue