diff options
Diffstat (limited to 'libmsi/libmsi-record.c')
-rw-r--r-- | libmsi/libmsi-record.c | 250 |
1 files changed, 93 insertions, 157 deletions
diff --git a/libmsi/libmsi-record.c b/libmsi/libmsi-record.c index 78b0e21..848ba61 100644 --- a/libmsi/libmsi-record.c +++ b/libmsi/libmsi-record.c @@ -20,24 +20,11 @@ #include <stdarg.h> -#define COBJMACROS - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" - #include "libmsi-record.h" #include "debug.h" -#include "unicode.h" #include "libmsi.h" #include "msipriv.h" -#include "objidl.h" -#include "winnls.h" -#include "ole2.h" - -#include "shlwapi.h" - #include "query.h" enum @@ -51,7 +38,7 @@ G_DEFINE_TYPE (LibmsiRecord, libmsi_record, G_TYPE_OBJECT); #define LIBMSI_FIELD_TYPE_NULL 0 #define LIBMSI_FIELD_TYPE_INT 1 -#define LIBMSI_FIELD_TYPE_WSTR 3 +#define LIBMSI_FIELD_TYPE_STR 3 #define LIBMSI_FIELD_TYPE_STREAM 4 static void @@ -66,11 +53,11 @@ _libmsi_free_field (LibmsiField *field ) case LIBMSI_FIELD_TYPE_NULL: case LIBMSI_FIELD_TYPE_INT: break; - case LIBMSI_FIELD_TYPE_WSTR: - msi_free( field->u.szwVal); + case LIBMSI_FIELD_TYPE_STR: + msi_free (field->u.szVal); break; case LIBMSI_FIELD_TYPE_STREAM: - IStream_Release( field->u.stream ); + g_object_unref (G_OBJECT (field->u.stream)); break; default: ERR ("Invalid field type %d\n", field->type); @@ -159,10 +146,10 @@ unsigned libmsi_record_get_field_count( const LibmsiRecord *rec ) return rec->count; } -static bool expr_int_from_string( const WCHAR *str, int *out ) +static bool expr_int_from_string( const char *str, int *out ) { int x = 0; - const WCHAR *p = str; + const char *p = str; if( *p == '-' ) /* skip the minus sign */ p++; @@ -191,7 +178,7 @@ unsigned _libmsi_record_copy_field( LibmsiRecord *in_rec, unsigned in_n, r = LIBMSI_RESULT_FUNCTION_FAILED; else if ( in_rec != out_rec || in_n != out_n ) { - WCHAR *str; + char *str; LibmsiField *in, *out; in = &in_rec->fields[in_n]; @@ -204,15 +191,15 @@ unsigned _libmsi_record_copy_field( LibmsiRecord *in_rec, unsigned in_n, case LIBMSI_FIELD_TYPE_INT: out->u.iVal = in->u.iVal; break; - case LIBMSI_FIELD_TYPE_WSTR: - str = strdupW( in->u.szwVal ); + case LIBMSI_FIELD_TYPE_STR: + str = strdup( in->u.szVal ); if ( !str ) r = LIBMSI_RESULT_OUTOFMEMORY; else - out->u.szwVal = str; + out->u.szVal = str; break; case LIBMSI_FIELD_TYPE_STREAM: - IStream_AddRef( in->u.stream ); + g_object_ref(G_OBJECT(in->u.stream)); out->u.stream = in->u.stream; break; default: @@ -241,8 +228,8 @@ int libmsi_record_get_integer( const LibmsiRecord *rec, unsigned iField) { case LIBMSI_FIELD_TYPE_INT: return rec->fields[iField].u.iVal; - case LIBMSI_FIELD_TYPE_WSTR: - if( expr_int_from_string( rec->fields[iField].u.szwVal, &ret ) ) + case LIBMSI_FIELD_TYPE_STR: + if( expr_int_from_string( rec->fields[iField].u.szVal, &ret ) ) return ret; return MSI_NULL_INTEGER; default: @@ -329,21 +316,15 @@ LibmsiResult libmsi_record_get_string(const LibmsiRecord *rec, unsigned iField, switch( rec->fields[iField].type ) { case LIBMSI_FIELD_TYPE_INT: - wsprintfA(buffer, "%d", rec->fields[iField].u.iVal); + sprintf(buffer, "%d", rec->fields[iField].u.iVal); len = strlen( buffer ); if (szValue) - strcpynA(szValue, buffer, *pcchValue); + strcpyn(szValue, buffer, *pcchValue); break; - case LIBMSI_FIELD_TYPE_WSTR: - len = WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, -1, - NULL, 0 , NULL, NULL); + case LIBMSI_FIELD_TYPE_STR: + len = strlen( rec->fields[iField].u.szVal ); if (szValue) - WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, -1, - szValue, *pcchValue, NULL, NULL); - if( szValue && *pcchValue && len>*pcchValue ) - szValue[*pcchValue-1] = 0; - if( len ) - len--; + strcpyn(szValue, rec->fields[iField].u.szVal, *pcchValue ); break; case LIBMSI_FIELD_TYPE_NULL: if( szValue && *pcchValue > 0 ) @@ -361,23 +342,23 @@ LibmsiResult libmsi_record_get_string(const LibmsiRecord *rec, unsigned iField, return ret; } -const WCHAR *_libmsi_record_get_string_raw( const LibmsiRecord *rec, unsigned iField ) +const char *_libmsi_record_get_string_raw( const LibmsiRecord *rec, unsigned iField ) { if( iField > rec->count ) return NULL; - if( rec->fields[iField].type != LIBMSI_FIELD_TYPE_WSTR ) + if( rec->fields[iField].type != LIBMSI_FIELD_TYPE_STR ) return NULL; - return rec->fields[iField].u.szwVal; + return rec->fields[iField].u.szVal; } -unsigned _libmsi_record_get_stringW(const LibmsiRecord *rec, unsigned iField, - WCHAR *szValue, unsigned *pcchValue) +unsigned _libmsi_record_get_string(const LibmsiRecord *rec, unsigned iField, + char *szValue, unsigned *pcchValue) { unsigned len=0, ret; - WCHAR buffer[16]; - static const WCHAR szFormat[] = { '%','d',0 }; + char buffer[16]; + static const char szFormat[] = "%d"; TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue); @@ -394,15 +375,15 @@ unsigned _libmsi_record_get_stringW(const LibmsiRecord *rec, unsigned iField, switch( rec->fields[iField].type ) { case LIBMSI_FIELD_TYPE_INT: - wsprintfW(buffer, szFormat, rec->fields[iField].u.iVal); - len = strlenW( buffer ); + sprintf(buffer, szFormat, rec->fields[iField].u.iVal); + len = strlen( buffer ); if (szValue) - strcpynW(szValue, buffer, *pcchValue); + strcpyn(szValue, buffer, *pcchValue); break; - case LIBMSI_FIELD_TYPE_WSTR: - len = strlenW( rec->fields[iField].u.szwVal ); + case LIBMSI_FIELD_TYPE_STR: + len = strlen( rec->fields[iField].u.szVal ); if (szValue) - strcpynW(szValue, rec->fields[iField].u.szwVal, *pcchValue); + strcpyn(szValue, rec->fields[iField].u.szVal, *pcchValue); break; case LIBMSI_FIELD_TYPE_NULL: if( szValue && *pcchValue > 0 ) @@ -419,17 +400,6 @@ unsigned _libmsi_record_get_stringW(const LibmsiRecord *rec, unsigned iField, return ret; } -static unsigned msi_get_stream_size( IStream *stm ) -{ - STATSTG stat; - HRESULT r; - - r = IStream_Stat( stm, &stat, STATFLAG_NONAME ); - if( FAILED(r) ) - return 0; - return stat.cbSize.QuadPart; -} - unsigned libmsi_record_get_field_size(const LibmsiRecord *rec, unsigned iField) { TRACE("%p %d\n", rec, iField); @@ -444,35 +414,25 @@ unsigned libmsi_record_get_field_size(const LibmsiRecord *rec, unsigned iField) { case LIBMSI_FIELD_TYPE_INT: return sizeof (int); - case LIBMSI_FIELD_TYPE_WSTR: - return strlenW( rec->fields[iField].u.szwVal ); + case LIBMSI_FIELD_TYPE_STR: + return strlen( rec->fields[iField].u.szVal ); case LIBMSI_FIELD_TYPE_NULL: break; case LIBMSI_FIELD_TYPE_STREAM: - return msi_get_stream_size( rec->fields[iField].u.stream ); + return gsf_input_size( rec->fields[iField].u.stream ); } return 0; } LibmsiResult libmsi_record_set_string( LibmsiRecord *rec, unsigned iField, const char *szValue ) { - WCHAR *str; + char *str; TRACE("%d %d %s\n", rec, iField, debugstr_a(szValue)); if( !rec ) return LIBMSI_RESULT_INVALID_HANDLE; - str = strdupAtoW( szValue ); - return _libmsi_record_set_stringW( rec, iField, str ); -} - -unsigned _libmsi_record_set_stringW( LibmsiRecord *rec, unsigned iField, const WCHAR *szValue ) -{ - WCHAR *str; - - TRACE("%p %d %s\n", rec, iField, debugstr_w(szValue)); - if( iField > rec->count ) return LIBMSI_RESULT_INVALID_FIELD; @@ -480,70 +440,60 @@ unsigned _libmsi_record_set_stringW( LibmsiRecord *rec, unsigned iField, const W if( szValue && szValue[0] ) { - str = strdupW( szValue ); - rec->fields[iField].type = LIBMSI_FIELD_TYPE_WSTR; - rec->fields[iField].u.szwVal = str; + str = strdup( szValue ); + rec->fields[iField].type = LIBMSI_FIELD_TYPE_STR; + rec->fields[iField].u.szVal = str; } else { rec->fields[iField].type = LIBMSI_FIELD_TYPE_NULL; - rec->fields[iField].u.szwVal = NULL; + rec->fields[iField].u.szVal = NULL; } return 0; } -/* read the data in a file into an IStream */ -static unsigned _libmsi_addstream_from_file(const char *szFile, IStream **pstm) +/* read the data in a file into a memory-backed GsfInput */ +static unsigned _libmsi_addstream_from_file(const char *szFile, GsfInput **pstm) { - unsigned sz, szHighWord = 0, read; - HANDLE handle; - HGLOBAL hGlob = 0; - HRESULT hr; - ULARGE_INTEGER ulSize; + GsfInput *stm; + char *data; + off_t sz; - TRACE("reading %s\n", debugstr_a(szFile)); - - /* read the file into memory */ - handle = CreateFileA(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if( handle == INVALID_HANDLE_VALUE ) - return GetLastError(); - sz = GetFileSize(handle, &szHighWord); - if( sz != INVALID_FILE_SIZE && szHighWord == 0 ) + stm = gsf_input_stdio_new(szFile, NULL); + if (!stm) { - hGlob = GlobalAlloc(GMEM_FIXED, sz); - if( hGlob ) - { - bool r = ReadFile(handle, hGlob, sz, &read, NULL); - if( !r ) - { - GlobalFree(hGlob); - hGlob = 0; - } - } + WARN("open file failed for %s\n", debugstr_a(szFile)); + return LIBMSI_RESULT_OPEN_FAILED; } - CloseHandle(handle); - if( !hGlob ) - return LIBMSI_RESULT_FUNCTION_FAILED; - /* make a stream out of it, and set the correct file size */ - hr = CreateStreamOnHGlobal(hGlob, true, pstm); - if( FAILED( hr ) ) + sz = gsf_input_size(stm); + if (sz == 0) { - GlobalFree(hGlob); - return LIBMSI_RESULT_FUNCTION_FAILED; + data = g_malloc(1); } + else + { + data = g_try_malloc(sz); + if (!data) + return LIBMSI_RESULT_NOT_ENOUGH_MEMORY; - /* set the correct size - CreateStreamOnHGlobal screws it up */ - ulSize.QuadPart = sz; - IStream_SetSize(*pstm, ulSize); + if (!gsf_input_read(stm, sz, data)) + { + g_object_unref(G_OBJECT(stm)); + return LIBMSI_RESULT_FUNCTION_FAILED; + } + } + + g_object_unref(G_OBJECT(stm)); + *pstm = gsf_input_memory_new(data, sz, true); - TRACE("read %s, %d bytes into IStream %p\n", debugstr_a(szFile), sz, *pstm); + TRACE("read %s, %d bytes into GsfInput %p\n", debugstr_a(szFile), sz, *pstm); return LIBMSI_RESULT_SUCCESS; } -unsigned _libmsi_record_load_stream(LibmsiRecord *rec, unsigned iField, IStream *stream) +unsigned _libmsi_record_load_stream(LibmsiRecord *rec, unsigned iField, GsfInput *stream) { if ( (iField == 0) || (iField > rec->count) ) return LIBMSI_RESULT_INVALID_PARAMETER; @@ -557,8 +507,8 @@ unsigned _libmsi_record_load_stream(LibmsiRecord *rec, unsigned iField, IStream unsigned _libmsi_record_load_stream_from_file(LibmsiRecord *rec, unsigned iField, const char *szFilename) { - IStream *stm = NULL; - HRESULT r; + GsfInput *stm; + unsigned r; if( (iField == 0) || (iField > rec->count) ) return LIBMSI_RESULT_INVALID_PARAMETER; @@ -566,9 +516,6 @@ unsigned _libmsi_record_load_stream_from_file(LibmsiRecord *rec, unsigned iField /* no filename means we should seek back to the start of the stream */ if( !szFilename ) { - LARGE_INTEGER ofs; - ULARGE_INTEGER cur; - if( rec->fields[iField].type != LIBMSI_FIELD_TYPE_STREAM ) return LIBMSI_RESULT_INVALID_FIELD; @@ -576,10 +523,7 @@ unsigned _libmsi_record_load_stream_from_file(LibmsiRecord *rec, unsigned iField if( !stm ) return LIBMSI_RESULT_INVALID_FIELD; - ofs.QuadPart = 0; - r = IStream_Seek( stm, ofs, STREAM_SEEK_SET, &cur ); - if( FAILED( r ) ) - return LIBMSI_RESULT_FUNCTION_FAILED; + gsf_input_seek( stm, 0, G_SEEK_SET ); } else { @@ -613,9 +557,8 @@ LibmsiResult libmsi_record_load_stream(LibmsiRecord *rec, unsigned iField, const unsigned _libmsi_record_save_stream(const LibmsiRecord *rec, unsigned iField, char *buf, unsigned *sz) { - unsigned count; - HRESULT r; - IStream *stm; + uint64_t left; + GsfInput *stm; TRACE("%p %d %p %p\n", rec, iField, buf, sz); @@ -638,34 +581,26 @@ unsigned _libmsi_record_save_stream(const LibmsiRecord *rec, unsigned iField, ch if( !stm ) return LIBMSI_RESULT_INVALID_PARAMETER; + left = gsf_input_size(stm) - gsf_input_tell(stm); + /* if there's no buffer pointer, calculate the length to the end */ if( !buf ) { - LARGE_INTEGER ofs; - ULARGE_INTEGER end, cur; - - ofs.QuadPart = cur.QuadPart = 0; - end.QuadPart = 0; - IStream_Seek( stm, ofs, STREAM_SEEK_SET, &cur ); - IStream_Seek( stm, ofs, STREAM_SEEK_END, &end ); - ofs.QuadPart = cur.QuadPart; - IStream_Seek( stm, ofs, STREAM_SEEK_SET, &cur ); - *sz = end.QuadPart - cur.QuadPart; + *sz = left; return LIBMSI_RESULT_SUCCESS; } /* read the data */ - count = 0; - r = IStream_Read( stm, buf, *sz, &count ); - if( FAILED( r ) ) + if (*sz > left) + *sz = left; + + if (*sz > 0 && !gsf_input_read( stm, *sz, buf )) { *sz = 0; return LIBMSI_RESULT_FUNCTION_FAILED; } - *sz = count; - return LIBMSI_RESULT_SUCCESS; } @@ -685,7 +620,7 @@ LibmsiResult libmsi_record_save_stream(LibmsiRecord *rec, unsigned iField, char return ret; } -unsigned _libmsi_record_set_IStream( LibmsiRecord *rec, unsigned iField, IStream *stm ) +unsigned _libmsi_record_set_gsf_input( LibmsiRecord *rec, unsigned iField, GsfInput *stm ) { TRACE("%p %d %p\n", rec, iField, stm); @@ -696,12 +631,12 @@ unsigned _libmsi_record_set_IStream( LibmsiRecord *rec, unsigned iField, IStream rec->fields[iField].type = LIBMSI_FIELD_TYPE_STREAM; rec->fields[iField].u.stream = stm; - IStream_AddRef( stm ); + g_object_ref(G_OBJECT(stm)); return LIBMSI_RESULT_SUCCESS; } -unsigned _libmsi_record_get_IStream( const LibmsiRecord *rec, unsigned iField, IStream **pstm) +unsigned _libmsi_record_get_gsf_input( const LibmsiRecord *rec, unsigned iField, GsfInput **pstm) { TRACE("%p %d %p\n", rec, iField, pstm); @@ -712,7 +647,7 @@ unsigned _libmsi_record_get_IStream( const LibmsiRecord *rec, unsigned iField, I return LIBMSI_RESULT_INVALID_FIELD; *pstm = rec->fields[iField].u.stream; - IStream_AddRef( *pstm ); + g_object_ref(G_OBJECT(*pstm)); return LIBMSI_RESULT_SUCCESS; } @@ -731,12 +666,13 @@ LibmsiRecord *_libmsi_record_clone(LibmsiRecord *rec) { if (rec->fields[i].type == LIBMSI_FIELD_TYPE_STREAM) { - if (FAILED(IStream_Clone(rec->fields[i].u.stream, - &clone->fields[i].u.stream))) + GsfInput *stm = gsf_input_dup(rec->fields[i].u.stream, NULL); + if (!stm) { g_object_unref(clone); return NULL; } + clone->fields[i].u.stream = stm; clone->fields[i].type = LIBMSI_FIELD_TYPE_STREAM; } else @@ -768,8 +704,8 @@ bool _libmsi_record_compare_fields(const LibmsiRecord *a, const LibmsiRecord *b, return false; break; - case LIBMSI_FIELD_TYPE_WSTR: - if (strcmpW(a->fields[field].u.szwVal, b->fields[field].u.szwVal)) + case LIBMSI_FIELD_TYPE_STR: + if (strcmp(a->fields[field].u.szVal, b->fields[field].u.szVal)) return false; break; @@ -797,23 +733,23 @@ bool _libmsi_record_compare(const LibmsiRecord *a, const LibmsiRecord *b) return true; } -WCHAR *msi_dup_record_field( LibmsiRecord *rec, int field ) +char *msi_dup_record_field( LibmsiRecord *rec, int field ) { unsigned sz = 0; - WCHAR *str; + char *str; unsigned r; if (libmsi_record_is_null( rec, field )) return NULL; - r = _libmsi_record_get_stringW( rec, field, NULL, &sz ); + r = _libmsi_record_get_string( rec, field, NULL, &sz ); if (r != LIBMSI_RESULT_SUCCESS) return NULL; sz++; - str = msi_alloc( sz * sizeof(WCHAR) ); + str = msi_alloc( sz * sizeof(char) ); if (!str) return NULL; str[0] = 0; - r = _libmsi_record_get_stringW( rec, field, str, &sz ); + r = _libmsi_record_get_string( rec, field, str, &sz ); if (r != LIBMSI_RESULT_SUCCESS) { ERR("failed to get string!\n"); |