Misha Koshelev : msi: automation: Implement StringList::_NewEnum.

Alexandre Julliard julliard at wine.codeweavers.com
Fri May 18 13:56:12 CDT 2007


Module: wine
Branch: master
Commit: 01460f6753476c4d5b66d3b2a56a25907b19b0c8
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=01460f6753476c4d5b66d3b2a56a25907b19b0c8

Author: Misha Koshelev <mk144210 at bcm.edu>
Date:   Fri May 18 11:23:19 2007 -0500

msi: automation: Implement StringList::_NewEnum.

---

 dlls/msi/automation.c        |  203 +++++++++++++++++++++++++++++++++++++++++-
 dlls/msi/msiserver.idl       |    2 +
 dlls/msi/msiserver_dispids.h |    1 +
 dlls/msi/tests/automation.c  |   13 +--
 4 files changed, 210 insertions(+), 9 deletions(-)

diff --git a/dlls/msi/automation.c b/dlls/msi/automation.c
index 98ec166..63fea99 100644
--- a/dlls/msi/automation.c
+++ b/dlls/msi/automation.c
@@ -80,6 +80,24 @@ interface AutomationObject {
 };
 
 /*
+ * ListEnumerator - IEnumVARIANT implementation for MSI automation lists.
+ */
+
+typedef interface ListEnumerator ListEnumerator;
+
+interface ListEnumerator {
+    /* VTables */
+    const IEnumVARIANTVtbl *lpVtbl;
+
+    /* Object reference count */
+    LONG ref;
+
+    /* Current position and pointer to AutomationObject that stores actual data */
+    ULONG ulPos;
+    AutomationObject *pObj;
+};
+
+/*
  * Structures for additional data required by specific automation objects
  */
 
@@ -96,6 +114,7 @@ typedef struct {
 /* VTables */
 static const struct IDispatchVtbl AutomationObject_Vtbl;
 static const struct IProvideMultipleClassInfoVtbl AutomationObject_IProvideMultipleClassInfo_Vtbl;
+static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl;
 
 /* Load type info so we don't have to process GetIDsOfNames */
 HRESULT load_type_info(IDispatch *iface, ITypeInfo **pptinfo, REFIID clsid, LCID lcid)
@@ -170,6 +189,31 @@ HRESULT create_automation_object(MSIHANDLE msiHandle, IUnknown *pUnkOuter, LPVOI
     return S_OK;
 }
 
+/* Create a list enumerator, placing the result in the pointer ppObj.  */
+HRESULT create_list_enumerator(IUnknown *pUnkOuter, LPVOID *ppObj, AutomationObject *pObj, ULONG ulPos)
+{
+    ListEnumerator *object;
+
+    TRACE("(%p,%p,%p,%uld)\n", pUnkOuter, ppObj, pObj, ulPos);
+
+    if( pUnkOuter )
+        return CLASS_E_NOAGGREGATION;
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ListEnumerator));
+
+    /* Set all the VTable references */
+    object->lpVtbl = &ListEnumerator_Vtbl;
+    object->ref = 1;
+
+    /* Store data that was passed */
+    object->ulPos = ulPos;
+    object->pObj = pObj;
+    if (pObj) IDispatch_AddRef((IDispatch *)pObj);
+
+    *ppObj = object;
+    return S_OK;
+}
+
 /* Macros to get pointer to AutomationObject from the other VTables. */
 static inline AutomationObject *obj_from_IProvideMultipleClassInfo( IProvideMultipleClassInfo *iface )
 {
@@ -512,6 +556,148 @@ static const IProvideMultipleClassInfoVtbl AutomationObject_IProvideMultipleClas
 };
 
 /*
+ * ListEnumerator methods
+ */
+
+/*** IUnknown methods ***/
+static HRESULT WINAPI ListEnumerator_QueryInterface(IEnumVARIANT* iface, REFIID riid, void** ppvObject)
+{
+    ListEnumerator *This = (ListEnumerator *)iface;
+
+    TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
+
+    if (ppvObject == NULL)
+      return E_INVALIDARG;
+
+    *ppvObject = 0;
+
+    if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IEnumVARIANT))
+        *ppvObject = This;
+    else
+    {
+        TRACE("() : asking for unsupported interface %s\n",debugstr_guid(riid));
+        return E_NOINTERFACE;
+    }
+
+    IClassFactory_AddRef(iface);
+    return S_OK;
+}
+
+static ULONG WINAPI ListEnumerator_AddRef(IEnumVARIANT* iface)
+{
+    ListEnumerator *This = (ListEnumerator *)iface;
+
+    TRACE("(%p/%p)\n", iface, This);
+
+    return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI ListEnumerator_Release(IEnumVARIANT* iface)
+{
+    ListEnumerator *This = (ListEnumerator *)iface;
+    ULONG ref = InterlockedDecrement(&This->ref);
+
+    TRACE("(%p/%p)\n", iface, This);
+
+    if (!ref)
+    {
+        if (This->pObj) IDispatch_Release((IDispatch *)This->pObj);
+        HeapFree(GetProcessHeap(), 0, This);
+    }
+
+    return ref;
+}
+
+/* IEnumVARIANT methods */
+
+static HRESULT WINAPI ListEnumerator_Next(IEnumVARIANT* iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
+{
+    ListEnumerator *This = (ListEnumerator *)iface;
+    ListData *data = (ListData *)private_data(This->pObj);
+    ULONG idx, local;
+
+    TRACE("(%p,%uld,%p,%p)\n", iface, celt, rgVar, pCeltFetched);
+
+    if (pCeltFetched != NULL)
+        *pCeltFetched = 0;
+
+    if (rgVar == NULL)
+        return S_FALSE;
+
+    for (local = 0; local < celt; local++)
+        VariantInit(&rgVar[local]);
+
+    for (idx = This->ulPos, local = 0; idx < data->ulCount && local < celt; idx++, local++)
+        VariantCopy(&rgVar[local], &data->pVars[idx]);
+
+    if (pCeltFetched != NULL)
+        *pCeltFetched = local;
+    This->ulPos = idx;
+
+    return (local < celt) ? S_FALSE : S_OK;
+}
+
+static HRESULT WINAPI ListEnumerator_Skip(IEnumVARIANT* iface, ULONG celt)
+{
+    ListEnumerator *This = (ListEnumerator *)iface;
+    ListData *data = (ListData *)private_data(This->pObj);
+
+    TRACE("(%p,%uld)\n", iface, celt);
+
+    This->ulPos += celt;
+    if (This->ulPos >= data->ulCount)
+    {
+        This->ulPos = data->ulCount;
+        return S_FALSE;
+    }
+    return S_OK;
+}
+
+static HRESULT WINAPI ListEnumerator_Reset(IEnumVARIANT* iface)
+{
+    ListEnumerator *This = (ListEnumerator *)iface;
+
+    TRACE("(%p)\n", iface);
+
+    This->ulPos = 0;
+    return S_OK;
+}
+
+static HRESULT WINAPI ListEnumerator_Clone(IEnumVARIANT* iface, IEnumVARIANT **ppEnum)
+{
+    ListEnumerator *This = (ListEnumerator *)iface;
+    HRESULT hr;
+
+    TRACE("(%p,%p)\n", iface, ppEnum);
+
+    if (ppEnum == NULL)
+        return S_FALSE;
+
+    *ppEnum = NULL;
+    hr = create_list_enumerator(NULL, (LPVOID *)ppEnum, This->pObj, 0);
+    if (FAILED(hr))
+    {
+        if (*ppEnum)
+            IUnknown_Release(*ppEnum);
+        return hr;
+    }
+
+    IUnknown_AddRef(*ppEnum);
+    return S_OK;
+}
+
+static const struct IEnumVARIANTVtbl ListEnumerator_Vtbl =
+{
+    ListEnumerator_QueryInterface,
+    ListEnumerator_AddRef,
+    ListEnumerator_Release,
+    ListEnumerator_Next,
+    ListEnumerator_Skip,
+    ListEnumerator_Reset,
+    ListEnumerator_Clone
+};
+
+/*
  * Individual Object Invocation Functions
  */
 
@@ -649,13 +835,28 @@ static HRESULT WINAPI ListImpl_Invoke(
     ListData *data = (ListData *)private_data(This);
     HRESULT hr;
     VARIANTARG varg0;
+    IUnknown *pUnk = NULL;
 
     VariantInit(&varg0);
 
     switch (dispIdMember)
     {
+         case DISPID_LIST__NEWENUM:
+             if (wFlags & DISPATCH_METHOD) {
+                 V_VT(pVarResult) = VT_UNKNOWN;
+                 if (SUCCEEDED(hr = create_list_enumerator(NULL, (LPVOID *)&pUnk, This, 0)))
+                 {
+                     IUnknown_AddRef(pUnk);
+                     V_UNKNOWN(pVarResult) = pUnk;
+                 }
+                 else
+                     ERR("Failed to create IEnumVARIANT object, hresult 0x%08x\n", hr);
+             }
+             else return DISP_E_MEMBERNOTFOUND;
+             break;
+
          case DISPID_LIST_ITEM:
-            if (wFlags & DISPATCH_PROPERTYGET) {
+             if (wFlags & DISPATCH_PROPERTYGET) {
                 hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
                 if (FAILED(hr)) return hr;
                 if (V_I4(&varg0) < 0 || V_I4(&varg0) >= data->ulCount)
diff --git a/dlls/msi/msiserver.idl b/dlls/msi/msiserver.idl
index 485334c..360e4f1 100644
--- a/dlls/msi/msiserver.idl
+++ b/dlls/msi/msiserver.idl
@@ -114,6 +114,8 @@ library WindowsInstaller
     {
         properties:
         methods:
+        [id(DISPID_LIST__NEWENUM)]
+            IUnknown _NewEnum();
         [id(DISPID_LIST_ITEM), propget]
             BSTR Item(long Index);
         [id(DISPID_LIST_COUNT), propget]
diff --git a/dlls/msi/msiserver_dispids.h b/dlls/msi/msiserver_dispids.h
index 5ef21c8..694090e 100644
--- a/dlls/msi/msiserver_dispids.h
+++ b/dlls/msi/msiserver_dispids.h
@@ -29,6 +29,7 @@
 #define DISPID_RECORD_STRINGDATA 1
 #define DISPID_RECORD_INTEGERDATA 2
 
+#define DISPID_LIST__NEWENUM -4
 #define DISPID_LIST_ITEM 0
 #define DISPID_LIST_COUNT 1
 
diff --git a/dlls/msi/tests/automation.c b/dlls/msi/tests/automation.c
index 82fe05e..9bd7d03 100644
--- a/dlls/msi/tests/automation.c
+++ b/dlls/msi/tests/automation.c
@@ -1910,15 +1910,12 @@ static void test_Installer(void)
         ULONG celt;
 
         /* StringList::_NewEnum */
-        todo_wine
+        hr = StringList__NewEnum(pStringList, &pUnk);
+        ok(hr == S_OK, "StringList_NewEnum failed, hresult 0x%08x\n", hr);
+        if (hr == S_OK)
         {
-            hr = StringList__NewEnum(pStringList, &pUnk);
-            ok(hr == S_OK, "StringList_NewEnum failed, hresult 0x%08x\n", hr);
-            if (hr == S_OK)
-            {
-                hr = IUnknown_QueryInterface(pUnk, &IID_IEnumVARIANT, (void **)&pEnum);
-                ok (hr == S_OK, "IUnknown::QueryInterface returned 0x%08x\n", hr);
-            }
+            hr = IUnknown_QueryInterface(pUnk, &IID_IEnumVARIANT, (void **)&pEnum);
+            ok (hr == S_OK, "IUnknown::QueryInterface returned 0x%08x\n", hr);
         }
         if (!pEnum)
             skip("IEnumVARIANT tests\n");




More information about the wine-cvs mailing list