diff --git a/dlls/msi/database.c b/dlls/msi/database.c index 70bcd90b49e..ec944be7070 100644 --- a/dlls/msi/database.c +++ b/dlls/msi/database.c @@ -377,6 +377,7 @@ static LPWSTR msi_build_createsql_columns(LPWSTR *columns_data, LPWSTR *types, D 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}; @@ -421,6 +422,11 @@ static LPWSTR msi_build_createsql_columns(LPWSTR *columns_data, LPWSTR *types, D else type = type_long; break; + case 'v': + lstrcpyW(extra, type_notnull); + case 'V': + type = type_object; + break; default: ERR("Unknown type: %c\n", types[i][0]); msi_free(columns); @@ -522,8 +528,32 @@ static UINT msi_add_table_to_db(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types, return r; } +static LPWSTR msi_import_stream_filename(LPCWSTR path, LPCWSTR name) +{ + DWORD len; + LPWSTR fullname, ptr; + + len = lstrlenW(path) + lstrlenW(name) + 1; + fullname = msi_alloc(len*sizeof(WCHAR)); + if (!fullname) + return NULL; + + lstrcpyW( fullname, path ); + + /* chop off extension from path */ + ptr = strrchrW(fullname, '.'); + if (!ptr) + { + msi_free (fullname); + return NULL; + } + *ptr++ = '\\'; + lstrcpyW( ptr, name ); + return fullname; +} + static UINT construct_record(DWORD num_columns, LPWSTR *types, - LPWSTR *data, MSIRECORD **rec) + LPWSTR *data, LPWSTR path, MSIRECORD **rec) { UINT i; @@ -542,6 +572,20 @@ static UINT construct_record(DWORD num_columns, LPWSTR *types, if (*data[i]) MSI_RecordSetInteger(*rec, i + 1, atoiW(data[i])); break; + case 'V': case 'v': + if (*data[i]) + { + UINT r; + LPWSTR file = msi_import_stream_filename(path, data[i]); + if (!file) + return ERROR_FUNCTION_FAILED; + + r = MSI_RecordSetStreamFromFileW(*rec, i + 1, file); + msi_free (file); + if (r != ERROR_SUCCESS) + return ERROR_FUNCTION_FAILED; + } + break; default: ERR("Unhandled column type: %c\n", types[i][0]); msiobj_release(&(*rec)->hdr); @@ -554,7 +598,8 @@ static UINT construct_record(DWORD num_columns, LPWSTR *types, static UINT msi_add_records_to_table(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types, LPWSTR *labels, LPWSTR **records, - int num_columns, int num_records) + int num_columns, int num_records, + LPWSTR path) { UINT r; int i; @@ -579,7 +624,7 @@ static UINT msi_add_records_to_table(MSIDATABASE *db, LPWSTR *columns, LPWSTR *t for (i = 0; i < num_records; i++) { - r = construct_record(num_columns, types, records[i], &rec); + r = construct_record(num_columns, types, records[i], path, &rec); if (r != ERROR_SUCCESS) goto done; @@ -683,7 +728,7 @@ static UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file) } } - r = msi_add_records_to_table( db, columns, types, labels, records, num_columns, num_records ); + r = msi_add_records_to_table( db, columns, types, labels, records, num_columns, num_records, path ); } done: diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 408c9686030..8c4bd3a4515 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -704,6 +704,7 @@ extern UINT MSI_RecordReadStream( MSIRECORD *, UINT, char *, LPDWORD); extern UINT MSI_RecordSetStream(MSIRECORD *, UINT, IStream *); extern UINT MSI_RecordGetFieldCount( const MSIRECORD *rec ); extern UINT MSI_RecordStreamToFile( MSIRECORD *, UINT, LPCWSTR ); +extern UINT MSI_RecordSetStreamFromFileW( MSIRECORD *, UINT, LPCWSTR ); extern UINT MSI_RecordCopyField( MSIRECORD *, UINT, MSIRECORD *, UINT ); extern MSIRECORD *MSI_CloneRecord( MSIRECORD * ); extern BOOL MSI_RecordsAreEqual( MSIRECORD *, MSIRECORD * ); diff --git a/dlls/msi/record.c b/dlls/msi/record.c index 9211e1c582c..68eab694370 100644 --- a/dlls/msi/record.c +++ b/dlls/msi/record.c @@ -673,7 +673,7 @@ UINT MSI_RecordSetStream(MSIRECORD *rec, UINT iField, IStream *stream) return ERROR_SUCCESS; } -static UINT MSI_RecordSetStreamFromFileW(MSIRECORD *rec, UINT iField, LPCWSTR szFilename) +UINT MSI_RecordSetStreamFromFileW(MSIRECORD *rec, UINT iField, LPCWSTR szFilename) { IStream *stm = NULL; HRESULT r; diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c index d408c49e34b..ec0bf30f910 100644 --- a/dlls/msi/tests/db.c +++ b/dlls/msi/tests/db.c @@ -1966,23 +1966,23 @@ static void test_binary_import(void) GetCurrentDirectory(MAX_PATH, path); r = MsiDatabaseImport(hdb, path, "bin_import.idt"); - todo_wine ok(r == ERROR_SUCCESS , "Failed to import Binary table\n"); + ok(r == ERROR_SUCCESS , "Failed to import Binary table\n"); /* read file from the Binary table */ query = "SELECT * FROM `Binary`"; r = do_query(hdb, query, &rec); - todo_wine ok(r == ERROR_SUCCESS, "SELECT query failed: %d\n", r); + ok(r == ERROR_SUCCESS, "SELECT query failed: %d\n", r); size = MAX_PATH; r = MsiRecordGetString(rec, 1, file, &size); - todo_wine ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r); - todo_wine ok(!lstrcmp(file, "filename1"), "Expected 'filename1', got %s\n", file); + ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r); + ok(!lstrcmp(file, "filename1"), "Expected 'filename1', got %s\n", file); size = MAX_PATH; memset(buf, 0, MAX_PATH); r = MsiRecordReadStream(rec, 2, buf, &size); - todo_wine ok(r == ERROR_SUCCESS, "Failed to get stream: %d\n", r); - todo_wine ok(!lstrcmp(buf, "just some words"), + ok(r == ERROR_SUCCESS, "Failed to get stream: %d\n", r); + ok(!lstrcmp(buf, "just some words"), "Expected 'just some words', got %s\n", buf); r = MsiCloseHandle(rec);