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
From 027366c3e742f8368522bbc85f1bdf1483c64721 Mon Sep 17 00:00:00 2001
From: Misha Koshelev <[EMAIL PROTECTED]>
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

/*
 * Implementation of scripting for Microsoft Installer (msi.dll)
 *
 * Copyright 2007 Misha Koshelev
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#define COBJMACROS

#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winuser.h"
#include "msidefs.h"
#include "msipriv.h"
#include "activscp.h"
#include "oleauto.h"
#include "wine/debug.h"
#include "wine/unicode.h"

WINE_DEFAULT_DEBUG_CHANNEL(msi);

const WCHAR szJScript[] = { 'J','S','c','r','i','p','t',0};
const WCHAR szVBScript[] = { 'V','B','S','c','r','i','p','t',0};

typedef struct {
    IActiveScriptSite lpVtbl;
    LONG ref;
} IMSIActiveScriptSite;

static const struct IActiveScriptSiteVtbl ASS_Vtbl;

static HRESULT ASS_create(IUnknown *pUnkOuter, LPVOID *ppObj)
{
    IMSIActiveScriptSite* object; 

    TRACE("(%p,%p)\n", pUnkOuter, ppObj);

    if( pUnkOuter )
        return CLASS_E_NOAGGREGATION;

    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IMSIActiveScriptSite));

    object->lpVtbl.lpVtbl = &ASS_Vtbl;
    object->ref = 1;

    *ppObj = object;

    return S_OK;
}

/*
 * Helper functions to run scripts 
 */

LPCWSTR read_script_from_file(LPCWSTR szFile)
{
    HANDLE hFile;
    DWORD sz, szHighWord = 0, read;
    WCHAR *script;

    hFile = CreateFileW(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
    if (hFile == INVALID_HANDLE_VALUE) 
	return NULL;

    sz = GetFileSize(hFile, &szHighWord);
    if (sz == INVALID_FILE_SIZE || szHighWord != 0) 
	return NULL;

    script = msi_alloc(sizeof(CHAR)*sz);
    if (!script) 
	return NULL;
  
    if (!ReadFile(hFile, (LPVOID)script, sz, &read, NULL)) 
    {
	msi_free(script);
	return NULL;
    }

    return script;
}

/* JScript or VBScript? */
LPCWSTR progid_from_type(INT type)
{
    if (type & msidbCustomActionTypeJScript) return szJScript;
    else if (type & msidbCustomActionTypeVBScript) return szVBScript;
  
    ERR("Unknown script type %d\n", type);
    return NULL;
}

/**
 * Call a script. This is our meat and potatoes. 
 */
DWORD call_script(MSIPACKAGE *package, INT type, LPCWSTR filename, LPCWSTR function, LPCWSTR action)
{
    LPCWSTR script = NULL;
    HRESULT hr;
    IActiveScript *iActiveScript = NULL;
    IActiveScriptParse *iActiveScriptParse = NULL;
    IActiveScriptSite *iMSIActiveScriptSite = NULL;
    IDispatch *iDispatch = NULL;
    DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
    DISPID dispid;
    CLSID clsid;
    VARIANT var;

    /* Return success by default (e.g., if Windows Script not installed) - not native behavior */
    DWORD ret = ERROR_SUCCESS;    

    CoInitialize(NULL);

    /* Create IMSIActiveScriptSite object */
    hr = ASS_create(NULL, (void **)&iMSIActiveScriptSite);
    if (hr != S_OK) goto done;

    /* Create the scripting engine */
    hr = CLSIDFromProgID(progid_from_type(type), &clsid);
    if (FAILED(hr)) goto done;
    hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IActiveScript, (void **)&iActiveScript);
    if (FAILED(hr)) goto done;

    /* If we got this far, Windows Script is installed, so don't return success by default anymore */
    ret = ERROR_FUNCTION_FAILED;

    /* Try to load the script file */
    script = read_script_from_file(filename);
    if (!script) goto done;

    /* Get the IActiveScriptParse engine interface */
    hr = IActiveScript_QueryInterface(iActiveScript, &IID_IActiveScriptParse, (void **)&iActiveScriptParse);
    if (FAILED(hr)) goto done;

    /* Give our host to the engine */
    hr = IActiveScript_SetScriptSite(iActiveScript, iMSIActiveScriptSite);
    if (FAILED(hr)) goto done;

    /* Initialize the script engine */
    hr = IActiveScriptParse_InitNew(iActiveScriptParse);
    if (FAILED(hr)) goto done;

    /* Pass the script to the engine */
    hr = IActiveScriptParse_ParseScriptText(iActiveScriptParse, script, NULL, NULL, NULL, 0, 0, 0L, NULL, NULL);
    if (FAILED(hr)) goto done;

    /* Start processing the script */
    hr = IActiveScript_SetScriptState(iActiveScript, SCRIPTSTATE_CONNECTED);
    if (FAILED(hr)) goto done;

    /* Call a function if necessary through the IDispatch interface */
    if (function != NULL && strlenW(function) > 0) {
	TRACE("Calling function %s", debugstr_w(function));

	hr = IActiveScript_GetScriptDispatch(iActiveScript, NULL, &iDispatch);
	if (FAILED(hr)) goto done; 

	hr = IDispatch_GetIDsOfNames(iDispatch, &IID_NULL, (WCHAR **)&function, 1,LOCALE_USER_DEFAULT, &dispid);
	if (FAILED(hr)) goto done;
  
	hr = IDispatch_Invoke(iDispatch, dispid, &IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparamsNoArgs, &var, NULL, NULL);
	if (FAILED(hr)) goto done;

	/* Check return value, if it's not IDOK we failed */
	hr = VariantChangeType(&var, &var, 0, VT_I4);
	if (FAILED(hr)) goto done;
	
	if (V_I4(&var) == IDOK) 
	    ret = ERROR_SUCCESS;
	else ret = ERROR_FUNCTION_FAILED;

	VariantClear(&var);
    } else {
	/* If no function to be called, MSI behavior is to succeed */
	ret = ERROR_SUCCESS;
    }

done:

    /* Free everything that needs to be freed */
    if (iDispatch) IDispatch_Release(iDispatch);
    if (iActiveScript) IActiveScript_Release(iActiveScript);
    if (iMSIActiveScriptSite) IActiveScriptSite_Release(iMSIActiveScriptSite);
    if (script) msi_free((WCHAR *)script);

    CoUninitialize();    /* must call even if CoInitialize failed */

    return ret;
}

/*** IUnknown methods ***/
static HRESULT WINAPI IMSIActiveScriptSite_QueryInterface(IActiveScriptSite* iface, REFIID riid, void** ppvObject)
{
    IMSIActiveScriptSite *This = (IMSIActiveScriptSite *)iface;

    FIXME("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);

    if (IsEqualGUID(riid, &IID_IUnknown) ||
        IsEqualGUID(riid, &IID_IActiveScriptSite))
    {
        IClassFactory_AddRef(iface);
        *ppvObject = This;
        return S_OK;
    }

    ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);

    return E_NOINTERFACE;
}

static ULONG WINAPI IMSIActiveScriptSite_AddRef(IActiveScriptSite* iface)
{
    IMSIActiveScriptSite *This = (IMSIActiveScriptSite *)iface;

    TRACE("(%p/%p)\n", iface, This);

    return InterlockedIncrement(&This->ref);
}

static ULONG WINAPI IMSIActiveScriptSite_Release(IActiveScriptSite* iface)
{
    IMSIActiveScriptSite *This = (IMSIActiveScriptSite *)iface;
    ULONG ref = InterlockedDecrement(&This->ref);

    TRACE("(%p/%p)\n", iface, This);

    if (!ref)
        HeapFree(GetProcessHeap(), 0, This);

    return ref;
}

/*** IActiveScriptSite methods **/
static HRESULT WINAPI IMSIActiveScriptSite_GetLCID(IActiveScriptSite* iface, LCID* plcid)
{
    IMSIActiveScriptSite *This = (IMSIActiveScriptSite *)iface;   
    FIXME("(%p/%p)->(%p) stub!\n", This, iface, plcid);
    return E_NOTIMPL;
}

static HRESULT WINAPI IMSIActiveScriptSite_GetItemInfo(IActiveScriptSite* iface, LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown** ppiunkItem, ITypeInfo** ppti)
{
    IMSIActiveScriptSite *This = (IMSIActiveScriptSite *)iface;
    FIXME("(%p/%p)->(%p,%d,%p,%p) stub!\n", This, iface, pstrName, dwReturnMask, ppiunkItem, ppti);
    return TYPE_E_ELEMENTNOTFOUND;
}

static HRESULT WINAPI IMSIActiveScriptSite_GetDocVersionString(IActiveScriptSite* iface, BSTR* pbstrVersion)
{
    IMSIActiveScriptSite *This = (IMSIActiveScriptSite *)iface;
    FIXME("(%p/%p)->(%p) stub\n", This, iface, pbstrVersion);
    return E_NOTIMPL;
}

static HRESULT WINAPI IMSIActiveScriptSite_OnScriptTerminate(IActiveScriptSite* iface, const VARIANT* pvarResult, const EXCEPINFO* pexcepinfo)
{
    IMSIActiveScriptSite *This = (IMSIActiveScriptSite *)iface;
    FIXME("(%p/%p)->(%p,%p) stub\n", This, iface, pvarResult, pexcepinfo);
    return S_OK;
}

static HRESULT WINAPI IMSIActiveScriptSite_OnStateChange(IActiveScriptSite* iface, SCRIPTSTATE ssScriptState)
{
    switch (ssScriptState) {
	case SCRIPTSTATE_UNINITIALIZED:
	      TRACE("State: Uninitialized.\n");
	      break;

	case SCRIPTSTATE_INITIALIZED:
	      TRACE("State: Initialized.\n");
	      break;

	case SCRIPTSTATE_STARTED:
	      TRACE("State: Started.\n");
	      break;

	case SCRIPTSTATE_CONNECTED:
	      TRACE("State: Connected.\n");
	      break;

	case SCRIPTSTATE_DISCONNECTED:
	      TRACE("State: Disconnected.\n");
	      break;

	case SCRIPTSTATE_CLOSED:
	      TRACE("State: Closed.\n");
	      break;

	default:
	      ERR("Unknown State: %d\n", ssScriptState);
	      break;
    }
  
    return S_OK;
}

static HRESULT WINAPI IMSIActiveScriptSite_OnScriptError(IActiveScriptSite* iface, IActiveScriptError* pscripterror)
{
    IMSIActiveScriptSite *This = (IMSIActiveScriptSite *)iface;
    EXCEPINFO exception;
    HRESULT hr;

    TRACE("(%p/%p)->(%p)\n", This, iface, pscripterror);
    hr = IActiveScriptError_GetExceptionInfo(pscripterror, &exception);
    if (SUCCEEDED(hr))
	ERR("script error: %s", debugstr_w(exception.bstrDescription));

    return S_OK;
}

static HRESULT WINAPI IMSIActiveScriptSite_OnEnterScript(IActiveScriptSite* iface)
{
    IMSIActiveScriptSite *This = (IMSIActiveScriptSite *)iface;
    FIXME("(%p/%p) stub\n", This, iface);
    return S_OK;
}

static HRESULT WINAPI IMSIActiveScriptSite_OnLeaveScript(IActiveScriptSite* iface)
{
    IMSIActiveScriptSite *This = (IMSIActiveScriptSite *)iface;
    FIXME("(%p/%p) stub\n", This, iface);
    return S_OK;
}

static const struct IActiveScriptSiteVtbl ASS_Vtbl = 
{
    IMSIActiveScriptSite_QueryInterface,
    IMSIActiveScriptSite_AddRef,
    IMSIActiveScriptSite_Release,
    IMSIActiveScriptSite_GetLCID,
    IMSIActiveScriptSite_GetItemInfo,
    IMSIActiveScriptSite_GetDocVersionString,
    IMSIActiveScriptSite_OnScriptTerminate,
    IMSIActiveScriptSite_OnStateChange,
    IMSIActiveScriptSite_OnScriptError,
    IMSIActiveScriptSite_OnEnterScript,
    IMSIActiveScriptSite_OnLeaveScript    
};


Reply via email to