diff options
Diffstat (limited to 'libmsi/libmsi-database.c')
-rw-r--r-- | libmsi/libmsi-database.c | 940 |
1 files changed, 387 insertions, 553 deletions
diff --git a/libmsi/libmsi-database.c b/libmsi/libmsi-database.c index ce85457..6b9f25f 100644 --- a/libmsi/libmsi-database.c +++ b/libmsi/libmsi-database.c @@ -24,21 +24,11 @@ #include <fcntl.h> #include <sys/stat.h> -#define COBJMACROS -#define NONAMELESSUNION - -#include "windef.h" -#include "winbase.h" -#include "winnls.h" - #include "libmsi-database.h" #include "debug.h" -#include "unicode.h" #include "libmsi.h" #include "msipriv.h" -#include "objidl.h" -#include "objbase.h" #include "query.h" enum @@ -72,19 +62,19 @@ const char clsid_msi_patch[16] = { 0x86, 0x10, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x0 typedef struct _LibmsiTransform { struct list entry; - IStorage *stg; + GsfInfile *stg; } LibmsiTransform; typedef struct _LibmsiStorage { struct list entry; - WCHAR *name; - IStorage *stg; + char *name; + GsfInfile *stg; } LibmsiStorage; typedef struct _LibmsiStream { struct list entry; - WCHAR *name; - IStream *stm; + char *name; + GsfInput *stm; } LibmsiStream; static void @@ -213,86 +203,33 @@ libmsi_database_class_init (LibmsiDatabaseClass *klass) G_PARAM_STATIC_STRINGS)); } -static HRESULT stream_to_storage(IStream *stm, IStorage **stg) -{ - ILockBytes *lockbytes = NULL; - STATSTG stat; - void *data; - HRESULT hr; - unsigned size, read; - ULARGE_INTEGER offset; - - hr = IStream_Stat(stm, &stat, STATFLAG_NONAME); - if (FAILED(hr)) - return hr; - - if (stat.cbSize.QuadPart >> 32) - { - ERR("Storage is too large\n"); - return E_FAIL; - } - - size = stat.cbSize.QuadPart; - data = msi_alloc(size); - if (!data) - return E_OUTOFMEMORY; - - hr = IStream_Read(stm, data, size, &read); - if (FAILED(hr) || read != size) - goto done; - - hr = CreateILockBytesOnHGlobal(NULL, true, &lockbytes); - if (FAILED(hr)) - goto done; - - ZeroMemory(&offset, sizeof(ULARGE_INTEGER)); - hr = ILockBytes_WriteAt(lockbytes, offset, data, size, &read); - if (FAILED(hr) || read != size) - goto done; - - hr = StgOpenStorageOnILockBytes(lockbytes, NULL, - STGM_READWRITE | STGM_SHARE_DENY_NONE, - NULL, 0, stg); - if (FAILED(hr)) - goto done; - -done: - msi_free(data); - if (lockbytes) ILockBytes_Release(lockbytes); - return hr; -} - -unsigned msi_open_storage( LibmsiDatabase *db, const WCHAR *stname ) +unsigned msi_open_storage( LibmsiDatabase *db, const char *stname ) { - unsigned r; - HRESULT hr; + unsigned r = LIBMSI_RESULT_NOT_ENOUGH_MEMORY; LibmsiStorage *storage; + GsfInput *in; LIST_FOR_EACH_ENTRY( storage, &db->storages, LibmsiStorage, entry ) { - if( !strcmpW( stname, storage->name ) ) + if( !strcmp( stname, storage->name ) ) { - TRACE("found %s\n", debugstr_w(stname)); + TRACE("found %s\n", debugstr_a(stname)); return; } } if (!(storage = msi_alloc_zero( sizeof(LibmsiStorage) ))) return LIBMSI_RESULT_NOT_ENOUGH_MEMORY; - storage->name = strdupW( stname ); + storage->name = strdup( stname ); if (!storage->name) - { - r = LIBMSI_RESULT_NOT_ENOUGH_MEMORY; goto done; - } - hr = IStorage_OpenStorage(db->infile, stname, NULL, - STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, - &storage->stg); - if (FAILED(hr)) - { - r = LIBMSI_RESULT_FUNCTION_FAILED; + in = gsf_infile_child_by_name(db->infile, stname); + if (!GSF_IS_INFILE(in)) + goto done; + + storage->stg = GSF_INFILE(in); + if (!storage->stg) goto done; - } list_add_tail( &db->storages, &storage->entry ); r = LIBMSI_RESULT_SUCCESS; @@ -306,12 +243,11 @@ done: return r; } -unsigned msi_create_storage( LibmsiDatabase *db, const WCHAR *stname, IStream *stm ) +unsigned msi_create_storage( LibmsiDatabase *db, const char *stname, GsfInput *stm ) { LibmsiStorage *storage; - IStorage *origstg = NULL; + GsfInfile *origstg = NULL; bool found = false; - HRESULT hr; unsigned r; if ( db->mode == LIBMSI_DB_OPEN_READONLY ) @@ -319,9 +255,9 @@ unsigned msi_create_storage( LibmsiDatabase *db, const WCHAR *stname, IStream *s LIST_FOR_EACH_ENTRY( storage, &db->storages, LibmsiStorage, entry ) { - if( !strcmpW( stname, storage->name ) ) + if( !strcmp( stname, storage->name ) ) { - TRACE("found %s\n", debugstr_w(stname)); + TRACE("found %s\n", debugstr_a(stname)); found = true; break; } @@ -329,7 +265,7 @@ unsigned msi_create_storage( LibmsiDatabase *db, const WCHAR *stname, IStream *s if (!found) { if (!(storage = msi_alloc_zero( sizeof(LibmsiStorage) ))) return LIBMSI_RESULT_NOT_ENOUGH_MEMORY; - storage->name = strdupW( stname ); + storage->name = strdup( stname ); if (!storage->name) { msi_free(storage); @@ -337,19 +273,19 @@ unsigned msi_create_storage( LibmsiDatabase *db, const WCHAR *stname, IStream *s } } - r = stream_to_storage(stm, &origstg); - if (r != LIBMSI_RESULT_SUCCESS) + origstg = gsf_infile_msole_new(stm, NULL); + if (origstg == NULL) goto done; if (found) { if (storage->stg) - IStorage_Release(storage->stg); + g_object_unref(G_OBJECT(storage->stg)); } else { list_add_tail( &db->storages, &storage->entry ); } storage->stg = origstg; - IStorage_AddRef(storage->stg); + g_object_ref(G_OBJECT(storage->stg)); r = LIBMSI_RESULT_SUCCESS; @@ -362,38 +298,38 @@ done: } if (origstg) - IStorage_Release(origstg); + g_object_unref(G_OBJECT(origstg)); return r; } -void msi_destroy_storage( LibmsiDatabase *db, const WCHAR *stname ) +void msi_destroy_storage( LibmsiDatabase *db, const char *stname ) { LibmsiStorage *storage, *storage2; LIST_FOR_EACH_ENTRY_SAFE( storage, storage2, &db->storages, LibmsiStorage, entry ) { - if (!strcmpW( stname, storage->name )) + if (!strcmp( stname, storage->name )) { - TRACE("destroying %s\n", debugstr_w(stname)); + TRACE("destroying %s\n", debugstr_a(stname)); list_remove( &storage->entry ); - IStorage_Release( storage->stg ); + g_object_unref(G_OBJECT(storage->stg)); msi_free( storage ); break; } } } -static unsigned find_infile_stream( LibmsiDatabase *db, const WCHAR *name, IStream **stm ) +static unsigned find_infile_stream( LibmsiDatabase *db, const char *name, GsfInput **stm ) { LibmsiStream *stream; LIST_FOR_EACH_ENTRY( stream, &db->streams, LibmsiStream, entry ) { - if( !strcmpW( name, stream->name ) ) + if( !strcmp( name, stream->name ) ) { - TRACE("found %s\n", debugstr_w(name)); + TRACE("found %s\n", debugstr_a(name)); *stm = stream->stm; return LIBMSI_RESULT_SUCCESS; } @@ -402,69 +338,56 @@ static unsigned find_infile_stream( LibmsiDatabase *db, const WCHAR *name, IStre return LIBMSI_RESULT_FUNCTION_FAILED; } -static unsigned msi_alloc_stream( LibmsiDatabase *db, const WCHAR *stname, IStream *stm) +static unsigned msi_alloc_stream( LibmsiDatabase *db, const char *stname, GsfInput *stm) { LibmsiStream *stream; - TRACE("%p %s %p", db, debugstr_w(stname), stm); + TRACE("%p %s %p", db, debugstr_a(stname), stm); if (!(stream = msi_alloc( sizeof(LibmsiStream) ))) return LIBMSI_RESULT_NOT_ENOUGH_MEMORY; - stream->name = strdupW( stname ); + stream->name = strdup( stname ); stream->stm = stm; - IStream_AddRef( stm ); + g_object_ref(G_OBJECT(stm)); list_add_tail( &db->streams, &stream->entry ); return LIBMSI_RESULT_SUCCESS; } -unsigned write_raw_stream_data( LibmsiDatabase *db, const WCHAR *stname, - const void *data, unsigned sz, IStream **outstm ) +unsigned write_raw_stream_data( LibmsiDatabase *db, const char *stname, + const void *data, unsigned sz, GsfInput **outstm ) { - HRESULT r; unsigned ret = LIBMSI_RESULT_FUNCTION_FAILED; - unsigned count; - IStream *stm = NULL; - HANDLE hGlob; + GsfInput *stm = NULL; + char *mem; LibmsiStream *stream; - ULARGE_INTEGER size; if (db->mode == LIBMSI_DB_OPEN_READONLY) return LIBMSI_RESULT_FUNCTION_FAILED; LIST_FOR_EACH_ENTRY( stream, &db->streams, LibmsiStream, entry ) { - if( !strcmpW( stname, stream->name ) ) + if( !strcmp( stname, stream->name ) ) { msi_destroy_stream( db, stname ); break; } } - hGlob = GlobalAlloc(GMEM_FIXED, sz); - if (!hGlob) + mem = g_try_malloc(sz == 0 ? 1 : sz); + if (!mem) return LIBMSI_RESULT_FUNCTION_FAILED; if (data || sz) - memcpy(hGlob, data, sz); - - r = CreateStreamOnHGlobal(hGlob, true, &stm); - if( FAILED( r ) ) - { - GlobalFree(hGlob); - return LIBMSI_RESULT_FUNCTION_FAILED; - } - - /* set the correct size - CreateStreamOnHGlobal screws it up */ - size.QuadPart = sz; - IStream_SetSize(stm, size); + memcpy(mem, data, sz); + stm = gsf_input_memory_new(mem, sz, true); ret = msi_alloc_stream( db, stname, stm); *outstm = stm; return ret; } -unsigned msi_create_stream( LibmsiDatabase *db, const WCHAR *stname, IStream *stm ) +unsigned msi_create_stream( LibmsiDatabase *db, const char *stname, GsfInput *stm ) { LibmsiStream *stream; - WCHAR *encname = NULL; + char *encname = NULL; unsigned r = LIBMSI_RESULT_FUNCTION_FAILED; bool found = false; @@ -475,7 +398,7 @@ unsigned msi_create_stream( LibmsiDatabase *db, const WCHAR *stname, IStream *st LIST_FOR_EACH_ENTRY( stream, &db->streams, LibmsiStream, entry ) { - if( !strcmpW( encname, stream->name ) ) + if( !strcmp( encname, stream->name ) ) { found = true; break; @@ -484,18 +407,19 @@ unsigned msi_create_stream( LibmsiDatabase *db, const WCHAR *stname, IStream *st if (found) { if (stream->stm) - IStream_Release(stream->stm); + g_object_unref(G_OBJECT(stream->stm)); stream->stm = stm; - IStream_AddRef(stream->stm); + g_object_ref(G_OBJECT(stream->stm)); r = LIBMSI_RESULT_SUCCESS; } else r = msi_alloc_stream( db, encname, stm ); + msi_free(encname); return r; } unsigned msi_enum_db_streams(LibmsiDatabase *db, - unsigned (*fn)(const WCHAR *, IStream *, void *), + unsigned (*fn)(const char *, GsfInput *, void *), void *opaque) { unsigned r; @@ -503,12 +427,12 @@ unsigned msi_enum_db_streams(LibmsiDatabase *db, LIST_FOR_EACH_ENTRY_SAFE( stream, stream2, &db->streams, LibmsiStream, entry ) { - IStream *stm; + GsfInput *stm; stm = stream->stm; - IStream_AddRef(stm); + g_object_ref(G_OBJECT(stm)); r = fn( stream->name, stm, opaque); - IStream_Release(stm); + g_object_unref(G_OBJECT(stm)); if (r) { return r; @@ -519,7 +443,7 @@ unsigned msi_enum_db_streams(LibmsiDatabase *db, } unsigned msi_enum_db_storages(LibmsiDatabase *db, - unsigned (*fn)(const WCHAR *, IStorage *, void *), + unsigned (*fn)(const char *, GsfInfile *, void *), void *opaque) { unsigned r; @@ -527,12 +451,12 @@ unsigned msi_enum_db_storages(LibmsiDatabase *db, LIST_FOR_EACH_ENTRY_SAFE( storage, storage2, &db->storages, LibmsiStorage, entry ) { - IStorage *stg; + GsfInfile *stg; stg = storage->stg; - IStorage_AddRef(stg); + g_object_ref(G_OBJECT(stg)); r = fn( storage->name, stg, opaque); - IStorage_Release(stg); + g_object_unref(G_OBJECT(stg)); if (r) { return r; @@ -542,71 +466,64 @@ unsigned msi_enum_db_storages(LibmsiDatabase *db, return LIBMSI_RESULT_SUCCESS; } -unsigned clone_infile_stream( LibmsiDatabase *db, const WCHAR *name, IStream **stm ) +unsigned clone_infile_stream( LibmsiDatabase *db, const char *name, GsfInput **stm ) { - IStream *stream; + GsfInput *stream; if (find_infile_stream( db, name, &stream ) == LIBMSI_RESULT_SUCCESS) { - HRESULT r; - LARGE_INTEGER pos; - - r = IStream_Clone( stream, stm ); - if( FAILED( r ) ) + stream = gsf_input_dup( stream, NULL ); + if( !stream ) { - WARN("failed to clone stream r = %08x!\n", r); - return LIBMSI_RESULT_FUNCTION_FAILED; - } - - pos.QuadPart = 0; - r = IStream_Seek( *stm, pos, STREAM_SEEK_SET, NULL ); - if( FAILED( r ) ) - { - IStream_Release( *stm ); + WARN("failed to clone stream\n"); return LIBMSI_RESULT_FUNCTION_FAILED; } + gsf_input_seek( stream, 0, G_SEEK_SET ); + *stm = stream; return LIBMSI_RESULT_SUCCESS; } return LIBMSI_RESULT_FUNCTION_FAILED; } -unsigned msi_get_raw_stream( LibmsiDatabase *db, const WCHAR *stname, IStream **stm ) +unsigned msi_get_raw_stream( LibmsiDatabase *db, const char *stname, GsfInput **stm ) { - HRESULT r; - WCHAR decoded[MAX_STREAM_NAME_LEN]; + unsigned ret = LIBMSI_RESULT_FUNCTION_FAILED; + char decoded[MAX_STREAM_NAME_LEN]; LibmsiTransform *transform; decode_streamname( stname, decoded ); - TRACE("%s -> %s\n", debugstr_w(stname), debugstr_w(decoded)); + TRACE("%s -> %s\n", debugstr_a(stname), debugstr_a(decoded)); if (clone_infile_stream( db, stname, stm ) == LIBMSI_RESULT_SUCCESS) return LIBMSI_RESULT_SUCCESS; LIST_FOR_EACH_ENTRY( transform, &db->transforms, LibmsiTransform, entry ) { - r = IStorage_OpenStream( transform->stg, stname, NULL, - STGM_READ | STGM_SHARE_EXCLUSIVE, 0, stm ); - if (SUCCEEDED(r)) - return LIBMSI_RESULT_SUCCESS; + *stm = gsf_infile_child_by_name( transform->stg, stname ); + if (*stm) + { + ret = LIBMSI_RESULT_SUCCESS; + break; + } } - return LIBMSI_RESULT_FUNCTION_FAILED; + return ret; } -void msi_destroy_stream( LibmsiDatabase *db, const WCHAR *stname ) +void msi_destroy_stream( LibmsiDatabase *db, const char *stname ) { LibmsiStream *stream, *stream2; LIST_FOR_EACH_ENTRY_SAFE( stream, stream2, &db->streams, LibmsiStream, entry ) { - if (!strcmpW( stname, stream->name )) + if (!strcmp( stname, stream->name )) { - TRACE("destroying %s\n", debugstr_w(stname)); + TRACE("destroying %s\n", debugstr_a(stname)); list_remove( &stream->entry ); - IStream_Release( stream->stm ); + g_object_unref(G_OBJECT(stream->stm)); msi_free( stream ); break; } @@ -619,7 +536,7 @@ static void free_storages( LibmsiDatabase *db ) { LibmsiStorage *s = LIST_ENTRY(list_head( &db->storages ), LibmsiStorage, entry); list_remove( &s->entry ); - IStorage_Release( s->stg ); + g_object_unref(G_OBJECT(s->stg)); msi_free( s->name ); msi_free( s ); } @@ -631,19 +548,19 @@ static void free_streams( LibmsiDatabase *db ) { LibmsiStream *s = LIST_ENTRY(list_head( &db->streams ), LibmsiStream, entry); list_remove( &s->entry ); - IStream_Release( s->stm ); + g_object_unref(G_OBJECT(s->stm)); msi_free( s->name ); msi_free( s ); } } -void append_storage_to_db( LibmsiDatabase *db, IStorage *stg ) +void append_storage_to_db( LibmsiDatabase *db, GsfInfile *stg ) { LibmsiTransform *t; t = msi_alloc( sizeof *t ); t->stg = stg; - IStorage_AddRef( stg ); + g_object_ref(G_OBJECT(t->stg)); list_add_head( &db->transforms, &t->entry ); #if 0 @@ -667,13 +584,14 @@ LibmsiResult _libmsi_database_close(LibmsiDatabase *db, bool committed) if ( db->infile ) { - IStorage_Release( db->infile ); + g_object_unref(G_OBJECT(db->infile)); db->infile = NULL; } if ( db->outfile ) { - IStorage_Release( db->outfile ); + gsf_output_close(GSF_OUTPUT(db->outfile)); + g_object_unref(G_OBJECT(db->outfile)); db->outfile = NULL; } free_streams( db ); @@ -698,11 +616,10 @@ LibmsiResult _libmsi_database_close(LibmsiDatabase *db, bool committed) LibmsiResult _libmsi_database_start_transaction(LibmsiDatabase *db) { unsigned ret = LIBMSI_RESULT_SUCCESS; - IStorage *stg = NULL; - WCHAR *szwPersist; + GsfOutput *out; + GsfOutfile *stg = NULL; char *tmpfile = NULL; char path[PATH_MAX]; - HRESULT hr; if( db->mode == LIBMSI_DB_OPEN_READONLY ) return LIBMSI_RESULT_SUCCESS; @@ -721,33 +638,40 @@ LibmsiResult _libmsi_database_start_transaction(LibmsiDatabase *db) TRACE("%p %s\n", db, szPersist); - szwPersist = strdupAtoW(db->outpath); - hr = StgCreateDocfile( szwPersist, - STGM_CREATE|STGM_TRANSACTED|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, &stg ); - - msi_free(szwPersist); - - if ( SUCCEEDED(hr) ) - hr = IStorage_SetClass( stg, db->patch ? &clsid_msi_patch : &clsid_msi_database ); + out = gsf_output_stdio_new(db->outpath, NULL); + if (!out) + { + 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(db->outpath)); + return LIBMSI_RESULT_OPEN_FAILED; + } - if( FAILED( hr ) ) + if (!gsf_outfile_msole_set_class_id(GSF_OUTFILE_MSOLE(stg), + db->patch ? clsid_msi_patch : clsid_msi_database )) { - WARN("open failed hr = %08x for %s\n", hr, debugstr_a(db->outpath)); + WARN("set guid failed\n"); ret = LIBMSI_RESULT_FUNCTION_FAILED; goto end; } db->outfile = stg; - IStorage_AddRef( db->outfile ); + g_object_ref(G_OBJECT(db->outfile)); end: if (ret) { if (db->outfile) - IStorage_Release( db->outfile ); + g_object_unref(G_OBJECT(db->outfile)); db->outfile = NULL; } if (stg) - IStorage_Release( stg ); + g_object_unref(G_OBJECT(stg)); + msi_free(tmpfile); return ret; } @@ -760,10 +684,10 @@ LibmsiResult libmsi_database_open(const char *szDBPath, const char *szPersist, L if( !pdb ) return LIBMSI_RESULT_INVALID_PARAMETER; - if (!strchr( szDBPath, '\\' )) + if (!strstr( szDBPath, G_DIR_SEPARATOR_S )) { getcwd( path, MAX_PATH ); - strcat( path, "\\" ); + strcat( path, G_DIR_SEPARATOR_S ); strcat( path, szDBPath ); } else @@ -774,43 +698,23 @@ LibmsiResult libmsi_database_open(const char *szDBPath, const char *szPersist, L return *pdb ? LIBMSI_RESULT_SUCCESS : LIBMSI_RESULT_OPEN_FAILED; } -static WCHAR *msi_read_text_archive(const char *path, unsigned *len) +static char *msi_read_text_archive(const char *path, unsigned *len) { - int fd; - struct stat st; - char *data = NULL; - WCHAR *wdata = NULL; - ssize_t nread; + char *data; + size_t nread; - /* TODO g_file_get_contents */ - fd = open( path, O_RDONLY | O_BINARY); - if (fd == -1) + if (!g_file_get_contents(path, &data, &nread, NULL)) return NULL; - fstat (fd, &st); - if (!(data = msi_alloc( st.st_size ))) goto done; - - nread = read(fd, data, st.st_size); - if (nread != st.st_size) goto done; - - while (!data[st.st_size - 1]) st.st_size--; - *len = MultiByteToWideChar( CP_ACP, 0, data, st.st_size, NULL, 0 ); - if ((wdata = msi_alloc( (*len + 1) * sizeof(WCHAR) ))) - { - MultiByteToWideChar( CP_ACP, 0, data, st.st_size, wdata, *len ); - wdata[*len] = 0; - } - -done: - close( fd ); - msi_free( data ); - return wdata; + while (!data[nread - 1]) nread--; + *len = nread; + return data; } -static void msi_parse_line(WCHAR **line, WCHAR ***entries, unsigned *num_entries, unsigned *len) +static void msi_parse_line(char **line, char ***entries, unsigned *num_entries, unsigned *len) { - WCHAR *ptr = *line; - WCHAR *save; + char *ptr = *line; + char *save; unsigned i, count = 1, chars_left = *len; *entries = NULL; @@ -826,7 +730,7 @@ static void msi_parse_line(WCHAR **line, WCHAR ***entries, unsigned *num_entries chars_left--; } - *entries = msi_alloc(count * sizeof(WCHAR *)); + *entries = msi_alloc(count * sizeof(char *)); if (!*entries) return; @@ -877,41 +781,41 @@ static void msi_parse_line(WCHAR **line, WCHAR ***entries, unsigned *num_entries *num_entries = count; } -static WCHAR *msi_build_createsql_prelude(WCHAR *table) +static char *msi_build_createsql_prelude(char *table) { - WCHAR *prelude; + char *prelude; unsigned size; - static const WCHAR create_fmt[] = {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','%','s','`',' ','(',' ',0}; + static const char create_fmt[] = "CREATE TABLE `%s` ("; - size = sizeof(create_fmt)/sizeof(create_fmt[0]) + strlenW(table) - 2; - prelude = msi_alloc(size * sizeof(WCHAR)); + size = sizeof(create_fmt)/sizeof(create_fmt[0]) + strlen(table) - 2; + prelude = msi_alloc(size * sizeof(char)); if (!prelude) return NULL; - sprintfW(prelude, create_fmt, table); + sprintf(prelude, create_fmt, table); return prelude; } -static WCHAR *msi_build_createsql_columns(WCHAR **columns_data, WCHAR **types, unsigned num_columns) +static char *msi_build_createsql_columns(char **columns_data, char **types, unsigned num_columns) { - WCHAR *columns; - WCHAR *p; - const WCHAR *type; + char *columns; + char *p; + const char *type; unsigned sql_size = 1, i, len; - WCHAR expanded[128], *ptr; - WCHAR size[10], comma[2], extra[30]; - - static const WCHAR column_fmt[] = {'`','%','s','`',' ','%','s','%','s','%','s','%','s',' ',0}; - static const WCHAR size_fmt[] = {'(','%','s',')',0}; - static const WCHAR type_char[] = {'C','H','A','R',0}; - static const WCHAR type_int[] = {'I','N','T',0}; - static const WCHAR type_long[] = {'L','O','N','G',0}; - static const WCHAR type_object[] = {'O','B','J','E','C','T',0}; - static const WCHAR type_notnull[] = {' ','N','O','T',' ','N','U','L','L',0}; - static const WCHAR localizable[] = {' ','L','O','C','A','L','I','Z','A','B','L','E',0}; - - columns = msi_alloc_zero(sql_size * sizeof(WCHAR)); + char expanded[128], *ptr; + char size[10], comma[2], extra[30]; + + static const char column_fmt[] = "`%s` %s%s%s%s "; + static const char size_fmt[] = "(%s)"; + static const char type_char[] = "CHAR"; + static const char type_int[] = "INT"; + static const char type_long[] = "LONG"; + static const char type_object[] = "OBJECT"; + static const char type_notnull[] = " NOT NULL"; + static const char localizable[] = " LOCALIZABLE"; + + columns = msi_alloc_zero(sql_size * sizeof(char)); if (!columns) return NULL; @@ -926,28 +830,28 @@ static WCHAR *msi_build_createsql_columns(WCHAR **columns_data, WCHAR **types, u comma[0] = ','; ptr = &types[i][1]; - len = atolW(ptr); + len = atol(ptr); extra[0] = '\0'; switch (types[i][0]) { case 'l': - strcpyW(extra, type_notnull); + strcpy(extra, type_notnull); /* fall through */ case 'L': - strcatW(extra, localizable); + strcat(extra, localizable); type = type_char; - sprintfW(size, size_fmt, ptr); + sprintf(size, size_fmt, ptr); break; case 's': - strcpyW(extra, type_notnull); + strcpy(extra, type_notnull); /* fall through */ case 'S': type = type_char; - sprintfW(size, size_fmt, ptr); + sprintf(size, size_fmt, ptr); break; case 'i': - strcpyW(extra, type_notnull); + strcpy(extra, type_notnull); /* fall through */ case 'I': if (len <= 2) @@ -962,7 +866,7 @@ static WCHAR *msi_build_createsql_columns(WCHAR **columns_data, WCHAR **types, u } break; case 'v': - strcpyW(extra, type_notnull); + strcpy(extra, type_notnull); /* fall through */ case 'V': type = type_object; @@ -973,10 +877,10 @@ static WCHAR *msi_build_createsql_columns(WCHAR **columns_data, WCHAR **types, u return NULL; } - sprintfW(expanded, column_fmt, columns_data[i], type, size, extra, comma); - sql_size += strlenW(expanded); + sprintf(expanded, column_fmt, columns_data[i], type, size, extra, comma); + sql_size += strlen(expanded); - p = msi_realloc(columns, sql_size * sizeof(WCHAR)); + p = msi_realloc(columns, sql_size * sizeof(char)); if (!p) { msi_free(columns); @@ -984,60 +888,60 @@ static WCHAR *msi_build_createsql_columns(WCHAR **columns_data, WCHAR **types, u } columns = p; - strcatW(columns, expanded); + strcat(columns, expanded); } return columns; } -static WCHAR *msi_build_createsql_postlude(WCHAR **primary_keys, unsigned num_keys) +static char *msi_build_createsql_postlude(char **primary_keys, unsigned num_keys) { - WCHAR *postlude; - WCHAR *keys; - WCHAR *ptr; + char *postlude; + char *keys; + char *ptr; unsigned size, key_size, i; - static const WCHAR key_fmt[] = {'`','%','s','`',',',' ',0}; - static const WCHAR postlude_fmt[] = {'P','R','I','M','A','R','Y',' ','K','E','Y',' ','%','s',')',0}; + static const char key_fmt[] = "`%s`, "; + static const char postlude_fmt[] = "PRIMARY KEY %s)"; for (i = 0, size = 1; i < num_keys; i++) - size += strlenW(key_fmt) + strlenW(primary_keys[i]) - 2; + size += strlen(key_fmt) + strlen(primary_keys[i]) - 2; - keys = msi_alloc(size * sizeof(WCHAR)); + keys = msi_alloc(size * sizeof(char)); if (!keys) return NULL; for (i = 0, ptr = keys; i < num_keys; i++) { - key_size = strlenW(key_fmt) + strlenW(primary_keys[i]) -2; - sprintfW(ptr, key_fmt, primary_keys[i]); + key_size = strlen(key_fmt) + strlen(primary_keys[i]) -2; + sprintf(ptr, key_fmt, primary_keys[i]); ptr += key_size; } /* remove final ', ' */ *(ptr - 2) = '\0'; - size = strlenW(postlude_fmt) + size - 1; - postlude = msi_alloc(size * sizeof(WCHAR)); + size = strlen(postlude_fmt) + size - 1; + postlude = msi_alloc(size * sizeof(char)); if (!postlude) goto done; - sprintfW(postlude, postlude_fmt, keys); + sprintf(postlude, postlude_fmt, keys); done: msi_free(keys); return postlude; } -static unsigned msi_add_table_to_db(LibmsiDatabase *db, WCHAR **columns, WCHAR **types, WCHAR **labels, unsigned num_labels, unsigned num_columns) +static unsigned msi_add_table_to_db(LibmsiDatabase *db, char **columns, char **types, char **labels, unsigned num_labels, unsigned num_columns) { unsigned r = LIBMSI_RESULT_OUTOFMEMORY; unsigned size; LibmsiQuery *view; - WCHAR *create_sql = NULL; - WCHAR *prelude; - WCHAR *columns_sql; - WCHAR *postlude; + char *create_sql = NULL; + char *prelude; + char *columns_sql; + char *postlude; prelude = msi_build_createsql_prelude(labels[0]); columns_sql = msi_build_createsql_columns(columns, types, num_columns); @@ -1046,14 +950,14 @@ static unsigned msi_add_table_to_db(LibmsiDatabase *db, WCHAR **columns, WCHAR * if (!prelude || !columns_sql || !postlude) goto done; - size = strlenW(prelude) + strlenW(columns_sql) + strlenW(postlude) + 1; - create_sql = msi_alloc(size * sizeof(WCHAR)); + size = strlen(prelude) + strlen(columns_sql) + strlen(postlude) + 1; + create_sql = msi_alloc(size * sizeof(char)); if (!create_sql) goto done; - strcpyW(create_sql, prelude); - strcatW(create_sql, columns_sql); - strcatW(create_sql, postlude); + strcpy(create_sql, prelude); + strcat(create_sql, columns_sql); + strcat(create_sql, postlude); r = _libmsi_database_open_query( db, create_sql, &view ); if (r != LIBMSI_RESULT_SUCCESS) @@ -1071,14 +975,13 @@ done: return r; } -static char *msi_import_stream_filename(const char *path, const WCHAR *name) +static char *msi_import_stream_filename(const char *path, const char *name) { unsigned len; - char *ascii_name = strdupWtoA(name); char *fullname; char *ptr; - len = strlen(path) + strlen(ascii_name) + 1; + len = strlen(path) + strlen(name) + 1; fullname = msi_alloc(len); if (!fullname) return NULL; @@ -1092,14 +995,13 @@ static char *msi_import_stream_filename(const char *path, const WCHAR *name) msi_free (fullname); return NULL; } - *ptr++ = '\\'; - strcpy( ptr, ascii_name ); - msi_free( ascii_name ); + strcpy( ptr, G_DIR_SEPARATOR_S ); + strcat( ptr, name ); return fullname; } -static unsigned construct_record(unsigned num_columns, WCHAR **types, - WCHAR **data, const char *path, LibmsiRecord **rec) +static unsigned construct_record(unsigned num_columns, char **types, + char **data, const char *path, LibmsiRecord **rec) { unsigned i; @@ -1112,11 +1014,11 @@ static unsigned construct_record(unsigned num_columns, WCHAR **types, switch (types[i][0]) { case 'L': case 'l': case 'S': case 's': - _libmsi_record_set_stringW(*rec, i + 1, data[i]); + libmsi_record_set_string(*rec, i + 1, data[i]); break; case 'I': case 'i': if (*data[i]) - libmsi_record_set_int(*rec, i + 1, atoiW(data[i])); + libmsi_record_set_int(*rec, i + 1, atoi(data[i])); break; case 'V': case 'v': if (*data[i]) @@ -1142,8 +1044,8 @@ static unsigned construct_record(unsigned num_columns, WCHAR **types, return LIBMSI_RESULT_SUCCESS; } -static unsigned msi_add_records_to_table(LibmsiDatabase *db, WCHAR **columns, WCHAR **types, - WCHAR **labels, WCHAR ***records, +static unsigned msi_add_records_to_table(LibmsiDatabase *db, char **columns, char **types, + char **labels, char ***records, int num_columns, int num_records, const char *path) { @@ -1197,18 +1099,16 @@ static unsigned _libmsi_database_import(LibmsiDatabase *db, const char *folder, unsigned num_columns = 0; unsigned num_records = 0; char *path = NULL; - WCHAR **columns = NULL; - WCHAR **types = NULL; - WCHAR **labels = NULL; - WCHAR *ptr; - WCHAR *data = NULL; - WCHAR ***records = NULL; - WCHAR ***temp_records; - - static const WCHAR suminfo[] = - {'_','S','u','m','m','a','r','y','I','n','f','o','r','m','a','t','i','o','n',0}; - static const WCHAR forcecodepage[] = - {'_','F','o','r','c','e','C','o','d','e','p','a','g','e',0}; + char **columns = NULL; + char **types = NULL; + char **labels = NULL; + char *ptr; + char *data = NULL; + char ***records = NULL; + char ***temp_records; + + static const char suminfo[] = "_SummaryInformation"; + static const char forcecodepage[] = "_ForceCodepage"; TRACE("%p %s %s\n", db, debugstr_a(folder), debugstr_a(file) ); @@ -1221,7 +1121,7 @@ static unsigned _libmsi_database_import(LibmsiDatabase *db, const char *folder, return LIBMSI_RESULT_OUTOFMEMORY; strcpy( path, folder ); - strcat( path, "\\" ); + strcat( path, G_DIR_SEPARATOR_S ); strcat( path, file ); data = msi_read_text_archive( path, &len ); @@ -1234,9 +1134,9 @@ static unsigned _libmsi_database_import(LibmsiDatabase *db, const char *folder, msi_parse_line( &ptr, &labels, &num_labels, &len ); if (num_columns == 1 && !columns[0][0] && num_labels == 1 && !labels[0][0] && - num_types == 2 && !strcmpW( types[1], forcecodepage )) + num_types == 2 && !strcmp( types[1], forcecodepage )) { - r = msi_set_string_table_codepage( db->strings, atoiW( types[0] ) ); + r = msi_set_string_table_codepage( db->strings, atoi( types[0] ) ); goto done; } @@ -1246,7 +1146,7 @@ static unsigned _libmsi_database_import(LibmsiDatabase *db, const char *folder, goto done; } - records = msi_alloc(sizeof(WCHAR **)); + records = msi_alloc(sizeof(char **)); if (!records) { r = LIBMSI_RESULT_OUTOFMEMORY; @@ -1259,7 +1159,7 @@ static unsigned _libmsi_database_import(LibmsiDatabase *db, const char *folder, msi_parse_line( &ptr, &records[num_records], NULL, &len ); num_records++; - temp_records = msi_realloc(records, (num_records + 1) * sizeof(WCHAR **)); + temp_records = msi_realloc(records, (num_records + 1) * sizeof(char **)); if (!temp_records) { r = LIBMSI_RESULT_OUTOFMEMORY; @@ -1268,7 +1168,7 @@ static unsigned _libmsi_database_import(LibmsiDatabase *db, const char *folder, records = temp_records; } - if (!strcmpW(labels[0], suminfo)) + if (!strcmp(labels[0], suminfo)) { r = msi_add_suminfo( db, records, num_records, num_columns ); if (r != LIBMSI_RESULT_SUCCESS) @@ -1390,20 +1290,18 @@ static unsigned msi_export_forcecodepage( int fd, unsigned codepage ) return LIBMSI_RESULT_SUCCESS; } -static unsigned _libmsi_database_export( LibmsiDatabase *db, const WCHAR *table, +static unsigned _libmsi_database_export( LibmsiDatabase *db, const char *table, int fd) { - static const WCHAR query[] = { - 's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','%','s',0 }; - static const WCHAR forcecodepage[] = { - '_','F','o','r','c','e','C','o','d','e','p','a','g','e',0 }; + static const char query[] = "select * from %s"; + static const char forcecodepage[] = "_ForceCodepage"; LibmsiRecord *rec = NULL; LibmsiQuery *view = NULL; unsigned r; - TRACE("%p %s %d\n", db, debugstr_w(table), fd ); + TRACE("%p %s %d\n", db, debugstr_a(table), fd ); - if (!strcmpW( table, forcecodepage )) + if (!strcmp( table, forcecodepage )) { unsigned codepage = msi_get_string_table_codepage( db->strings ); r = msi_export_forcecodepage( fd, codepage ); @@ -1433,7 +1331,7 @@ static unsigned _libmsi_database_export( LibmsiDatabase *db, const WCHAR *table, r = _libmsi_database_get_primary_keys( db, table, &rec ); if (r == LIBMSI_RESULT_SUCCESS) { - _libmsi_record_set_stringW( rec, 0, table ); + libmsi_record_set_string( rec, 0, table ); msi_export_record( fd, rec, 0 ); g_object_unref(rec); } @@ -1448,7 +1346,7 @@ done: } /*********************************************************************** - * MsiExportDatabaseW [MSI.@] + * MsiExportDatabase [MSI.@] * * Writes a file containing the table data as tab separated ASCII. * @@ -1465,27 +1363,16 @@ done: LibmsiResult libmsi_database_export( LibmsiDatabase *db, const char *szTable, int fd ) { - WCHAR *table = NULL; unsigned r = LIBMSI_RESULT_OUTOFMEMORY; TRACE("%x %s %d\n", db, debugstr_a(szTable), fd); - if( szTable ) - { - table = strdupAtoW( szTable ); - if( !table ) - goto end; - } - if( !db ) return LIBMSI_RESULT_INVALID_HANDLE; g_object_ref(db); - r = _libmsi_database_export( db, table, fd ); + r = _libmsi_database_export( db, szTable, fd ); g_object_unref(db); - -end: - msi_free(table); return r; } @@ -1493,13 +1380,13 @@ typedef struct _tagMERGETABLE { struct list entry; struct list rows; - WCHAR *name; + char *name; unsigned numconflicts; - WCHAR **columns; + char **columns; unsigned numcolumns; - WCHAR **types; + char **types; unsigned numtypes; - WCHAR **labels; + char **labels; unsigned numlabels; } MERGETABLE; @@ -1518,7 +1405,7 @@ typedef struct _tagMERGEDATA struct list *tabledata; } MERGEDATA; -static bool merge_type_match(const WCHAR *type1, const WCHAR *type2) +static bool merge_type_match(const char *type1, const char *type2) { if (((type1[0] == 'l') || (type1[0] == 's')) && ((type2[0] == 'l') || (type2[0] == 's'))) @@ -1528,7 +1415,7 @@ static bool merge_type_match(const WCHAR *type1, const WCHAR *type2) ((type2[0] == 'L') || (type2[0] == 'S'))) return true; - return !strcmpW( type1, type2 ); + return !strcmp( type1, type2 ); } static unsigned merge_verify_colnames(LibmsiQuery *dbview, LibmsiQuery *mergeview) @@ -1550,7 +1437,7 @@ static unsigned merge_verify_colnames(LibmsiQuery *dbview, LibmsiQuery *mergevie if (!_libmsi_record_get_string_raw(mergerec, i)) break; - if (strcmpW( _libmsi_record_get_string_raw( dbrec, i ), _libmsi_record_get_string_raw( mergerec, i ) )) + if (strcmp( _libmsi_record_get_string_raw( dbrec, i ), _libmsi_record_get_string_raw( mergerec, i ) )) { r = LIBMSI_RESULT_DATATYPE_MISMATCH; goto done; @@ -1591,7 +1478,7 @@ done: } static unsigned merge_verify_primary_keys(LibmsiDatabase *db, LibmsiDatabase *mergedb, - const WCHAR *table) + const char *table) { LibmsiRecord *dbrec, *mergerec = NULL; unsigned r, i, count; @@ -1613,7 +1500,7 @@ static unsigned merge_verify_primary_keys(LibmsiDatabase *db, LibmsiDatabase *me for (i = 1; i <= count; i++) { - if (strcmpW( _libmsi_record_get_string_raw( dbrec, i ), _libmsi_record_get_string_raw( mergerec, i ) )) + if (strcmp( _libmsi_record_get_string_raw( dbrec, i ), _libmsi_record_get_string_raw( mergerec, i ) )) { r = LIBMSI_RESULT_DATATYPE_MISMATCH; goto done; @@ -1627,11 +1514,11 @@ done: return r; } -static WCHAR *get_key_value(LibmsiQuery *view, const WCHAR *key, LibmsiRecord *rec) +static char *get_key_value(LibmsiQuery *view, const char *key, LibmsiRecord *rec) { LibmsiRecord *colnames; - WCHAR *str; - WCHAR *val; + char *str; + char *val; unsigned r, i = 0, sz = 0; int cmp; @@ -1642,13 +1529,13 @@ static WCHAR *get_key_value(LibmsiQuery *view, const WCHAR *key, LibmsiRecord *r do { str = msi_dup_record_field(colnames, ++i); - cmp = strcmpW( key, str ); + cmp = strcmp( key, str ); msi_free(str); } while (cmp); g_object_unref(colnames); - r = _libmsi_record_get_stringW(rec, i, NULL, &sz); + r = _libmsi_record_get_string(rec, i, NULL, &sz); if (r != LIBMSI_RESULT_SUCCESS) return NULL; sz++; @@ -1656,24 +1543,24 @@ static WCHAR *get_key_value(LibmsiQuery *view, const WCHAR *key, LibmsiRecord *r if (_libmsi_record_get_string_raw(rec, i)) /* check record field is a string */ { /* quote string record fields */ - const WCHAR szQuote[] = {'\'', 0}; + const char szQuote[] = "'"; sz += 2; - val = msi_alloc(sz*sizeof(WCHAR)); + val = msi_alloc(sz*sizeof(char)); if (!val) return NULL; - strcpyW(val, szQuote); - r = _libmsi_record_get_stringW(rec, i, val+1, &sz); - strcpyW(val+1+sz, szQuote); + strcpy(val, szQuote); + r = _libmsi_record_get_string(rec, i, val+1, &sz); + strcpy(val+1+sz, szQuote); } else { /* do not quote integer record fields */ - val = msi_alloc(sz*sizeof(WCHAR)); + val = msi_alloc(sz*sizeof(char)); if (!val) return NULL; - r = _libmsi_record_get_stringW(rec, i, val, &sz); + r = _libmsi_record_get_string(rec, i, val, &sz); } if (r != LIBMSI_RESULT_SUCCESS) @@ -1686,31 +1573,27 @@ static WCHAR *get_key_value(LibmsiQuery *view, const WCHAR *key, LibmsiRecord *r return val; } -static WCHAR *create_diff_row_query(LibmsiDatabase *merge, LibmsiQuery *view, - WCHAR *table, LibmsiRecord *rec) +static char *create_diff_row_query(LibmsiDatabase *merge, LibmsiQuery *view, + char *table, LibmsiRecord *rec) { - WCHAR *query = NULL; - WCHAR *clause = NULL; - WCHAR *val; - const WCHAR *setptr; - const WCHAR *key; + char *query = NULL; + char *clause = NULL; + char *val; + const char *setptr; + const char *key; unsigned size, oldsize; LibmsiRecord *keys; unsigned r, i, count; - static const WCHAR keyset[] = { - '`','%','s','`',' ','=',' ','%','s',' ','A','N','D',' ',0}; - static const WCHAR lastkeyset[] = { - '`','%','s','`',' ','=',' ','%','s',' ',0}; - static const WCHAR fmt[] = {'S','E','L','E','C','T',' ','*',' ', - 'F','R','O','M',' ','`','%','s','`',' ', - 'W','H','E','R','E',' ','%','s',0}; + static const char keyset[] = "`%s` = %s AND"; + static const char lastkeyset[] = "`%s` = %s "; + static const char fmt[] = "SELECT * FROM %s WHERE %s"; r = _libmsi_database_get_primary_keys(merge, table, &keys); if (r != LIBMSI_RESULT_SUCCESS) return NULL; - clause = msi_alloc_zero(sizeof(WCHAR)); + clause = msi_alloc_zero(sizeof(char)); if (!clause) goto done; @@ -1727,24 +1610,24 @@ static WCHAR *create_diff_row_query(LibmsiDatabase *merge, LibmsiQuery *view, setptr = keyset; oldsize = size; - size += strlenW(setptr) + strlenW(key) + strlenW(val) - 4; - clause = msi_realloc(clause, size * sizeof (WCHAR)); + size += strlen(setptr) + strlen(key) + strlen(val) - 4; + clause = msi_realloc(clause, size * sizeof (char)); if (!clause) { msi_free(val); goto done; } - sprintfW(clause + oldsize - 1, setptr, key, val); + sprintf(clause + oldsize - 1, setptr, key, val); msi_free(val); } - size = strlenW(fmt) + strlenW(table) + strlenW(clause) + 1; - query = msi_alloc(size * sizeof(WCHAR)); + size = strlen(fmt) + strlen(table) + strlen(clause) + 1; + query = msi_alloc(size * sizeof(char)); if (!query) goto done; - sprintfW(query, fmt, table, clause); + sprintf(query, fmt, table, clause); done: msi_free(clause); @@ -1759,7 +1642,7 @@ static unsigned merge_diff_row(LibmsiRecord *rec, void *param) MERGEROW *mergerow; LibmsiQuery *dbview = NULL; LibmsiRecord *row = NULL; - WCHAR *query = NULL; + char *query = NULL; unsigned r = LIBMSI_RESULT_SUCCESS; if (table_view_exists(data->db, table->name)) @@ -1812,7 +1695,7 @@ done: return r; } -static unsigned msi_get_table_labels(LibmsiDatabase *db, const WCHAR *table, WCHAR ***labels, unsigned *numlabels) +static unsigned msi_get_table_labels(LibmsiDatabase *db, const char *table, char ***labels, unsigned *numlabels) { unsigned r, i, count; LibmsiRecord *prec = NULL; @@ -1823,17 +1706,17 @@ static unsigned msi_get_table_labels(LibmsiDatabase *db, const WCHAR *table, WCH count = libmsi_record_get_field_count(prec); *numlabels = count + 1; - *labels = msi_alloc((*numlabels)*sizeof(WCHAR *)); + *labels = msi_alloc((*numlabels)*sizeof(char *)); if (!*labels) { r = LIBMSI_RESULT_OUTOFMEMORY; goto end; } - (*labels)[0] = strdupW(table); + (*labels)[0] = strdup(table); for (i=1; i<=count; i++ ) { - (*labels)[i] = strdupW(_libmsi_record_get_string_raw(prec, i)); + (*labels)[i] = strdup(_libmsi_record_get_string_raw(prec, i)); } end: @@ -1841,7 +1724,7 @@ end: return r; } -static unsigned msi_get_query_columns(LibmsiQuery *query, WCHAR ***columns, unsigned *numcolumns) +static unsigned msi_get_query_columns(LibmsiQuery *query, char ***columns, unsigned *numcolumns) { unsigned r, i, count; LibmsiRecord *prec = NULL; @@ -1851,7 +1734,7 @@ static unsigned msi_get_query_columns(LibmsiQuery *query, WCHAR ***columns, unsi return r; count = libmsi_record_get_field_count(prec); - *columns = msi_alloc(count*sizeof(WCHAR *)); + *columns = msi_alloc(count*sizeof(char *)); if (!*columns) { r = LIBMSI_RESULT_OUTOFMEMORY; @@ -1860,7 +1743,7 @@ static unsigned msi_get_query_columns(LibmsiQuery *query, WCHAR ***columns, unsi for (i=1; i<=count; i++ ) { - (*columns)[i-1] = strdupW(_libmsi_record_get_string_raw(prec, i)); + (*columns)[i-1] = strdup(_libmsi_record_get_string_raw(prec, i)); } *numcolumns = count; @@ -1870,7 +1753,7 @@ end: return r; } -static unsigned msi_get_query_types(LibmsiQuery *query, WCHAR ***types, unsigned *numtypes) +static unsigned msi_get_query_types(LibmsiQuery *query, char ***types, unsigned *numtypes) { unsigned r, i, count; LibmsiRecord *prec = NULL; @@ -1880,7 +1763,7 @@ static unsigned msi_get_query_types(LibmsiQuery *query, WCHAR ***types, unsigned return r; count = libmsi_record_get_field_count(prec); - *types = msi_alloc(count*sizeof(WCHAR *)); + *types = msi_alloc(count*sizeof(char *)); if (!*types) { r = LIBMSI_RESULT_OUTOFMEMORY; @@ -1890,7 +1773,7 @@ static unsigned msi_get_query_types(LibmsiQuery *query, WCHAR ***types, unsigned *numtypes = count; for (i=1; i<=count; i++ ) { - (*types)[i-1] = strdupW(_libmsi_record_get_string_raw(prec, i)); + (*types)[i-1] = strdup(_libmsi_record_get_string_raw(prec, i)); } end: @@ -1946,14 +1829,13 @@ static void free_merge_table(MERGETABLE *table) msi_free(table); } -static unsigned msi_get_merge_table (LibmsiDatabase *db, const WCHAR *name, MERGETABLE **ptable) +static unsigned msi_get_merge_table (LibmsiDatabase *db, const char *name, MERGETABLE **ptable) { unsigned r; MERGETABLE *table; LibmsiQuery *mergeview = NULL; - static const WCHAR query[] = {'S','E','L','E','C','T',' ','*',' ', - 'F','R','O','M',' ','`','%','s','`',0}; + static const char query[] = "SELECT * FROM %s"; table = msi_alloc_zero(sizeof(MERGETABLE)); if (!table) @@ -1980,7 +1862,7 @@ static unsigned msi_get_merge_table (LibmsiDatabase *db, const WCHAR *name, MERG list_init(&table->rows); - table->name = strdupW(name); + table->name = strdup(name); table->numconflicts = 0; g_object_unref(mergeview); @@ -2000,11 +1882,10 @@ static unsigned merge_diff_tables(LibmsiRecord *rec, void *param) MERGETABLE *table; LibmsiQuery *dbview = NULL; LibmsiQuery *mergeview = NULL; - const WCHAR *name; + const char *name; unsigned r; - static const WCHAR query[] = {'S','E','L','E','C','T',' ','*',' ', - 'F','R','O','M',' ','`','%','s','`',0}; + static const char query[] = "SELECT * FROM %s"; name = _libmsi_record_get_string_raw(rec, 1); @@ -2051,9 +1932,7 @@ done: static unsigned gather_merge_data(LibmsiDatabase *db, LibmsiDatabase *merge, struct list *tabledata) { - static const WCHAR query[] = { - 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', - '`','_','T','a','b','l','e','s','`',0}; + static const char query[] = "SELECT * FROM _Tables"; LibmsiQuery *view; MERGEDATA data; unsigned r; @@ -2100,26 +1979,17 @@ static unsigned merge_table(LibmsiDatabase *db, MERGETABLE *table) return LIBMSI_RESULT_SUCCESS; } -static unsigned update_merge_errors(LibmsiDatabase *db, const WCHAR *error, - WCHAR *table, unsigned numconflicts) +static unsigned update_merge_errors(LibmsiDatabase *db, const char *error, + char *table, unsigned numconflicts) { unsigned r; LibmsiQuery *view; - static const WCHAR create[] = { - 'C','R','E','A','T','E',' ','T','A','B','L','E',' ', - '`','%','s','`',' ','(','`','T','a','b','l','e','`',' ', - 'C','H','A','R','(','2','5','5',')',' ','N','O','T',' ', - 'N','U','L','L',',',' ','`','N','u','m','R','o','w','M','e','r','g','e', - 'C','o','n','f','l','i','c','t','s','`',' ','S','H','O','R','T',' ', - 'N','O','T',' ','N','U','L','L',' ','P','R','I','M','A','R','Y',' ', - 'K','E','Y',' ','`','T','a','b','l','e','`',')',0}; - static const WCHAR insert[] = { - 'I','N','S','E','R','T',' ','I','N','T','O',' ', - '`','%','s','`',' ','(','`','T','a','b','l','e','`',',',' ', - '`','N','u','m','R','o','w','M','e','r','g','e', - 'C','o','n','f','l','i','c','t','s','`',')',' ','V','A','L','U','E','S', - ' ','(','\'','%','s','\'',',',' ','%','d',')',0}; + static const char create[] = + "CREATE TABLE `%s` (`Table` CHAR(255) NOT NULL, " + "`NumRowMergeConflicts` SHORT NOT NULL PRIMARY KEY `Table`)"; + static const char insert[] = + "INSERT INTO `%s` (`Table`, `NumRowMergeConflicts`) VALUES ('%s', %d)"; if (!table_view_exists(db, error)) { @@ -2147,7 +2017,6 @@ LibmsiResult libmsi_database_merge(LibmsiDatabase *db, LibmsiDatabase *merge, { struct list tabledata = LIST_INIT(tabledata); struct list *item, *cursor; - WCHAR *szwTableName; MERGETABLE *table; bool conflicts; unsigned r; @@ -2161,7 +2030,6 @@ LibmsiResult libmsi_database_merge(LibmsiDatabase *db, LibmsiDatabase *merge, if (!db || !merge) return LIBMSI_RESULT_INVALID_HANDLE; - szwTableName = strdupAtoW(szTableName); g_object_ref(db); g_object_ref(merge); r = gather_merge_data(db, merge, &tabledata); @@ -2175,7 +2043,7 @@ LibmsiResult libmsi_database_merge(LibmsiDatabase *db, LibmsiDatabase *merge, { conflicts = true; - r = update_merge_errors(db, szwTableName, table->name, + r = update_merge_errors(db, szTableName, table->name, table->numconflicts); if (r != LIBMSI_RESULT_SUCCESS) break; @@ -2223,105 +2091,90 @@ LibmsiDBState libmsi_database_get_state( LibmsiDatabase *db ) static void cache_infile_structure( LibmsiDatabase *db ) { - IEnumSTATSTG *stgenum = NULL; - STATSTG stat; - IStream *stream; - HRESULT hr; - unsigned r, size; - WCHAR decname[0x40]; + int i, n; + char decname[0x40]; + unsigned r; - hr = IStorage_EnumElements(db->infile, 0, NULL, 0, &stgenum); - if (FAILED(hr)) - return; + n = gsf_infile_num_children(db->infile); /* TODO: error handling */ - while (true) + for (i = 0; i < n; i++) { - size = 0; - hr = IEnumSTATSTG_Next(stgenum, 1, &stat, &size); - if (FAILED(hr) || !size) - break; + GsfInput *in = gsf_infile_child_by_index(db->infile, i); + const uint8_t *name = (const uint8_t *) gsf_input_name(in); /* table streams are not in the _Streams table */ - if (stat.type == STGTY_STREAM) { - if (*stat.pwcsName == 0x4840) + if (!GSF_IS_INFILE(in) || gsf_infile_num_children(GSF_INFILE(in)) == -1) { + /* UTF-8 encoding of 0x4840. */ + if (name[0] == 0xe4 && name[1] == 0xa1 && name[2] == 0x80) { - decode_streamname( stat.pwcsName + 1, decname ); - if ( !strcmpW( decname, szStringPool ) || - !strcmpW( decname, szStringData ) ) - { - CoTaskMemFree(stat.pwcsName); + decode_streamname( name + 3, decname ); + if ( !strcmp( decname, szStringPool ) || + !strcmp( decname, szStringData ) ) continue; - } r = _libmsi_open_table( db, decname, false ); } else { - hr = IStorage_OpenStream( db->infile, stat.pwcsName, NULL, - STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream ); - if ( SUCCEEDED(hr) ) { - r = msi_alloc_stream(db, stat.pwcsName, stream); - IStream_Release(stream); - } + r = msi_alloc_stream(db, name, GSF_INPUT(in)); + g_object_unref(G_OBJECT(in)); } } else { - msi_open_storage(db, stat.pwcsName); + msi_open_storage(db, name); } - CoTaskMemFree(stat.pwcsName); } - - IEnumSTATSTG_Release(stgenum); } LibmsiResult _libmsi_database_open(LibmsiDatabase *db) { - WCHAR *szwDBPath; - HRESULT hr; - STATSTG stat; - IStorage *stg; + GsfInput *in; + GsfInfile *stg; + uint8_t uuid[16]; unsigned ret = LIBMSI_RESULT_OPEN_FAILED; TRACE("%p %s\n", db, db->path); - szwDBPath = strdupAtoW(db->path); - hr = StgOpenStorage( szwDBPath, NULL, - STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg); - msi_free(szwDBPath); - - if( FAILED( hr ) ) + in = gsf_input_stdio_new(db->path, NULL); + if (!in) { - WARN("open failed hr = %08x for %s\n", hr, debugstr_a(db->path)); + WARN("open file failed for %s\n", debugstr_a(db->path)); + return LIBMSI_RESULT_OPEN_FAILED; + } + stg = gsf_infile_msole_new( in, NULL ); + g_object_unref(G_OBJECT(in)); + if( !stg ) + { + WARN("open failed for %s\n", debugstr_a(db->path)); return LIBMSI_RESULT_OPEN_FAILED; } - hr = IStorage_Stat( stg, &stat, STATFLAG_NONAME ); - if( FAILED( hr ) ) + if( !gsf_infile_msole_get_class_id (GSF_INFILE_MSOLE(stg), uuid)) { FIXME("Failed to stat storage\n"); goto end; } - if ( memcmp( &stat.clsid, &clsid_msi_database, 16 ) != 0 && - memcmp( &stat.clsid, &clsid_msi_patch, 16 ) != 0 && - memcmp( &stat.clsid, &clsid_msi_transform, 16 ) != 0 ) + if ( memcmp( uuid, clsid_msi_database, 16 ) != 0 && + memcmp( uuid, clsid_msi_patch, 16 ) != 0 && + memcmp( uuid, clsid_msi_transform, 16 ) != 0 ) { ERR("storage GUID is not a MSI database GUID %s\n", - debugstr_guid(&stat.clsid) ); + debugstr_guid(uuid) ); goto end; } - if ( db->patch && memcmp( &stat.clsid, &clsid_msi_patch, 16 ) != 0 ) + if ( db->patch && memcmp( uuid, clsid_msi_patch, 16 ) != 0 ) { ERR("storage GUID is not the MSI patch GUID %s\n", - debugstr_guid(&stat.clsid) ); + debugstr_guid(uuid) ); goto end; } db->infile = stg; - IStorage_AddRef( db->infile ); + g_object_ref(G_OBJECT(db->infile)); cache_infile_structure( db ); @@ -2333,39 +2186,38 @@ LibmsiResult _libmsi_database_open(LibmsiDatabase *db) end: if (ret) { if (db->infile) - IStorage_Release( db->infile ); + g_object_unref(G_OBJECT(db->infile)); db->infile = NULL; } - IStorage_Release( stg ); + g_object_unref(G_OBJECT(stg)); return ret; } unsigned _libmsi_database_apply_transform( LibmsiDatabase *db, const char *szTransformFile, int iErrorCond ) { - HRESULT r; unsigned ret = LIBMSI_RESULT_FUNCTION_FAILED; - IStorage *stg = NULL; - STATSTG stat; - WCHAR *szwTransformFile = NULL; + GsfInput *in; + GsfInfile *stg; + uint8_t uuid[16]; TRACE("%p %s %d\n", db, debugstr_a(szTransformFile), iErrorCond); - szwTransformFile = strdupAtoW(szTransformFile); - if (!szwTransformFile) goto end; - - r = StgOpenStorage( szwTransformFile, NULL, - STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg); - if ( FAILED(r) ) + in = gsf_input_stdio_new(szTransformFile, NULL); + if (!in) { - WARN("failed to open transform 0x%08x\n", r); - return ret; + WARN("open file failed for transform %s\n", debugstr_a(szTransformFile)); + return LIBMSI_RESULT_OPEN_FAILED; } + stg = gsf_infile_msole_new( in, NULL ); + g_object_unref(G_OBJECT(in)); - r = IStorage_Stat( stg, &stat, STATFLAG_NONAME ); - if ( FAILED( r ) ) + if( !gsf_infile_msole_get_class_id (GSF_INFILE_MSOLE(stg), uuid)) + { + FIXME("Failed to stat storage\n"); goto end; + } - if ( memcmp( &stat.clsid, &clsid_msi_transform, 16 ) != 0 ) + if ( memcmp( uuid, clsid_msi_transform, 16 ) != 0 ) goto end; if( TRACE_ON( msi ) ) @@ -2374,8 +2226,7 @@ unsigned _libmsi_database_apply_transform( LibmsiDatabase *db, ret = msi_table_apply_transform( db, stg ); end: - msi_free(szwTransformFile); - IStorage_Release( stg ); + g_object_unref(G_OBJECT(stg)); return ret; } @@ -2393,65 +2244,79 @@ LibmsiResult libmsi_database_apply_transform( LibmsiDatabase *db, return r; } -static unsigned commit_storage( const WCHAR *name, IStorage *stg, void *opaque) +static int gsf_infile_copy(GsfInfile *inf, GsfOutfile *outf) +{ + int n = gsf_infile_num_children(inf); + int i; + + for (i = 0; i < n; i++) { + const char *name = gsf_infile_name_by_index(inf, i); + GsfInput *child = gsf_infile_child_by_index(inf, i); + GsfInfile *childf = GSF_IS_INFILE (child) ? GSF_INFILE (child) : NULL; + gboolean is_dir = childf && gsf_infile_num_children (childf) > 0; + GsfOutput *dest = gsf_outfile_new_child(outf, name, is_dir); + gboolean ok; + + if (is_dir) + ok = gsf_infile_copy(childf, GSF_OUTFILE(dest)); + else + ok = gsf_input_copy(child, dest); + + g_object_unref(G_OBJECT(child)); + g_object_unref(G_OBJECT(dest)); + if (!ok) + return false; + } + return true; +} + +static unsigned commit_storage( const char *name, GsfInfile *stg, void *opaque) { LibmsiDatabase *db = opaque; - IStorage *outstg; + GsfOutfile *outstg; unsigned ret = LIBMSI_RESULT_FUNCTION_FAILED; - HRESULT r; - TRACE("%s %p %p\n", debugstr_w(name), stg, opaque); + TRACE("%s %p %p\n", debugstr_a(name), stg, opaque); - r = IStorage_CreateStorage( db->outfile, name, - STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &outstg); - if ( FAILED(r) ) + outstg = GSF_OUTFILE(gsf_outfile_new_child( db->outfile, name, true )); + if ( !outstg ) return LIBMSI_RESULT_FUNCTION_FAILED; - r = IStorage_CopyTo( stg, 0, NULL, NULL, outstg ); - if ( FAILED(r) ) + if ( !gsf_infile_copy( stg, outstg ) ) goto end; ret = LIBMSI_RESULT_SUCCESS; end: - IStorage_Release(outstg); + gsf_output_close(GSF_OUTPUT(outstg)); + g_object_unref(G_OBJECT(outstg)); return ret; } -static unsigned commit_stream( const WCHAR *name, IStream *stm, void *opaque) +static unsigned commit_stream( const char *name, GsfInput *stm, void *opaque) { LibmsiDatabase *db = opaque; - STATSTG stat; - IStream *outstm; - ULARGE_INTEGER cbRead, cbWritten; + GsfOutput *outstm; unsigned ret = LIBMSI_RESULT_FUNCTION_FAILED; - HRESULT r; - WCHAR decname[0x40]; + char decname[0x40]; decode_streamname(name, decname); - TRACE("%s(%s) %p %p\n", debugstr_w(name), debugstr_w(decname), stm, opaque); + TRACE("%s(%s) %p %p\n", debugstr_a(name), debugstr_a(decname), stm, opaque); - IStream_Stat(stm, &stat, STATFLAG_NONAME); - r = IStorage_CreateStream( db->outfile, name, - STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &outstm); - if ( FAILED(r) ) + outstm = gsf_outfile_new_child( db->outfile, name, false ); + if ( !outstm ) return LIBMSI_RESULT_FUNCTION_FAILED; - IStream_SetSize( outstm, stat.cbSize ); - - r = IStream_CopyTo( stm, outstm, stat.cbSize, &cbRead, &cbWritten ); - if ( FAILED(r) ) - goto end; - - if (cbRead.QuadPart != stat.cbSize.QuadPart) - goto end; - if (cbWritten.QuadPart != stat.cbSize.QuadPart) + gsf_input_seek (stm, 0, G_SEEK_SET); + gsf_output_seek (outstm, 0, G_SEEK_SET); + if ( !gsf_input_copy( stm, outstm )) goto end; ret = LIBMSI_RESULT_SUCCESS; end: - IStream_Release(outstm); + gsf_output_close(GSF_OUTPUT(outstm)); + g_object_unref(G_OBJECT(outstm)); return ret; } @@ -2459,7 +2324,6 @@ LibmsiResult libmsi_database_commit( LibmsiDatabase *db ) { unsigned r = LIBMSI_RESULT_SUCCESS; unsigned bytes_per_strref; - HRESULT hr; TRACE("%d\n", db); @@ -2504,14 +2368,6 @@ LibmsiResult libmsi_database_commit( LibmsiDatabase *db ) /* FIXME: unlock the database */ - hr = IStorage_Commit( db->outfile, 0 ); - if (FAILED( hr )) - { - WARN("failed to commit changes 0x%08x\n", hr); - r = LIBMSI_RESULT_FUNCTION_FAILED; - goto end; - } - _libmsi_database_close(db, true); db->mode = LIBMSI_DB_OPEN_TRANSACT; _libmsi_database_open(db); @@ -2532,8 +2388,8 @@ struct msi_primary_key_record_info static unsigned msi_primary_key_iterator( LibmsiRecord *rec, void *param ) { struct msi_primary_key_record_info *info = param; - const WCHAR *name; - const WCHAR *table; + const char *name; + const char *table; unsigned type; type = libmsi_record_get_integer( rec, 4 ); @@ -2545,11 +2401,11 @@ static unsigned msi_primary_key_iterator( LibmsiRecord *rec, void *param ) if ( info->n == 1 ) { table = _libmsi_record_get_string_raw( rec, 1 ); - _libmsi_record_set_stringW( info->rec, 0, table); + libmsi_record_set_string( info->rec, 0, table); } name = _libmsi_record_get_string_raw( rec, 3 ); - _libmsi_record_set_stringW( info->rec, info->n, name ); + libmsi_record_set_string( info->rec, info->n, name ); } } @@ -2557,13 +2413,9 @@ static unsigned msi_primary_key_iterator( LibmsiRecord *rec, void *param ) } unsigned _libmsi_database_get_primary_keys( LibmsiDatabase *db, - const WCHAR *table, LibmsiRecord **prec ) + const char *table, LibmsiRecord **prec ) { - static const WCHAR sql[] = { - 's','e','l','e','c','t',' ','*',' ', - 'f','r','o','m',' ','`','_','C','o','l','u','m','n','s','`',' ', - 'w','h','e','r','e',' ', - '`','T','a','b','l','e','`',' ','=',' ','\'','%','s','\'',0 }; + static const char sql[] = "select * from `_Columns` where `Table` = '%s'"; struct msi_primary_key_record_info info; LibmsiQuery *query = NULL; unsigned r; @@ -2600,25 +2452,16 @@ unsigned _libmsi_database_get_primary_keys( LibmsiDatabase *db, LibmsiResult libmsi_database_get_primary_keys(LibmsiDatabase *db, const char *table, LibmsiRecord **prec) { - WCHAR *szwTable = NULL; unsigned r; TRACE("%d %s %p\n", db, debugstr_a(table), prec); - if( table ) - { - szwTable = strdupAtoW( table ); - if( !szwTable ) - return LIBMSI_RESULT_OUTOFMEMORY; - } - if( !db ) return LIBMSI_RESULT_INVALID_HANDLE; g_object_ref(db); - r = _libmsi_database_get_primary_keys( db, szwTable, prec ); + r = _libmsi_database_get_primary_keys( db, table, prec ); g_object_unref(db); - msi_free( szwTable ); return r; } @@ -2626,26 +2469,17 @@ LibmsiResult libmsi_database_get_primary_keys(LibmsiDatabase *db, LibmsiCondition libmsi_database_is_table_persistent( LibmsiDatabase *db, const char *szTableName) { - WCHAR *szwTableName = NULL; LibmsiCondition r; TRACE("%x %s\n", db, debugstr_a(szTableName)); - if( szTableName ) - { - szwTableName = strdupAtoW( szTableName ); - if( !szwTableName ) - return LIBMSI_CONDITION_ERROR; - } - g_object_ref(db); if( !db ) return LIBMSI_CONDITION_ERROR; - r = _libmsi_database_is_table_persistent( db, szwTableName ); + r = _libmsi_database_is_table_persistent( db, szTableName ); g_object_unref(db); - msi_free( szwTableName ); return r; } |