[1/4 revised] msi: Added handlers for JScript/VBScript actions that call one script function.

Misha Koshelev mk144210 at bcm.tmc.edu
Sun Feb 25 22:41:40 CST 2007


I have revised these patches according to Rob Shearman's comments about
them. Just as a reminder, these patches add JScript/VBScript support for
MSI (as the MSI specs specifically state that applications that need
this functionality must install Windows Script themselves) and partial
but easily expandable OLE automation functionality for MSI. As a proof
of concept, sufficient automation support is added to fix bug #7357, in
which Vector NTI cannot install completely because a JScript expands the
feature list (this is a consistency/conformance check of sorts for
custom actions 5/6&37/38).

Again, as per Rob's comments, each patch now applies cleanly to git and
will compile and pass all tests. Patch #1 creates custom action handlers
for all 8 script custom action types using a framework similar to that
used for calling DLL functions. These custom action handlers all
converge on one function that is passed a script and a function to be
called (if any), and it outputs these in a FIXME. 

Changelog:
	* msi: Added handlers for JScript/VBScript actions that call one script
function.
-------------- next part --------------
From bfde4dd7c028bf9e708d12b92a8e8439cb3358f1 Mon Sep 17 00:00:00 2001
From: Misha Koshelev <mk144210 at bcm.tmc.edu>
Date: Sun, 25 Feb 2007 22:19:22 -0600
Subject: msi: Added handlers for JScript/VBScript actions that call one script function.
---
 dlls/msi/custom.c |  252 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 252 insertions(+), 0 deletions(-)

diff --git a/dlls/msi/custom.c b/dlls/msi/custom.c
index ba5c825..7cbbf40 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,234 @@ 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;
+    }
+
+    FIXME("function %s, script %s\n", debugstr_w( info->function ), debugstr_w( info->dllname ) );
+
+    hPackage = alloc_msihandle( &info->package->hdr );
+    if (hPackage)
+    {
+	r = S_OK;
+        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 script, 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( script );
+    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;
+
+    TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
+    
+    info = do_msidbCustomActionTypeScript( package, type, target, NULL, action );
+
+    return wait_thread_handle( info );
+}
+
+static UINT HANDLE_CustomType5_6(MSIPACKAGE *package, LPCWSTR source,
+                               LPCWSTR target, const INT type, LPCWSTR action)
+{
+    static const WCHAR query[] = {
+        'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+        '`','B','i' ,'n','a','r','y','`',' ','W','H','E','R','E',' ',
+        '`','N','a','m','e','`',' ','=',' ','\'','%','s','\'',0};
+    MSIRECORD *row = 0;
+    msi_custom_action_info *info;
+    CHAR *buffer = NULL;
+    WCHAR *bufferw = NULL;
+    DWORD sz = 0, szw = 0;
+    UINT r;
+
+    TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
+
+    row = MSI_QueryGetRecord(package->db, query, source);
+    if (!row)
+        return ERROR_FUNCTION_FAILED;
+
+    r = MSI_RecordReadStream(row, 2, NULL, &sz);
+    if (r != ERROR_SUCCESS)
+	return r;
+
+    buffer = msi_alloc(sizeof(CHAR)*(sz+1));
+    if (!buffer)
+	return ERROR_FUNCTION_FAILED;
+
+    r = MSI_RecordReadStream(row, 2, buffer, &sz);
+    if (r != ERROR_SUCCESS)
+    {
+	msi_free(buffer);
+	return r;
+    }
+
+    buffer[sz] = 0;
+    szw = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buffer, -1, bufferw, 0);
+    bufferw = msi_alloc(sizeof(WCHAR)*szw);
+    if (!szw)
+    {
+	msi_free(bufferw);
+	return ERROR_FUNCTION_FAILED;
+    }
+
+    r = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buffer, -1, bufferw, szw);
+    msi_free(buffer);    
+    if (!r)
+    {
+	msi_free(bufferw);
+	return ERROR_FUNCTION_FAILED;
+    }
+
+    info = do_msidbCustomActionTypeScript( package, type, bufferw, target, action );
+    msi_free(bufferw);
+    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;
+    HANDLE hFile;
+    DWORD sz, szw, szHighWord = 0, read;
+    CHAR *buffer=NULL;
+    WCHAR *bufferw=NULL;
+    BOOL bRet;
+    UINT r;
+
+    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;
+    }
+ 
+    hFile = CreateFileW(file->TargetPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+    if (hFile == INVALID_HANDLE_VALUE) 
+	return ERROR_FUNCTION_FAILED;
+ 
+    sz = GetFileSize(hFile, &szHighWord);
+    if (sz == INVALID_FILE_SIZE || szHighWord != 0) 
+    {
+	CloseHandle(hFile);
+	return ERROR_FUNCTION_FAILED;
+    }
+ 
+    buffer = msi_alloc(sizeof(CHAR)*(sz+1));
+    if (!buffer) 
+    {
+	CloseHandle(hFile);
+ 	return ERROR_FUNCTION_FAILED;
+    }
+   
+    bRet = ReadFile(hFile, (LPVOID)buffer, sz, &read, NULL);
+    CloseHandle(hFile);
+    if (!bRet);
+    {
+        msi_free(buffer);
+ 	return ERROR_FUNCTION_FAILED;
+    }
+
+    buffer[read] = 0;
+    szw = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buffer, -1, bufferw, 0);
+    bufferw = msi_alloc(sizeof(WCHAR)*szw);
+    if (!szw)
+    {
+	msi_free(bufferw);
+	return ERROR_FUNCTION_FAILED;
+    }
+
+    r = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buffer, -1, bufferw, szw);
+    msi_free(buffer);    
+    if (!r)
+    {
+	msi_free(bufferw);
+	return ERROR_FUNCTION_FAILED;
+    }
+
+    info = do_msidbCustomActionTypeScript( package, type, bufferw, target, action );
+    msi_free(bufferw);
+    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;
+
+    TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
+
+    prop = msi_dup_property(package,source);
+    if (!prop)
+	return ERROR_SUCCESS;
+      
+    info = do_msidbCustomActionTypeScript( package, type, prop, NULL, action );
+    msi_free(prop);
+    return wait_thread_handle( info );
+}
+
 void ACTION_FinishCustomActions(MSIPACKAGE* package)
 {
     struct list *item;
-- 
1.4.1



More information about the wine-patches mailing list