MSI query tool
Mike McCormack
mike at codeweavers.com
Wed Aug 6 09:55:01 CDT 2003
Hi,
This is program can be used to test the MSI patch in my previous post.
It's probably not clean enough to add to wine at the moment.
Sample queries:
SELECT * FROM _Columns WHERE Table = 'InstallExecuteSequence'
SELECT * FROM _Columns
SELECT * FROM InstallExecuteSequence ORDER BY Sequence
SELECT DISTINCT Number FROM _Columns WHERE Number <> 3
have fun,
Mike
-------------- next part --------------
#include "config.h"
#include <windows.h>
#include <shlwapi.h>
#include <stdio.h>
#include <string.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <msi.h>
#include <msiquery.h>
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(msiquery);
#define E( X ) case X: return #X;
static const char *error_to_string( UINT error )
{
switch( error )
{
E(ERROR_SUCCESS)
E(ERROR_BAD_QUERY_SYNTAX)
E(ERROR_FUNCTION_FAILED)
E(ERROR_INVALID_PARAMETER)
E(ERROR_CALL_NOT_IMPLEMENTED)
E(ERROR_NO_MORE_ITEMS)
E(ERROR_INVALID_HANDLE)
default:
return "UNKNOWN ERROR";
}
}
static UINT enum_tables( MSIHANDLE hdb, LPSTR query )
{
UINT res, i, count;
MSIHANDLE htable = 0;
fprintf(stderr,"Enumerating tables:\n");
res = MsiDatabaseOpenViewA(hdb, query, &htable);
if( res == ERROR_SUCCESS )
{
CHAR buffer[0x100];
MSIHANDLE hrec = 0;
DWORD sz,n=0;
res = MsiViewExecute(htable, 0);
if( res != ERROR_SUCCESS )
fprintf(stderr,"failed %d (%s)\n", res, error_to_string(res));
while( 1 )
{
res = MsiViewFetch(htable, &hrec);
if( res != ERROR_SUCCESS )
break;
fprintf(stderr,"row %2d : ",n++);
count = MsiRecordGetFieldCount( hrec );
for( i=1; i<=count; i++ )
{
if( MsiRecordIsNull( hrec, i ) )
{
strcpy( buffer, "nil" );
}
else
{
sz = sizeof buffer;
buffer[0]=0;
res = MsiRecordGetStringA(hrec, i, buffer, &sz);
if( res != ERROR_SUCCESS )
break;
buffer[sz]=0;
}
fprintf(stderr,"%s%s",buffer,(i==count)?"\n":" , ");
}
MsiCloseHandle( hrec );
}
res = MsiViewClose(htable);
if( res != ERROR_SUCCESS )
fprintf(stderr,"failed to close view %d (%s)\n",
res, error_to_string(res));
res = MsiCloseHandle( htable );
if( res != ERROR_SUCCESS )
fprintf(stderr,"failed to close view handle %d (%s)\n",
res, error_to_string(res));
}
else
fprintf(stderr,"query failed %d (%s)\n", res, error_to_string(res));
return res;
}
static char * init_hist( void )
{
char *hist_path , *hist = "msiquery_history", *home;
int len;
using_history();
home = getenv("HOME");
len = strlen( home ) + strlen( hist ) + 2;
hist_path = malloc( len );
if( !hist_path )
return;
sprintf( hist_path, "%s/%s", home, hist );
read_history( hist_path );
return hist_path;
}
int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show)
{
LPSTR szFilename = cmdline;
UINT res;
char *test = NULL, *hist;
int len = 100;
MSIHANDLE hdb = 0;
hist = init_hist();
if( cmdline && *cmdline )
{
res = MsiOpenDatabaseA(cmdline, MSIDBOPEN_READONLY, &hdb);
if( res != ERROR_SUCCESS )
printf("Error %d\n", res);
else
printf("OK\n", res);
}
while( 1 )
{
if( test )
free( test );
test = NULL;
test = readline("SQL> ");
if( !test )
break;
add_history( test );
len = strlen(test);
if(len && test[len-1]=='\n')
test[--len] = 0;
if( !strcmp( test, "quit") )
{
if( hdb )
MsiCloseHandle(hdb);
printf("Bye.\n", res );
break;
}
if( !strncmp( test, "keys ", 5) )
{
MSIHANDLE hrec = 0;
UINT count, i;
DWORD sz;
char buffer[0x40];
if( hdb )
{
res = MsiDatabaseGetPrimaryKeysA( hdb, &test[5], &hrec );
if( res == ERROR_SUCCESS )
{
count = MsiRecordGetFieldCount( hrec );
for( i=1; i<=count; i++ )
{
sz = sizeof buffer;
buffer[0]=0;
res = MsiRecordGetStringA(hrec, i, buffer, &sz);
if( res != ERROR_SUCCESS )
break;
buffer[sz]=0;
printf("Key %d : %s\n", buffer);
}
}
else
fprintf(stderr,"MsiDatabaseGetPrimaryKeysA "
"failed %d (%s)\n", res, error_to_string( res ) );
}
else
printf("No database available.\n", res );
continue;
}
if( !strncmp( test, "open ", 5) )
{
printf("Opening database %s... ");
res = MsiOpenDatabaseA(&test[5], MSIDBOPEN_READONLY, &hdb);
if( res != ERROR_SUCCESS )
printf("Error %d\n", res);
else
printf("OK\n", res);
continue;
}
if( !strcmp( test, "close") )
{
if( !hdb )
{
printf("no current database\n", res);
continue;
}
res = MsiCloseHandle(hdb);
hdb = 0;
printf("result %d\n", res );
continue;
}
res = enum_tables( hdb, test );
printf("result %d\n", res );
continue;
}
if( hist )
{
write_history( hist );
free( hist );
}
return 0;
}
-------------- next part --------------
name msiquery.exe
type win32
mode cuiexe
init main
import gdi32.dll
import kernel32.dll
import ntdll.dll
import user32.dll
-------------- next part --------------
### Generated by Winemaker
### Generic autoconf variables
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../..
SRCDIR = @srcdir@
VPATH = @srcdir@
SUBDIRS =
DLLS =
EXES = msiquery.exe
### Global settings
DEFINES =
EXTRAINCL = $(WINE_INCLUDE_PATH)
DLL_PATH =
LIBRARY_PATH =
LIBRARIES =
### msiquery sources and settings
msiquery_C_SRCS = msiquery.c
msiquery_CXX_SRCS =
msiquery_RC_SRCS =
msiquery_SPEC_SRCS =
msiquery_DLL_PATH =
msiquery_LIBRARY_PATH =
msiquery_LIBRARIES = readline history termcap
msiquery_IMPORTS = ole32 advapi32 kernel32 user32 gdi32 msi
msiquery_DEPENDS =
msiquery_OBJS = $(msiquery_C_SRCS:.c=.o) \
msiquery.exe.dbg.o \
$(msiquery_CXX_SRCS:.cpp=.o) \
$(EXTRA_OBJS)
### Global source lists
C_SRCS = $(msiquery_C_SRCS)
CXX_SRCS = $(msiquery_CXX_SRCS)
RC_SRCS = $(msiquery_RC_SRCS)
SPEC_SRCS = $(msiquery_SPEC_SRCS)
### Generic autoconf targets
all: $(SUBDIRS) $(DLLS) $(EXES:%=%.so)
@MAKE_RULES@
install:: $(SUBDIRS:%=%/__install__)
install-image:: $(SUBDIRS:%=%/__install-image__)
install install-image:: $(EXES:%=%.so) dummy
$(MKINSTALLDIRS) $(dlldir)
_list="$(DLLS) $(EXES:%=%.so)"; for i in $$_list; do $(INSTALL_PROGRAM) $$i $(dlldir)/$$i; done
uninstall:: $(SUBDIRS:%=%/__uninstall__) dummy
$(RM) $(EXES:%=$(dlldir)/%.so) $(DLLS:%=$(dlldir)/%)
### Target specific build rules
msiquery.exe.spec.c: $(msiquery_RC_SRCS:.rc=.res) $(msiquery_OBJS) $(WINEBUILD)
$(LDPATH) $(WINEBUILD) -fPIC $(msiquery_DLL_PATH) $(WINE_DLL_PATH) -o $@ --exe msiquery.exe $(msiquery_OBJS) $(msiquery_RC_SRCS:.rc=.res) $(msiquery_IMPORTS:%=-l%)
msiquery.exe.so: msiquery.exe.spec.o $(msiquery_OBJS) $(msiquery_DEPENDS)
$(LDSHARED) $(LDDLLFLAGS) -o $@ msiquery.exe.spec.o $(msiquery_OBJS) $(msiquery_LIBRARY_PATH) $(msiquery_LIBRARIES:%=-l%) $(DLL_LINK) $(LIBS) $(LIBUUID)
msiquery.exe.dbg.c: $(C_SRCS) $(C_SRCS16) $(WINEBUILD)
$(LDPATH) $(WINEBUILD) $(DEFS) -o $@ --debug -C$(SRCDIR) $(C_SRCS) $(C_SRCS16)
More information about the wine-patches
mailing list