MSI query tool

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




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

#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;
}

name    msiquery.exe
type    win32
mode    cuiexe
init    main

import gdi32.dll
import kernel32.dll
import ntdll.dll
import user32.dll

### 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)


[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux