Autosyncing with Wine HEAD

svn path=/trunk/; revision=24002
This commit is contained in:
The Wine Synchronizer 2006-09-09 17:48:42 +00:00
parent b5957ce896
commit 4246de3191
17 changed files with 6177 additions and 5530 deletions

View file

@ -3488,32 +3488,25 @@ end:
return rc;
}
static UINT msi_make_package_local( MSIPACKAGE *package, HKEY hkey )
static UINT msi_get_local_package_name( LPWSTR path )
{
static const WCHAR installerPathFmt[] = {
'%','s','\\','I','n','s','t','a','l','l','e','r','\\',0};
static const WCHAR fmt[] = {
'%','s','\\',
'I','n','s','t','a','l','l','e','r','\\',
'%','x','.','m','s','i',0};
static const WCHAR szOriginalDatabase[] =
{'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
WCHAR windir[MAX_PATH], path[MAX_PATH], packagefile[MAX_PATH];
INT num, start;
LPWSTR msiFilePath;
BOOL r;
static const WCHAR szInstaller[] = {
'\\','I','n','s','t','a','l','l','e','r','\\',0};
static const WCHAR fmt[] = { '%','x','.','m','s','i',0};
DWORD time, len, i;
HANDLE handle;
/* copy the package locally */
num = GetTickCount() & 0xffff;
if (!num)
num = 1;
start = num;
GetWindowsDirectoryW( windir, MAX_PATH );
snprintfW( packagefile, MAX_PATH, fmt, windir, num );
do
time = GetTickCount();
GetWindowsDirectoryW( path, MAX_PATH );
lstrcatW( path, szInstaller );
CreateDirectoryW( path, NULL );
len = lstrlenW(path);
for (i=0; i<0x10000; i++)
{
HANDLE handle = CreateFileW(packagefile,GENERIC_WRITE, 0, NULL,
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
snprintfW( &path[len], MAX_PATH - len, fmt, (time+i)&0xffff );
handle = CreateFileW( path, GENERIC_WRITE, 0, NULL,
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
if (handle != INVALID_HANDLE_VALUE)
{
CloseHandle(handle);
@ -3521,13 +3514,23 @@ static UINT msi_make_package_local( MSIPACKAGE *package, HKEY hkey )
}
if (GetLastError() != ERROR_FILE_EXISTS &&
GetLastError() != ERROR_SHARING_VIOLATION)
break;
if (!(++num & 0xffff)) num = 1;
sprintfW(packagefile,fmt,num);
} while (num != start);
return ERROR_FUNCTION_FAILED;
}
snprintfW( path, MAX_PATH, installerPathFmt, windir );
create_full_pathW(path);
return ERROR_SUCCESS;
}
static UINT msi_make_package_local( MSIPACKAGE *package, HKEY hkey )
{
static const WCHAR szOriginalDatabase[] =
{'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
WCHAR packagefile[MAX_PATH];
LPWSTR msiFilePath;
UINT r;
r = msi_get_local_package_name( packagefile );
if (r != ERROR_SUCCESS)
return r;
TRACE("Copying to local package %s\n",debugstr_w(packagefile));

View file

@ -221,17 +221,35 @@ static const MSIVIEWOPS create_ops =
CREATE_delete
};
static UINT check_columns( column_info *col_info )
{
column_info *c1, *c2;
/* check for two columns with the same name */
for( c1 = col_info; c1; c1 = c1->next )
for( c2 = c1->next; c2; c2 = c2->next )
if (!lstrcmpW(c1->column, c2->column))
return ERROR_BAD_QUERY_SYNTAX;
return ERROR_SUCCESS;
}
UINT CREATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
column_info *col_info, BOOL temp )
{
MSICREATEVIEW *cv = NULL;
UINT r;
TRACE("%p\n", cv );
r = check_columns( col_info );
if( r != ERROR_SUCCESS )
return r;
cv = msi_alloc_zero( sizeof *cv );
if( !cv )
return ERROR_FUNCTION_FAILED;
/* fill the structure */
cv->view.ops = &create_ops;
msiobj_addref( &db->hdr );

View file

@ -117,6 +117,31 @@ static BOOL check_execution_scheduling_options(MSIPACKAGE *package, LPCWSTR acti
return TRUE;
}
/* stores the CustomActionData before the action:
* [CustomActionData]Action
*/
LPWSTR msi_get_deferred_action(LPCWSTR action, LPWSTR actiondata)
{
LPWSTR deferred;
DWORD len;
static const WCHAR begin[] = {'[',0};
static const WCHAR end[] = {']',0};
if (!actiondata)
return strdupW(action);
len = lstrlenW(action) + lstrlenW(actiondata) + 3;
deferred = msi_alloc(len * sizeof(WCHAR));
lstrcpyW(deferred, begin);
lstrcatW(deferred, actiondata);
lstrcatW(deferred, end);
lstrcatW(deferred, action);
return deferred;
}
UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute)
{
UINT rc = ERROR_SUCCESS;
@ -128,8 +153,18 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute)
'=',' ','\'','%','s','\'',0};
UINT type;
LPCWSTR source, target;
LPWSTR ptr, deferred_data = NULL;
LPWSTR action_copy = strdupW(action);
WCHAR *deformated=NULL;
/* deferred action: [CustomActionData]Action */
if ((ptr = strchrW(action_copy, ']')))
{
deferred_data = action_copy + 1;
*ptr = '\0';
action = ptr + 1;
}
row = MSI_QueryGetRecord( package->db, ExecSeqQuery, action );
if (!row)
return ERROR_CALL_NOT_IMPLEMENTED;
@ -160,18 +195,22 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute)
}
if (!execute)
{
LPWSTR actiondata = msi_dup_property(package, action);
LPWSTR deferred = msi_get_deferred_action(action, actiondata);
if (type & msidbCustomActionTypeCommit)
{
TRACE("Deferring Commit Action!\n");
schedule_action(package, COMMIT_SCRIPT, action);
schedule_action(package, COMMIT_SCRIPT, deferred);
}
else
{
TRACE("Deferring Action!\n");
schedule_action(package, INSTALL_SCRIPT, action);
schedule_action(package, INSTALL_SCRIPT, deferred);
}
rc = ERROR_SUCCESS;
msi_free(deferred);
goto end;
}
else
@ -182,7 +221,9 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute)
'C','u','s','t','o','m','A','c','t','i','o','n','D','a','t','a',0};
static const WCHAR szBlank[] = {0};
LPWSTR actiondata = msi_dup_property( package, action );
if (actiondata)
if (deferred_data)
MSI_SetPropertyW(package,szActionData,deferred_data);
else if (actiondata)
MSI_SetPropertyW(package,szActionData,actiondata);
else
MSI_SetPropertyW(package,szActionData,szBlank);
@ -235,6 +276,7 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute)
}
end:
msi_free(action_copy);
msiobj_release(&row->hdr);
return rc;
}

View file

@ -287,18 +287,144 @@ end:
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 )
{
FIXME("%p %s %s %s\n", db, debugstr_w(table),
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;
return ERROR_CALL_NOT_IMPLEMENTED;
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 )
{

View file

@ -63,6 +63,7 @@ struct msi_control_tag
HBITMAP hBitmap;
HICON hIcon;
LPWSTR tabnext;
LPWSTR type;
HMODULE hDll;
float progress_current;
float progress_max;
@ -85,6 +86,7 @@ struct msi_dialog_tag
BOOL finished;
INT scale;
DWORD attributes;
SIZE size;
HWND hwnd;
LPWSTR default_font;
msi_font *font_list;
@ -177,6 +179,18 @@ static msi_control *msi_dialog_find_control( msi_dialog *dialog, LPCWSTR name )
return NULL;
}
static msi_control *msi_dialog_find_control_by_type( msi_dialog *dialog, LPCWSTR type )
{
msi_control *control;
if( !type )
return NULL;
LIST_FOR_EACH_ENTRY( control, &dialog->controls, msi_control, entry )
if( !strcmpW( control->type, type ) ) /* FIXME: case sensitive? */
return control;
return NULL;
}
static msi_control *msi_dialog_find_control_by_hwnd( msi_dialog *dialog, HWND hwnd )
{
msi_control *control;
@ -359,6 +373,7 @@ static msi_control *msi_dialog_create_window( msi_dialog *dialog,
control->hIcon = NULL;
control->hDll = NULL;
control->tabnext = strdupW( MSI_RecordGetString( rec, 11) );
control->type = strdupW( MSI_RecordGetString( rec, 3 ) );
control->progress_current = 0;
control->progress_max = 100;
@ -393,6 +408,24 @@ static msi_control *msi_dialog_create_window( msi_dialog *dialog,
return control;
}
static LPWSTR msi_dialog_get_uitext( msi_dialog *dialog, LPCWSTR key )
{
MSIRECORD *rec;
LPWSTR text;
static const WCHAR query[] = {
's','e','l','e','c','t',' ','*',' ',
'f','r','o','m',' ','`','U','I','T','e','x','t','`',' ',
'w','h','e','r','e',' ','`','K','e','y','`',' ','=',' ','\'','%','s','\'',0
};
rec = MSI_QueryGetRecord( dialog->package->db, query, key );
if (!rec) return NULL;
text = strdupW( MSI_RecordGetString( rec, 2 ) );
msiobj_release( &rec->hdr );
return text;
}
static MSIRECORD *msi_get_binary_record( MSIDATABASE *db, LPCWSTR name )
{
static const WCHAR query[] = {
@ -1374,6 +1407,13 @@ static UINT msi_dialog_progress_bar( msi_dialog *dialog, MSIRECORD *rec )
/******************** Path Edit ********************************************/
struct msi_pathedit_info
{
msi_dialog *dialog;
msi_control *control;
WNDPROC oldproc;
};
static LPWSTR msi_get_window_text( HWND hwnd )
{
UINT sz, r;
@ -1393,38 +1433,14 @@ static LPWSTR msi_get_window_text( HWND hwnd )
return buf;
}
static UINT msi_dialog_pathedit_handler( msi_dialog *dialog,
msi_control *control, WPARAM param )
static void msi_dialog_update_pathedit( msi_dialog *dialog, msi_control *control )
{
LPWSTR buf, prop;
BOOL indirect;
if( HIWORD(param) != EN_KILLFOCUS )
return ERROR_SUCCESS;
indirect = control->attributes & msidbControlAttributesIndirect;
prop = msi_dialog_dup_property( dialog, control->property, indirect );
/* FIXME: verify the new path */
buf = msi_get_window_text( control->hwnd );
MSI_SetPropertyW( dialog->package, prop, buf );
TRACE("edit %s contents changed, set %s\n", debugstr_w(control->name),
debugstr_w(prop));
msi_free( buf );
msi_free( prop );
return ERROR_SUCCESS;
}
static void msi_dialog_update_pathedit( msi_dialog *dialog )
{
msi_control *control;
LPWSTR prop, path;
BOOL indirect;
control = msi_dialog_find_control( dialog, szPathEdit );
if (!control && !(control = msi_dialog_find_control_by_type( dialog, szPathEdit )))
return;
indirect = control->attributes & msidbControlAttributesIndirect;
prop = msi_dialog_dup_property( dialog, control->property, indirect );
@ -1436,19 +1452,102 @@ static void msi_dialog_update_pathedit( msi_dialog *dialog )
msi_free( prop );
}
/* FIXME: test when this should fail */
static BOOL msi_dialog_verify_path( LPWSTR path )
{
if ( !lstrlenW( path ) )
return FALSE;
if ( PathIsRelativeW( path ) )
return FALSE;
return TRUE;
}
/* returns TRUE if the path is valid, FALSE otherwise */
static BOOL msi_dialog_onkillfocus( msi_dialog *dialog, msi_control *control )
{
LPWSTR buf, prop;
BOOL indirect;
BOOL valid;
indirect = control->attributes & msidbControlAttributesIndirect;
prop = msi_dialog_dup_property( dialog, control->property, indirect );
buf = msi_get_window_text( control->hwnd );
if ( !msi_dialog_verify_path( buf ) )
{
/* FIXME: display an error message box */
ERR("Invalid path %s\n", debugstr_w( buf ));
valid = FALSE;
SetFocus( control->hwnd );
}
else
{
valid = TRUE;
MSI_SetPropertyW( dialog->package, prop, buf );
}
msi_dialog_update_pathedit( dialog, control );
TRACE("edit %s contents changed, set %s\n", debugstr_w(control->name),
debugstr_w(prop));
msi_free( buf );
msi_free( prop );
return valid;
}
static LRESULT WINAPI MSIPathEdit_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
struct msi_pathedit_info *info = GetPropW(hWnd, szButtonData);
LRESULT r = 0;
TRACE("%p %04x %08x %08lx\n", hWnd, msg, wParam, lParam);
if ( msg == WM_KILLFOCUS )
{
/* if the path is invalid, don't handle this message */
if ( !msi_dialog_onkillfocus( info->dialog, info->control ) )
return 0;
}
r = CallWindowProcW(info->oldproc, hWnd, msg, wParam, lParam);
if ( msg == WM_NCDESTROY )
{
msi_free( info );
RemovePropW( hWnd, szButtonData );
}
return r;
}
static UINT msi_dialog_pathedit_control( msi_dialog *dialog, MSIRECORD *rec )
{
struct msi_pathedit_info *info;
msi_control *control;
LPCWSTR prop;
info = msi_alloc( sizeof *info );
if (!info)
return ERROR_FUNCTION_FAILED;
control = msi_dialog_add_control( dialog, rec, szEdit,
WS_BORDER | WS_TABSTOP );
control->handler = msi_dialog_pathedit_handler;
control->attributes = MSI_RecordGetInteger( rec, 8 );
prop = MSI_RecordGetString( rec, 9 );
control->property = msi_dialog_dup_property( dialog, prop, FALSE );
msi_dialog_update_pathedit( dialog );
info->dialog = dialog;
info->control = control;
info->oldproc = (WNDPROC) SetWindowLongPtrW( control->hwnd, GWLP_WNDPROC,
(LONG_PTR)MSIPathEdit_WndProc );
SetPropW( control->hwnd, szButtonData, info );
msi_dialog_update_pathedit( dialog, control );
return ERROR_SUCCESS;
}
@ -1961,13 +2060,14 @@ static UINT msi_dialog_list_box( msi_dialog *dialog, MSIRECORD *rec )
/******************** Directory Combo ***************************************/
static void msi_dialog_update_directory_combo( msi_dialog *dialog )
static void msi_dialog_update_directory_combo( msi_dialog *dialog, msi_control *control )
{
msi_control *control;
LPWSTR prop, path;
BOOL indirect;
control = msi_dialog_find_control( dialog, szDirectoryCombo );
if (!control && !(control = msi_dialog_find_control_by_type( dialog, szDirectoryCombo )))
return;
indirect = control->attributes & msidbControlAttributesIndirect;
prop = msi_dialog_dup_property( dialog, control->property, indirect );
path = msi_dup_property( dialog->package, prop );
@ -1999,20 +2099,72 @@ static UINT msi_dialog_directory_combo( msi_dialog *dialog, MSIRECORD *rec )
prop = MSI_RecordGetString( rec, 9 );
control->property = msi_dialog_dup_property( dialog, prop, FALSE );
msi_dialog_update_directory_combo( dialog );
msi_dialog_update_directory_combo( dialog, control );
return ERROR_SUCCESS;
}
/******************** Directory List ***************************************/
static void msi_dialog_update_directory_list( msi_dialog *dialog, msi_control *control )
{
WCHAR dir_spec[MAX_PATH];
WIN32_FIND_DATAW wfd;
LPWSTR prop, path;
BOOL indirect;
LVITEMW item;
HANDLE file;
static const WCHAR asterisk[] = {'*',0};
static const WCHAR dot[] = {'.',0};
static const WCHAR dotdot[] = {'.','.',0};
if (!control && !(control = msi_dialog_find_control_by_type( dialog, szDirectoryList )))
return;
/* clear the list-view */
SendMessageW( control->hwnd, LVM_DELETEALLITEMS, 0, 0 );
indirect = control->attributes & msidbControlAttributesIndirect;
prop = msi_dialog_dup_property( dialog, control->property, indirect );
path = msi_dup_property( dialog->package, prop );
lstrcpyW( dir_spec, path );
lstrcatW( dir_spec, asterisk );
file = FindFirstFileW( dir_spec, &wfd );
if ( file == INVALID_HANDLE_VALUE )
return;
do
{
if ( wfd.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY )
continue;
if ( !lstrcmpW( wfd.cFileName, dot ) || !lstrcmpW( wfd.cFileName, dotdot ) )
continue;
item.mask = LVIF_TEXT;
item.cchTextMax = MAX_PATH;
item.iItem = 0;
item.iSubItem = 0;
item.pszText = wfd.cFileName;
SendMessageW( control->hwnd, LVM_INSERTITEMW, 0, (LPARAM)&item );
} while ( FindNextFileW( file, &wfd ) );
msi_free( prop );
msi_free( path );
FindClose( file );
}
UINT msi_dialog_directorylist_up( msi_dialog *dialog )
{
msi_control *control;
LPWSTR prop, path, ptr;
BOOL indirect;
control = msi_dialog_find_control( dialog, szDirectoryList );
control = msi_dialog_find_control_by_type( dialog, szDirectoryList );
indirect = control->attributes & msidbControlAttributesIndirect;
prop = msi_dialog_dup_property( dialog, control->property, indirect );
@ -2025,8 +2177,9 @@ UINT msi_dialog_directorylist_up( msi_dialog *dialog )
MSI_SetPropertyW( dialog->package, prop, path );
msi_dialog_update_directory_combo( dialog );
msi_dialog_update_pathedit( dialog );
msi_dialog_update_directory_list( dialog, NULL );
msi_dialog_update_directory_combo( dialog, NULL );
msi_dialog_update_pathedit( dialog, NULL );
msi_free( path );
msi_free( prop );
@ -2034,13 +2187,60 @@ UINT msi_dialog_directorylist_up( msi_dialog *dialog )
return ERROR_SUCCESS;
}
static UINT msi_dialog_dirlist_handler( msi_dialog *dialog,
msi_control *control, WPARAM param )
{
LPNMHDR nmhdr = (LPNMHDR)param;
WCHAR new_path[MAX_PATH];
WCHAR text[MAX_PATH];
LPWSTR path, prop;
BOOL indirect;
LVITEMW item;
int index;
static const WCHAR backslash[] = {'\\',0};
if (nmhdr->code != LVN_ITEMACTIVATE)
return ERROR_SUCCESS;
index = SendMessageW( control->hwnd, LVM_GETNEXTITEM, -1, LVNI_SELECTED );
if ( index < 0 )
{
ERR("No list-view item selected!\n");
return ERROR_FUNCTION_FAILED;
}
item.iSubItem = 0;
item.pszText = text;
item.cchTextMax = MAX_PATH;
SendMessageW( control->hwnd, LVM_GETITEMTEXTW, index, (LPARAM)&item );
indirect = control->attributes & msidbControlAttributesIndirect;
prop = msi_dialog_dup_property( dialog, control->property, indirect );
path = msi_dup_property( dialog->package, prop );
lstrcpyW( new_path, path );
lstrcatW( new_path, text );
lstrcatW( new_path, backslash );
MSI_SetPropertyW( dialog->package, prop, new_path );
msi_dialog_update_directory_list( dialog, NULL );
msi_dialog_update_directory_combo( dialog, NULL );
msi_dialog_update_pathedit( dialog, NULL );
msi_free( prop );
msi_free( path );
return ERROR_SUCCESS;
}
static UINT msi_dialog_directory_list( msi_dialog *dialog, MSIRECORD *rec )
{
msi_control *control;
LPCWSTR prop;
DWORD style;
style = LVS_LIST | LVS_EDITLABELS | WS_VSCROLL | LVS_SHAREIMAGELISTS |
style = LVS_LIST | WS_VSCROLL | LVS_SHAREIMAGELISTS |
LVS_AUTOARRANGE | LVS_SINGLESEL | WS_BORDER |
LVS_SORTASCENDING | WS_CHILD | WS_GROUP | WS_TABSTOP;
control = msi_dialog_add_control( dialog, rec, WC_LISTVIEWW, style );
@ -2048,14 +2248,86 @@ static UINT msi_dialog_directory_list( msi_dialog *dialog, MSIRECORD *rec )
return ERROR_FUNCTION_FAILED;
control->attributes = MSI_RecordGetInteger( rec, 8 );
control->handler = msi_dialog_dirlist_handler;
prop = MSI_RecordGetString( rec, 9 );
control->property = msi_dialog_dup_property( dialog, prop, FALSE );
/* double click to activate an item in the list */
SendMessageW( control->hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE,
0, LVS_EX_TWOCLICKACTIVATE );
msi_dialog_update_directory_list( dialog, control );
return ERROR_SUCCESS;
}
/******************** VolumeCost List ***************************************/
static BOOL str_is_number( LPCWSTR str )
{
int i;
for (i = 0; i < lstrlenW( str ); i++)
if (!isdigitW(str[i]))
return FALSE;
return TRUE;
}
WCHAR column_keys[][80] =
{
{'V','o','l','u','m','e','C','o','s','t','V','o','l','u','m','e',0},
{'V','o','l','u','m','e','C','o','s','t','S','i','z','e',0},
{'V','o','l','u','m','e','C','o','s','t','A','v','a','i','l','a','b','l','e',0},
{'V','o','l','u','m','e','C','o','s','t','R','e','q','u','i','r','e','d',0},
{'V','o','l','u','m','e','C','o','s','t','D','i','f','f','e','r','e','n','c','e',0}
};
static void msi_dialog_vcl_add_columns( msi_dialog *dialog, msi_control *control, MSIRECORD *rec )
{
LPCWSTR text = MSI_RecordGetString( rec, 10 );
LPCWSTR begin = text, end;
WCHAR num[10];
LVCOLUMNW lvc;
DWORD count = 0;
LRESULT r;
static const WCHAR zero[] = {'0',0};
static const WCHAR negative[] = {'-',0};
while ((begin = strchrW( begin, '{' )) && count < 5)
{
if (!(end = strchrW( begin, '}' )))
return;
lstrcpynW( num, begin + 1, end - begin );
begin += end - begin + 1;
/* empty braces or '0' hides the column */
if ( !num[0] || !lstrcmpW( num, zero ) )
{
count++;
continue;
}
/* the width must be a positive number
* if a width is invalid, all remaining columns are hidden
*/
if ( !strncmpW( num, negative, 1 ) || !str_is_number( num ) )
return;
lvc.mask = LVCF_FMT | LVCF_ORDER | LVCF_WIDTH | LVCF_TEXT;
lvc.iOrder = count;
lvc.pszText = msi_dialog_get_uitext( dialog, column_keys[count++] );
lvc.cx = atolW( num );
lvc.fmt = LVCFMT_LEFT;
r = SendMessageW( control->hwnd, LVM_INSERTCOLUMNW, 0, (LPARAM)&lvc );
msi_free( lvc.pszText );
if ( r ) return;
}
}
static UINT msi_dialog_volumecost_list( msi_dialog *dialog, MSIRECORD *rec )
{
msi_control *control;
@ -2068,6 +2340,8 @@ static UINT msi_dialog_volumecost_list( msi_dialog *dialog, MSIRECORD *rec )
if (!control)
return ERROR_FUNCTION_FAILED;
msi_dialog_vcl_add_columns( dialog, control, rec );
return ERROR_SUCCESS;
}
@ -2292,10 +2566,27 @@ static void msi_dialog_adjust_dialog_pos( msi_dialog *dialog, MSIRECORD *rec, LP
center.y = MulDiv( center.y, yres, 100 );
/* turn the client pos into the window rectangle */
pos->left = center.x - sz.cx/2;
pos->right = pos->left + sz.cx;
pos->top = center.y - sz.cy/2;
pos->bottom = pos->top + sz.cy;
if (dialog->package->center_x && dialog->package->center_y)
{
pos->left = dialog->package->center_x - sz.cx / 2.0;
pos->right = pos->left + sz.cx;
pos->top = dialog->package->center_y - sz.cy / 2.0;
pos->bottom = pos->top + sz.cy;
}
else
{
pos->left = center.x - sz.cx/2;
pos->right = pos->left + sz.cx;
pos->top = center.y - sz.cy/2;
pos->bottom = pos->top + sz.cy;
/* save the center */
dialog->package->center_x = center.x;
dialog->package->center_y = center.y;
}
dialog->size.cx = sz.cx;
dialog->size.cy = sz.cy;
TRACE("%lu %lu %lu %lu\n", pos->left, pos->top, pos->right, pos->bottom);
@ -2609,6 +2900,19 @@ static LRESULT msi_dialog_oncommand( msi_dialog *dialog, WPARAM param, HWND hwnd
return 0;
}
static LRESULT msi_dialog_onnotify( msi_dialog *dialog, LPARAM param )
{
LPNMHDR nmhdr = (LPNMHDR) param;
msi_control *control = msi_dialog_find_control_by_hwnd( dialog, nmhdr->hwndFrom );
TRACE("%p %p", dialog, nmhdr->hwndFrom);
if ( control && control->handler )
control->handler( dialog, control, param );
return 0;
}
static void msi_dialog_setfocus( msi_dialog *dialog )
{
HWND hwnd = dialog->hWndFocus;
@ -2628,6 +2932,11 @@ static LRESULT WINAPI MSIDialog_WndProc( HWND hwnd, UINT msg,
switch (msg)
{
case WM_MOVE:
dialog->package->center_x = LOWORD(lParam) + dialog->size.cx / 2.0;
dialog->package->center_y = HIWORD(lParam) + dialog->size.cy / 2.0;
break;
case WM_CREATE:
return msi_dialog_oncreate( hwnd, (LPCREATESTRUCTW)lParam );
@ -2652,6 +2961,8 @@ static LRESULT WINAPI MSIDialog_WndProc( HWND hwnd, UINT msg,
case WM_DESTROY:
dialog->hwnd = NULL;
return 0;
case WM_NOTIFY:
return msi_dialog_onnotify( dialog, lParam );
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
@ -2861,6 +3172,7 @@ void msi_dialog_destroy( msi_dialog *dialog )
if( t->hIcon )
DestroyIcon( t->hIcon );
msi_free( t->tabnext );
msi_free( t->type );
msi_free( t );
if (t->hDll)
FreeLibrary( t->hDll );

View file

@ -50,19 +50,53 @@ static LPWSTR build_default_format(MSIRECORD* record)
{
int i;
int count;
LPWSTR rc;
static const WCHAR fmt[] = {'%','i',':',' ','[','%','i',']',' ',0};
WCHAR buf[11];
LPWSTR rc, buf;
static const WCHAR fmt[] = {'%','i',':',' ','%','s',' ',0};
static const WCHAR fmt_null[] = {'%','i',':',' ',' ',0};
static const WCHAR fmt_index[] = {'%','i',0};
LPCWSTR str;
WCHAR index[10];
DWORD size, max_len, len;
count = MSI_RecordGetFieldCount(record);
rc = msi_alloc((11*count)*sizeof(WCHAR));
rc[0] = 0;
max_len = MAX_PATH;
buf = msi_alloc((max_len + 1) * sizeof(WCHAR));
rc = NULL;
size = 1;
for (i = 1; i <= count; i++)
{
sprintfW(buf,fmt,i,i);
strcatW(rc,buf);
sprintfW(index,fmt_index,i);
str = MSI_RecordGetString(record, i);
len = (str) ? lstrlenW(str) : 0;
len += (sizeof(fmt_null) - 3) + lstrlenW(index);
size += len;
if (len > max_len)
{
max_len = len;
buf = msi_realloc(buf, (max_len + 1) * sizeof(WCHAR));
if (!buf) return NULL;
}
if (str)
sprintfW(buf,fmt,i,str);
else
sprintfW(buf,fmt_null,i);
if (!rc)
{
rc = msi_alloc(size * sizeof(WCHAR));
lstrcpyW(rc, buf);
}
else
{
rc = msi_realloc(rc, size * sizeof(WCHAR));
lstrcatW(rc, buf);
}
}
msi_free(buf);
return rc;
}
@ -131,8 +165,8 @@ static LPWSTR deformat_file(MSIPACKAGE* package, LPCWSTR key, DWORD* sz,
{
ERR("Unable to get ShortPath size (%s)\n",
debugstr_w( file->TargetPath) );
value = NULL;
*sz = 0;
value = strdupW( file->TargetPath );
*sz = (lstrlenW(value)) * sizeof(WCHAR);
}
}
}

View file

@ -66,7 +66,6 @@ static MSIRECORD *INSERT_merge_record( UINT fields, column_info *vl, MSIRECORD *
{
MSIRECORD *merged;
DWORD wildcard_count = 1, i;
const WCHAR *str;
merged = MSI_CreateRecord( fields );
for( i=1; i <= fields; i++ )
@ -88,10 +87,7 @@ static MSIRECORD *INSERT_merge_record( UINT fields, column_info *vl, MSIRECORD *
case EXPR_WILDCARD:
if( !rec )
goto err;
if( MSI_RecordIsNull( rec, wildcard_count ) )
goto err;
str = MSI_RecordGetString( rec, wildcard_count );
MSI_RecordSetStringW( merged, i, str );
MSI_RecordCopyField( rec, wildcard_count, merged, i );
wildcard_count++;
break;
default:
@ -238,6 +234,14 @@ static const MSIVIEWOPS insert_ops =
INSERT_find_matching_rows
};
static UINT count_column_info( column_info *ci )
{
UINT n = 0;
for ( ; ci; ci = ci->next )
n++;
return n;
}
UINT INSERT_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
column_info *columns, column_info *values, BOOL temp )
{
@ -247,6 +251,10 @@ UINT INSERT_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
TRACE("%p\n", iv );
/* there should be one value for each column */
if ( count_column_info( columns ) != count_column_info(values) )
return ERROR_BAD_QUERY_SYNTAX;
r = TABLE_CreateView( db, table, &tv );
if( r != ERROR_SUCCESS )
return r;
@ -258,7 +266,7 @@ UINT INSERT_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
tv->ops->delete( tv );
return r;
}
iv = msi_alloc_zero( sizeof *iv );
if( !iv )
return ERROR_FUNCTION_FAILED;

View file

@ -364,7 +364,7 @@ static const MSIVIEWOPS join_ops =
*/
static UINT join_check_condition(MSIJOINVIEW *jv, struct expr *cond)
{
UINT r, type = 0;
UINT r;
/* assume that we have `KeyColumn` = `SubkeyColumn` */
if ( cond->type != EXPR_COMPLEX )
@ -388,21 +388,6 @@ static UINT join_check_condition(MSIJOINVIEW *jv, struct expr *cond)
if (r != ERROR_SUCCESS)
return ERROR_FUNCTION_FAILED;
/* make sure both columns are keys */
r = jv->left->ops->get_column_info( jv->left, jv->left_key, NULL, &type );
if (r != ERROR_SUCCESS)
return ERROR_FUNCTION_FAILED;
if (!(type & MSITYPE_KEY))
return ERROR_FUNCTION_FAILED;
r = jv->right->ops->get_column_info( jv->right, jv->right_key, NULL, &type );
if (r != ERROR_SUCCESS)
return ERROR_FUNCTION_FAILED;
if (!(type & MSITYPE_KEY))
return ERROR_FUNCTION_FAILED;
TRACE("left %s (%u) right %s (%u)\n",
debugstr_w(cond->u.expr.left->u.column), jv->left_key,
debugstr_w(cond->u.expr.right->u.column), jv->right_key);

File diff suppressed because it is too large Load diff

View file

@ -231,6 +231,8 @@ typedef struct tagMSIPACKAGE
UINT CurrentInstallState;
msi_dialog *dialog;
LPWSTR next_dialog;
float center_x;
float center_y;
UINT WordCount;
@ -334,8 +336,6 @@ extern const WCHAR *msi_string_lookup_id( string_table *st, UINT id );
extern UINT msi_string_get_codepage( string_table *st );
extern UINT VIEW_find_column( MSIVIEW *view, LPCWSTR name, UINT *n );
extern BOOL TABLE_Exists( MSIDATABASE *db, LPWSTR name );
extern UINT read_raw_stream_data( MSIDATABASE*, LPCWSTR stname,
@ -371,6 +371,7 @@ extern UINT MSI_RecordSetStreamW( MSIRECORD *, unsigned int, LPCWSTR );
extern UINT MSI_RecordSetStreamA( MSIRECORD *, unsigned int, LPCSTR );
extern UINT MSI_RecordDataSize( MSIRECORD *, unsigned int );
extern UINT MSI_RecordStreamToFile( MSIRECORD *, unsigned int, LPCWSTR );
extern UINT MSI_RecordCopyField( MSIRECORD *, unsigned int, MSIRECORD *, unsigned int );
/* stream internals */
extern UINT get_raw_stream( MSIHANDLE hdb, LPCWSTR stname, IStream **stm );
@ -392,6 +393,9 @@ extern UINT MSI_DatabaseGetPrimaryKeys( MSIDATABASE *, LPCWSTR, MSIRECORD ** );
extern UINT MSI_ViewExecute( MSIQUERY*, MSIRECORD * );
extern UINT MSI_ViewFetch( MSIQUERY*, MSIRECORD ** );
extern UINT MSI_ViewClose( MSIQUERY* );
extern UINT MSI_ViewGetColumnInfo(MSIQUERY *, MSICOLINFO, MSIRECORD **);
extern UINT VIEW_find_column( MSIVIEW *, LPCWSTR, UINT * );
/* install internals */
extern UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel );

View file

@ -480,48 +480,28 @@ static UINT msi_set_record_type_string( MSIRECORD *rec, UINT field, UINT type )
return MSI_RecordSetStringW( rec, field, szType );
}
UINT WINAPI MsiViewGetColumnInfo(MSIHANDLE hView, MSICOLINFO info, MSIHANDLE *hRec)
UINT MSI_ViewGetColumnInfo( MSIQUERY *query, MSICOLINFO info, MSIRECORD **prec )
{
MSIVIEW *view = NULL;
MSIQUERY *query = NULL;
MSIRECORD *rec = NULL;
UINT r = ERROR_FUNCTION_FAILED, i, count = 0, type;
MSIRECORD *rec;
MSIVIEW *view = query->view;
LPWSTR name;
TRACE("%ld %d %p\n", hView, info, hRec);
if( !hRec )
return ERROR_INVALID_PARAMETER;
if( info != MSICOLINFO_NAMES && info != MSICOLINFO_TYPES )
return ERROR_INVALID_PARAMETER;
query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
if( !query )
return ERROR_INVALID_HANDLE;
view = query->view;
if( !view )
goto out;
return ERROR_FUNCTION_FAILED;
if( !view->ops->get_dimensions )
goto out;
return ERROR_FUNCTION_FAILED;
r = view->ops->get_dimensions( view, NULL, &count );
if( r )
goto out;
if( r != ERROR_SUCCESS )
return r;
if( !count )
{
r = ERROR_INVALID_PARAMETER;
goto out;
}
return ERROR_INVALID_PARAMETER;
rec = MSI_CreateRecord( count );
if( !rec )
{
r = ERROR_FUNCTION_FAILED;
goto out;
}
return ERROR_FUNCTION_FAILED;
for( i=0; i<count; i++ )
{
@ -536,14 +516,38 @@ UINT WINAPI MsiViewGetColumnInfo(MSIHANDLE hView, MSICOLINFO info, MSIHANDLE *hR
msi_free( name );
}
*hRec = alloc_msihandle( &rec->hdr );
if (! *hRec)
r = ERROR_NOT_ENOUGH_MEMORY;
*prec = rec;
return ERROR_SUCCESS;
}
out:
msiobj_release( &query->hdr );
if( rec )
UINT WINAPI MsiViewGetColumnInfo(MSIHANDLE hView, MSICOLINFO info, MSIHANDLE *hRec)
{
MSIQUERY *query = NULL;
MSIRECORD *rec = NULL;
UINT r;
TRACE("%ld %d %p\n", hView, info, hRec);
if( !hRec )
return ERROR_INVALID_PARAMETER;
if( info != MSICOLINFO_NAMES && info != MSICOLINFO_TYPES )
return ERROR_INVALID_PARAMETER;
query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
if( !query )
return ERROR_INVALID_HANDLE;
r = MSI_ViewGetColumnInfo( query, info, &rec );
if ( r == ERROR_SUCCESS )
{
*hRec = alloc_msihandle( &rec->hdr );
if ( !*hRec )
r = ERROR_NOT_ENOUGH_MEMORY;
msiobj_release( &rec->hdr );
}
msiobj_release( &query->hdr );
return r;
}

View file

@ -43,7 +43,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(msidb);
#define MSIFIELD_NULL 0
#define MSIFIELD_INT 1
#define MSIFIELD_STR 2
#define MSIFIELD_WSTR 3
#define MSIFIELD_STREAM 4
@ -154,6 +153,53 @@ static BOOL string2intW( LPCWSTR str, int *out )
return TRUE;
}
UINT MSI_RecordCopyField( MSIRECORD *in_rec, unsigned int in_n,
MSIRECORD *out_rec, unsigned int out_n )
{
UINT r = ERROR_SUCCESS;
msiobj_lock( &in_rec->hdr );
if ( in_n > in_rec->count || out_n > out_rec->count )
r = ERROR_FUNCTION_FAILED;
else if ( in_rec != out_rec || in_n != out_n )
{
LPWSTR str;
MSIFIELD *in, *out;
in = &in_rec->fields[in_n];
out = &out_rec->fields[out_n];
switch ( in->type )
{
case MSIFIELD_NULL:
break;
case MSIFIELD_INT:
out->u.iVal = in->u.iVal;
break;
case MSIFIELD_WSTR:
str = strdupW( in->u.szwVal );
if ( !str )
r = ERROR_OUTOFMEMORY;
else
out->u.szwVal = str;
break;
case MSIFIELD_STREAM:
IStream_AddRef( in->u.stream );
out->u.stream = in->u.stream;
break;
default:
ERR("invalid field type %d\n", in->type);
}
if (r == ERROR_SUCCESS)
out->type = in->type;
}
msiobj_unlock( &in_rec->hdr );
return r;
}
int MSI_RecordGetInteger( MSIRECORD *rec, unsigned int iField)
{
int ret = 0;

View file

@ -102,13 +102,34 @@ static UINT SELECT_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT va
static UINT SELECT_insert_row( struct tagMSIVIEW *view, MSIRECORD *record )
{
MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
UINT i, table_cols, r;
MSIRECORD *outrec;
TRACE("%p %p\n", sv, record );
if( !sv->table )
return ERROR_FUNCTION_FAILED;
if ( !sv->table )
return ERROR_FUNCTION_FAILED;
return sv->table->ops->insert_row( sv->table, record );
/* rearrange the record to suit the table */
r = sv->table->ops->get_dimensions( sv->table, NULL, &table_cols );
if (r != ERROR_SUCCESS)
return r;
outrec = MSI_CreateRecord( table_cols + 1 );
for (i=0; i<sv->num_cols; i++)
{
r = MSI_RecordCopyField( record, i+1, outrec, sv->cols[i] );
if (r != ERROR_SUCCESS)
goto fail;
}
r = sv->table->ops->insert_row( sv->table, outrec );
fail:
msiobj_release( &outrec->hdr );
return r;
}
static UINT SELECT_execute( struct tagMSIVIEW *view, MSIRECORD *record )

View file

@ -108,7 +108,7 @@ static struct expr * EXPR_wildcard( void *info );
%token TK_ROW TK_RP TK_RSHIFT
%token TK_SELECT TK_SEMI TK_SET TK_SHORT TK_SLASH TK_SPACE TK_STAR TK_STATEMENT
%token <str> TK_STRING
%token TK_TABLE TK_TEMP TK_THEN TK_TRANSACTION TK_TRIGGER
%token TK_TABLE TK_TEMPORARY TK_THEN TK_TRANSACTION TK_TRIGGER
%token TK_UMINUS TK_UNCLOSED_STRING TK_UNION TK_UNIQUE
%token TK_UPDATE TK_UPLUS TK_USING
%token TK_VACUUM TK_VALUES TK_VIEW
@ -171,7 +171,7 @@ oneinsert:
YYABORT;
$$ = insert;
}
| TK_INSERT TK_INTO table TK_LP selcollist TK_RP TK_VALUES TK_LP constlist TK_RP TK_TEMP
| TK_INSERT TK_INTO table TK_LP selcollist TK_RP TK_VALUES TK_LP constlist TK_RP TK_TEMPORARY
{
SQL_input *sql = (SQL_input*) info;
MSIVIEW *insert = NULL;
@ -304,6 +304,10 @@ column_type:
{
$$ = $1 | MSITYPE_LOCALIZABLE;
}
| data_type_l TK_TEMPORARY
{
FIXME("temporary column\n");
}
;
data_type_l:

View file

@ -37,7 +37,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(msidb);
#define HASH_SIZE 67
#define HASH_SIZE 0x101
typedef struct _msistring
{

View file

@ -926,20 +926,7 @@ static void msi_free_colinfo( MSICOLUMNINFO *colinfo, UINT count )
LPWSTR MSI_makestring( MSIDATABASE *db, UINT stringid)
{
UINT sz=0, r;
LPWSTR str;
r = msi_id2stringW( db->strings, stringid, NULL, &sz );
if( r != ERROR_SUCCESS )
return NULL;
str = msi_alloc( sz*sizeof (WCHAR) );
if( !str )
return str;
r = msi_id2stringW( db->strings, stringid, str, &sz );
if( r == ERROR_SUCCESS )
return str;
msi_free( str );
return NULL;
return strdupW(msi_string_lookup_id( db->strings, stringid ));
}
static UINT get_tablecolumns( MSIDATABASE *db,
@ -1116,7 +1103,7 @@ static UINT TABLE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, ISt
{
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
UINT ival = 0, refcol = 0, r;
LPWSTR sval;
LPCWSTR sval;
LPWSTR full_name;
DWORD len;
static const WCHAR szDot[] = { '.', 0 };
@ -1140,7 +1127,7 @@ static UINT TABLE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, ISt
return r;
/* lookup the string value from the string table */
sval = MSI_makestring( tv->db, refcol );
sval = msi_string_lookup_id( tv->db->strings, refcol );
if( !sval )
return ERROR_INVALID_PARAMETER;
@ -1154,7 +1141,6 @@ static UINT TABLE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, ISt
if( r )
ERR("fetching stream %s, error = %d\n",debugstr_w(full_name), r);
msi_free( full_name );
msi_free( sval );
return r;
}
@ -1302,12 +1288,38 @@ static UINT msi_table_find_row( MSITABLEVIEW *tv, MSIRECORD *rec, UINT *row );
static UINT table_validate_new( MSITABLEVIEW *tv, MSIRECORD *rec )
{
UINT r, row;
UINT r, row, i;
/* check there's no null values where they're not allowed */
for( i = 0; i < tv->num_cols; i++ )
{
if ( tv->columns[i].type & MSITYPE_NULLABLE )
continue;
if ( tv->columns[i].type & MSITYPE_STRING )
{
LPCWSTR str;
str = MSI_RecordGetString( rec, i+1 );
if (str == NULL || str[0] == 0)
return ERROR_INVALID_DATA;
}
else
{
UINT n;
n = MSI_RecordGetInteger( rec, i+1 );
if (n == MSI_NULL_INTEGER)
return ERROR_INVALID_DATA;
}
}
/* check there's no duplicate keys */
r = msi_table_find_row( tv, rec, &row );
if (r != ERROR_SUCCESS)
return ERROR_SUCCESS;
return ERROR_INVALID_DATA;
if (r == ERROR_SUCCESS)
return ERROR_INVALID_DATA;
return ERROR_SUCCESS;
}
static UINT msi_table_modify_row( MSITABLEVIEW *tv, MSIRECORD *rec,
@ -1352,6 +1364,11 @@ static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec )
TRACE("%p %p\n", tv, rec );
/* check that the key is unique - can we find a matching row? */
r = table_validate_new( tv, rec );
if( r != ERROR_SUCCESS )
return ERROR_FUNCTION_FAILED;
r = table_create_new_row( view, &row );
TRACE("insert_row returned %08x\n", r);
if( r != ERROR_SUCCESS )

View file

@ -39,6 +39,8 @@ struct Keyword {
int tokenType; /* The token value for this keyword */
};
#define MAX_TOKEN_LEN 11
static const WCHAR ABORT_W[] = { 'A','B','O','R','T',0 };
static const WCHAR AFTER_W[] = { 'A','F','T','E','R',0 };
static const WCHAR ALTER_W[] = { 'A','L','T','E','R',0 };
@ -245,8 +247,7 @@ static const Keyword aKeywordTable[] = {
{ SHORT_W, TK_SHORT },
{ STATEMENT_W, TK_STATEMENT },
{ TABLE_W, TK_TABLE },
{ TEMP_W, TK_TEMP },
{ TEMPORARY_W, TK_TEMP },
/*{ TEMPORARY_W, TK_TEMPORARY },*/
{ THEN_W, TK_THEN },
{ TRANSACTION_W, TK_TRANSACTION },
{ TRIGGER_W, TK_TRIGGER },
@ -263,21 +264,34 @@ static const Keyword aKeywordTable[] = {
#define KEYWORD_COUNT ( sizeof aKeywordTable/sizeof (Keyword) )
/*
** Comparison function for binary search.
*/
static int compKeyword(const void *m1, const void *m2){
const Keyword *k1 = m1, *k2 = m2;
return strcmpiW( k1->zName, k2->zName );
}
/*
** This function looks up an identifier to determine if it is a
** keyword. If it is a keyword, the token code of that keyword is
** returned. If the input is not a keyword, TK_ID is returned.
*/
static int sqliteKeywordCode(const WCHAR *z, int n){
UINT i;
WCHAR str[MAX_TOKEN_LEN+1];
Keyword key, *r;
for(i=0; i<KEYWORD_COUNT; i++)
{
if(strncmpiW(z, aKeywordTable[i].zName, n))
continue;
if(lstrlenW(aKeywordTable[i].zName) == n )
return aKeywordTable[i].tokenType;
}
if( n>MAX_TOKEN_LEN )
return TK_ID;
memcpy( str, z, n*sizeof (WCHAR) );
str[n] = 0;
key.tokenType = 0;
key.zName = str;
r = bsearch( &key, aKeywordTable, KEYWORD_COUNT, sizeof (Keyword), compKeyword );
if( r )
return r->tokenType;
return TK_ID;
}