Commit e726b54c authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

msi: Cache ITypeInfo instances for automation objects instead of reloading every time.

parent 55f0663e
...@@ -42,6 +42,71 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi); ...@@ -42,6 +42,71 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
#define REG_INDEX_CLASSES_ROOT 0 #define REG_INDEX_CLASSES_ROOT 0
#define REG_INDEX_DYN_DATA 6 #define REG_INDEX_DYN_DATA 6
static REFIID tid_ids[] = {
&DIID_Database,
&DIID_Installer,
&DIID_Record,
&DIID_Session,
&DIID_StringList,
&DIID_SummaryInfo,
&DIID_View
};
static ITypeLib *typelib;
static ITypeInfo *typeinfos[LAST_tid];
HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo)
{
HRESULT hr;
if (!typelib)
{
ITypeLib *lib;
hr = LoadRegTypeLib(&LIBID_WindowsInstaller, 1, 0, LOCALE_NEUTRAL, &lib);
if (FAILED(hr)) {
static const WCHAR msiserverW[] = {'m','s','i','s','e','r','v','e','r','.','t','l','b',0};
hr = LoadTypeLib(msiserverW, &lib);
if (FAILED(hr)) {
ERR("Could not load msiserver.tlb\n");
return hr;
}
}
if (InterlockedCompareExchangePointer((void**)&typelib, lib, NULL))
ITypeLib_Release(lib);
}
if (!typeinfos[tid])
{
ITypeInfo *ti;
hr = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti);
if (FAILED(hr)) {
ERR("Could not load ITypeInfo for %s\n", debugstr_guid(tid_ids[tid]));
return hr;
}
if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
ITypeInfo_Release(ti);
}
*typeinfo = typeinfos[tid];
return S_OK;
}
void release_typelib(void)
{
unsigned i;
for (i = 0; i < sizeof(typeinfos)/sizeof(*typeinfos); i++)
if (typeinfos[i])
ITypeInfo_Release(typeinfos[i]);
if (typelib)
ITypeLib_Release(typelib);
}
/* /*
* AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function * AutomationObject - "base" class for all automation objects. For each interface, we implement Invoke function
* called from AutomationObject::Invoke. * called from AutomationObject::Invoke.
...@@ -60,9 +125,8 @@ struct AutomationObject { ...@@ -60,9 +125,8 @@ struct AutomationObject {
IProvideMultipleClassInfo IProvideMultipleClassInfo_iface; IProvideMultipleClassInfo IProvideMultipleClassInfo_iface;
LONG ref; LONG ref;
/* Clsid for this class and it's appropriate ITypeInfo object */ /* type id for this class */
LPCLSID clsid; tid_t tid;
ITypeInfo *iTypeInfo;
/* The MSI handle of the current object */ /* The MSI handle of the current object */
MSIHANDLE msiHandle; MSIHANDLE msiHandle;
...@@ -110,37 +174,6 @@ static inline AutomationObject *impl_from_IDispatch( IDispatch *iface ) ...@@ -110,37 +174,6 @@ static inline AutomationObject *impl_from_IDispatch( IDispatch *iface )
return CONTAINING_RECORD(iface, AutomationObject, IDispatch_iface); return CONTAINING_RECORD(iface, AutomationObject, IDispatch_iface);
} }
/* Load type info so we don't have to process GetIDsOfNames */
HRESULT load_type_info(IDispatch *iface, ITypeInfo **pptinfo, REFIID clsid, LCID lcid)
{
static const WCHAR msiserverW[] = {'m','s','i','s','e','r','v','e','r','.','t','l','b',0};
ITypeInfo *ti = NULL;
ITypeLib *lib = NULL;
HRESULT hr;
TRACE("(%p)->(%s, %d)\n", iface, debugstr_guid(clsid), lcid);
/* Load registered type library */
hr = LoadRegTypeLib(&LIBID_WindowsInstaller, 1, 0, lcid, &lib);
if (FAILED(hr)) {
hr = LoadTypeLib(msiserverW, &lib);
if (FAILED(hr)) {
ERR("Could not load msiserver.tlb\n");
return hr;
}
}
/* Get type information for object */
hr = ITypeLib_GetTypeInfoOfGuid(lib, clsid, &ti);
ITypeLib_Release(lib);
if (FAILED(hr)) {
ERR("Could not load ITypeInfo for %s\n", debugstr_guid(clsid));
return hr;
}
*pptinfo = ti;
return S_OK;
}
/* AutomationObject methods */ /* AutomationObject methods */
static HRESULT WINAPI AutomationObject_QueryInterface(IDispatch* iface, REFIID riid, void** ppvObject) static HRESULT WINAPI AutomationObject_QueryInterface(IDispatch* iface, REFIID riid, void** ppvObject)
{ {
...@@ -155,7 +188,7 @@ static HRESULT WINAPI AutomationObject_QueryInterface(IDispatch* iface, REFIID r ...@@ -155,7 +188,7 @@ static HRESULT WINAPI AutomationObject_QueryInterface(IDispatch* iface, REFIID r
if (IsEqualGUID(riid, &IID_IUnknown) || if (IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_IDispatch) || IsEqualGUID(riid, &IID_IDispatch) ||
IsEqualGUID(riid, This->clsid)) IsEqualGUID(riid, tid_ids[This->tid]))
*ppvObject = &This->IDispatch_iface; *ppvObject = &This->IDispatch_iface;
else if (IsEqualGUID(riid, &IID_IProvideClassInfo) || else if (IsEqualGUID(riid, &IID_IProvideClassInfo) ||
IsEqualGUID(riid, &IID_IProvideClassInfo2) || IsEqualGUID(riid, &IID_IProvideClassInfo2) ||
...@@ -191,7 +224,6 @@ static ULONG WINAPI AutomationObject_Release(IDispatch* iface) ...@@ -191,7 +224,6 @@ static ULONG WINAPI AutomationObject_Release(IDispatch* iface)
if (!ref) if (!ref)
{ {
if (This->funcFree) This->funcFree(This); if (This->funcFree) This->funcFree(This);
ITypeInfo_Release(This->iTypeInfo);
MsiCloseHandle(This->msiHandle); MsiCloseHandle(This->msiHandle);
msi_free(This); msi_free(This);
} }
...@@ -217,11 +249,16 @@ static HRESULT WINAPI AutomationObject_GetTypeInfo( ...@@ -217,11 +249,16 @@ static HRESULT WINAPI AutomationObject_GetTypeInfo(
ITypeInfo** ppTInfo) ITypeInfo** ppTInfo)
{ {
AutomationObject *This = impl_from_IDispatch(iface); AutomationObject *This = impl_from_IDispatch(iface);
HRESULT hr;
TRACE("(%p/%p)->(%d,%d,%p)\n", iface, This, iTInfo, lcid, ppTInfo); TRACE("(%p/%p)->(%d,%d,%p)\n", iface, This, iTInfo, lcid, ppTInfo);
ITypeInfo_AddRef(This->iTypeInfo); hr = get_typeinfo(This->tid, ppTInfo);
*ppTInfo = This->iTypeInfo; if (FAILED(hr))
return S_OK; return hr;
ITypeInfo_AddRef(*ppTInfo);
return hr;
} }
static HRESULT WINAPI AutomationObject_GetIDsOfNames( static HRESULT WINAPI AutomationObject_GetIDsOfNames(
...@@ -233,18 +270,25 @@ static HRESULT WINAPI AutomationObject_GetIDsOfNames( ...@@ -233,18 +270,25 @@ static HRESULT WINAPI AutomationObject_GetIDsOfNames(
DISPID* rgDispId) DISPID* rgDispId)
{ {
AutomationObject *This = impl_from_IDispatch(iface); AutomationObject *This = impl_from_IDispatch(iface);
ITypeInfo *ti;
HRESULT hr; HRESULT hr;
TRACE("(%p/%p)->(%p,%p,%d,%d,%p)\n", iface, This, riid, rgszNames, cNames, lcid, rgDispId); TRACE("(%p/%p)->(%p,%p,%d,%d,%p)\n", iface, This, riid, rgszNames, cNames, lcid, rgDispId);
if (!IsEqualGUID(riid, &IID_NULL)) return E_INVALIDARG; if (!IsEqualGUID(riid, &IID_NULL)) return E_INVALIDARG;
hr = ITypeInfo_GetIDsOfNames(This->iTypeInfo, rgszNames, cNames, rgDispId);
hr = get_typeinfo(This->tid, &ti);
if (FAILED(hr))
return hr;
hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
if (hr == DISP_E_UNKNOWNNAME) if (hr == DISP_E_UNKNOWNNAME)
{ {
UINT idx; UINT idx;
for (idx=0; idx<cNames; idx++) for (idx=0; idx<cNames; idx++)
{ {
if (rgDispId[idx] == DISPID_UNKNOWN) if (rgDispId[idx] == DISPID_UNKNOWN)
FIXME("Unknown member %s, clsid %s\n", debugstr_w(rgszNames[idx]), debugstr_guid(This->clsid)); FIXME("Unknown member %s, clsid %s\n", debugstr_w(rgszNames[idx]), debugstr_guid(tid_ids[This->tid]));
} }
} }
return hr; return hr;
...@@ -270,6 +314,7 @@ static HRESULT WINAPI AutomationObject_Invoke( ...@@ -270,6 +314,7 @@ static HRESULT WINAPI AutomationObject_Invoke(
unsigned int uArgErr; unsigned int uArgErr;
VARIANT varResultDummy; VARIANT varResultDummy;
BSTR bstrName = NULL; BSTR bstrName = NULL;
ITypeInfo *ti;
TRACE("(%p/%p)->(%d,%p,%d,%d,%p,%p,%p,%p)\n", iface, This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); TRACE("(%p/%p)->(%d,%p,%d,%d,%p,%p,%p,%p)\n", iface, This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
...@@ -289,21 +334,25 @@ static HRESULT WINAPI AutomationObject_Invoke( ...@@ -289,21 +334,25 @@ static HRESULT WINAPI AutomationObject_Invoke(
if (puArgErr == NULL) puArgErr = &uArgErr; if (puArgErr == NULL) puArgErr = &uArgErr;
if (pVarResult == NULL) pVarResult = &varResultDummy; if (pVarResult == NULL) pVarResult = &varResultDummy;
hr = get_typeinfo(This->tid, &ti);
if (FAILED(hr))
return hr;
/* Assume return type is void unless determined otherwise */ /* Assume return type is void unless determined otherwise */
VariantInit(pVarResult); VariantInit(pVarResult);
/* If we are tracing, we want to see the name of the member we are invoking */ /* If we are tracing, we want to see the name of the member we are invoking */
if (TRACE_ON(msi)) if (TRACE_ON(msi))
{ {
ITypeInfo_GetDocumentation(This->iTypeInfo, dispIdMember, &bstrName, NULL, NULL, NULL); ITypeInfo_GetDocumentation(ti, dispIdMember, &bstrName, NULL, NULL, NULL);
TRACE("Method %d, %s\n", dispIdMember, debugstr_w(bstrName)); TRACE("Method %d, %s\n", dispIdMember, debugstr_w(bstrName));
} }
hr = This->funcInvoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr); hr = This->funcInvoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
if (hr == DISP_E_MEMBERNOTFOUND) { if (hr == DISP_E_MEMBERNOTFOUND) {
if (bstrName == NULL) ITypeInfo_GetDocumentation(This->iTypeInfo, dispIdMember, &bstrName, NULL, NULL, NULL); if (bstrName == NULL) ITypeInfo_GetDocumentation(ti, dispIdMember, &bstrName, NULL, NULL, NULL);
FIXME("Method %d, %s wflags %d not implemented, clsid %s\n", dispIdMember, debugstr_w(bstrName), wFlags, debugstr_guid(This->clsid)); FIXME("Method %d, %s wflags %d not implemented, clsid %s\n", dispIdMember, debugstr_w(bstrName), wFlags, debugstr_guid(tid_ids[This->tid]));
} }
else if (pExcepInfo && else if (pExcepInfo &&
(hr == DISP_E_PARAMNOTFOUND || (hr == DISP_E_PARAMNOTFOUND ||
...@@ -315,7 +364,7 @@ static HRESULT WINAPI AutomationObject_Invoke( ...@@ -315,7 +364,7 @@ static HRESULT WINAPI AutomationObject_Invoke(
unsigned namesNo, i; unsigned namesNo, i;
BOOL bFirst = TRUE; BOOL bFirst = TRUE;
if (FAILED(ITypeInfo_GetNames(This->iTypeInfo, dispIdMember, bstrParamNames, if (FAILED(ITypeInfo_GetNames(ti, dispIdMember, bstrParamNames,
MAX_FUNC_PARAMS, &namesNo))) MAX_FUNC_PARAMS, &namesNo)))
{ {
TRACE("Failed to retrieve names for dispIdMember %d\n", dispIdMember); TRACE("Failed to retrieve names for dispIdMember %d\n", dispIdMember);
...@@ -391,8 +440,15 @@ static ULONG WINAPI ProvideMultipleClassInfo_Release(IProvideMultipleClassInfo* ...@@ -391,8 +440,15 @@ static ULONG WINAPI ProvideMultipleClassInfo_Release(IProvideMultipleClassInfo*
static HRESULT WINAPI ProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo* iface, ITypeInfo** ppTI) static HRESULT WINAPI ProvideMultipleClassInfo_GetClassInfo(IProvideMultipleClassInfo* iface, ITypeInfo** ppTI)
{ {
AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface); AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
HRESULT hr;
TRACE("(%p/%p)->(%p)\n", iface, This, ppTI); TRACE("(%p/%p)->(%p)\n", iface, This, ppTI);
return load_type_info(&This->IDispatch_iface, ppTI, This->clsid, 0);
hr = get_typeinfo(This->tid, ppTI);
if (SUCCEEDED(hr))
ITypeInfo_AddRef(*ppTI);
return hr;
} }
static HRESULT WINAPI ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo* iface, DWORD dwGuidKind, GUID* pGUID) static HRESULT WINAPI ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo* iface, DWORD dwGuidKind, GUID* pGUID)
...@@ -403,7 +459,7 @@ static HRESULT WINAPI ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo ...@@ -403,7 +459,7 @@ static HRESULT WINAPI ProvideMultipleClassInfo_GetGUID(IProvideMultipleClassInfo
if (dwGuidKind != GUIDKIND_DEFAULT_SOURCE_DISP_IID) if (dwGuidKind != GUIDKIND_DEFAULT_SOURCE_DISP_IID)
return E_INVALIDARG; return E_INVALIDARG;
else { else {
*pGUID = *This->clsid; *pGUID = *tid_ids[This->tid];
return S_OK; return S_OK;
} }
} }
...@@ -420,7 +476,7 @@ static HRESULT WINAPI ProvideMultipleClassInfo_GetMultiTypeInfoCount(IProvideMul ...@@ -420,7 +476,7 @@ static HRESULT WINAPI ProvideMultipleClassInfo_GetMultiTypeInfoCount(IProvideMul
static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo* iface, static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleClassInfo* iface,
ULONG iti, ULONG iti,
DWORD dwFlags, DWORD dwFlags,
ITypeInfo** pptiCoClass, ITypeInfo** ti,
DWORD* pdwTIFlags, DWORD* pdwTIFlags,
ULONG* pcdispidReserved, ULONG* pcdispidReserved,
IID* piidPrimary, IID* piidPrimary,
...@@ -428,13 +484,19 @@ static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleCl ...@@ -428,13 +484,19 @@ static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleCl
{ {
AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface); AutomationObject *This = impl_from_IProvideMultipleClassInfo(iface);
TRACE("(%p/%p)->(%d,%d,%p,%p,%p,%p,%p)\n", iface, This, iti, dwFlags, pptiCoClass, pdwTIFlags, pcdispidReserved, piidPrimary, piidSource); TRACE("(%p/%p)->(%d,%d,%p,%p,%p,%p,%p)\n", iface, This, iti, dwFlags, ti, pdwTIFlags, pcdispidReserved, piidPrimary, piidSource);
if (iti != 0) if (iti != 0)
return E_INVALIDARG; return E_INVALIDARG;
if (dwFlags & MULTICLASSINFO_GETTYPEINFO) if (dwFlags & MULTICLASSINFO_GETTYPEINFO)
load_type_info(&This->IDispatch_iface, pptiCoClass, This->clsid, 0); {
HRESULT hr = get_typeinfo(This->tid, ti);
if (FAILED(hr))
return hr;
ITypeInfo_AddRef(*ti);
}
if (dwFlags & MULTICLASSINFO_GETNUMRESERVEDDISPIDS) if (dwFlags & MULTICLASSINFO_GETNUMRESERVEDDISPIDS)
{ {
...@@ -442,13 +504,11 @@ static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleCl ...@@ -442,13 +504,11 @@ static HRESULT WINAPI ProvideMultipleClassInfo_GetInfoOfIndex(IProvideMultipleCl
*pcdispidReserved = 0; *pcdispidReserved = 0;
} }
if (dwFlags & MULTICLASSINFO_GETIIDPRIMARY){ if (dwFlags & MULTICLASSINFO_GETIIDPRIMARY)
*piidPrimary = *This->clsid; *piidPrimary = *tid_ids[This->tid];
}
if (dwFlags & MULTICLASSINFO_GETIIDSOURCE){ if (dwFlags & MULTICLASSINFO_GETIIDSOURCE)
*piidSource = *This->clsid; *piidSource = *tid_ids[This->tid];
}
return S_OK; return S_OK;
} }
...@@ -464,23 +524,21 @@ static const IProvideMultipleClassInfoVtbl ProvideMultipleClassInfoVtbl = ...@@ -464,23 +524,21 @@ static const IProvideMultipleClassInfoVtbl ProvideMultipleClassInfoVtbl =
ProvideMultipleClassInfo_GetInfoOfIndex ProvideMultipleClassInfo_GetInfoOfIndex
}; };
static HRESULT init_automation_object(AutomationObject *This, MSIHANDLE msiHandle, REFIID clsid, static HRESULT init_automation_object(AutomationObject *This, MSIHANDLE msiHandle, tid_t tid,
autoInvokeFunc invokeFunc, autoFreeFunc freeFunc) autoInvokeFunc invokeFunc, autoFreeFunc freeFunc)
{ {
TRACE("(%p, %d, %s, %p, %p)\n", This, msiHandle, debugstr_guid(clsid), invokeFunc, freeFunc); TRACE("(%p, %d, %s, %p, %p)\n", This, msiHandle, debugstr_guid(tid_ids[tid]), invokeFunc, freeFunc);
This->IDispatch_iface.lpVtbl = &AutomationObjectVtbl; This->IDispatch_iface.lpVtbl = &AutomationObjectVtbl;
This->IProvideMultipleClassInfo_iface.lpVtbl = &ProvideMultipleClassInfoVtbl; This->IProvideMultipleClassInfo_iface.lpVtbl = &ProvideMultipleClassInfoVtbl;
This->ref = 1; This->ref = 1;
This->msiHandle = msiHandle; This->msiHandle = msiHandle;
This->clsid = (LPCLSID)clsid; This->tid = tid;
This->funcInvoke = invokeFunc; This->funcInvoke = invokeFunc;
This->funcFree = freeFunc; This->funcFree = freeFunc;
/* Load our TypeInfo so we don't have to process GetIDsOfNames */ return S_OK;
This->iTypeInfo = NULL;
return load_type_info(&This->IDispatch_iface, &This->iTypeInfo, clsid, 0);
} }
/* /*
...@@ -933,7 +991,7 @@ static HRESULT create_record(MSIHANDLE msiHandle, IDispatch **disp) ...@@ -933,7 +991,7 @@ static HRESULT create_record(MSIHANDLE msiHandle, IDispatch **disp)
record = msi_alloc(sizeof(*record)); record = msi_alloc(sizeof(*record));
if (!record) return E_OUTOFMEMORY; if (!record) return E_OUTOFMEMORY;
hr = init_automation_object(record, msiHandle, &DIID_Record, RecordImpl_Invoke, NULL); hr = init_automation_object(record, msiHandle, Record_tid, RecordImpl_Invoke, NULL);
if (hr != S_OK) if (hr != S_OK)
{ {
msi_free(record); msi_free(record);
...@@ -1049,7 +1107,7 @@ static HRESULT create_list(const WCHAR *product, IDispatch **dispatch) ...@@ -1049,7 +1107,7 @@ static HRESULT create_list(const WCHAR *product, IDispatch **dispatch)
list = msi_alloc_zero(sizeof(ListObject)); list = msi_alloc_zero(sizeof(ListObject));
if (!list) return E_OUTOFMEMORY; if (!list) return E_OUTOFMEMORY;
hr = init_automation_object(&list->autoobj, 0, &DIID_StringList, ListImpl_Invoke, ListImpl_Free); hr = init_automation_object(&list->autoobj, 0, StringList_tid, ListImpl_Invoke, ListImpl_Free);
if (hr != S_OK) if (hr != S_OK)
{ {
msi_free(list); msi_free(list);
...@@ -2363,7 +2421,7 @@ HRESULT create_msiserver(IUnknown *outer, void **ppObj) ...@@ -2363,7 +2421,7 @@ HRESULT create_msiserver(IUnknown *outer, void **ppObj)
installer = msi_alloc(sizeof(AutomationObject)); installer = msi_alloc(sizeof(AutomationObject));
if (!installer) return E_OUTOFMEMORY; if (!installer) return E_OUTOFMEMORY;
hr = init_automation_object(installer, 0, &DIID_Installer, InstallerImpl_Invoke, NULL); hr = init_automation_object(installer, 0, Installer_tid, InstallerImpl_Invoke, NULL);
if (hr != S_OK) if (hr != S_OK)
{ {
msi_free(installer); msi_free(installer);
...@@ -2383,7 +2441,7 @@ HRESULT create_session(MSIHANDLE msiHandle, IDispatch *installer, IDispatch **di ...@@ -2383,7 +2441,7 @@ HRESULT create_session(MSIHANDLE msiHandle, IDispatch *installer, IDispatch **di
session = msi_alloc(sizeof(SessionObject)); session = msi_alloc(sizeof(SessionObject));
if (!session) return E_OUTOFMEMORY; if (!session) return E_OUTOFMEMORY;
hr = init_automation_object(&session->autoobj, msiHandle, &DIID_Session, SessionImpl_Invoke, NULL); hr = init_automation_object(&session->autoobj, msiHandle, Session_tid, SessionImpl_Invoke, NULL);
if (hr != S_OK) if (hr != S_OK)
{ {
msi_free(session); msi_free(session);
...@@ -2406,7 +2464,7 @@ static HRESULT create_database(MSIHANDLE msiHandle, IDispatch **dispatch) ...@@ -2406,7 +2464,7 @@ static HRESULT create_database(MSIHANDLE msiHandle, IDispatch **dispatch)
database = msi_alloc(sizeof(AutomationObject)); database = msi_alloc(sizeof(AutomationObject));
if (!database) return E_OUTOFMEMORY; if (!database) return E_OUTOFMEMORY;
hr = init_automation_object(database, msiHandle, &DIID_Database, DatabaseImpl_Invoke, NULL); hr = init_automation_object(database, msiHandle, Database_tid, DatabaseImpl_Invoke, NULL);
if (hr != S_OK) if (hr != S_OK)
{ {
msi_free(database); msi_free(database);
...@@ -2428,7 +2486,7 @@ static HRESULT create_view(MSIHANDLE msiHandle, IDispatch **dispatch) ...@@ -2428,7 +2486,7 @@ static HRESULT create_view(MSIHANDLE msiHandle, IDispatch **dispatch)
view = msi_alloc(sizeof(AutomationObject)); view = msi_alloc(sizeof(AutomationObject));
if (!view) return E_OUTOFMEMORY; if (!view) return E_OUTOFMEMORY;
hr = init_automation_object(view, msiHandle, &DIID_View, ViewImpl_Invoke, NULL); hr = init_automation_object(view, msiHandle, View_tid, ViewImpl_Invoke, NULL);
if (hr != S_OK) if (hr != S_OK)
{ {
msi_free(view); msi_free(view);
...@@ -2448,7 +2506,7 @@ static HRESULT create_summaryinfo(MSIHANDLE msiHandle, IDispatch **disp) ...@@ -2448,7 +2506,7 @@ static HRESULT create_summaryinfo(MSIHANDLE msiHandle, IDispatch **disp)
info = msi_alloc(sizeof(*info)); info = msi_alloc(sizeof(*info));
if (!info) return E_OUTOFMEMORY; if (!info) return E_OUTOFMEMORY;
hr = init_automation_object(info, msiHandle, &DIID_SummaryInfo, SummaryInfoImpl_Invoke, NULL); hr = init_automation_object(info, msiHandle, SummaryInfo_tid, SummaryInfoImpl_Invoke, NULL);
if (hr != S_OK) if (hr != S_OK)
{ {
msi_free(info); msi_free(info);
......
...@@ -79,6 +79,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) ...@@ -79,6 +79,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
msi_dialog_unregister_class(); msi_dialog_unregister_class();
msi_free_handle_table(); msi_free_handle_table();
msi_free( gszLogFile ); msi_free( gszLogFile );
release_typelib();
break; break;
} }
return TRUE; return TRUE;
......
...@@ -1072,9 +1072,21 @@ extern VOID ControlEvent_SubscribeToEvent(MSIPACKAGE *package, msi_dialog *dialo ...@@ -1072,9 +1072,21 @@ extern VOID ControlEvent_SubscribeToEvent(MSIPACKAGE *package, msi_dialog *dialo
LPCWSTR event, LPCWSTR control, LPCWSTR attribute) DECLSPEC_HIDDEN; LPCWSTR event, LPCWSTR control, LPCWSTR attribute) DECLSPEC_HIDDEN;
/* OLE automation */ /* OLE automation */
typedef enum tid_t {
Database_tid,
Installer_tid,
Record_tid,
Session_tid,
StringList_tid,
SummaryInfo_tid,
View_tid,
LAST_tid
} tid_t;
extern HRESULT create_msiserver(IUnknown *pOuter, LPVOID *ppObj) DECLSPEC_HIDDEN; extern HRESULT create_msiserver(IUnknown *pOuter, LPVOID *ppObj) DECLSPEC_HIDDEN;
extern HRESULT create_session(MSIHANDLE msiHandle, IDispatch *pInstaller, IDispatch **pDispatch) DECLSPEC_HIDDEN; extern HRESULT create_session(MSIHANDLE msiHandle, IDispatch *pInstaller, IDispatch **pDispatch) DECLSPEC_HIDDEN;
extern HRESULT load_type_info(IDispatch *iface, ITypeInfo **pptinfo, REFIID clsid, LCID lcid) DECLSPEC_HIDDEN; extern HRESULT get_typeinfo(tid_t tid, ITypeInfo **ti) DECLSPEC_HIDDEN;
extern void release_typelib(void) DECLSPEC_HIDDEN;
/* Scripting */ /* Scripting */
extern DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function, LPCWSTR action) DECLSPEC_HIDDEN; extern DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function, LPCWSTR action) DECLSPEC_HIDDEN;
......
...@@ -268,8 +268,12 @@ static HRESULT WINAPI MsiActiveScriptSite_GetItemInfo(IActiveScriptSite* iface, ...@@ -268,8 +268,12 @@ static HRESULT WINAPI MsiActiveScriptSite_GetItemInfo(IActiveScriptSite* iface,
/* Are we looking for the session object? */ /* Are we looking for the session object? */
if (!strcmpW(szSession, pstrName)) { if (!strcmpW(szSession, pstrName)) {
if (dwReturnMask & SCRIPTINFO_ITYPEINFO) if (dwReturnMask & SCRIPTINFO_ITYPEINFO) {
return load_type_info(This->pSession, ppti, &DIID_Session, 0); HRESULT hr = get_typeinfo(Session_tid, ppti);
if (SUCCEEDED(hr))
ITypeInfo_AddRef(*ppti);
return hr;
}
else if (dwReturnMask & SCRIPTINFO_IUNKNOWN) { else if (dwReturnMask & SCRIPTINFO_IUNKNOWN) {
IDispatch_QueryInterface(This->pSession, &IID_IUnknown, (void **)ppiunkItem); IDispatch_QueryInterface(This->pSession, &IID_IUnknown, (void **)ppiunkItem);
return S_OK; return S_OK;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment