diff options
author | Marc-André Lureau <marcandre.lureau@gmail.com> | 2012-12-10 00:01:22 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2012-12-11 11:23:19 +0100 |
commit | ae4c81e4fca5bb5816b5cbabb17a7dcc22f58a3b (patch) | |
tree | 76012c4f3d176b748961c24f96e87724804f260a /libmsi | |
parent | 0ffc9bc6e55b5e42766e68fb6cc087f6cbead6e0 (diff) | |
download | msitools-ae4c81e4fca5bb5816b5cbabb17a7dcc22f58a3b.tar.gz msitools-ae4c81e4fca5bb5816b5cbabb17a7dcc22f58a3b.tar.xz msitools-ae4c81e4fca5bb5816b5cbabb17a7dcc22f58a3b.zip |
convert to GObject
Diffstat (limited to 'libmsi')
-rw-r--r-- | libmsi/Makefile.am | 42 | ||||
-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 | 91 | ||||
-rw-r--r-- | libmsi/insert.c | 14 | ||||
-rw-r--r-- | libmsi/libmsi-database.c | 419 | ||||
-rw-r--r-- | libmsi/libmsi-query.c | 215 | ||||
-rw-r--r-- | libmsi/libmsi-record.c | 128 | ||||
-rw-r--r-- | libmsi/libmsi-summary-info.c | 172 | ||||
-rw-r--r-- | libmsi/msipriv.h | 56 | ||||
-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, 742 insertions, 447 deletions
diff --git a/libmsi/Makefile.am b/libmsi/Makefile.am index c3f285e..4ce4413 100644 --- a/libmsi/Makefile.am +++ b/libmsi/Makefile.am @@ -1,24 +1,43 @@ +NULL = lib_LTLIBRARIES = libmsi.la AM_CPPFLAGS = -I$(top_srcdir)/include -I$(srcdir) -I. -DUNICODE \ -I$(srcdir)/winstubs -include $(srcdir)/winstubs/winstubs.h \ - $(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 \ - query.h \ - unicode.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 \ - utf16/snprintfW.c utf16/sprintfW.c utf16/strtolW.c +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 \ + utf16/snprintfW.c \ + utf16/sprintfW.c \ + utf16/strtolW.c \ + $(NULL) libmsi_la_LDFLAGS = -no-undefined -rpath $(libdir) \ -export-symbols-regex='^libmsi_' @@ -26,5 +45,6 @@ libmsi_la_LDFLAGS = -no-undefined -rpath $(libdir) \ libmsi_la_LIBADD = \ $(GLIB_LIBS) \ $(GSF_LIBS) \ + $(GOBJECT_LIBS) \ -lshlwapi \ -lole32 diff --git a/libmsi/alter.c b/libmsi/alter.c index bd99dc2..90b4550 100644 --- a/libmsi/alter.c +++ b/libmsi/alter.c @@ -97,10 +97,10 @@ static bool check_column_exists(LibmsiDatabase *db, const WCHAR *table, const WC 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); } @@ -132,7 +132,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 52cff0d..3cdc576 100644 --- a/libmsi/create.c +++ b/libmsi/create.c @@ -104,7 +104,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; @@ -183,8 +183,7 @@ unsigned create_view_create( LibmsiDatabase *db, LibmsiView **view, const WCHAR /* 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 5a1fdb2..80b841f 100644 --- a/libmsi/distinct.c +++ b/libmsi/distinct.c @@ -226,7 +226,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; @@ -295,8 +295,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 42710d2..0000000 --- a/libmsi/handle.c +++ /dev/null @@ -1,91 +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 - */ - -#define COBJMACROS - -#include <stdarg.h> -#include <assert.h> - -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "shlwapi.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 777fc48..9192129 100644 --- a/libmsi/insert.c +++ b/libmsi/insert.c @@ -98,7 +98,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; } @@ -168,12 +168,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; } @@ -244,7 +244,7 @@ static unsigned insert_view_execute( LibmsiView *view, LibmsiRecord *record ) err: if( values ) - msiobj_release( &values->hdr ); + g_object_unref(values); return r; } @@ -303,7 +303,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; @@ -379,9 +379,9 @@ unsigned insert_view_create( LibmsiDatabase *db, LibmsiView **view, const WCHAR /* 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 a960fc2..ce85457 100644 --- a/libmsi/libmsi-database.c +++ b/libmsi/libmsi-database.c @@ -30,6 +30,9 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" + +#include "libmsi-database.h" + #include "debug.h" #include "unicode.h" #include "libmsi.h" @@ -38,6 +41,18 @@ #include "objbase.h" #include "query.h" +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 }; @@ -72,26 +87,130 @@ typedef struct _LibmsiStream { IStream *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 ); - IStorage_Release( t->stg ); - msi_free( t ); + 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); } } -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( db, false ); - free_cached_tables( db ); - free_transforms( db ); - msi_free(db->path); + _libmsi_database_close (self, false); + free_cached_tables (self); + free_transforms (self); + + 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)); } static HRESULT stream_to_storage(IStream *stm, IStorage **stg) @@ -576,7 +695,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; IStorage *stg = NULL; @@ -588,22 +707,21 @@ 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); - szwPersist = strdupAtoW(szPersist); + szwPersist = strdupAtoW(db->outpath); hr = StgCreateDocfile( szwPersist, STGM_CREATE|STGM_TRANSACTED|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, &stg ); @@ -614,7 +732,7 @@ LibmsiResult _libmsi_database_start_transaction(LibmsiDatabase *db, const char * if( FAILED( hr ) ) { - WARN("open failed hr = %08x for %s\n", hr, debugstr_a(szPersist)); + WARN("open failed hr = %08x for %s\n", hr, debugstr_a(db->outpath)); ret = LIBMSI_RESULT_FUNCTION_FAILED; goto end; } @@ -622,18 +740,6 @@ LibmsiResult _libmsi_database_start_transaction(LibmsiDatabase *db, const char * db->outfile = stg; IStorage_AddRef( db->outfile ); - if (!strchr( szPersist, '\\' )) - { - getcwd( path, MAX_PATH ); - strcat( path, "\\" ); - strcat( path, szPersist ); - } - else - strcpy( path, szPersist ); - - db->outpath = strdup( path ); - db->rename_outpath = (tmpfile != NULL); - end: if (ret) { if (db->outfile) @@ -642,10 +748,32 @@ end: } if (stg) IStorage_Release( stg ); - msi_free(tmpfile); 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 (!strchr( szDBPath, '\\' )) + { + getcwd( path, MAX_PATH ); + strcat( path, "\\" ); + strcat( path, szDBPath ); + } + else + strcpy( path, szDBPath ); + + *pdb = libmsi_database_new (path, szPersist, NULL); + + return *pdb ? LIBMSI_RESULT_SUCCESS : LIBMSI_RESULT_OPEN_FAILED; +} + static WCHAR *msi_read_text_archive(const char *path, unsigned *len) { int fd; @@ -933,7 +1061,7 @@ static unsigned msi_add_table_to_db(LibmsiDatabase *db, WCHAR **columns, WCHAR * r = _libmsi_query_execute(view, NULL); libmsi_query_close(view); - msiobj_release(&view->hdr); + g_object_unref(view); done: msi_free(prelude); @@ -1006,7 +1134,7 @@ static unsigned construct_record(unsigned num_columns, WCHAR **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; } } @@ -1048,11 +1176,11 @@ static unsigned msi_add_records_to_table(LibmsiDatabase *db, WCHAR **columns, WC 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: @@ -1188,9 +1316,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; } @@ -1290,7 +1418,7 @@ static unsigned _libmsi_database_export( LibmsiDatabase *db, const WCHAR *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 */ @@ -1298,7 +1426,7 @@ static unsigned _libmsi_database_export( LibmsiDatabase *db, const WCHAR *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 */ @@ -1307,12 +1435,12 @@ static unsigned _libmsi_database_export( LibmsiDatabase *db, const WCHAR *table, { _libmsi_record_set_stringW( 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: @@ -1337,8 +1465,6 @@ done: LibmsiResult libmsi_database_export( LibmsiDatabase *db, const char *szTable, int fd ) { - WCHAR *path = NULL; - WCHAR *file = NULL; WCHAR *table = NULL; unsigned r = LIBMSI_RESULT_OUTOFMEMORY; @@ -1354,15 +1480,12 @@ 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, table, fd ); - msiobj_release( &db->hdr ); + g_object_unref(db); end: - msi_free( table ); - msi_free( path ); - msi_free( file ); - + msi_free(table); return r; } @@ -1434,8 +1557,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); @@ -1461,8 +1584,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; } @@ -1498,8 +1621,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; } @@ -1523,7 +1646,7 @@ static WCHAR *get_key_value(LibmsiQuery *view, const WCHAR *key, LibmsiRecord *r msi_free(str); } while (cmp); - msiobj_release(&colnames->hdr); + g_object_unref(colnames); r = _libmsi_record_get_stringW(rec, i, NULL, &sz); if (r != LIBMSI_RESULT_SUCCESS) @@ -1625,7 +1748,7 @@ static WCHAR *create_diff_row_query(LibmsiDatabase *merge, LibmsiQuery *view, done: msi_free(clause); - msiobj_release(&keys->hdr); + g_object_unref(keys); return query; } @@ -1684,8 +1807,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; } @@ -1714,7 +1837,7 @@ static unsigned msi_get_table_labels(LibmsiDatabase *db, const WCHAR *table, WCH } end: - msiobj_release( &prec->hdr ); + g_object_unref(prec); return r; } @@ -1743,7 +1866,7 @@ static unsigned msi_get_query_columns(LibmsiQuery *query, WCHAR ***columns, unsi *numcolumns = count; end: - msiobj_release( &prec->hdr ); + g_object_unref(prec); return r; } @@ -1771,7 +1894,7 @@ static unsigned msi_get_query_types(LibmsiQuery *query, WCHAR ***types, unsigned } end: - msiobj_release( &prec->hdr ); + g_object_unref(prec); return r; } @@ -1784,7 +1907,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); } } @@ -1860,12 +1983,12 @@ static unsigned msi_get_merge_table (LibmsiDatabase *db, const WCHAR *name, MERG table->name = strdupW(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; @@ -1920,8 +2043,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; } @@ -1943,7 +2066,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; } @@ -2005,7 +2128,7 @@ static unsigned update_merge_errors(LibmsiDatabase *db, const WCHAR *error, return r; r = _libmsi_query_execute(view, NULL); - msiobj_release(&view->hdr); + g_object_unref(view); if (r != LIBMSI_RESULT_SUCCESS) return r; } @@ -2015,7 +2138,7 @@ static unsigned update_merge_errors(LibmsiDatabase *db, const WCHAR *error, return r; r = _libmsi_query_execute(view, NULL); - msiobj_release(&view->hdr); + g_object_unref(view); return r; } @@ -2039,8 +2162,8 @@ LibmsiResult libmsi_database_merge(LibmsiDatabase *db, LibmsiDatabase *merge, return LIBMSI_RESULT_INVALID_HANDLE; szwTableName = strdupAtoW(szTableName); - 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; @@ -2076,8 +2199,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; } @@ -2090,10 +2213,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; } @@ -2262,11 +2385,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; } @@ -2343,7 +2466,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; @@ -2390,11 +2513,12 @@ LibmsiResult libmsi_database_commit( LibmsiDatabase *db ) } _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; } @@ -2466,9 +2590,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; } @@ -2491,9 +2615,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, szwTable, prec ); - msiobj_release( &db->hdr ); + g_object_unref(db); msi_free( szwTable ); return r; @@ -2514,95 +2638,68 @@ LibmsiCondition libmsi_database_is_table_persistent( return LIBMSI_CONDITION_ERROR; } - msiobj_addref( &db->hdr ); + g_object_ref(db); if( !db ) return LIBMSI_CONDITION_ERROR; r = _libmsi_database_is_table_persistent( db, szwTableName ); - msiobj_release( &db->hdr ); + g_object_unref(db); msi_free( szwTableName ); 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 ); - - 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; - } + LibmsiDatabase *p = LIBMSI_DATABASE (self); + LibmsiResult ret; - 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 (!strchr( szDBPath, '\\' )) - { - getcwd( path, MAX_PATH ); - strcat( path, "\\" ); - 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 b5a48ad..34512d9 100644 --- a/libmsi/libmsi-query.c +++ b/libmsi/libmsi-query.c @@ -25,6 +25,9 @@ #include "windef.h" #include "winbase.h" #include "winerror.h" + +#include "libmsi-query.h" + #include "debug.h" #include "unicode.h" #include "libmsi.h" @@ -35,20 +38,124 @@ #include "query.h" +enum +{ + PROP_0, + + PROP_DATABASE, + PROP_QUERY, +}; + +G_DEFINE_TYPE (LibmsiQuery, libmsi_query, G_TYPE_OBJECT); + +static void +libmsi_query_init (LibmsiQuery *p) +{ + list_init (&p->mem); +} -static void _libmsi_query_destroy( LibmsiObject *arg ) +static void +libmsi_query_finalize (GObject *object) { - LibmsiQuery *query = (LibmsiQuery*) arg; + 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; + WCHAR *szwQuery; + unsigned r; + + szwQuery = strdupAtoW(p->query); + r = _libmsi_parse_sql (p->database, szwQuery, &p->view, &p->mem); + msi_free(szwQuery); + + return r == LIBMSI_RESULT_SUCCESS; } unsigned _libmsi_view_find_column( LibmsiView *table, const WCHAR *name, const WCHAR *table_name, unsigned *n ) @@ -100,44 +207,26 @@ 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, szwQuery, pQuery ); - msiobj_release( &db->hdr ); + g_object_unref(db); msi_free( szwQuery ); return r; } unsigned _libmsi_database_open_query(LibmsiDatabase *db, - const WCHAR *szQuery, LibmsiQuery **pView) + const WCHAR *szwQuery, LibmsiQuery **pView) { - LibmsiQuery *query; - unsigned r; - + char *szQuery; TRACE("%s %p\n", debugstr_w(szQuery), pView); - if( !szQuery) - return LIBMSI_RESULT_INVALID_PARAMETER; + szQuery = strdupWtoA(szwQuery); + *pView = libmsi_query_new (db, szQuery, NULL); + msi_free(szQuery); - /* 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 ); - - 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 WCHAR *fmt, ... ) @@ -186,7 +275,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; } @@ -233,7 +322,7 @@ LibmsiRecord *_libmsi_query_get_record( LibmsiDatabase *db, const WCHAR *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; } @@ -254,7 +343,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; @@ -327,7 +416,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 ++; @@ -346,9 +435,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; } @@ -362,7 +451,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; @@ -370,7 +459,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; } @@ -398,16 +487,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; } @@ -469,7 +558,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; @@ -503,9 +592,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; } @@ -524,7 +613,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; @@ -536,7 +625,29 @@ LibmsiDBError libmsi_query_get_error( LibmsiQuery *query, char *buffer, unsigned else r = LIBMSI_DB_ERROR_MOREDATA; } - *buflen = len - 1; - msiobj_release( &query->hdr ); + + *buflen = len; + 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 225475e..78b0e21 100644 --- a/libmsi/libmsi-record.c +++ b/libmsi/libmsi-record.c @@ -25,6 +25,9 @@ #include "windef.h" #include "winbase.h" #include "winerror.h" + +#include "libmsi-record.h" + #include "debug.h" #include "unicode.h" #include "libmsi.h" @@ -37,16 +40,29 @@ #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_WSTR 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; @@ -57,34 +73,82 @@ static void _libmsi_free_field( LibmsiField *field ) IStream_Release( 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 ) @@ -197,14 +261,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; } @@ -540,9 +604,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; } @@ -613,9 +678,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; } @@ -668,7 +734,7 @@ LibmsiRecord *_libmsi_record_clone(LibmsiRecord *rec) if (FAILED(IStream_Clone(rec->fields[i].u.stream, &clone->fields[i].u.stream))) { - msiobj_release(&clone->hdr); + g_object_unref(clone); return NULL; } clone->fields[i].type = LIBMSI_FIELD_TYPE_STREAM; @@ -678,7 +744,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; } } @@ -756,3 +822,11 @@ WCHAR *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 3e7644e..00a10e3 100644 --- a/libmsi/libmsi-summary-info.c +++ b/libmsi/libmsi-summary-info.c @@ -22,6 +22,8 @@ #include <time.h> #include <assert.h> +#include "libmsi-summary-info.h" + #define COBJMACROS #define NONAMELESSUNION @@ -30,54 +32,127 @@ #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 WCHAR szSumInfo[] = {5 ,'S','u','m','m','a','r','y','I','n','f','o','r','m','a','t','i','o','n',0}; 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, IStream *stm ); +static unsigned load_summary_info (LibmsiSummaryInfo *si, IStream *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) { - IStream *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); - si->update_count = uiUpdateCount; - msiobj_addref( &db->hdr ); - si->database = db; + 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; + } +} + +static void +libmsi_summary_info_constructed (GObject *object) +{ + LibmsiSummaryInfo *self = LIBMSI_SUMMARY_INFO (object); + LibmsiSummaryInfo *p = self; + IStream *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 ); + r = msi_get_raw_stream (p->database, szSumInfo, &stm); + if (r == 0) { + load_summary_info (self, stm); IStream_Release( 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 ) @@ -479,7 +554,18 @@ 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 ) +{ + LibmsiSummaryInfo *si; + + 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; @@ -493,7 +579,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) { @@ -501,7 +587,7 @@ LibmsiResult libmsi_database_get_summary_info( LibmsiDatabase *db, ret = LIBMSI_RESULT_SUCCESS; } - msiobj_release( &db->hdr ); + g_object_unref(db); return ret; } @@ -512,10 +598,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; } @@ -539,7 +625,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 ) @@ -584,7 +670,7 @@ LibmsiResult libmsi_summary_info_get_property( FIXME("Unknown property variant type\n"); break; } - msiobj_release( &si->hdr ); + g_object_unref(si); return ret; } @@ -601,7 +687,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]; @@ -639,7 +725,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; } @@ -758,7 +844,7 @@ end: if (r == LIBMSI_RESULT_SUCCESS) r = suminfo_persist( si ); - msiobj_release( &si->hdr ); + g_object_unref(si); return r; } @@ -771,8 +857,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 d9fb5e8..b085e27 100644 --- a/libmsi/msipriv.h +++ b/libmsi/msipriv.h @@ -59,24 +59,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; - LONG 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; + IStorage *infile; IStorage *outfile; string_table *strings; @@ -85,25 +74,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 @@ -117,12 +108,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 { @@ -284,13 +276,14 @@ 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 char clsid_msi_transform[16]; extern const char clsid_msi_database[16]; @@ -315,11 +308,6 @@ typedef struct { unsigned msi_strcpy_to_awstring( const WCHAR *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 ); @@ -361,7 +349,7 @@ extern void append_storage_to_db( LibmsiDatabase *db, IStorage *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_IStream( LibmsiRecord *, unsigned, IStream *); extern unsigned _libmsi_record_get_IStream( const LibmsiRecord *, unsigned, IStream **); extern const WCHAR *_libmsi_record_get_string_raw( const LibmsiRecord *, unsigned ); @@ -381,7 +369,7 @@ extern WCHAR *encode_streamname(bool bTable, const WCHAR *in); extern void decode_streamname(const WCHAR *in, WCHAR *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 WCHAR *stname, IStream *stm ); diff --git a/libmsi/select.c b/libmsi/select.c index 949a70a..d596d12 100644 --- a/libmsi/select.c +++ b/libmsi/select.c @@ -138,7 +138,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; } @@ -170,7 +170,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 75122f6..0d1c604 100644 --- a/libmsi/table.c +++ b/libmsi/table.c @@ -870,7 +870,7 @@ unsigned msi_create_table( LibmsiDatabase *db, const WCHAR *name, column_info *c tv->ops->delete( tv ); tv = NULL; - msiobj_release( &rec->hdr ); + g_object_unref(rec); rec = NULL; if( persistent != LIBMSI_CONDITION_FALSE ) @@ -924,7 +924,7 @@ unsigned msi_create_table( LibmsiDatabase *db, const WCHAR *name, column_info *c 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 ); @@ -1326,8 +1326,8 @@ static unsigned _libmsi_add_stream( LibmsiDatabase *db, const WCHAR *name, IStre 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; } @@ -1903,7 +1903,7 @@ static unsigned table_view_remove_column(LibmsiView *view, const WCHAR *table, u msi_update_table_columns(tv->db, table); done: - msiobj_release(&rec->hdr); + g_object_unref(rec); columns->ops->delete(columns); return r; } @@ -1982,7 +1982,7 @@ static unsigned table_view_add_column(LibmsiView *view, const WCHAR *table, unsi } done: - msiobj_release(&rec->hdr); + g_object_unref(rec); return r; } @@ -2026,7 +2026,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; @@ -2597,7 +2597,7 @@ static unsigned msi_table_load_transform( LibmsiDatabase *db, IStorage *stg, if (number != MSI_NULL_INTEGER && !strcmpW( 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 7a2a523..47b7caf 100644 --- a/libmsi/update.c +++ b/libmsi/update.c @@ -117,8 +117,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; } @@ -177,7 +177,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; @@ -246,8 +246,7 @@ unsigned update_view_create( LibmsiDatabase *db, LibmsiView **view, WCHAR *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 62cfe75..b7b5ff0 100644 --- a/libmsi/where.c +++ b/libmsi/where.c @@ -339,7 +339,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; @@ -901,7 +901,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; @@ -1112,8 +1112,7 @@ unsigned where_view_create( LibmsiDatabase *db, LibmsiView **view, WCHAR *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) |