📄 database.c
字号:
r = MSI_DatabaseOpenViewW( db, create_sql, &view );
msi_free(create_sql);
if (r != ERROR_SUCCESS)
return r;
r = MSI_ViewExecute(view, NULL);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
return r;
}
static LPWSTR msi_build_insertsql_prelude(LPWSTR table)
{
LPWSTR prelude;
DWORD size;
static const WCHAR insert_fmt[] = {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','%','s','`',' ','(',' ',0};
size = sizeof(insert_fmt) + lstrlenW(table) - 2;
prelude = msi_alloc(size * sizeof(WCHAR));
if (!prelude)
return NULL;
sprintfW(prelude, insert_fmt, table);
return prelude;
}
static LPWSTR msi_build_insertsql_columns(LPWSTR *columns_data, LPWSTR *types, DWORD num_columns)
{
LPWSTR columns;
DWORD sql_size = 1, i;
WCHAR expanded[128];
static const WCHAR column_fmt[] = {'`','%','s','`',',',' ',0};
columns = msi_alloc_zero(sql_size * sizeof(WCHAR));
if (!columns)
return NULL;
for (i = 0; i < num_columns; i++)
{
sprintfW(expanded, column_fmt, columns_data[i]);
sql_size += lstrlenW(expanded);
if (i == num_columns - 1)
{
sql_size -= 2;
expanded[lstrlenW(expanded) - 2] = '\0';
}
columns = msi_realloc(columns, sql_size * sizeof(WCHAR));
if (!columns)
return NULL;
lstrcatW(columns, expanded);
}
return columns;
}
static LPWSTR msi_build_insertsql_data(LPWSTR **records, LPWSTR *types, DWORD num_columns, DWORD irec)
{
LPWSTR columns;
DWORD sql_size = 1, i;
WCHAR expanded[128];
static const WCHAR str_fmt[] = {'\'','%','s','\'',',',' ',0};
static const WCHAR int_fmt[] = {'%','s',',',' ',0};
static const WCHAR empty[] = {'\'','\'',',',' ',0};
columns = msi_alloc_zero(sql_size * sizeof(WCHAR));
if (!columns)
return NULL;
for (i = 0; i < num_columns; i++)
{
switch (types[i][0])
{
case 'L': case 'l': case 'S': case 's':
sprintfW(expanded, str_fmt, records[irec][i]);
break;
case 'I': case 'i':
if (*records[0][i])
sprintfW(expanded, int_fmt, records[irec][i]);
else
lstrcpyW(expanded, empty);
break;
default:
return NULL;
}
if (i == num_columns - 1)
expanded[lstrlenW(expanded) - 2] = '\0';
sql_size += lstrlenW(expanded);
columns = msi_realloc(columns, sql_size * sizeof(WCHAR));
if (!columns)
return NULL;
lstrcatW(columns, expanded);
}
return columns;
}
static UINT msi_add_records_to_table(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types,
LPWSTR *labels, LPWSTR **records,
int num_columns, int num_records)
{
MSIQUERY *view;
LPWSTR insert_sql;
DWORD size, i;
UINT r = ERROR_SUCCESS;
static const WCHAR mid[] = {' ',')',' ','V','A','L','U','E','S',' ','(',' ',0};
static const WCHAR end[] = {' ',')',0};
LPWSTR prelude = msi_build_insertsql_prelude(labels[0]);
LPWSTR columns_sql = msi_build_insertsql_columns(columns, types, num_columns);
for (i = 0; i < num_records; i++)
{
LPWSTR data = msi_build_insertsql_data(records, types, num_columns, i);
size = lstrlenW(prelude) + lstrlenW(columns_sql) + sizeof(mid) + lstrlenW(data) + sizeof(end) - 1;
insert_sql = msi_alloc(size * sizeof(WCHAR));
if (!insert_sql)
return ERROR_OUTOFMEMORY;
lstrcpyW(insert_sql, prelude);
lstrcatW(insert_sql, columns_sql);
lstrcatW(insert_sql, mid);
lstrcatW(insert_sql, data);
lstrcatW(insert_sql, end);
msi_free(data);
r = MSI_DatabaseOpenViewW( db, insert_sql, &view );
msi_free(insert_sql);
if (r != ERROR_SUCCESS)
goto done;
r = MSI_ViewExecute(view, NULL);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
}
done:
msi_free(prelude);
msi_free(columns_sql);
return r;
}
UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
{
UINT r;
DWORD len, i;
DWORD num_labels;
DWORD num_columns, num_records = 0;
LPWSTR *columns, *types, *labels;
LPWSTR path, ptr, data;
LPWSTR **records;
static const WCHAR backslash[] = {'\\',0};
TRACE("%p %s %s\n", db, debugstr_w(folder), debugstr_w(file) );
if( folder == NULL || file == NULL )
return ERROR_INVALID_PARAMETER;
len = lstrlenW(folder) + lstrlenW(backslash) + lstrlenW(file) + 1;
path = msi_alloc( len * sizeof(WCHAR) );
if (!path)
return ERROR_OUTOFMEMORY;
lstrcpyW( path, folder );
lstrcatW( path, backslash );
lstrcatW( path, file );
data = msi_read_text_archive( path );
ptr = data;
msi_parse_line( &ptr, &columns, &num_columns );
msi_parse_line( &ptr, &types, NULL );
msi_parse_line( &ptr, &labels, &num_labels );
records = msi_alloc(sizeof(LPWSTR *));
if (!records)
return ERROR_OUTOFMEMORY;
/* read in the table records */
while (*ptr)
{
msi_parse_line( &ptr, &records[num_records], NULL );
num_records++;
records = msi_realloc(records, (num_records + 1) * sizeof(LPWSTR *));
if (!records)
return ERROR_OUTOFMEMORY;
}
r = msi_add_table_to_db( db, columns, types, labels, num_labels, num_columns );
if (r != ERROR_SUCCESS)
goto done;
r = msi_add_records_to_table( db, columns, types, labels, records, num_columns, num_records );
done:
msi_free(path);
msi_free(data);
msi_free(columns);
msi_free(types);
msi_free(labels);
for (i = 0; i < num_records; i++)
msi_free(records[i]);
msi_free(records);
return r;
}
UINT WINAPI MsiDatabaseImportW(MSIHANDLE handle, LPCWSTR szFolder, LPCWSTR szFilename)
{
MSIDATABASE *db;
UINT r;
TRACE("%lx %s %s\n",handle,debugstr_w(szFolder), debugstr_w(szFilename));
db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
if( !db )
return ERROR_INVALID_HANDLE;
r = MSI_DatabaseImport( db, szFolder, szFilename );
msiobj_release( &db->hdr );
return r;
}
UINT WINAPI MsiDatabaseImportA( MSIHANDLE handle,
LPCSTR szFolder, LPCSTR szFilename )
{
LPWSTR path = NULL, file = NULL;
UINT r = ERROR_OUTOFMEMORY;
TRACE("%lx %s %s\n", handle, debugstr_a(szFolder), debugstr_a(szFilename));
if( szFolder )
{
path = strdupAtoW( szFolder );
if( !path )
goto end;
}
if( szFilename )
{
file = strdupAtoW( szFilename );
if( !file )
goto end;
}
r = MsiDatabaseImportW( handle, path, file );
end:
msi_free( path );
msi_free( file );
return r;
}
static UINT msi_export_record( HANDLE handle, MSIRECORD *row, UINT start )
{
UINT i, count, len, r = ERROR_SUCCESS;
const char *sep;
char *buffer;
DWORD sz;
len = 0x100;
buffer = msi_alloc( len );
if ( !buffer )
return ERROR_OUTOFMEMORY;
count = MSI_RecordGetFieldCount( row );
for ( i=start; i<=count; i++ )
{
sz = len;
r = MSI_RecordGetStringA( row, i, buffer, &sz );
if (r == ERROR_MORE_DATA)
{
char *p = msi_realloc( buffer, sz + 1 );
if (!p)
break;
len = sz + 1;
buffer = p;
}
sz = len;
r = MSI_RecordGetStringA( row, i, buffer, &sz );
if (r != ERROR_SUCCESS)
break;
if (!WriteFile( handle, buffer, sz, &sz, NULL ))
{
r = ERROR_FUNCTION_FAILED;
break;
}
sep = (i < count) ? "\t" : "\r\n";
if (!WriteFile( handle, sep, strlen(sep), &sz, NULL ))
{
r = ERROR_FUNCTION_FAILED;
break;
}
}
msi_free( buffer );
return r;
}
static UINT msi_export_row( MSIRECORD *row, void *arg )
{
return msi_export_record( arg, row, 1 );
}
UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
LPCWSTR folder, LPCWSTR file )
{
static const WCHAR query[] = {
's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','%','s',0 };
static const WCHAR szbs[] = { '\\', 0 };
MSIRECORD *rec = NULL;
MSIQUERY *view = NULL;
LPWSTR filename;
HANDLE handle;
UINT len, r;
TRACE("%p %s %s %s\n", db, debugstr_w(table),
debugstr_w(folder), debugstr_w(file) );
if( folder == NULL || file == NULL )
return ERROR_INVALID_PARAMETER;
len = lstrlenW(folder) + lstrlenW(file) + 2;
filename = msi_alloc(len * sizeof (WCHAR));
if (!filename)
return ERROR_OUTOFMEMORY;
lstrcpyW( filename, folder );
lstrcatW( filename, szbs );
lstrcatW( filename, file );
handle = CreateFileW( filename, GENERIC_READ | GENERIC_WRITE, 0,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
msi_free( filename );
if (handle == INVALID_HANDLE_VALUE)
return ERROR_FUNCTION_FAILED;
r = MSI_OpenQuery( db, &view, query, table );
if (r == ERROR_SUCCESS)
{
/* write out row 1, the column names */
r = MSI_ViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
if (r == ERROR_SUCCESS)
{
msi_export_record( handle, rec, 1 );
msiobj_release( &rec->hdr );
}
/* write out row 2, the column types */
r = MSI_ViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
if (r == ERROR_SUCCESS)
{
msi_export_record( handle, rec, 1 );
msiobj_release( &rec->hdr );
}
/* write out row 3, the table name + keys */
r = MSI_DatabaseGetPrimaryKeys( db, table, &rec );
if (r == ERROR_SUCCESS)
{
MSI_RecordSetStringW( rec, 0, table );
msi_export_record( handle, rec, 0 );
msiobj_release( &rec->hdr );
}
/* write out row 4 onwards, the data */
r = MSI_IterateRecords( view, 0, msi_export_row, handle );
msiobj_release( &view->hdr );
}
CloseHandle( handle );
return r;
}
/***********************************************************************
* MsiExportDatabaseW [MSI.@]
*
* Writes a file containing the table data as tab separated ASCII.
*
* The format is as follows:
*
* row1 : colname1 <tab> colname2 <tab> .... colnameN <cr> <lf>
* row2 : coltype1 <tab> coltype2 <tab> .... coltypeN <cr> <lf>
* row3 : tablename <tab> key1 <tab> key2 <tab> ... keyM <cr> <lf>
*
* Followed by the data, starting at row 1 with one row per line
*
* row4 : data <tab> data <tab> data <tab> ... data <cr> <lf>
*/
UINT WINAPI MsiDatabaseExportW( MSIHANDLE handle, LPCWSTR szTable,
LPCWSTR szFolder, LPCWSTR szFilename )
{
MSIDATABASE *db;
UINT r;
TRACE("%lx %s %s %s\n", handle, debugstr_w(szTable),
debugstr_w(szFolder), debugstr_w(szFilename));
db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
if( !db )
return ERROR_INVALID_HANDLE;
r = MSI_DatabaseExport( db, szTable, szFolder, szFilename );
msiobj_release( &db->hdr );
return r;
}
UINT WINAPI MsiDatabaseExportA( MSIHANDLE handle, LPCSTR szTable,
LPCSTR szFolder, LPCSTR szFilename )
{
LPWSTR path = NULL, file = NULL, table = NULL;
UINT r = ERROR_OUTOFMEMORY;
TRACE("%lx %s %s %s\n", handle, debugstr_a(szTable),
debugstr_a(szFolder), debugstr_a(szFilename));
if( szTable )
{
table = strdupAtoW( szTable );
if( !table )
goto end;
}
if( szFolder )
{
path = strdupAtoW( szFolder );
if( !path )
goto end;
}
if( szFilename )
{
file = strdupAtoW( szFilename );
if( !file )
goto end;
}
r = MsiDatabaseExportW( handle, table, path, file );
end:
msi_free( table );
msi_free( path );
msi_free( file );
return r;
}
MSIDBSTATE WINAPI MsiGetDatabaseState( MSIHANDLE handle )
{
MSIDBSTATE ret = MSIDBSTATE_READ;
MSIDATABASE *db;
TRACE("%ld\n", handle);
db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
if (!db)
return MSIDBSTATE_ERROR;
if (db->mode != MSIDBOPEN_READONLY )
ret = MSIDBSTATE_WRITE;
msiobj_release( &db->hdr );
return ret;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -