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

Misha Koshelev mk144210 at bcm.tmc.edu
Thu Mar 1 16:09:19 CST 2007


I am resending the entire patchset as James Hawkins suggested. The only
changes from my previous patchset are in patch #2 (add full IDL from
Windows Installer 3.0 vs 2.0 in the old patchset) and patch #3 (added
more proper variant handling using GetDispId as per Rob's suggestion and
removed unnecessary comments as per James' suggestion).

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.

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 23bf248186531b63d36f200ca2744b29c401dd6a Mon Sep 17 00:00:00 2001
From: Misha Koshelev <mk144210 at bcm.tmc.edu>
Date: Wed, 28 Feb 2007 12:07:42 -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 c6c07cf..bc6b7dc 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),
@@ -856,6 +880,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