msi: Add full JScript/VBScript support and partial expandable
OLE automation support. [PATCH 3/3]
Misha Koshelev
mk144210 at bcm.tmc.edu
Sun Feb 25 13:14:09 CST 2007
On Sun, 2007-02-25 at 13:00 +0000, Robert Shearman wrote:
> Misha Koshelev wrote:
> > +/* Macros to get pointer to AutomationObject) from the other VTables. */
> >
>
> Typo with extra ")" here.
>
> > +HRESULT WINAPI SessionImpl_Invoke(
> > + AutomationObject* This,
> > + DISPID dispIdMember,
> > + REFIID riid,
> > + LCID lcid,
> > + WORD wFlags,
> > + DISPPARAMS* pDispParams,
> > + VARIANT* pVarResult,
> > + EXCEPINFO* pExcepInfo,
> > + UINT* puArgErr)
> > +{
> > + WCHAR szString[MAX_MSI_STRING];
> > + DWORD dwLen = MAX_MSI_STRING;
> > + IDispatch *iDispatch = NULL;
> > + MSIHANDLE msiHandle;
> > + LANGID langId;
> > + UINT ret;
> > + INSTALLSTATE iInstalled, iAction;
> >
>
> Some error checking here would be good, like you do in
> AutomationObject_Invoke.
>
Well perhaps there is a little confusion here as these functions are
actually always called from _within_ AutomationObject_Invoke, hence the
error checking is already done. I did this as there is quite a few
objects to implement and to save writing the same code over and over I
thought this would be a good idea. Do you think I should rename these
functions to something else so it is more clear that they are not
actually called directly through an IDispatch interface but rather from
an AutomationObject?
> > +
> > + switch (dispIdMember)
> > + {
> >
> ...
> > +/*
> > + * AutomationObject - "base" class for all automation objects so we don't have to repeat functions. Just
> > + * need to implement Invoke function for each dispinterface and pass the new function
> > + * to create_automation_object.
> > + */
> > +
> > +typedef struct {
> > + /*
> > + * VTables - We provide IDispatch, IProvideClassInfo, IProvideClassInfo2, IProvideMultipleClassInfo
> > + */
> > + const IDispatchVtbl *lpVtbl;
> > + const IProvideClassInfoVtbl *lpvtblIProvideClassInfo;
> > + const IProvideClassInfo2Vtbl *lpvtblIProvideClassInfo2;
> > + const IProvideMultipleClassInfoVtbl *lpvtblIProvideMultipleClassInfo;
> > +
> > + /* Object reference count */
> > + LONG ref;
> > +
> > + /* Clsid for this class and it's appropriate ITypeInfo object */
> > + LPCLSID clsid;
> > + ITypeInfo *iTypeInfo;
> > +
> > + /* The MSI handle of the current object */
> > + MSIHANDLE msiHandle;;
> > +
> > + /* A function that is called from IDispatch::Invoke, specific to this type of object */
> > + LPVOID funcInvoke;
> > +} AutomationObject;
> >
>
> You shouldn't need to expose the implementation details of
> AutomationObject outside of automation.c.
>
> > +
> > +/* This is the function that one needs to call to create an automation object. */
> > +extern HRESULT create_automation_object(MSIHANDLE msiHandle, IUnknown *pUnkOuter, LPVOID *ppObj, REFIID clsid, LPVOID funcInvoke);
> >
>
> It is dangerous to use LPVOID as the type to pass a function in.
>
> > +
> > +/* We need to expose these functions because our IActiveScriptSite calls it */
> > +extern HRESULT WINAPI LoadTypeInfo(IDispatch *iface, ITypeInfo **pptinfo, REFIID clsid, LCID lcid);
> > +extern HRESULT WINAPI SessionImpl_Invoke(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
> > +
> > +/* Disp Ids
> > + * (not complete, look in msiserver.idl to add more) */
> > +typedef enum {
> > + RecordDispId_StringData=1,
> > + RecordDispId_IntegerData,
> > + RecordDispId_SetStream,
> > + RecordDispId_ReadStream,
> > + RecordDispId_FieldCount,
> > + RecordDispId_IsNull,
> > + RecordDispId_DataSize,
> > + RecordDispId_ClearData,
> > + RecordDispId_FormatText
> > +} RecordDispId;
> > +
> > +typedef enum {
> > + ViewDispId_Execute=1,
> > + ViewDispId_Fetch,
> > + ViewDispId_Modify,
> > + ViewDispId_Close,
> > + ViewDispId_ColumnInfo,
> > + ViewDispId_GetError
> > +} ViewDispId;
> > +
> > +typedef enum {
> > + DatabaseDispId_DatabaseState=1,
> > + DatabaseDispId_SummaryInformation,
> > + DatabaseDispId_OpenView,
> > + DatabaseDispId_Commit,
> > + DatabaseDispId_PrimaryKeys,
> > + DatabaseDispId_Import,
> > + DatabaseDispId_Export,
> > + DatabaseDispId_Merge,
> > + DatabaseDispId_GenerateTransform,
> > + DatabaseDispId_ApplyTransform,
> > + DatabaseDispId_EnableUIPreview,
> > + DatabaseDispId_TablePersistent,
> > + DatabaseDispId_CreateTransformSummaryInfo
> > +} DatabaseDispId;
> > +
> > +typedef enum {
> > + SessionDispId_Installer=1,
> > + SessionDispId_Property,
> > + SessionDispId_Language,
> > + SessionDispId_Mode,
> > + SessionDispId_Database,
> > + SessionDispId_SourcePath,
> > + SessionDispId_TargetPath,
> > + SessionDispId_DoAction,
> > + SessionDispId_Sequence,
> > + SessionDispId_EvaluateCondition,
> > + SessionDispId_FormatRecord,
> > + SessionDispId_Message,
> > + SessionDispId_FeatureCurrentState,
> > + SessionDispId_FeatureRequestState,
> > + SessionDispId_FeatureValidStates,
> > + SessionDispId_FeatureCost,
> > + SessionDispId_ComponentCurrentState,
> > + SessionDispId_ComponentRequestState,
> > + SessionDispId_SetInstallLevel,
> > + SessionDispId_VerifyDiskSpace,
> > + SessionDispId_ProductProperty,
> > + SessionDispId_FeatureInfo,
> > + SessionDispId_ComponentCost
> > +} SessionDispId;
> >
>
> See dlls/oleaut32/tests/tmarshal_dispids.h and
> dlls/oleaut32/tests/tmarshal.idl for how to use DISPIDs properly.
>
> > +typedef struct {
> > + IActiveScriptSite lpVtbl;
> > + AutomationObject *session;
> >
>
> You don't actually access this as anything other than an IDispatch
> object, so you might as well change to "IDispatch *session".
>
> > +LPCWSTR read_script_from_file(LPCWSTR szFile, INT type)
> >
>
> Should be static.
>
> > +/* JScript or VBScript? */
> > +LPCWSTR progid_from_type(INT type)
> >
>
> Should also be static.
>
> > +
> > +/*
> > + * Call a script. This is our meat and potatoes.
> > + * - Currently, since the function is relatively new, it will always end up returning S_OK.
> > + * Think of it like a bonus feature, we can run the script - great. If we have a problem,
> > + * we are no worse off than if this function had not been called.
> > + */
> > +DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR filename, LPCWSTR function, LPCWSTR action)
> > +{
> > + LPCWSTR script = NULL, progId = NULL;
> > + HRESULT hr;
> > + IActiveScript *iActiveScript = NULL;
> > + IActiveScriptParse *iActiveScriptParse = NULL;
> >
>
> I haven't seen this variable notation style before. In Hungarian
> notation "p" is used instead of "i" to show a pointer to an object
> exposing the interface declared.
>
Other comments sound good, I will make appropriate changes. I think I
will make patch 2 the scripting functions with a dummy call_script that
just does a TRACE, and then patch 3 will apply automation and scripting.
Misha
More information about the wine-devel
mailing list