diff options
Diffstat (limited to 'libmsi')
-rw-r--r-- | libmsi/Makefile.am | 36 | ||||
-rw-r--r-- | libmsi/alter.c | 6 | ||||
-rw-r--r-- | libmsi/create.c | 5 | ||||
-rw-r--r-- | libmsi/distinct.c | 5 | ||||
-rw-r--r-- | libmsi/handle.c | 85 | ||||
-rw-r--r-- | libmsi/insert.c | 14 | ||||
-rw-r--r-- | libmsi/libmsi-database.c | 415 | ||||
-rw-r--r-- | libmsi/libmsi-query.c | 204 | ||||
-rw-r--r-- | libmsi/libmsi-record.c | 132 | ||||
-rw-r--r-- | libmsi/libmsi-summary-info.c | 174 | ||||
-rw-r--r-- | libmsi/msipriv.h | 62 | ||||
-rw-r--r-- | libmsi/select.c | 4 | ||||
-rw-r--r-- | libmsi/table.c | 16 | ||||
-rw-r--r-- | libmsi/update.c | 9 | ||||
-rw-r--r-- | libmsi/where.c | 7 |
15 files changed, 735 insertions, 439 deletions
diff --git a/libmsi/Makefile.am b/libmsi/Makefile.am index e6f6677..afeefae 100644 --- a/libmsi/Makefile.am +++ b/libmsi/Makefile.am @@ -1,23 +1,41 @@ +NULL = lib_LTLIBRARIES = libmsi.la AM_CPPFLAGS = -I$(top_srcdir)/include -I$(srcdir) -I. \ - $(GLIB_CFLAGS) $(GSF_CFLAGS) + $(GLIB_CFLAGS) $(GSF_CFLAGS) $(GOBJECT_CFLAGS) AM_CFLAGS = -Wunused -Wimplicit AM_YFLAGS = -d BUILT_SOURCES = sql-parser.c sql-parser.h -noinst_HEADERS = \ - list.h \ - msipriv.h \ +noinst_HEADERS = \ + list.h \ + msipriv.h \ query.h -libmsi_la_SOURCES = libmsi-database.c libmsi-query.c libmsi-record.c \ - libmsi-summary-info.c alter.c create.c delete.c distinct.c \ - drop.c handle.c insert.c select.c storages.c streams.c \ - string.c table.c tokenize.c update.c where.c sql-parser.y +libmsi_la_SOURCES = \ + alter.c \ + create.c \ + delete.c \ + distinct.c \ + drop.c \ + insert.c \ + libmsi-database.c \ + libmsi-query.c \ + libmsi-record.c \ + libmsi-summary-info.c \ + select.c \ + sql-parser.y \ + storages.c \ + streams.c \ + string.c \ + table.c \ + tokenize.c \ + update.c \ + where.c \ + $(NULL) libmsi_la_LDFLAGS = -no-undefined -rpath $(libdir) \ -export-symbols-regex='^libmsi_' -libmsi_la_LIBADD = $(GLIB_LIBS) $(GSF_LIBS) +libmsi_la_LIBADD = $(GLIB_LIBS) $(GSF_LIBS) $(GOBJECT_LIBS) diff --git a/libmsi/alter.c b/libmsi/alter.c index c4ae96b..e6e56e6 100644 --- a/libmsi/alter.c +++ b/libmsi/alter.c @@ -88,10 +88,10 @@ static bool check_column_exists(LibmsiDatabase *db, const char *table, const cha r = _libmsi_query_fetch(view, &rec); if (r == LIBMSI_RESULT_SUCCESS) - msiobj_release(&rec->hdr); + g_object_unref(rec); done: - msiobj_release(&view->hdr); + g_object_unref(view); return (r == LIBMSI_RESULT_SUCCESS); } @@ -119,7 +119,7 @@ static unsigned alter_add_column(LibmsiAlterView *av) if (r == LIBMSI_RESULT_SUCCESS) { r = _libmsi_query_iterate_records(view, NULL, count_iter, &colnum); - msiobj_release(&view->hdr); + g_object_unref(view); if (r != LIBMSI_RESULT_SUCCESS) { columns->ops->delete(columns); diff --git a/libmsi/create.c b/libmsi/create.c index ef1ac6d..745a0e1 100644 --- a/libmsi/create.c +++ b/libmsi/create.c @@ -97,7 +97,7 @@ static unsigned create_view_delete( LibmsiView *view ) TRACE("%p\n", cv ); - msiobj_release( &cv->db->hdr ); + g_object_unref(cv->db); msi_free( cv ); return LIBMSI_RESULT_SUCCESS; @@ -176,8 +176,7 @@ unsigned create_view_create( LibmsiDatabase *db, LibmsiView **view, const char * /* fill the structure */ cv->view.ops = &create_ops; - msiobj_addref( &db->hdr ); - cv->db = db; + cv->db = g_object_ref(db); cv->name = table; cv->col_info = col_info; cv->bIsTemp = temp; diff --git a/libmsi/distinct.c b/libmsi/distinct.c index 89614e3..d134b03 100644 --- a/libmsi/distinct.c +++ b/libmsi/distinct.c @@ -220,7 +220,7 @@ static unsigned distinct_view_delete( LibmsiView *view ) dv->table->ops->delete( dv->table ); msi_free( dv->translation ); - msiobj_release( &dv->db->hdr ); + g_object_unref(dv->db); msi_free( dv ); return LIBMSI_RESULT_SUCCESS; @@ -289,8 +289,7 @@ unsigned distinct_view_create( LibmsiDatabase *db, LibmsiView **view, LibmsiView /* fill the structure */ dv->view.ops = &distinct_ops; - msiobj_addref( &db->hdr ); - dv->db = db; + dv->db = g_object_ref(db); dv->table = table; dv->translation = NULL; dv->row_count = 0; diff --git a/libmsi/handle.c b/libmsi/handle.c deleted file mode 100644 index e1b4494..0000000 --- a/libmsi/handle.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Implementation of the Microsoft Installer (msi.dll) - * - * Copyright 2002-2004 Mike McCormack for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include <stdarg.h> -#include <assert.h> - -#include "debug.h" -#include "libmsi.h" -#include "msipriv.h" - - -void *alloc_msiobject(unsigned size, msihandledestructor destroy ) -{ - LibmsiObject *info; - - info = msi_alloc_zero( size ); - if( info ) - { - info->magic = 0xC007C0DE; - info->refcount = 1; - info->destructor = destroy; - } - - return info; -} - -void msiobj_addref( LibmsiObject *info ) -{ - if( !info ) - return; - - assert(info->magic == 0xC007C0DE); - __sync_add_and_fetch(&info->refcount, 1); -} - -int msiobj_release( LibmsiObject *obj ) -{ - int ret; - - if( !obj ) - return -1; - - assert(obj->magic == 0xC007C0DE); - ret = __sync_sub_and_fetch( &obj->refcount, 1 ); - if( ret==0 ) - { - if( obj->destructor ) - obj->destructor( obj ); - obj->magic = 0xDEADB0D7; - msi_free( obj ); - TRACE("object %p destroyed\n", obj); - } - - return ret; -} - -/*********************************************************** - * libmsi_unref [MSI.@] - */ -LibmsiResult libmsi_unref(void *obj) -{ - TRACE("%x\n",obj); - - if( obj ) - msiobj_release( obj ); - - return LIBMSI_RESULT_SUCCESS; -} diff --git a/libmsi/insert.c b/libmsi/insert.c index 9ad48a7..1301584 100644 --- a/libmsi/insert.c +++ b/libmsi/insert.c @@ -91,7 +91,7 @@ LibmsiRecord *msi_query_merge_record( unsigned fields, const column_info *vl, Li return merged; err: - msiobj_release( &merged->hdr ); + g_object_unref(merged); return NULL; } @@ -161,12 +161,12 @@ static unsigned msi_arrange_record(LibmsiInsertView *iv, LibmsiRecord **values) } } } - msiobj_release(&(*values)->hdr); + g_object_unref(*values); *values = padded; return LIBMSI_RESULT_SUCCESS; err: - msiobj_release(&padded->hdr); + g_object_unref(padded); return r; } @@ -237,7 +237,7 @@ static unsigned insert_view_execute( LibmsiView *view, LibmsiRecord *record ) err: if( values ) - msiobj_release( &values->hdr ); + g_object_unref(values); return r; } @@ -296,7 +296,7 @@ static unsigned insert_view_delete( LibmsiView *view ) sv = iv->sv; if( sv ) sv->ops->delete( sv ); - msiobj_release( &iv->db->hdr ); + g_object_unref(iv->db); msi_free( iv ); return LIBMSI_RESULT_SUCCESS; @@ -372,9 +372,9 @@ unsigned insert_view_create( LibmsiDatabase *db, LibmsiView **view, const char * /* fill the structure */ iv->view.ops = &insert_ops; - msiobj_addref( &db->hdr ); + iv->table = tv; - iv->db = db; + iv->db = g_object_ref(db); iv->vals = values; iv->bIsTemp = temp; iv->sv = sv; diff --git a/libmsi/libmsi-database.c b/libmsi/libmsi-database.c index 19c7a62..6b9f25f 100644 --- a/libmsi/libmsi-database.c +++ b/libmsi/libmsi-database.c @@ -24,14 +24,28 @@ #include <fcntl.h> #include <sys/stat.h> +#include "libmsi-database.h" + #include "debug.h" #include "libmsi.h" #include "msipriv.h" #include "query.h" -const uint8_t clsid_msi_transform[16] = { 0x82, 0x10, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46 }; -const uint8_t clsid_msi_database[16] = { 0x84, 0x10, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46 }; -const uint8_t clsid_msi_patch[16] = { 0x86, 0x10, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46 }; +enum +{ + PROP_0, + + PROP_PATH, + PROP_MODE, + PROP_OUTPATH, + PROP_PATCH, +}; + +G_DEFINE_TYPE (LibmsiDatabase, libmsi_database, G_TYPE_OBJECT); + +const char clsid_msi_transform[16] = { 0x82, 0x10, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46 }; +const char clsid_msi_database[16] = { 0x84, 0x10, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46 }; +const char clsid_msi_patch[16] = { 0x86, 0x10, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46 }; /* * .MSI file format @@ -63,26 +77,130 @@ typedef struct _LibmsiStream { GsfInput *stm; } LibmsiStream; -static void free_transforms( LibmsiDatabase *db ) +static void +libmsi_database_init (LibmsiDatabase *p) { - while( !list_empty( &db->transforms ) ) - { - LibmsiTransform *t = LIST_ENTRY( list_head( &db->transforms ), - LibmsiTransform, entry ); - list_remove( &t->entry ); + list_init (&p->tables); + list_init (&p->transforms); + list_init (&p->streams); + list_init (&p->storages); +} + +static void +libmsi_database_constructed (GObject *object) +{ + G_OBJECT_CLASS (libmsi_database_parent_class)->constructed (object); +} + +static void +free_transforms (LibmsiDatabase *db) +{ + while (!list_empty(&db->transforms)) { + LibmsiTransform *t = LIST_ENTRY(list_head(&db->transforms), + LibmsiTransform, entry); + list_remove(&t->entry); g_object_unref(G_OBJECT(t->stg)); - msi_free( t ); + msi_free(t); } } -static void _libmsi_database_destroy( LibmsiObject *arg ) +static void +libmsi_database_finalize (GObject *object) { - LibmsiDatabase *db = (LibmsiDatabase *) arg; + LibmsiDatabase *self = LIBMSI_DATABASE (object); + LibmsiDatabase *p = self; + + _libmsi_database_close (self, false); + free_cached_tables (self); + free_transforms (self); - _libmsi_database_close( db, false ); - free_cached_tables( db ); - free_transforms( db ); - msi_free(db->path); + g_free (p->path); + + G_OBJECT_CLASS (libmsi_database_parent_class)->finalize (object); +} + +static void +libmsi_database_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + g_return_if_fail (LIBMSI_IS_DATABASE (object)); + LibmsiDatabase *p = LIBMSI_DATABASE (object); + + switch (prop_id) { + case PROP_PATH: + g_return_if_fail (p->path == NULL); + p->path = g_value_dup_string (value); + break; + case PROP_MODE: + g_return_if_fail (p->mode == NULL); + p->mode = (const char*)g_value_get_int (value); + break; + case PROP_OUTPATH: + g_return_if_fail (p->outpath == NULL); + p->outpath = (const char*)g_value_dup_string (value); + break; + case PROP_PATCH: + p->patch = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +libmsi_database_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + g_return_if_fail (LIBMSI_IS_DATABASE (object)); + LibmsiDatabase *p = LIBMSI_DATABASE (object); + + switch (prop_id) { + case PROP_PATH: + g_value_set_string (value, p->path); + break; + case PROP_MODE: + g_value_set_int (value, (int)p->mode); + break; + case PROP_OUTPATH: + g_value_set_string (value, p->outpath); + break; + case PROP_PATCH: + g_value_set_boolean (value, p->patch); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +libmsi_database_class_init (LibmsiDatabaseClass *klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = libmsi_database_finalize; + object_class->set_property = libmsi_database_set_property; + object_class->get_property = libmsi_database_get_property; + object_class->constructed = libmsi_database_constructed; + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PATH, + g_param_spec_string ("path", "path", "path", NULL, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MODE, + g_param_spec_int ("mode", "mode", "mode", 0, G_MAXINT, 0, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_OUTPATH, + g_param_spec_string ("outpath", "outpath", "outpath", NULL, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PATCH, + g_param_spec_boolean ("patch", "patch", "patch", FALSE, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); } unsigned msi_open_storage( LibmsiDatabase *db, const char *stname ) @@ -495,7 +613,7 @@ LibmsiResult _libmsi_database_close(LibmsiDatabase *db, bool committed) db->outpath = NULL; } -LibmsiResult _libmsi_database_start_transaction(LibmsiDatabase *db, const char *szPersist) +LibmsiResult _libmsi_database_start_transaction(LibmsiDatabase *db) { unsigned ret = LIBMSI_RESULT_SUCCESS; GsfOutput *out; @@ -506,32 +624,31 @@ LibmsiResult _libmsi_database_start_transaction(LibmsiDatabase *db, const char * if( db->mode == LIBMSI_DB_OPEN_READONLY ) return LIBMSI_RESULT_SUCCESS; - if( szPersist == LIBMSI_DB_OPEN_TRANSACT ) + db->rename_outpath = false; + if( !db->outpath ) { strcpy( path, db->path ); - strcat( path, ".tmp" ); - tmpfile = strdup(path); - szPersist = tmpfile; - } - else if( IS_INTMSIDBOPEN(szPersist) ) - { - ERR("unknown flag %p\n",szPersist); - return LIBMSI_RESULT_INVALID_PARAMETER; + if( db->mode == LIBMSI_DB_OPEN_TRANSACT ) + { + strcat( path, ".tmp" ); + db->rename_outpath = true; + } + db->outpath = strdup(path); } TRACE("%p %s\n", db, szPersist); - out = gsf_output_stdio_new(szPersist, NULL); + out = gsf_output_stdio_new(db->outpath, NULL); if (!out) { - WARN("open file failed for %s\n", debugstr_a(szPersist)); + WARN("open file failed for %s\n", debugstr_a(db->outpath)); return LIBMSI_RESULT_OPEN_FAILED; } stg = gsf_outfile_msole_new(out); g_object_unref(G_OBJECT(out)); if (!stg) { - WARN("open failed for %s\n", debugstr_a(szPersist)); + WARN("open failed for %s\n", debugstr_a(db->outpath)); return LIBMSI_RESULT_OPEN_FAILED; } @@ -546,18 +663,6 @@ LibmsiResult _libmsi_database_start_transaction(LibmsiDatabase *db, const char * db->outfile = stg; g_object_ref(G_OBJECT(db->outfile)); - if (!strstr( szPersist, G_DIR_SEPARATOR_S )) - { - getcwd( path, MAX_PATH ); - strcat( path, G_DIR_SEPARATOR_S ); - strcat( path, szPersist ); - } - else - strcpy( path, szPersist ); - - db->outpath = strdup( path ); - db->rename_outpath = (tmpfile != NULL); - end: if (ret) { if (db->outfile) @@ -570,6 +675,29 @@ end: return ret; } +LibmsiResult libmsi_database_open(const char *szDBPath, const char *szPersist, LibmsiDatabase **pdb) +{ + char path[MAX_PATH]; + + TRACE("%s %p\n",debugstr_a(szDBPath),szPersist ); + + if( !pdb ) + return LIBMSI_RESULT_INVALID_PARAMETER; + + if (!strstr( szDBPath, G_DIR_SEPARATOR_S )) + { + getcwd( path, MAX_PATH ); + strcat( path, G_DIR_SEPARATOR_S ); + strcat( path, szDBPath ); + } + else + strcpy( path, szDBPath ); + + *pdb = libmsi_database_new (path, szPersist, NULL); + + return *pdb ? LIBMSI_RESULT_SUCCESS : LIBMSI_RESULT_OPEN_FAILED; +} + static char *msi_read_text_archive(const char *path, unsigned *len) { char *data; @@ -837,7 +965,7 @@ static unsigned msi_add_table_to_db(LibmsiDatabase *db, char **columns, char **t r = _libmsi_query_execute(view, NULL); libmsi_query_close(view); - msiobj_release(&view->hdr); + g_object_unref(view); done: msi_free(prelude); @@ -908,7 +1036,7 @@ static unsigned construct_record(unsigned num_columns, char **types, break; default: ERR("Unhandled column type: %c\n", types[i][0]); - msiobj_release(&(*rec)->hdr); + g_object_unref(*rec); return LIBMSI_RESULT_FUNCTION_FAILED; } } @@ -950,11 +1078,11 @@ static unsigned msi_add_records_to_table(LibmsiDatabase *db, char **columns, cha r = view->ops->insert_row(view, rec, -1, false); if (r != LIBMSI_RESULT_SUCCESS) { - msiobj_release(&rec->hdr); + g_object_unref(rec); goto done; } - msiobj_release(&rec->hdr); + g_object_unref(rec); } done: @@ -1088,9 +1216,9 @@ LibmsiResult libmsi_database_import(LibmsiDatabase *db, const char *szFolder, co if( !db ) return LIBMSI_RESULT_INVALID_HANDLE; - msiobj_addref( &db->hdr ); + g_object_ref(db); r = _libmsi_database_import( db, szFolder, szFilename ); - msiobj_release( &db->hdr ); + g_object_unref(db); return r; } @@ -1188,7 +1316,7 @@ static unsigned _libmsi_database_export( LibmsiDatabase *db, const char *table, if (r == LIBMSI_RESULT_SUCCESS) { msi_export_record( fd, rec, 1 ); - msiobj_release( &rec->hdr ); + g_object_unref(rec); } /* write out row 2, the column types */ @@ -1196,7 +1324,7 @@ static unsigned _libmsi_database_export( LibmsiDatabase *db, const char *table, if (r == LIBMSI_RESULT_SUCCESS) { msi_export_record( fd, rec, 1 ); - msiobj_release( &rec->hdr ); + g_object_unref(rec); } /* write out row 3, the table name + keys */ @@ -1205,12 +1333,12 @@ static unsigned _libmsi_database_export( LibmsiDatabase *db, const char *table, { libmsi_record_set_string( rec, 0, table ); msi_export_record( fd, rec, 0 ); - msiobj_release( &rec->hdr ); + g_object_unref(rec); } /* write out row 4 onwards, the data */ r = _libmsi_query_iterate_records( view, 0, msi_export_row, (void *)(intptr_t) fd ); - msiobj_release( &view->hdr ); + g_object_unref(view); } done: @@ -1242,9 +1370,9 @@ LibmsiResult libmsi_database_export( LibmsiDatabase *db, const char *szTable, if( !db ) return LIBMSI_RESULT_INVALID_HANDLE; - msiobj_addref ( &db->hdr ); + g_object_ref(db); r = _libmsi_database_export( db, szTable, fd ); - msiobj_release( &db->hdr ); + g_object_unref(db); return r; } @@ -1316,8 +1444,8 @@ static unsigned merge_verify_colnames(LibmsiQuery *dbview, LibmsiQuery *mergevie } } - msiobj_release(&dbrec->hdr); - msiobj_release(&mergerec->hdr); + g_object_unref(dbrec); + g_object_unref(mergerec); dbrec = mergerec = NULL; r = _libmsi_query_get_column_info(dbview, LIBMSI_COL_INFO_TYPES, &dbrec); @@ -1343,8 +1471,8 @@ static unsigned merge_verify_colnames(LibmsiQuery *dbview, LibmsiQuery *mergevie } done: - msiobj_release(&dbrec->hdr); - msiobj_release(&mergerec->hdr); + g_object_unref(dbrec); + g_object_unref(mergerec); return r; } @@ -1380,8 +1508,8 @@ static unsigned merge_verify_primary_keys(LibmsiDatabase *db, LibmsiDatabase *me } done: - msiobj_release(&dbrec->hdr); - msiobj_release(&mergerec->hdr); + g_object_unref(dbrec); + g_object_unref(mergerec); return r; } @@ -1405,7 +1533,7 @@ static char *get_key_value(LibmsiQuery *view, const char *key, LibmsiRecord *rec msi_free(str); } while (cmp); - msiobj_release(&colnames->hdr); + g_object_unref(colnames); r = _libmsi_record_get_string(rec, i, NULL, &sz); if (r != LIBMSI_RESULT_SUCCESS) @@ -1503,7 +1631,7 @@ static char *create_diff_row_query(LibmsiDatabase *merge, LibmsiQuery *view, done: msi_free(clause); - msiobj_release(&keys->hdr); + g_object_unref(keys); return query; } @@ -1562,8 +1690,8 @@ static unsigned merge_diff_row(LibmsiRecord *rec, void *param) done: msi_free(query); - msiobj_release(&row->hdr); - msiobj_release(&dbview->hdr); + g_object_unref(row); + g_object_unref(dbview); return r; } @@ -1592,7 +1720,7 @@ static unsigned msi_get_table_labels(LibmsiDatabase *db, const char *table, char } end: - msiobj_release( &prec->hdr ); + g_object_unref(prec); return r; } @@ -1621,7 +1749,7 @@ static unsigned msi_get_query_columns(LibmsiQuery *query, char ***columns, unsig *numcolumns = count; end: - msiobj_release( &prec->hdr ); + g_object_unref(prec); return r; } @@ -1649,7 +1777,7 @@ static unsigned msi_get_query_types(LibmsiQuery *query, char ***types, unsigned } end: - msiobj_release( &prec->hdr ); + g_object_unref(prec); return r; } @@ -1662,7 +1790,7 @@ static void merge_free_rows(MERGETABLE *table) MERGEROW *row = LIST_ENTRY(item, MERGEROW, entry); list_remove(&row->entry); - msiobj_release(&row->data->hdr); + g_object_unref(row); msi_free(row); } } @@ -1737,12 +1865,12 @@ static unsigned msi_get_merge_table (LibmsiDatabase *db, const char *name, MERGE table->name = strdup(name); table->numconflicts = 0; - msiobj_release(&mergeview->hdr); + g_object_unref(mergeview); *ptable = table; return LIBMSI_RESULT_SUCCESS; err: - msiobj_release(&mergeview->hdr); + g_object_unref(mergeview); free_merge_table(table); *ptable = NULL; return r; @@ -1796,8 +1924,8 @@ static unsigned merge_diff_tables(LibmsiRecord *rec, void *param) list_add_tail(data->tabledata, &table->entry); done: - msiobj_release(&dbview->hdr); - msiobj_release(&mergeview->hdr); + g_object_unref(dbview); + g_object_unref(mergeview); return r; } @@ -1817,7 +1945,7 @@ static unsigned gather_merge_data(LibmsiDatabase *db, LibmsiDatabase *merge, data.merge = merge; data.tabledata = tabledata; r = _libmsi_query_iterate_records(view, NULL, merge_diff_tables, &data); - msiobj_release(&view->hdr); + g_object_unref(view); return r; } @@ -1870,7 +1998,7 @@ static unsigned update_merge_errors(LibmsiDatabase *db, const char *error, return r; r = _libmsi_query_execute(view, NULL); - msiobj_release(&view->hdr); + g_object_unref(view); if (r != LIBMSI_RESULT_SUCCESS) return r; } @@ -1880,7 +2008,7 @@ static unsigned update_merge_errors(LibmsiDatabase *db, const char *error, return r; r = _libmsi_query_execute(view, NULL); - msiobj_release(&view->hdr); + g_object_unref(view); return r; } @@ -1902,8 +2030,8 @@ LibmsiResult libmsi_database_merge(LibmsiDatabase *db, LibmsiDatabase *merge, if (!db || !merge) return LIBMSI_RESULT_INVALID_HANDLE; - msiobj_addref( &db->hdr ); - msiobj_addref( &merge->hdr ); + g_object_ref(db); + g_object_ref(merge); r = gather_merge_data(db, merge, &tabledata); if (r != LIBMSI_RESULT_SUCCESS) goto done; @@ -1939,8 +2067,8 @@ LibmsiResult libmsi_database_merge(LibmsiDatabase *db, LibmsiDatabase *merge, r = LIBMSI_RESULT_FUNCTION_FAILED; done: - msiobj_release(&db->hdr); - msiobj_release(&merge->hdr); + g_object_unref(db); + g_object_unref(merge); return r; } @@ -1953,10 +2081,10 @@ LibmsiDBState libmsi_database_get_state( LibmsiDatabase *db ) if( !db ) return LIBMSI_RESULT_INVALID_HANDLE; - msiobj_addref( &db->hdr ); + g_object_ref(db); if (db->mode != LIBMSI_DB_OPEN_READONLY ) ret = LIBMSI_DB_STATE_WRITE; - msiobj_release( &db->hdr ); + g_object_unref(db); return ret; } @@ -2108,11 +2236,11 @@ LibmsiResult libmsi_database_apply_transform( LibmsiDatabase *db, { unsigned r; - msiobj_addref( &db->hdr ); + g_object_ref(db); if( !db ) return LIBMSI_RESULT_INVALID_HANDLE; r = _libmsi_database_apply_transform( db, szTransformFile, iErrorCond ); - msiobj_release( &db->hdr ); + g_object_unref(db); return r; } @@ -2202,7 +2330,7 @@ LibmsiResult libmsi_database_commit( LibmsiDatabase *db ) if( !db ) return LIBMSI_RESULT_INVALID_HANDLE; - msiobj_addref( &db->hdr ); + g_object_ref(db); if (db->mode == LIBMSI_DB_OPEN_READONLY) goto end; @@ -2241,11 +2369,12 @@ LibmsiResult libmsi_database_commit( LibmsiDatabase *db ) /* FIXME: unlock the database */ _libmsi_database_close(db, true); + db->mode = LIBMSI_DB_OPEN_TRANSACT; _libmsi_database_open(db); - _libmsi_database_start_transaction(db, LIBMSI_DB_OPEN_TRANSACT); + _libmsi_database_start_transaction(db); end: - msiobj_release( &db->hdr ); + g_object_unref(db); return r; } @@ -2313,9 +2442,9 @@ unsigned _libmsi_database_get_primary_keys( LibmsiDatabase *db, if( r == LIBMSI_RESULT_SUCCESS ) *prec = info.rec; else - msiobj_release( &info.rec->hdr ); + g_object_unref(info.rec); } - msiobj_release( &query->hdr ); + g_object_unref(query); return r; } @@ -2330,9 +2459,9 @@ LibmsiResult libmsi_database_get_primary_keys(LibmsiDatabase *db, if( !db ) return LIBMSI_RESULT_INVALID_HANDLE; - msiobj_addref( &db->hdr ); + g_object_ref(db); r = _libmsi_database_get_primary_keys( db, table, prec ); - msiobj_release( &db->hdr ); + g_object_unref(db); return r; } @@ -2344,93 +2473,67 @@ LibmsiCondition libmsi_database_is_table_persistent( TRACE("%x %s\n", db, debugstr_a(szTableName)); - msiobj_addref( &db->hdr ); + g_object_ref(db); if( !db ) return LIBMSI_CONDITION_ERROR; r = _libmsi_database_is_table_persistent( db, szTableName ); - msiobj_release( &db->hdr ); + g_object_unref(db); return r; } -LibmsiResult libmsi_database_open(const char *szDBPath, const char *szPersist, LibmsiDatabase **pdb) +/* TODO: use GInitable */ +static gboolean +init (LibmsiDatabase *self, GError **error) { - LibmsiDatabase *db = NULL; - unsigned ret = LIBMSI_RESULT_SUCCESS; - const char *szMode; - bool patch = false; - char path[MAX_PATH]; - - TRACE("%s %p\n",debugstr_a(szDBPath),szPersist ); + LibmsiDatabase *p = LIBMSI_DATABASE (self); + LibmsiResult ret; - if( !pdb ) - return LIBMSI_RESULT_INVALID_PARAMETER; - - if (IS_INTMSIDBOPEN(szPersist - LIBMSI_DB_OPEN_PATCHFILE)) - { - TRACE("Database is a patch\n"); - szPersist -= LIBMSI_DB_OPEN_PATCHFILE; - patch = true; - } - - szMode = szPersist; - db = alloc_msiobject( sizeof (LibmsiDatabase), _libmsi_database_destroy ); - if( !db ) - { - FIXME("Failed to allocate a handle\n"); - goto end; + if (p->mode == LIBMSI_DB_OPEN_CREATE) { + p->strings = msi_init_string_table (&p->bytes_per_strref); + } else { + if (_libmsi_database_open(self)) + return FALSE; } - if (!strstr( szDBPath, G_DIR_SEPARATOR_S )) - { - getcwd( path, MAX_PATH ); - strcat( path, G_DIR_SEPARATOR_S ); - strcat( path, szDBPath ); - } - else - strcpy( path, szDBPath ); + p->media_transform_offset = MSI_INITIAL_MEDIA_TRANSFORM_OFFSET; + p->media_transform_disk_id = MSI_INITIAL_MEDIA_TRANSFORM_DISKID; - db->patch = patch; - db->mode = szMode; - list_init( &db->tables ); - list_init( &db->transforms ); - list_init( &db->streams ); - list_init( &db->storages ); + if (TRACE_ON(msi)) + enum_stream_names (p->infile); - if( szPersist != LIBMSI_DB_OPEN_CREATE ) - { - db->path = strdup( path ); - ret = _libmsi_database_open(db); - if (ret) - goto end; - } else { - szPersist = szDBPath; - db->strings = msi_init_string_table( &db->bytes_per_strref ); - } + ret = _libmsi_database_start_transaction (self); - db->media_transform_offset = MSI_INITIAL_MEDIA_TRANSFORM_OFFSET; - db->media_transform_disk_id = MSI_INITIAL_MEDIA_TRANSFORM_DISKID; + return !ret; +} - if( TRACE_ON( msi ) ) - enum_stream_names( db->infile ); +LibmsiDatabase * +libmsi_database_new (const gchar *path, const char *persist, GError **error) +{ + LibmsiDatabase *self; + gboolean patch = false; - if( szPersist == LIBMSI_DB_OPEN_CREATE ) - ret = _libmsi_database_start_transaction(db, szDBPath); - else - ret = _libmsi_database_start_transaction(db, szPersist); - if (ret) - goto end; + g_return_val_if_fail (path != NULL, NULL); - ret = LIBMSI_RESULT_SUCCESS; + if (IS_INTMSIDBOPEN (persist - LIBMSI_DB_OPEN_PATCHFILE)) { + TRACE("Database is a patch\n"); + persist -= LIBMSI_DB_OPEN_PATCHFILE; + patch = true; + } - msiobj_addref( &db->hdr ); - *pdb = db; + self = g_object_new (LIBMSI_TYPE_DATABASE, + "path", path, + "patch", patch, + "outpath", IS_INTMSIDBOPEN(persist) ? NULL : persist, + "mode", (int)(intptr_t)(IS_INTMSIDBOPEN(persist) ? persist : LIBMSI_DB_OPEN_TRANSACT), + NULL); -end: - if( db ) - msiobj_release( &db->hdr ); + if (!init (self, error)) { + g_object_unref (self); + return NULL; + } - return ret; + return self; } diff --git a/libmsi/libmsi-query.c b/libmsi/libmsi-query.c index b76b859..d0c8a3b 100644 --- a/libmsi/libmsi-query.c +++ b/libmsi/libmsi-query.c @@ -20,28 +20,130 @@ #include <stdarg.h> +#include "libmsi-query.h" + #include "debug.h" #include "libmsi.h" #include "msipriv.h" - #include "query.h" +enum +{ + PROP_0, + + PROP_DATABASE, + PROP_QUERY, +}; -static void _libmsi_query_destroy( LibmsiObject *arg ) +G_DEFINE_TYPE (LibmsiQuery, libmsi_query, G_TYPE_OBJECT); + +static void +libmsi_query_init (LibmsiQuery *p) { - LibmsiQuery *query = (LibmsiQuery*) arg; + list_init (&p->mem); +} + +static void +libmsi_query_finalize (GObject *object) +{ + LibmsiQuery *self = LIBMSI_QUERY (object); + LibmsiQuery *p = self; struct list *ptr, *t; - if( query->view && query->view->ops->delete ) - query->view->ops->delete( query->view ); - msiobj_release( &query->db->hdr ); + if (p->view && p->view->ops->delete) + p->view->ops->delete (p->view); - LIST_FOR_EACH_SAFE( ptr, t, &query->mem ) - { - msi_free( ptr ); + if (p->database) + g_object_unref (p->database); + + LIST_FOR_EACH_SAFE (ptr, t, &p->mem) { + msi_free (ptr); + } + + g_free (p->query); + + G_OBJECT_CLASS (libmsi_query_parent_class)->finalize (object); +} + +static void +libmsi_query_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + LibmsiQuery *p = LIBMSI_QUERY (object); + g_return_if_fail (LIBMSI_IS_QUERY (object)); + + switch (prop_id) { + case PROP_DATABASE: + g_return_if_fail (p->database == NULL); + p->database = g_value_dup_object (value); + break; + case PROP_QUERY: + g_return_if_fail (p->query == NULL); + p->query = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +libmsi_query_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + LibmsiQuery *p = LIBMSI_QUERY (object); + g_return_if_fail (LIBMSI_IS_QUERY (object)); + + switch (prop_id) { + case PROP_DATABASE: + g_value_set_object (value, p->database); + break; + case PROP_QUERY: + g_value_set_string (value, p->query); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; } } +static void +libmsi_query_constructed (GObject *object) +{ + G_OBJECT_CLASS (libmsi_query_parent_class)->constructed (object); +} + +static void +libmsi_query_class_init (LibmsiQueryClass *klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = libmsi_query_finalize; + object_class->set_property = libmsi_query_set_property; + object_class->get_property = libmsi_query_get_property; + object_class->constructed = libmsi_query_constructed; + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DATABASE, + g_param_spec_object ("database", "database", "database", LIBMSI_TYPE_DATABASE, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_QUERY, + g_param_spec_string ("query", "query", "query", NULL, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); +} + +/* TODO: use GInitable */ +static gboolean +init (LibmsiQuery *self, GError **error) +{ + LibmsiQuery *p = self; + unsigned r; + + r = _libmsi_parse_sql (p->database, p->query, &p->view, &p->mem); + + return r == LIBMSI_RESULT_SUCCESS; +} + unsigned _libmsi_view_find_column( LibmsiView *table, const char *name, const char *table_name, unsigned *n ) { const char *col_name; @@ -81,10 +183,10 @@ LibmsiResult libmsi_database_open_query(LibmsiDatabase *db, if( !db ) return LIBMSI_RESULT_INVALID_HANDLE; - msiobj_addref( &db->hdr); + g_object_ref(db); r = _libmsi_database_open_query( db, szQuery, pQuery ); - msiobj_release( &db->hdr ); + g_object_unref(db); return r; } @@ -92,32 +194,11 @@ LibmsiResult libmsi_database_open_query(LibmsiDatabase *db, unsigned _libmsi_database_open_query(LibmsiDatabase *db, const char *szQuery, LibmsiQuery **pView) { - LibmsiQuery *query; - unsigned r; - TRACE("%s %p\n", debugstr_a(szQuery), pView); - if( !szQuery) - return LIBMSI_RESULT_INVALID_PARAMETER; - - /* pre allocate a handle to hold a pointer to the view */ - query = alloc_msiobject( sizeof (LibmsiQuery), _libmsi_query_destroy ); - if( !query ) - return LIBMSI_RESULT_FUNCTION_FAILED; - - msiobj_addref( &db->hdr ); - query->db = db; - list_init( &query->mem ); + *pView = libmsi_query_new (db, szQuery, NULL); - r = _libmsi_parse_sql( db, szQuery, &query->view, &query->mem ); - if( r == LIBMSI_RESULT_SUCCESS ) - { - msiobj_addref( &query->hdr ); - *pView = query; - } - - msiobj_release( &query->hdr ); - return r; + return *pView ? LIBMSI_RESULT_SUCCESS : LIBMSI_RESULT_BAD_QUERY_SYNTAX; } unsigned _libmsi_query_open( LibmsiDatabase *db, LibmsiQuery **view, const char *fmt, ... ) @@ -166,7 +247,7 @@ unsigned _libmsi_query_iterate_records( LibmsiQuery *view, unsigned *count, break; if (func) r = func( rec, param ); - msiobj_release( &rec->hdr ); + g_object_unref(rec); if( r != LIBMSI_RESULT_SUCCESS ) break; } @@ -213,7 +294,7 @@ LibmsiRecord *_libmsi_query_get_record( LibmsiDatabase *db, const char *fmt, ... _libmsi_query_execute( view, NULL ); _libmsi_query_fetch( view, &rec ); libmsi_query_close( view ); - msiobj_release( &view->hdr ); + g_object_unref(view); } return rec; } @@ -234,7 +315,7 @@ unsigned msi_view_get_row(LibmsiDatabase *db, LibmsiView *view, unsigned row, Li if (row >= row_count) return LIBMSI_RESULT_NO_MORE_ITEMS; - *rec = libmsi_record_new(col_count); + *rec = libmsi_record_new (col_count); if (!*rec) return LIBMSI_RESULT_FUNCTION_FAILED; @@ -307,7 +388,7 @@ LibmsiResult _libmsi_query_fetch(LibmsiQuery *query, LibmsiRecord **prec) if( !view ) return LIBMSI_RESULT_FUNCTION_FAILED; - r = msi_view_get_row(query->db, view, query->row, prec); + r = msi_view_get_row(query->database, view, query->row, prec); if (r == LIBMSI_RESULT_SUCCESS) query->row ++; @@ -326,9 +407,9 @@ LibmsiResult libmsi_query_fetch(LibmsiQuery *query, LibmsiRecord **record) if( !query ) return LIBMSI_RESULT_INVALID_HANDLE; - msiobj_addref( &query->hdr); + g_object_ref(query); ret = _libmsi_query_fetch( query, record ); - msiobj_release( &query->hdr ); + g_object_unref(query); return ret; } @@ -342,7 +423,7 @@ LibmsiResult libmsi_query_close(LibmsiQuery *query) if( !query ) return LIBMSI_RESULT_INVALID_HANDLE; - msiobj_addref( &query->hdr ); + g_object_ref(query); view = query->view; if( !view ) return LIBMSI_RESULT_FUNCTION_FAILED; @@ -350,7 +431,7 @@ LibmsiResult libmsi_query_close(LibmsiQuery *query) return LIBMSI_RESULT_FUNCTION_FAILED; ret = view->ops->close( view ); - msiobj_release( &query->hdr ); + g_object_unref(query); return ret; } @@ -378,16 +459,16 @@ LibmsiResult libmsi_query_execute(LibmsiQuery *query, LibmsiRecord *rec) if( !query ) return LIBMSI_RESULT_INVALID_HANDLE; - msiobj_addref( &query->hdr ); + g_object_ref(query); if( rec ) - msiobj_addref( &rec->hdr ); + g_object_ref(rec); ret = _libmsi_query_execute( query, rec ); - msiobj_release( &query->hdr ); + g_object_unref(query); if( rec ) - msiobj_release( &rec->hdr ); + g_object_unref(rec); return ret; } @@ -449,7 +530,7 @@ unsigned _libmsi_query_get_column_info( LibmsiQuery *query, LibmsiColInfo info, if( !count ) return LIBMSI_RESULT_INVALID_PARAMETER; - rec = libmsi_record_new( count ); + rec = libmsi_record_new (count); if( !rec ) return LIBMSI_RESULT_FUNCTION_FAILED; @@ -483,9 +564,9 @@ LibmsiResult libmsi_query_get_column_info(LibmsiQuery *query, LibmsiColInfo info if( !query ) return LIBMSI_RESULT_INVALID_HANDLE; - msiobj_addref ( &query->hdr ); + g_object_ref(query); r = _libmsi_query_get_column_info( query, info, prec ); - msiobj_release( &query->hdr ); + g_object_unref(query); return r; } @@ -504,7 +585,7 @@ LibmsiDBError libmsi_query_get_error( LibmsiQuery *query, char *buffer, unsigned if (!query) return LIBMSI_DB_ERROR_INVALIDARG; - msiobj_addref( &query->hdr); + g_object_ref(query); if ((r = query->view->error)) column = query->view->error_column; else column = szEmpty; @@ -518,6 +599,27 @@ LibmsiDBError libmsi_query_get_error( LibmsiQuery *query, char *buffer, unsigned } *buflen = len; - msiobj_release( &query->hdr ); + g_object_unref(query); return r; } + +LibmsiQuery* +libmsi_query_new (LibmsiDatabase *database, const char *query, GError **error) +{ + LibmsiQuery *self; + + g_return_val_if_fail (LIBMSI_IS_DATABASE (database), NULL); + g_return_val_if_fail (query != NULL, NULL); + + self = g_object_new (LIBMSI_TYPE_QUERY, + "database", database, + "query", query, + NULL); + + if (!init (self, error)) { + g_object_unref (self); + return NULL; + } + + return self; +} diff --git a/libmsi/libmsi-record.c b/libmsi/libmsi-record.c index abdf9e8..848ba61 100644 --- a/libmsi/libmsi-record.c +++ b/libmsi/libmsi-record.c @@ -20,60 +20,122 @@ #include <stdarg.h> +#include "libmsi-record.h" + #include "debug.h" #include "libmsi.h" #include "msipriv.h" - #include "query.h" +enum +{ + PROP_0, + + PROP_COUNT +}; + +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_STR 3 #define LIBMSI_FIELD_TYPE_STREAM 4 -static void _libmsi_free_field( LibmsiField *field ) +static void +libmsi_record_init (LibmsiRecord *self) { - switch( field->type ) - { +} + +static void +_libmsi_free_field (LibmsiField *field ) +{ + switch (field->type) { case LIBMSI_FIELD_TYPE_NULL: case LIBMSI_FIELD_TYPE_INT: break; case LIBMSI_FIELD_TYPE_STR: - msi_free( field->u.szVal); + msi_free (field->u.szVal); break; case LIBMSI_FIELD_TYPE_STREAM: - g_object_unref(G_OBJECT(field->u.stream)); + g_object_unref (G_OBJECT (field->u.stream)); break; default: - ERR("Invalid field type %d\n", field->type); + ERR ("Invalid field type %d\n", field->type); } } -void _libmsi_record_destroy( LibmsiObject *arg ) +static void +libmsi_record_finalize (GObject *object) { - LibmsiRecord *rec = (LibmsiRecord *) arg; + LibmsiRecord *p = LIBMSI_RECORD (object); unsigned i; - for( i=0; i<=rec->count; i++ ) - _libmsi_free_field( &rec->fields[i] ); + for (i = 0; i <= p->count; i++ ) + _libmsi_free_field (&p->fields[i]); + + g_free (p->fields); + + G_OBJECT_CLASS (libmsi_record_parent_class)->finalize (object); } -LibmsiRecord *libmsi_record_new( unsigned cParams ) +static void +libmsi_record_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - LibmsiRecord *rec; - unsigned len; + g_return_if_fail (LIBMSI_IS_RECORD (object)); + LibmsiRecord *p = LIBMSI_RECORD (object); - TRACE("%d\n", cParams); + switch (prop_id) { + case PROP_COUNT: + p->count = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} - if( cParams>65535 ) - return NULL; +static void +libmsi_record_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + g_return_if_fail (LIBMSI_IS_RECORD (object)); + LibmsiRecord *p = LIBMSI_RECORD (object); - len = sizeof (LibmsiRecord) + sizeof (LibmsiField)*cParams; - rec = alloc_msiobject( len, _libmsi_record_destroy ); - if( rec ) - rec->count = cParams; - return rec; + switch (prop_id) { + case PROP_COUNT: + g_value_set_uint (value, p->count); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +libmsi_record_constructed (GObject *object) +{ + LibmsiRecord *self = LIBMSI_RECORD (object); + LibmsiRecord *p = self; + + // FIXME: +1 could be removed if accessing with idx-1 + p->fields = g_new0 (LibmsiField, p->count + 1); + + G_OBJECT_CLASS (libmsi_record_parent_class)->constructed (object); +} + +static void +libmsi_record_class_init (LibmsiRecordClass *klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = libmsi_record_finalize; + object_class->set_property = libmsi_record_set_property; + object_class->get_property = libmsi_record_get_property; + object_class->constructed = libmsi_record_constructed; + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_COUNT, + g_param_spec_uint ("count", "count", "count", 0, 65535, 0, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); } unsigned libmsi_record_get_field_count( const LibmsiRecord *rec ) @@ -186,14 +248,14 @@ LibmsiResult libmsi_record_clear_data( LibmsiRecord *rec ) if( !rec ) return LIBMSI_RESULT_INVALID_HANDLE; - msiobj_addref( &rec->hdr ); + g_object_ref(rec); for( i=0; i<=rec->count; i++) { _libmsi_free_field( &rec->fields[i] ); rec->fields[i].type = LIBMSI_FIELD_TYPE_NULL; rec->fields[i].u.iVal = 0; } - msiobj_release( &rec->hdr ); + g_object_unref(rec); return LIBMSI_RESULT_SUCCESS; } @@ -486,9 +548,10 @@ LibmsiResult libmsi_record_load_stream(LibmsiRecord *rec, unsigned iField, const if( !rec ) return LIBMSI_RESULT_INVALID_HANDLE; - msiobj_addref( &rec->hdr ); + g_object_ref(rec); ret = _libmsi_record_load_stream_from_file( rec, iField, szFilename ); - msiobj_release( &rec->hdr ); + g_object_unref(rec); + return ret; } @@ -550,9 +613,10 @@ LibmsiResult libmsi_record_save_stream(LibmsiRecord *rec, unsigned iField, char if( !rec ) return LIBMSI_RESULT_INVALID_HANDLE; - msiobj_addref( &rec->hdr ); + g_object_ref(rec); ret = _libmsi_record_save_stream( rec, iField, buf, sz ); - msiobj_release( &rec->hdr ); + g_object_unref(rec); + return ret; } @@ -605,7 +669,7 @@ LibmsiRecord *_libmsi_record_clone(LibmsiRecord *rec) GsfInput *stm = gsf_input_dup(rec->fields[i].u.stream, NULL); if (!stm) { - msiobj_release(&clone->hdr); + g_object_unref(clone); return NULL; } clone->fields[i].u.stream = stm; @@ -616,7 +680,7 @@ LibmsiRecord *_libmsi_record_clone(LibmsiRecord *rec) r = _libmsi_record_copy_field(rec, i, clone, i); if (r != LIBMSI_RESULT_SUCCESS) { - msiobj_release(&clone->hdr); + g_object_unref(clone); return NULL; } } @@ -694,3 +758,11 @@ char *msi_dup_record_field( LibmsiRecord *rec, int field ) } return str; } + +LibmsiRecord * +libmsi_record_new (guint count) +{ + return g_object_new (LIBMSI_TYPE_RECORD, + "count", count, + NULL); +} diff --git a/libmsi/libmsi-summary-info.c b/libmsi/libmsi-summary-info.c index c18f1e8..fafa9e8 100644 --- a/libmsi/libmsi-summary-info.c +++ b/libmsi/libmsi-summary-info.c @@ -22,58 +22,133 @@ #include <time.h> #include <assert.h> +#include "libmsi-summary-info.h" + #include "debug.h" #include "libmsi.h" #include "msipriv.h" + +enum +{ + PROP_0, + + PROP_DATABASE, + PROP_UPDATE_COUNT, +}; + +G_DEFINE_TYPE (LibmsiSummaryInfo, libmsi_summary_info, G_TYPE_OBJECT); + static const char szSumInfo[] = "\5SummaryInformation"; static const uint8_t fmtid_SummaryInformation[16] = { 0xe0, 0x85, 0x9f, 0xf2, 0xf9, 0x4f, 0x68, 0x10, 0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9}; static unsigned load_summary_info( LibmsiSummaryInfo *si, GsfInput *stm ); -static void free_prop( LibmsiOLEVariant *prop ) +static void +libmsi_summary_info_init (LibmsiSummaryInfo *p) +{ +} + +static void +free_prop (LibmsiOLEVariant *prop) { if (prop->vt == OLEVT_LPSTR) - msi_free( prop->strval ); + msi_free (prop->strval); prop->vt = OLEVT_EMPTY; } -static void _libmsi_summary_info_destroy( LibmsiObject *arg ) +static void +libmsi_summary_info_finalize (GObject *object) { - LibmsiSummaryInfo *si = (LibmsiSummaryInfo *) arg; + LibmsiSummaryInfo *p = LIBMSI_SUMMARY_INFO (object); unsigned i; - for( i = 0; i < MSI_MAX_PROPS; i++ ) - free_prop( &si->property[i] ); - msiobj_release( &si->database->hdr ); + for (i = 0; i < MSI_MAX_PROPS; i++) + free_prop (&p->property[i]); + + if (p->database) + g_object_unref (p->database); + + G_OBJECT_CLASS (libmsi_summary_info_parent_class)->finalize (object); } -LibmsiSummaryInfo *_libmsi_get_summary_information( LibmsiDatabase *db, unsigned uiUpdateCount ) +static void +summary_info_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - GsfInput *stm = NULL; - LibmsiSummaryInfo *si; - unsigned r; + g_return_if_fail (LIBMSI_IS_SUMMARY_INFO (object)); + LibmsiSummaryInfo *p = LIBMSI_SUMMARY_INFO (object); - TRACE("%p %d\n", db, uiUpdateCount ); + switch (prop_id) { + case PROP_DATABASE: + g_return_if_fail (p->database == NULL); + p->database = g_value_dup_object (value); + break; + case PROP_UPDATE_COUNT: + p->update_count = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} - si = alloc_msiobject( sizeof (LibmsiSummaryInfo), _libmsi_summary_info_destroy ); - if( !si ) - return si; +static void +summary_info_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + g_return_if_fail (LIBMSI_IS_SUMMARY_INFO (object)); + LibmsiSummaryInfo *p = LIBMSI_SUMMARY_INFO (object); + + switch (prop_id) { + case PROP_DATABASE: + g_value_set_object (value, p->database); + break; + case PROP_UPDATE_COUNT: + g_value_set_uint (value, p->update_count); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} - si->update_count = uiUpdateCount; - msiobj_addref( &db->hdr ); - si->database = db; +static void +libmsi_summary_info_constructed (GObject *object) +{ + LibmsiSummaryInfo *self = LIBMSI_SUMMARY_INFO (object); + LibmsiSummaryInfo *p = self; + GsfInput *stm = NULL; + unsigned r; /* read the stream... if we fail, we'll start with an empty property set */ - r = msi_get_raw_stream( db, szSumInfo, &stm ); - if( r == 0 ) - { - load_summary_info( si, stm ); - g_object_unref(G_OBJECT(stm)); + r = msi_get_raw_stream (p->database, szSumInfo, &stm); + if (r == 0) { + load_summary_info (self, stm); + g_object_unref (G_OBJECT (stm)); } - return si; + G_OBJECT_CLASS (libmsi_summary_info_parent_class)->constructed (object); +} + +static void +libmsi_summary_info_class_init (LibmsiSummaryInfoClass *klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = libmsi_summary_info_finalize; + object_class->set_property = summary_info_set_property; + object_class->get_property = summary_info_get_property; + object_class->constructed = libmsi_summary_info_constructed; + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DATABASE, + g_param_spec_object ("database", "database", "database", LIBMSI_TYPE_DATABASE, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_UPDATE_COUNT, + g_param_spec_uint ("update-count", "update-count", "update-count", 0, G_MAXUINT, 0, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); } static unsigned get_type( unsigned uiProperty ) @@ -466,7 +541,20 @@ static unsigned suminfo_persist( LibmsiSummaryInfo *si ) return r; } -LibmsiResult libmsi_database_get_summary_info( LibmsiDatabase *db, +LibmsiSummaryInfo *_libmsi_get_summary_information( LibmsiDatabase *db, unsigned uiUpdateCount ) +{ + GsfInput *stm = NULL; + LibmsiSummaryInfo *si; + unsigned r; + + TRACE("%p %d\n", db, uiUpdateCount ); + + si = libmsi_summary_info_new (db, uiUpdateCount, NULL); + + return si; +} + +LibmsiResult libmsi_database_get_summary_info( LibmsiDatabase *db, unsigned uiUpdateCount, LibmsiSummaryInfo **psi ) { LibmsiSummaryInfo *si; @@ -480,7 +568,7 @@ LibmsiResult libmsi_database_get_summary_info( LibmsiDatabase *db, if( !db ) return LIBMSI_RESULT_INVALID_HANDLE; - msiobj_addref( &db->hdr); + g_object_ref(db); si = _libmsi_get_summary_information( db, uiUpdateCount ); if (si) { @@ -488,7 +576,7 @@ LibmsiResult libmsi_database_get_summary_info( LibmsiDatabase *db, ret = LIBMSI_RESULT_SUCCESS; } - msiobj_release( &db->hdr ); + g_object_unref(db); return ret; } @@ -499,10 +587,10 @@ LibmsiResult libmsi_summary_info_get_property_count(LibmsiSummaryInfo *si, unsig if( !si ) return LIBMSI_RESULT_INVALID_HANDLE; - msiobj_addref( &si->hdr ); + g_object_ref(si); if( pCount ) *pCount = get_property_count( si->property ); - msiobj_release( &si->hdr ); + g_object_unref(si); return LIBMSI_RESULT_SUCCESS; } @@ -526,7 +614,7 @@ LibmsiResult libmsi_summary_info_get_property( if( !si ) return LIBMSI_RESULT_INVALID_HANDLE; - msiobj_addref( &si->hdr ); + g_object_ref(si); prop = &si->property[uiProperty]; switch( prop->vt ) @@ -571,7 +659,7 @@ LibmsiResult libmsi_summary_info_get_property( FIXME("Unknown property variant type\n"); break; } - msiobj_release( &si->hdr ); + g_object_unref(si); return ret; } @@ -588,7 +676,7 @@ static LibmsiResult _libmsi_summary_info_set_property( LibmsiSummaryInfo *si, un if( type == OLEVT_FILETIME && !pftValue ) return LIBMSI_RESULT_INVALID_PARAMETER; - msiobj_addref( &si->hdr); + g_object_ref(si); prop = &si->property[uiProperty]; @@ -626,7 +714,7 @@ static LibmsiResult _libmsi_summary_info_set_property( LibmsiSummaryInfo *si, un ret = LIBMSI_RESULT_SUCCESS; end: - msiobj_release( &si->hdr ); + g_object_unref(si); return ret; } @@ -745,7 +833,7 @@ end: if (r == LIBMSI_RESULT_SUCCESS) r = suminfo_persist( si ); - msiobj_release( &si->hdr ); + g_object_unref(si); return r; } @@ -758,8 +846,22 @@ LibmsiResult libmsi_summary_info_persist( LibmsiSummaryInfo *si ) if( !si ) return LIBMSI_RESULT_INVALID_HANDLE; - msiobj_addref( &si->hdr); + g_object_ref(si); ret = suminfo_persist( si ); - msiobj_release( &si->hdr ); + g_object_unref(si); + return ret; } + +LibmsiSummaryInfo* +libmsi_summary_info_new (LibmsiDatabase *database, unsigned update_count, GError **error) +{ + LibmsiSummaryInfo *self; + + self = g_object_new (LIBMSI_TYPE_SUMMARY_INFO, + "database", database, + "update-count", update_count, + NULL); + + return self; +} diff --git a/libmsi/msipriv.h b/libmsi/msipriv.h index e660424..a298ae3 100644 --- a/libmsi/msipriv.h +++ b/libmsi/msipriv.h @@ -70,24 +70,13 @@ typedef struct _LibmsiTable LibmsiTable; struct string_table; typedef struct string_table string_table; -struct _LibmsiObject; -typedef struct _LibmsiObject LibmsiObject; - -typedef void (*msihandledestructor)( LibmsiObject * ); - -struct _LibmsiObject -{ - unsigned magic; - int refcount; - msihandledestructor destructor; -}; - #define MSI_INITIAL_MEDIA_TRANSFORM_OFFSET 10000 #define MSI_INITIAL_MEDIA_TRANSFORM_DISKID 30000 -typedef struct _LibmsiDatabase +struct _LibmsiDatabase { - LibmsiObject hdr; + GObject parent; + GsfInfile *infile; GsfOutfile *outfile; string_table *strings; @@ -96,25 +85,27 @@ typedef struct _LibmsiDatabase char *outpath; bool rename_outpath; bool patch; - const char *mode; + const char *mode; /* FIXME: turn this into an enum */ unsigned media_transform_offset; unsigned media_transform_disk_id; struct list tables; struct list transforms; struct list streams; struct list storages; -} LibmsiDatabase; +}; typedef struct _LibmsiView LibmsiView; -typedef struct _LibmsiQuery +struct _LibmsiQuery { - LibmsiObject hdr; + GObject parent; + LibmsiView *view; unsigned row; - LibmsiDatabase *db; + LibmsiDatabase *database; + gchar *query; struct list mem; -} LibmsiQuery; +}; /* maybe we can use a Variant instead of doing it ourselves? */ typedef struct _LibmsiField @@ -128,12 +119,13 @@ typedef struct _LibmsiField } u; } LibmsiField; -typedef struct _LibmsiRecord +struct _LibmsiRecord { - LibmsiObject hdr; + GObject parent; + unsigned count; /* as passed to libmsi_record_new */ - LibmsiField fields[1]; /* nb. array size is count+1 */ -} LibmsiRecord; + LibmsiField *fields; /* nb. array size is count+1 */ +}; typedef struct _column_info { @@ -295,17 +287,18 @@ typedef struct _LibmsiOLEVariant }; } LibmsiOLEVariant; -typedef struct _LibmsiSummaryInfo +struct _LibmsiSummaryInfo { - LibmsiObject hdr; + GObject parent; + LibmsiDatabase *database; unsigned update_count; LibmsiOLEVariant property[MSI_MAX_PROPS]; -} LibmsiSummaryInfo; +}; -extern const guint8 clsid_msi_transform[16]; -extern const guint8 clsid_msi_database[16]; -extern const guint8 clsid_msi_patch[16]; +extern const char clsid_msi_transform[16]; +extern const char clsid_msi_database[16]; +extern const char clsid_msi_patch[16]; /* handle unicode/ascii output in the Msi* API functions */ typedef struct { @@ -326,11 +319,6 @@ typedef struct { unsigned msi_strcpy_to_awstring( const char *str, awstring *awbuf, unsigned *sz ); -/* handle functions */ -extern void *alloc_msiobject(unsigned size, msihandledestructor destroy ); -extern void msiobj_addref(LibmsiObject *); -extern int msiobj_release(LibmsiObject *); - extern void free_cached_tables( LibmsiDatabase *db ); extern unsigned _libmsi_database_commit_tables( LibmsiDatabase *db, unsigned bytes_per_strref ); @@ -372,7 +360,7 @@ extern void append_storage_to_db( LibmsiDatabase *db, GsfInfile *stg ); extern unsigned _libmsi_database_commit_storages( LibmsiDatabase *db ); /* record internals */ -extern void _libmsi_record_destroy( LibmsiObject * ); +extern void _libmsi_record_destroy( LibmsiRecord * ); extern unsigned _libmsi_record_set_gsf_input( LibmsiRecord *, unsigned, GsfInput *); extern unsigned _libmsi_record_get_gsf_input( const LibmsiRecord *, unsigned, GsfInput **); extern const char *_libmsi_record_get_string_raw( const LibmsiRecord *, unsigned ); @@ -391,7 +379,7 @@ extern char *encode_streamname(bool bTable, const char *in); extern void decode_streamname(const char *in, char *out); /* database internals */ -extern LibmsiResult _libmsi_database_start_transaction(LibmsiDatabase *db, const char *szPersist); +extern LibmsiResult _libmsi_database_start_transaction(LibmsiDatabase *db); extern LibmsiResult _libmsi_database_open(LibmsiDatabase *db); extern LibmsiResult _libmsi_database_close(LibmsiDatabase *db, bool committed); unsigned msi_create_stream( LibmsiDatabase *db, const char *stname, GsfInput *stm ); diff --git a/libmsi/select.c b/libmsi/select.c index e0967b4..7fe5a16 100644 --- a/libmsi/select.c +++ b/libmsi/select.c @@ -132,7 +132,7 @@ static unsigned select_view_set_row( LibmsiView *view, unsigned row, LibmsiRecor if (r == LIBMSI_RESULT_SUCCESS) r = sv->table->ops->set_row( sv->table, row, expanded, expanded_mask ); - msiobj_release( &expanded->hdr ); + g_object_unref(expanded); return r; } @@ -164,7 +164,7 @@ static unsigned select_view_insert_row( LibmsiView *view, LibmsiRecord *record, r = sv->table->ops->insert_row( sv->table, outrec, row, temporary ); fail: - msiobj_release( &outrec->hdr ); + g_object_unref(outrec); return r; } diff --git a/libmsi/table.c b/libmsi/table.c index da6c376..9871958 100644 --- a/libmsi/table.c +++ b/libmsi/table.c @@ -799,7 +799,7 @@ unsigned msi_create_table( LibmsiDatabase *db, const char *name, column_info *co tv->ops->delete( tv ); tv = NULL; - msiobj_release( &rec->hdr ); + g_object_unref(rec); rec = NULL; if( persistent != LIBMSI_CONDITION_FALSE ) @@ -853,7 +853,7 @@ unsigned msi_create_table( LibmsiDatabase *db, const char *name, column_info *co err: if (rec) - msiobj_release( &rec->hdr ); + g_object_unref(rec); /* FIXME: remove values from the string table on error */ if( tv ) tv->ops->delete( tv ); @@ -1252,8 +1252,8 @@ static unsigned _libmsi_add_stream( LibmsiDatabase *db, const char *name, GsfInp r = _libmsi_query_execute( query, rec ); err: - msiobj_release( &query->hdr ); - msiobj_release( &rec->hdr ); + g_object_unref(query); + g_object_unref(rec); return r; } @@ -1829,7 +1829,7 @@ static unsigned table_view_remove_column(LibmsiView *view, const char *table, un msi_update_table_columns(tv->db, table); done: - msiobj_release(&rec->hdr); + g_object_unref(rec); columns->ops->delete(columns); return r; } @@ -1908,7 +1908,7 @@ static unsigned table_view_add_column(LibmsiView *view, const char *table, unsig } done: - msiobj_release(&rec->hdr); + g_object_unref(rec); return r; } @@ -1952,7 +1952,7 @@ static unsigned table_view_drop(LibmsiView *view) free_table(tv->table); done: - msiobj_release(&rec->hdr); + g_object_unref(rec); tables->ops->delete(tables); return r; @@ -2522,7 +2522,7 @@ static unsigned msi_table_load_transform( LibmsiDatabase *db, GsfInfile *stg, if (number != MSI_NULL_INTEGER && !strcmp( name, szColumns )) msi_update_table_columns( db, table ); - msiobj_release( &rec->hdr ); + g_object_unref(rec); } n += sz; diff --git a/libmsi/update.c b/libmsi/update.c index 9b63fd6..95effb4 100644 --- a/libmsi/update.c +++ b/libmsi/update.c @@ -111,8 +111,8 @@ static unsigned update_view_execute( LibmsiView *view, LibmsiRecord *record ) } done: - if ( where ) msiobj_release( &where->hdr ); - if ( values ) msiobj_release( &values->hdr ); + if ( where ) g_object_unref(where); + if ( values ) g_object_unref(values); return r; } @@ -171,7 +171,7 @@ static unsigned update_view_delete( LibmsiView *view ) wv = uv->wv; if( wv ) wv->ops->delete( wv ); - msiobj_release( &uv->db->hdr ); + g_object_unref(uv->db); msi_free( uv ); return LIBMSI_RESULT_SUCCESS; @@ -240,8 +240,7 @@ unsigned update_view_create( LibmsiDatabase *db, LibmsiView **view, char *table, /* fill the structure */ uv->view.ops = &update_ops; - msiobj_addref( &db->hdr ); - uv->db = db; + uv->db = g_object_ref(db); uv->vals = columns; uv->wv = sv; *view = (LibmsiView*) uv; diff --git a/libmsi/where.c b/libmsi/where.c index 154a22a..18473ec 100644 --- a/libmsi/where.c +++ b/libmsi/where.c @@ -332,7 +332,7 @@ static unsigned where_view_set_row( LibmsiView *view, unsigned row, LibmsiRecord if (r == LIBMSI_RESULT_SUCCESS) r = table->view->ops->set_row(table->view, rows[table->table_index], reduced, reduced_mask); - msiobj_release(&reduced->hdr); + g_object_unref(reduced); } while ((table = table->next)); return r; @@ -894,7 +894,7 @@ static unsigned where_view_delete( LibmsiView *view ) msi_free(wv->order_info); wv->order_info = NULL; - msiobj_release( &wv->db->hdr ); + g_object_unref(wv->db); msi_free( wv ); return LIBMSI_RESULT_SUCCESS; @@ -1105,8 +1105,7 @@ unsigned where_view_create( LibmsiDatabase *db, LibmsiView **view, char *tables, /* fill the structure */ wv->view.ops = &where_ops; - msiobj_addref( &db->hdr ); - wv->db = db; + wv->db = g_object_ref(db); wv->cond = cond; while (*tables) |