Module: wine Branch: master Commit: d33c0e14ae7088e608a6bfb30008774f1905eb1c URL: http://source.winehq.org/git/wine.git/?a=commit;h=d33c0e14ae7088e608a6bfb300...
Author: Dmitry Timoshkov dmitry@baikal.ru Date: Tue Jan 28 11:54:48 2014 +0900
taskschd: Implement ITaskFolderCollection::get__NewEnum.
---
dlls/taskschd/folder_collection.c | 157 ++++++++++++++++++++++++++++++++++++- dlls/taskschd/tests/scheduler.c | 4 - 2 files changed, 155 insertions(+), 6 deletions(-)
diff --git a/dlls/taskschd/folder_collection.c b/dlls/taskschd/folder_collection.c index e8e4933..c8cc89b 100644 --- a/dlls/taskschd/folder_collection.c +++ b/dlls/taskschd/folder_collection.c @@ -42,6 +42,8 @@ typedef struct LONG count; } TaskFolderCollection;
+static HRESULT NewEnum_create(TaskFolderCollection *folders, IUnknown **obj); + static inline TaskFolderCollection *impl_from_ITaskFolderCollection(ITaskFolderCollection *iface) { return CONTAINING_RECORD(iface, TaskFolderCollection, ITaskFolderCollection_iface); @@ -190,8 +192,13 @@ static HRESULT WINAPI folders_get_Item(ITaskFolderCollection *iface, VARIANT ind
static HRESULT WINAPI folders_get__NewEnum(ITaskFolderCollection *iface, IUnknown **penum) { - FIXME("%p,%p: stub\n", iface, penum); - return E_NOTIMPL; + TaskFolderCollection *folders = impl_from_ITaskFolderCollection(iface); + + TRACE("%p,%p\n", iface, penum); + + if (!penum) return E_POINTER; + + return NewEnum_create(folders, penum); }
static const ITaskFolderCollectionVtbl TaskFolderCollection_vtbl = @@ -319,3 +326,149 @@ HRESULT TaskFolderCollection_create(const WCHAR *path, ITaskFolderCollection **o
return S_OK; } + +typedef struct +{ + IEnumVARIANT IEnumVARIANT_iface; + LONG ref, pos; + TaskFolderCollection *folders; +} EnumVARIANT; + +static inline EnumVARIANT *impl_from_IEnumVARIANT(IEnumVARIANT *iface) +{ + return CONTAINING_RECORD(iface, EnumVARIANT, IEnumVARIANT_iface); +} + +static HRESULT WINAPI enumvar_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **obj) +{ + if (!riid || !obj) return E_INVALIDARG; + + TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj); + + if (IsEqualGUID(riid, &IID_IEnumVARIANT) || + IsEqualGUID(riid, &IID_IUnknown)) + { + IEnumVARIANT_AddRef(iface); + *obj = iface; + return S_OK; + } + + FIXME("interface %s is not implemented\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI enumvar_AddRef(IEnumVARIANT *iface) +{ + EnumVARIANT *enumvar = impl_from_IEnumVARIANT(iface); + return InterlockedIncrement(&enumvar->ref); +} + +static ULONG WINAPI enumvar_Release(IEnumVARIANT *iface) +{ + EnumVARIANT *enumvar = impl_from_IEnumVARIANT(iface); + LONG ref = InterlockedDecrement(&enumvar->ref); + + if (!ref) + { + TRACE("destroying %p\n", iface); + ITaskFolderCollection_Release(&enumvar->folders->ITaskFolderCollection_iface); + heap_free(enumvar); + } + + return ref; +} + +static HRESULT WINAPI enumvar_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *var, ULONG *fetched) +{ + EnumVARIANT *enumvar = impl_from_IEnumVARIANT(iface); + LONG i; + + TRACE("%p,%u,%p,%p\n", iface, celt, var, fetched); + + for (i = 0; i < celt && enumvar->pos < enumvar->folders->count; i++) + { + ITaskFolder *folder; + HRESULT hr; + + hr = TaskFolder_create(enumvar->folders->path, enumvar->folders->list[enumvar->pos++], &folder, FALSE); + if (hr) return hr; + + if (!var) + { + ITaskFolder_Release(folder); + return E_POINTER; + } + + V_VT(&var[i]) = VT_DISPATCH; + V_DISPATCH(&var[i]) = (IDispatch *)folder; + } + + if (fetched) *fetched = i; + + return i == celt ? S_OK : S_FALSE; +} + +static HRESULT WINAPI enumvar_Skip(IEnumVARIANT *iface, ULONG celt) +{ + EnumVARIANT *enumvar = impl_from_IEnumVARIANT(iface); + + TRACE("%p,%u\n", iface, celt); + + enumvar->pos += celt; + + if (enumvar->pos > enumvar->folders->count) + { + enumvar->pos = enumvar->folders->count; + return S_FALSE; + } + + return S_OK; +} + +static HRESULT WINAPI enumvar_Reset(IEnumVARIANT *iface) +{ + EnumVARIANT *enumvar = impl_from_IEnumVARIANT(iface); + + TRACE("%p\n", iface); + + enumvar->pos = 0; + + return S_OK; +} + +static HRESULT WINAPI enumvar_Clone(IEnumVARIANT *iface, IEnumVARIANT **penum) +{ + FIXME("%p,%p: stub\n", iface, penum); + return E_NOTIMPL; +} + +static const struct IEnumVARIANTVtbl EnumVARIANT_vtbl = +{ + enumvar_QueryInterface, + enumvar_AddRef, + enumvar_Release, + enumvar_Next, + enumvar_Skip, + enumvar_Reset, + enumvar_Clone +}; + +static HRESULT NewEnum_create(TaskFolderCollection *folders, IUnknown **obj) +{ + EnumVARIANT *enumvar; + + enumvar = heap_alloc(sizeof(*enumvar)); + if (!enumvar) return E_OUTOFMEMORY; + + enumvar->IEnumVARIANT_iface.lpVtbl = &EnumVARIANT_vtbl; + enumvar->ref = 1; + enumvar->pos = 0; + enumvar->folders = folders; + ITaskFolderCollection_AddRef(&folders->ITaskFolderCollection_iface); + + *obj = (IUnknown *)&enumvar->IEnumVARIANT_iface; + + TRACE("created %p\n", *obj); + + return S_OK; +} diff --git a/dlls/taskschd/tests/scheduler.c b/dlls/taskschd/tests/scheduler.c index d9f622e..f30a1be 100644 --- a/dlls/taskschd/tests/scheduler.c +++ b/dlls/taskschd/tests/scheduler.c @@ -544,10 +544,7 @@ static void test_FolderCollection(void) ok(hr == E_NOINTERFACE, "expected E_NOINTERFACE, got %#x\n", hr);
hr = ITaskFolderCollection_get__NewEnum(folders, &unknown); -todo_wine ok(hr == S_OK, "get__NewEnum error %#x\n", hr); - /* FIXME: remove once implemented */ - if (hr != S_OK) goto failed; hr = IUnknown_QueryInterface(unknown, &IID_IEnumUnknown, (void **)&enumvar); ok(hr == E_NOINTERFACE, "expected E_NOINTERFACE, got %#x\n", hr); hr = IUnknown_QueryInterface(unknown, &IID_IEnumVARIANT, (void **)&enumvar); @@ -592,7 +589,6 @@ todo_wine IDispatch_Release(V_DISPATCH(&var[0])); IDispatch_Release(V_DISPATCH(&var[1]));
-failed: ITaskFolderCollection_Release(folders);
hr = ITaskFolder_DeleteFolder(root, Wine_Folder1, 0);