Working on JScript/VBScript support for MSI

Misha Koshelev mk144210 at bcm.tmc.edu
Mon Feb 19 17:42:38 CST 2007


Hi, since MSDN states that any installer that requires JScript/VBScript
must make sure to install it, and since some applications require these
for install (bug #7353 and another one is there for VBScript for a
different installer), I figure there is no reason why builtin MSI cannot
use Microsoft Script if it is there (and plus when we have our own
JScript/VBScript we will be able to use it off the bat with MSI). 

I have posted my initial work on this on the bugzilla for bug #7353. The
first file (a patch, will attach also) is my patch which updates
custom.c to have the appropriate handlers for the custom action types,
extracts the script from the appropriate place, writes it to a file, and
uses a framework very similar to the current thread framework for DLLs
to call my helper call_script function. This first patch, in theory,
should not have to change much (if at all), although I have not
thoroughly tested it yet so it probably will. 

The second file (and attached here too) is dlls/msi/script.c, which is
where the meat and potatoes of the actual call_script function is/will
be. Right now it is pretty barebones, but it does load the script from
the file and calls it appropriately.

Now I am working on implementing the Session object, although it looks
like a wrapper around MSI functions we already have so I think it should
be doable.

Anyways, any comments on my work so far will be appreciated.

Misha
-------------- next part --------------
From 027366c3e742f8368522bbc85f1bdf1483c64721 Mon Sep 17 00:00:00 2001
From: Misha Koshelev <mk144210 at bcm.tmc.edu>
Date: Mon, 19 Feb 2007 17:29:15 -0600
Subject: msi: Added initial JScript/VBScript support functions.
---
 dlls/msi/Makefile.in |    1 
 dlls/msi/custom.c    |  217 ++++++++++++++++++++++++++++++++++++++++++++++++++
 dlls/msi/msipriv.h   |    1 
 3 files changed, 219 insertions(+), 0 deletions(-)

diff --git a/dlls/msi/Makefile.in b/dlls/msi/Makefile.in
index 5fb0941..3f6fd87 100644
--- a/dlls/msi/Makefile.in
+++ b/dlls/msi/Makefile.in
@@ -37,6 +37,7 @@ C_SRCS = \
 	record.c \
 	registry.c \
 	regsvr.c \
+	script.c \
 	select.c \
 	source.c \
 	string.c \
diff --git a/dlls/msi/custom.c b/dlls/msi/custom.c
index ba5c825..8b5401e 100644
--- a/dlls/msi/custom.c
+++ b/dlls/msi/custom.c
@@ -58,6 +58,14 @@ static UINT HANDLE_CustomType50(MSIPACKA
                                 LPCWSTR target, const INT type, LPCWSTR action);
 static UINT HANDLE_CustomType34(MSIPACKAGE *package, LPCWSTR source,
                                 LPCWSTR target, const INT type, LPCWSTR action);
+static UINT HANDLE_CustomType37_38(MSIPACKAGE *package, LPCWSTR source,
+                                LPCWSTR target, const INT type, LPCWSTR action);
+static UINT HANDLE_CustomType5_6(MSIPACKAGE *package, LPCWSTR source,
+                                LPCWSTR target, const INT type, LPCWSTR action);
+static UINT HANDLE_CustomType21_22(MSIPACKAGE *package, LPCWSTR source,
+                                LPCWSTR target, const INT type, LPCWSTR action);
+static UINT HANDLE_CustomType53_54(MSIPACKAGE *package, LPCWSTR source,
+                                LPCWSTR target, const INT type, LPCWSTR action);
 
 typedef UINT (WINAPI *MsiCustomActionEntryPoint)( MSIHANDLE );
 
@@ -266,6 +274,22 @@ UINT ACTION_CustomAction(MSIPACKAGE *pac
             rc = MSI_SetPropertyW(package,source,deformated);
             msi_free(deformated);
             break;
+	case 37: /* JScript/VBScript text stored in target column. */
+	case 38:
+	    rc = HANDLE_CustomType37_38(package,source,target,type,action);
+	    break;
+	case 5:
+	case 6: /* JScript/VBScript file stored in a Binary table stream. */
+	    rc = HANDLE_CustomType5_6(package,source,target,type,action);
+	    break;
+	case 21: /* JScript/VBScript file installed with the product. */
+	case 22:
+	    rc = HANDLE_CustomType21_22(package,source,target,type,action);
+	    break;
+	case 53: /* JScript/VBScript text specified by a property value. */
+	case 54:
+	    rc = HANDLE_CustomType53_54(package,source,target,type,action);
+	    break;
         default:
             FIXME("UNHANDLED ACTION TYPE %i (%s %s)\n",
              type & CUSTOM_ACTION_TYPE_MASK, debugstr_w(source),
@@ -855,6 +879,199 @@ static UINT HANDLE_CustomType34(MSIPACKA
     return wait_process_handle(package, type, info.hProcess, action);
 }
 
+static DWORD WINAPI ACTION_CallScript( const LPGUID guid )
+{
+    msi_custom_action_info *info;
+    MSIHANDLE hPackage;
+    UINT r = ERROR_FUNCTION_FAILED;
+
+    info = find_action_by_guid( guid );
+    if (!info)
+    {
+        ERR("failed to find action %s\n", debugstr_guid( guid) );
+        return r;
+    }
+
+    TRACE("%s %s\n", debugstr_w( info->dllname ), debugstr_w( info->function ) );
+
+    hPackage = alloc_msihandle( &info->package->hdr );
+    if (hPackage)
+    {
+	TRACE("calling %s\n", debugstr_w( info->function ) );
+	r = call_script( info->package, info->type, info->dllname, info->function, info->action);
+        MsiCloseHandle( hPackage );
+    }
+    else
+        ERR("failed to create handle for %p\n", info->package );
+
+    return r;
+}
+
+static DWORD WINAPI ScriptThread( LPVOID arg )
+{
+    LPGUID guid = arg;
+    DWORD rc = 0;
+
+    TRACE("custom action (%x) started\n", GetCurrentThreadId() );
+
+    rc = ACTION_CallScript( guid );
+
+    TRACE("custom action (%x) returned %i\n", GetCurrentThreadId(), rc );
+
+    MsiCloseAllHandles();
+    return rc;
+}
+
+static msi_custom_action_info *do_msidbCustomActionTypeScript(
+    MSIPACKAGE *package, INT type, LPCWSTR dllname, LPCWSTR function, LPCWSTR action )
+{
+    msi_custom_action_info *info;
+
+    info = msi_alloc( sizeof *info );
+    if (!info)
+        return NULL;
+
+    msiobj_addref( &package->hdr );
+    info->package = package;
+    info->type = type;
+    info->function = strdupW( function );
+    info->dllname = strdupW( dllname );
+    info->action = strdupW( action );
+    CoCreateGuid( &info->guid );
+
+    EnterCriticalSection( &msi_custom_action_cs );
+    list_add_tail( &msi_pending_custom_actions, &info->entry );
+    LeaveCriticalSection( &msi_custom_action_cs );
+
+    info->handle = CreateThread( NULL, 0, ScriptThread, &info->guid, 0, NULL );
+    if (!info->handle)
+    {
+        free_custom_action_data( info );
+        return NULL;
+    }
+
+    return info;
+}
+
+static UINT HANDLE_CustomType37_38(MSIPACKAGE *package, LPCWSTR source,
+                               LPCWSTR target, const INT type, LPCWSTR action)
+{
+    msi_custom_action_info *info;
+    WCHAR tmp_file[MAX_PATH];
+    WCHAR fmt[MAX_PATH];
+    static const WCHAR f1[] = {'m','s','i',0};
+    HANDLE file;
+    DWORD sz, write;
+
+    TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
+  
+    if (MSI_GetPropertyW(package, cszTempFolder, fmt, &sz) != ERROR_SUCCESS)
+        GetTempPathW(MAX_PATH, fmt);
+
+    if (GetTempFileNameW(fmt, f1, 0, tmp_file) == 0)
+    {
+        TRACE("Unable to create file\n");
+        return ERROR_FUNCTION_FAILED;
+    }
+    track_tempfile(package, tmp_file);
+
+    /* Write out script from target field to file (a little roundabout but makes script code simpler) */
+    file = CreateFileW(tmp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
+                       FILE_ATTRIBUTE_NORMAL, NULL);
+    if (file == INVALID_HANDLE_VALUE)
+        return ERROR_FUNCTION_FAILED;
+    else
+    {
+	WriteFile(file, target, sizeof(WCHAR)*strlenW(target), &write, NULL);
+        CloseHandle(file);
+    }
+    
+    info = do_msidbCustomActionTypeScript( package, type, tmp_file, NULL, action );
+
+    return wait_thread_handle( info );
+}
+
+static UINT HANDLE_CustomType5_6(MSIPACKAGE *package, LPCWSTR source,
+                               LPCWSTR target, const INT type, LPCWSTR action)
+{
+    msi_custom_action_info *info;
+    WCHAR tmp_file[MAX_PATH];
+    UINT r;
+
+    TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
+
+    r = store_binary_to_temp(package, source, tmp_file);
+    if (r != ERROR_SUCCESS)
+	return r;
+
+    info = do_msidbCustomActionTypeScript( package, type, tmp_file, target, action );
+
+    return wait_thread_handle( info );
+}
+
+static UINT HANDLE_CustomType21_22(MSIPACKAGE *package, LPCWSTR source,
+                               LPCWSTR target, const INT type, LPCWSTR action)
+{
+    msi_custom_action_info *info;
+    MSIFILE *file;
+
+    TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
+
+    file = get_loaded_file(package,source);
+    if (!file)
+    {
+	ERR("invalid file key %s\n", debugstr_w(source));
+	return ERROR_FUNCTION_FAILED;
+    }
+
+    info = do_msidbCustomActionTypeScript( package, type, file->TargetPath, target, action );
+
+    return wait_thread_handle( info );
+}
+
+static UINT HANDLE_CustomType53_54(MSIPACKAGE *package, LPCWSTR source,
+                               LPCWSTR target, const INT type, LPCWSTR action)
+{
+    msi_custom_action_info *info;
+    WCHAR *prop;
+    WCHAR tmp_file[MAX_PATH];
+    WCHAR fmt[MAX_PATH];
+    static const WCHAR f1[] = {'m','s','i',0};
+    HANDLE file;
+    DWORD sz, write;
+
+    TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
+
+    prop = msi_dup_property(package,source);
+    if (!prop)
+	return ERROR_SUCCESS;
+      
+    if (MSI_GetPropertyW(package, cszTempFolder, fmt, &sz) != ERROR_SUCCESS)
+        GetTempPathW(MAX_PATH, fmt);
+
+    if (GetTempFileNameW(fmt, f1, 0, tmp_file) == 0)
+    {
+        TRACE("Unable to create file\n");
+        return ERROR_FUNCTION_FAILED;
+    }
+    track_tempfile(package, tmp_file);
+
+    /* Write out script from target field to file (a little roundabout but makes script code simpler) */
+    file = CreateFileW(tmp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
+                       FILE_ATTRIBUTE_NORMAL, NULL);
+    if (file == INVALID_HANDLE_VALUE)
+        return ERROR_FUNCTION_FAILED;
+    else
+    {
+	WriteFile(file, prop, sizeof(WCHAR)*strlenW(prop), &write, NULL);
+        CloseHandle(file);
+    }
+    
+    info = do_msidbCustomActionTypeScript( package, type, tmp_file, NULL, action );
+
+    return wait_thread_handle( info );
+}
+
 void ACTION_FinishCustomActions(MSIPACKAGE* package)
 {
     struct list *item;
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index b01bb27..b00dc11 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -750,6 +750,7 @@ extern UINT ACTION_RegisterMIMEInfo(MSIP
 extern UINT ACTION_RegisterFonts(MSIPACKAGE *package);
 
 /* Helpers */
+extern DWORD call_script(MSIPACKAGE *package, INT type, LPCWSTR filename, LPCWSTR function, LPCWSTR action);
 extern DWORD deformat_string(MSIPACKAGE *package, LPCWSTR ptr, WCHAR** data );
 extern LPWSTR msi_dup_record_field(MSIRECORD *row, INT index);
 extern LPWSTR msi_dup_property(MSIPACKAGE *package, LPCWSTR prop);
-- 
1.4.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: script.c
Type: text/x-csrc
Size: 10887 bytes
Desc: not available
Url : http://www.winehq.org/pipermail/wine-devel/attachments/20070219/073f522f/script-0001.c


More information about the wine-devel mailing list