2 * Copyright 2014 Dmitry Timoshkov
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "taskschd_private.h"
29 #include "wine/unicode.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(taskschd
);
34 static const char root
[] = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Schedule\\TaskCache\\Tree";
38 ITaskFolderCollection ITaskFolderCollection_iface
;
43 } TaskFolderCollection
;
45 static HRESULT
NewEnum_create(TaskFolderCollection
*folders
, IUnknown
**obj
);
47 static inline TaskFolderCollection
*impl_from_ITaskFolderCollection(ITaskFolderCollection
*iface
)
49 return CONTAINING_RECORD(iface
, TaskFolderCollection
, ITaskFolderCollection_iface
);
52 static ULONG WINAPI
folders_AddRef(ITaskFolderCollection
*iface
)
54 TaskFolderCollection
*folders
= impl_from_ITaskFolderCollection(iface
);
55 return InterlockedIncrement(&folders
->ref
);
58 static void free_list(LPWSTR
*list
, LONG count
)
62 for (i
= 0; i
< count
; i
++)
68 static ULONG WINAPI
folders_Release(ITaskFolderCollection
*iface
)
70 TaskFolderCollection
*folders
= impl_from_ITaskFolderCollection(iface
);
71 LONG ref
= InterlockedDecrement(&folders
->ref
);
75 TRACE("destroying %p\n", iface
);
76 free_list(folders
->list
, folders
->count
);
77 heap_free(folders
->path
);
84 static HRESULT WINAPI
folders_QueryInterface(ITaskFolderCollection
*iface
, REFIID riid
, void **obj
)
86 if (!riid
|| !obj
) return E_INVALIDARG
;
88 TRACE("%p,%s,%p\n", iface
, debugstr_guid(riid
), obj
);
90 if (IsEqualGUID(riid
, &IID_ITaskFolderCollection
) ||
91 IsEqualGUID(riid
, &IID_IDispatch
) ||
92 IsEqualGUID(riid
, &IID_IUnknown
))
94 ITaskFolderCollection_AddRef(iface
);
99 FIXME("interface %s is not implemented\n", debugstr_guid(riid
));
101 return E_NOINTERFACE
;
104 static HRESULT WINAPI
folders_GetTypeInfoCount(ITaskFolderCollection
*iface
, UINT
*count
)
106 FIXME("%p,%p: stub\n", iface
, count
);
110 static HRESULT WINAPI
folders_GetTypeInfo(ITaskFolderCollection
*iface
, UINT index
, LCID lcid
, ITypeInfo
**info
)
112 FIXME("%p,%u,%u,%p: stub\n", iface
, index
, lcid
, info
);
116 static HRESULT WINAPI
folders_GetIDsOfNames(ITaskFolderCollection
*iface
, REFIID riid
, LPOLESTR
*names
,
117 UINT count
, LCID lcid
, DISPID
*dispid
)
119 FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface
, debugstr_guid(riid
), names
, count
, lcid
, dispid
);
123 static HRESULT WINAPI
folders_Invoke(ITaskFolderCollection
*iface
, DISPID dispid
, REFIID riid
, LCID lcid
, WORD flags
,
124 DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excepinfo
, UINT
*argerr
)
126 FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface
, dispid
, debugstr_guid(riid
), lcid
, flags
,
127 params
, result
, excepinfo
, argerr
);
131 static HRESULT WINAPI
folders_get_Count(ITaskFolderCollection
*iface
, LONG
*count
)
133 TaskFolderCollection
*folders
= impl_from_ITaskFolderCollection(iface
);
135 TRACE("%p,%p\n", iface
, count
);
137 if (!count
) return E_POINTER
;
139 *count
= folders
->count
;
144 static LONG
get_var_int(const VARIANT
*var
)
169 FIXME("unsupported variant type %d\n", V_VT(var
));
174 static HRESULT WINAPI
folders_get_Item(ITaskFolderCollection
*iface
, VARIANT index
, ITaskFolder
**folder
)
176 TaskFolderCollection
*folders
= impl_from_ITaskFolderCollection(iface
);
179 TRACE("%p,%s,%p\n", iface
, debugstr_variant(&index
), folder
);
181 if (!folder
) return E_POINTER
;
183 if (V_VT(&index
) == VT_BSTR
)
184 return TaskFolder_create(folders
->path
, V_BSTR(&index
), folder
, FALSE
);
186 idx
= get_var_int(&index
);
187 /* collections are 1 based */
188 if (idx
< 1 || idx
> folders
->count
)
191 return TaskFolder_create(folders
->path
, folders
->list
[idx
- 1], folder
, FALSE
);
194 static HRESULT WINAPI
folders_get__NewEnum(ITaskFolderCollection
*iface
, IUnknown
**penum
)
196 TaskFolderCollection
*folders
= impl_from_ITaskFolderCollection(iface
);
198 TRACE("%p,%p\n", iface
, penum
);
200 if (!penum
) return E_POINTER
;
202 return NewEnum_create(folders
, penum
);
205 static const ITaskFolderCollectionVtbl TaskFolderCollection_vtbl
=
207 folders_QueryInterface
,
210 folders_GetTypeInfoCount
,
212 folders_GetIDsOfNames
,
219 static HRESULT
reg_open_folder(const WCHAR
*path
, HKEY
*hfolder
)
224 ret
= RegCreateKeyA(HKEY_LOCAL_MACHINE
, root
, &hroot
);
225 if (ret
) return HRESULT_FROM_WIN32(ret
);
227 while (*path
== '\\') path
++;
228 ret
= RegOpenKeyExW(hroot
, path
, 0, KEY_ALL_ACCESS
, hfolder
);
229 if (ret
== ERROR_FILE_NOT_FOUND
)
230 ret
= ERROR_PATH_NOT_FOUND
;
234 return HRESULT_FROM_WIN32(ret
);
237 static inline void reg_close_folder(HKEY hfolder
)
239 RegCloseKey(hfolder
);
242 static HRESULT
create_folders_list(const WCHAR
*path
, LPWSTR
**folders_list
, LONG
*folders_count
)
246 WCHAR name
[MAX_PATH
];
247 LONG ret
, idx
, allocated
, count
;
250 *folders_list
= NULL
;
253 hr
= reg_open_folder(path
, &hfolder
);
257 list
= heap_alloc(allocated
* sizeof(LPWSTR
));
260 reg_close_folder(hfolder
);
261 return E_OUTOFMEMORY
;
266 while (!(ret
= RegEnumKeyW(hfolder
, idx
++, name
, MAX_PATH
)))
268 /* FIXME: differentiate between folders and tasks */
269 if (count
>= allocated
)
273 new_list
= heap_realloc(list
, allocated
* sizeof(LPWSTR
));
276 reg_close_folder(hfolder
);
277 free_list(list
, count
);
278 return E_OUTOFMEMORY
;
283 list
[count
] = heap_strdupW(name
);
286 reg_close_folder(hfolder
);
287 free_list(list
, count
);
288 return E_OUTOFMEMORY
;
294 reg_close_folder(hfolder
);
296 *folders_list
= list
;
297 *folders_count
= count
;
302 HRESULT
TaskFolderCollection_create(const WCHAR
*path
, ITaskFolderCollection
**obj
)
304 TaskFolderCollection
*folders
;
309 hr
= create_folders_list(path
, &list
, &count
);
312 folders
= heap_alloc(sizeof(*folders
));
315 free_list(list
, count
);
316 return E_OUTOFMEMORY
;
319 folders
->ITaskFolderCollection_iface
.lpVtbl
= &TaskFolderCollection_vtbl
;
321 folders
->path
= heap_strdupW(path
);
322 folders
->count
= count
;
323 folders
->list
= list
;
324 *obj
= &folders
->ITaskFolderCollection_iface
;
326 TRACE("created %p\n", *obj
);
333 IEnumVARIANT IEnumVARIANT_iface
;
335 TaskFolderCollection
*folders
;
338 static inline EnumVARIANT
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
340 return CONTAINING_RECORD(iface
, EnumVARIANT
, IEnumVARIANT_iface
);
343 static HRESULT WINAPI
enumvar_QueryInterface(IEnumVARIANT
*iface
, REFIID riid
, void **obj
)
345 if (!riid
|| !obj
) return E_INVALIDARG
;
347 TRACE("%p,%s,%p\n", iface
, debugstr_guid(riid
), obj
);
349 if (IsEqualGUID(riid
, &IID_IEnumVARIANT
) ||
350 IsEqualGUID(riid
, &IID_IUnknown
))
352 IEnumVARIANT_AddRef(iface
);
357 FIXME("interface %s is not implemented\n", debugstr_guid(riid
));
359 return E_NOINTERFACE
;
362 static ULONG WINAPI
enumvar_AddRef(IEnumVARIANT
*iface
)
364 EnumVARIANT
*enumvar
= impl_from_IEnumVARIANT(iface
);
365 return InterlockedIncrement(&enumvar
->ref
);
368 static ULONG WINAPI
enumvar_Release(IEnumVARIANT
*iface
)
370 EnumVARIANT
*enumvar
= impl_from_IEnumVARIANT(iface
);
371 LONG ref
= InterlockedDecrement(&enumvar
->ref
);
375 TRACE("destroying %p\n", iface
);
376 ITaskFolderCollection_Release(&enumvar
->folders
->ITaskFolderCollection_iface
);
383 static HRESULT WINAPI
enumvar_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*var
, ULONG
*fetched
)
385 EnumVARIANT
*enumvar
= impl_from_IEnumVARIANT(iface
);
388 TRACE("%p,%u,%p,%p\n", iface
, celt
, var
, fetched
);
390 for (i
= 0; i
< celt
&& enumvar
->pos
< enumvar
->folders
->count
; i
++)
395 hr
= TaskFolder_create(enumvar
->folders
->path
, enumvar
->folders
->list
[enumvar
->pos
++], &folder
, FALSE
);
400 ITaskFolder_Release(folder
);
404 V_VT(&var
[i
]) = VT_DISPATCH
;
405 V_DISPATCH(&var
[i
]) = (IDispatch
*)folder
;
408 if (fetched
) *fetched
= i
;
410 return i
== celt
? S_OK
: S_FALSE
;
413 static HRESULT WINAPI
enumvar_Skip(IEnumVARIANT
*iface
, ULONG celt
)
415 EnumVARIANT
*enumvar
= impl_from_IEnumVARIANT(iface
);
417 TRACE("%p,%u\n", iface
, celt
);
419 enumvar
->pos
+= celt
;
421 if (enumvar
->pos
> enumvar
->folders
->count
)
423 enumvar
->pos
= enumvar
->folders
->count
;
430 static HRESULT WINAPI
enumvar_Reset(IEnumVARIANT
*iface
)
432 EnumVARIANT
*enumvar
= impl_from_IEnumVARIANT(iface
);
434 TRACE("%p\n", iface
);
441 static HRESULT WINAPI
enumvar_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**penum
)
443 EnumVARIANT
*enumvar
= impl_from_IEnumVARIANT(iface
);
445 TRACE("%p,%p\n", iface
, penum
);
447 return NewEnum_create(enumvar
->folders
, (IUnknown
**)penum
);
450 static const struct IEnumVARIANTVtbl EnumVARIANT_vtbl
=
452 enumvar_QueryInterface
,
461 static HRESULT
NewEnum_create(TaskFolderCollection
*folders
, IUnknown
**obj
)
463 EnumVARIANT
*enumvar
;
465 enumvar
= heap_alloc(sizeof(*enumvar
));
466 if (!enumvar
) return E_OUTOFMEMORY
;
468 enumvar
->IEnumVARIANT_iface
.lpVtbl
= &EnumVARIANT_vtbl
;
471 enumvar
->folders
= folders
;
472 ITaskFolderCollection_AddRef(&folders
->ITaskFolderCollection_iface
);
474 *obj
= (IUnknown
*)&enumvar
->IEnumVARIANT_iface
;
476 TRACE("created %p\n", *obj
);