crypt32: Fix adding trusted roots to store.
[wine/zf.git] / dlls / taskschd / folder.c
blobeea404acd27be51caddd5a5feca41ab1145e1b7c
1 /*
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
19 #include <stdarg.h>
21 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winreg.h"
26 #include "objbase.h"
27 #include "taskschd.h"
28 #include "schrpc.h"
29 #include "taskschd_private.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(taskschd);
35 typedef struct
37 ITaskFolder ITaskFolder_iface;
38 LONG ref;
39 WCHAR *path;
40 } TaskFolder;
42 static inline TaskFolder *impl_from_ITaskFolder(ITaskFolder *iface)
44 return CONTAINING_RECORD(iface, TaskFolder, ITaskFolder_iface);
47 static ULONG WINAPI TaskFolder_AddRef(ITaskFolder *iface)
49 TaskFolder *folder = impl_from_ITaskFolder(iface);
50 return InterlockedIncrement(&folder->ref);
53 static ULONG WINAPI TaskFolder_Release(ITaskFolder *iface)
55 TaskFolder *folder = impl_from_ITaskFolder(iface);
56 LONG ref = InterlockedDecrement(&folder->ref);
58 if (!ref)
60 TRACE("destroying %p\n", iface);
61 heap_free(folder->path);
62 heap_free(folder);
65 return ref;
68 static HRESULT WINAPI TaskFolder_QueryInterface(ITaskFolder *iface, REFIID riid, void **obj)
70 if (!riid || !obj) return E_INVALIDARG;
72 TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj);
74 if (IsEqualGUID(riid, &IID_ITaskFolder) ||
75 IsEqualGUID(riid, &IID_IDispatch) ||
76 IsEqualGUID(riid, &IID_IUnknown))
78 ITaskFolder_AddRef(iface);
79 *obj = iface;
80 return S_OK;
83 FIXME("interface %s is not implemented\n", debugstr_guid(riid));
84 *obj = NULL;
85 return E_NOINTERFACE;
88 static HRESULT WINAPI TaskFolder_GetTypeInfoCount(ITaskFolder *iface, UINT *count)
90 FIXME("%p,%p: stub\n", iface, count);
91 return E_NOTIMPL;
94 static HRESULT WINAPI TaskFolder_GetTypeInfo(ITaskFolder *iface, UINT index, LCID lcid, ITypeInfo **info)
96 FIXME("%p,%u,%u,%p: stub\n", iface, index, lcid, info);
97 return E_NOTIMPL;
100 static HRESULT WINAPI TaskFolder_GetIDsOfNames(ITaskFolder *iface, REFIID riid, LPOLESTR *names,
101 UINT count, LCID lcid, DISPID *dispid)
103 FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid);
104 return E_NOTIMPL;
107 static HRESULT WINAPI TaskFolder_Invoke(ITaskFolder *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags,
108 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr)
110 FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags,
111 params, result, excepinfo, argerr);
112 return E_NOTIMPL;
115 static HRESULT WINAPI TaskFolder_get_Name(ITaskFolder *iface, BSTR *name)
117 TaskFolder *folder = impl_from_ITaskFolder(iface);
118 const WCHAR *p_name;
120 TRACE("%p,%p\n", iface, name);
122 if (!name) return E_POINTER;
124 p_name = wcsrchr(folder->path, '\\');
125 if (!p_name)
126 p_name = folder->path;
127 else
128 if (p_name[1] != 0) p_name++;
130 *name = SysAllocString(p_name);
131 if (!*name) return E_OUTOFMEMORY;
133 return S_OK;
136 static HRESULT WINAPI TaskFolder_get_Path(ITaskFolder *iface, BSTR *path)
138 TaskFolder *folder = impl_from_ITaskFolder(iface);
140 TRACE("%p,%p\n", iface, path);
142 if (!path) return E_POINTER;
144 *path = SysAllocString(folder->path);
145 if (!*path) return E_OUTOFMEMORY;
147 return S_OK;
150 static HRESULT WINAPI TaskFolder_GetFolder(ITaskFolder *iface, BSTR path, ITaskFolder **new_folder)
152 TaskFolder *folder = impl_from_ITaskFolder(iface);
154 TRACE("%p,%s,%p\n", iface, debugstr_w(path), folder);
156 if (!path) return E_INVALIDARG;
157 if (!new_folder) return E_POINTER;
159 return TaskFolder_create(folder->path, path, new_folder, FALSE);
162 static HRESULT WINAPI TaskFolder_GetFolders(ITaskFolder *iface, LONG flags, ITaskFolderCollection **folders)
164 TaskFolder *folder = impl_from_ITaskFolder(iface);
166 TRACE("%p,%x,%p: stub\n", iface, flags, folders);
168 if (!folders) return E_POINTER;
170 if (flags)
171 FIXME("unsupported flags %x\n", flags);
173 return TaskFolderCollection_create(folder->path, folders);
176 static inline BOOL is_variant_null(const VARIANT *var)
178 return V_VT(var) == VT_EMPTY || V_VT(var) == VT_NULL ||
179 (V_VT(var) == VT_BSTR && (V_BSTR(var) == NULL || !*V_BSTR(var)));
182 static HRESULT WINAPI TaskFolder_CreateFolder(ITaskFolder *iface, BSTR path, VARIANT sddl, ITaskFolder **new_folder)
184 TaskFolder *folder = impl_from_ITaskFolder(iface);
185 ITaskFolder *tmp_folder = NULL;
186 HRESULT hr;
188 TRACE("%p,%s,%s,%p\n", iface, debugstr_w(path), debugstr_variant(&sddl), folder);
190 if (!path) return E_INVALIDARG;
192 if (!new_folder) new_folder = &tmp_folder;
194 if (!is_variant_null(&sddl))
195 FIXME("security descriptor %s is ignored\n", debugstr_variant(&sddl));
197 hr = TaskFolder_create(folder->path, path, new_folder, TRUE);
198 if (tmp_folder)
199 ITaskFolder_Release(tmp_folder);
201 return hr;
204 WCHAR *get_full_path(const WCHAR *parent, const WCHAR *path)
206 static const WCHAR bslash[] = { '\\', 0 };
207 WCHAR *folder_path;
208 int len = 0;
210 if (path) len = lstrlenW(path);
212 if (parent) len += lstrlenW(parent);
214 /* +1 if parent is not '\' terminated */
215 folder_path = heap_alloc((len + 2) * sizeof(WCHAR));
216 if (!folder_path) return NULL;
218 folder_path[0] = 0;
220 if (parent)
221 lstrcpyW(folder_path, parent);
223 if (path && *path)
225 len = lstrlenW(folder_path);
226 if (!len || folder_path[len - 1] != '\\')
227 lstrcatW(folder_path, bslash);
229 while (*path == '\\') path++;
230 lstrcatW(folder_path, path);
233 len = lstrlenW(folder_path);
234 if (!len)
235 lstrcatW(folder_path, bslash);
237 return folder_path;
240 static HRESULT WINAPI TaskFolder_DeleteFolder(ITaskFolder *iface, BSTR name, LONG flags)
242 TaskFolder *folder = impl_from_ITaskFolder(iface);
243 WCHAR *folder_path;
244 HRESULT hr;
246 TRACE("%p,%s,%x\n", iface, debugstr_w(name), flags);
248 if (!name || !*name) return E_ACCESSDENIED;
250 if (flags)
251 FIXME("unsupported flags %x\n", flags);
253 folder_path = get_full_path(folder->path, name);
254 if (!folder_path) return E_OUTOFMEMORY;
256 hr = SchRpcDelete(folder_path, 0);
257 heap_free(folder_path);
258 return hr;
261 static HRESULT WINAPI TaskFolder_GetTask(ITaskFolder *iface, BSTR name, IRegisteredTask **task)
263 TaskFolder *folder = impl_from_ITaskFolder(iface);
264 ITaskDefinition *taskdef;
265 HRESULT hr;
267 TRACE("%p,%s,%p\n", iface, debugstr_w(name), task);
269 if (!task) return E_POINTER;
271 hr = TaskDefinition_create(&taskdef);
272 if (hr != S_OK) return hr;
274 hr = RegisteredTask_create(folder->path, name, taskdef, 0, 0, task, FALSE);
275 if (hr != S_OK)
276 ITaskDefinition_Release(taskdef);
277 return hr;
280 static HRESULT WINAPI TaskFolder_GetTasks(ITaskFolder *iface, LONG flags, IRegisteredTaskCollection **tasks)
282 TaskFolder *folder = impl_from_ITaskFolder(iface);
284 TRACE("%p,%x,%p: stub\n", iface, flags, tasks);
286 if (!tasks) return E_POINTER;
288 return RegisteredTaskCollection_create(folder->path, tasks);
291 static HRESULT WINAPI TaskFolder_DeleteTask(ITaskFolder *iface, BSTR name, LONG flags)
293 TaskFolder *folder = impl_from_ITaskFolder(iface);
294 WCHAR *folder_path;
295 HRESULT hr;
297 TRACE("%p,%s,%x\n", iface, debugstr_w(name), flags);
299 if (!name || !*name) return E_ACCESSDENIED;
301 if (flags)
302 FIXME("unsupported flags %x\n", flags);
304 folder_path = get_full_path(folder->path, name);
305 if (!folder_path) return E_OUTOFMEMORY;
307 hr = SchRpcDelete(folder_path, 0);
308 heap_free(folder_path);
309 return hr;
312 static HRESULT WINAPI TaskFolder_RegisterTask(ITaskFolder *iface, BSTR name, BSTR xml, LONG flags,
313 VARIANT user, VARIANT password, TASK_LOGON_TYPE logon,
314 VARIANT sddl, IRegisteredTask **task)
316 TaskFolder *folder = impl_from_ITaskFolder(iface);
317 IRegisteredTask *regtask = NULL;
318 ITaskDefinition *taskdef;
319 HRESULT hr;
321 TRACE("%p,%s,%s,%x,%s,%s,%d,%s,%p\n", iface, debugstr_w(name), debugstr_w(xml), flags,
322 debugstr_variant(&user), debugstr_variant(&password), logon, debugstr_variant(&sddl), task);
324 if (!xml) return HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER);
326 if (!task) task = &regtask;
328 hr = TaskDefinition_create(&taskdef);
329 if (hr != S_OK) return hr;
331 hr = ITaskDefinition_put_XmlText(taskdef, xml);
332 if (hr == S_OK)
333 hr = RegisteredTask_create(folder->path, name, taskdef, flags, logon, task, TRUE);
335 if (hr != S_OK)
336 ITaskDefinition_Release(taskdef);
338 if (regtask)
339 IRegisteredTask_Release(regtask);
341 return hr;
344 static HRESULT WINAPI TaskFolder_RegisterTaskDefinition(ITaskFolder *iface, BSTR name, ITaskDefinition *definition, LONG flags,
345 VARIANT user, VARIANT password, TASK_LOGON_TYPE logon,
346 VARIANT sddl, IRegisteredTask **task)
348 TaskFolder *folder = impl_from_ITaskFolder(iface);
349 IRegisteredTask *regtask = NULL;
350 HRESULT hr;
352 FIXME("%p,%s,%p,%x,%s,%s,%d,%s,%p: stub\n", iface, debugstr_w(name), definition, flags,
353 debugstr_variant(&user), debugstr_variant(&password), logon, debugstr_variant(&sddl), task);
355 if (!is_variant_null(&sddl))
356 FIXME("security descriptor %s is ignored\n", debugstr_variant(&sddl));
358 if (!is_variant_null(&user) || !is_variant_null(&password))
359 FIXME("user/password are ignored\n");
361 if (!task) task = &regtask;
363 ITaskDefinition_AddRef(definition);
364 hr = RegisteredTask_create(folder->path, name, definition, flags, logon, task, TRUE);
365 if (hr != S_OK)
366 ITaskDefinition_Release(definition);
368 if (regtask)
369 IRegisteredTask_Release(regtask);
371 return hr;
374 static HRESULT WINAPI TaskFolder_GetSecurityDescriptor(ITaskFolder *iface, LONG info, BSTR *sddl)
376 FIXME("%p,%x,%p: stub\n", iface, info, sddl);
377 return E_NOTIMPL;
380 static HRESULT WINAPI TaskFolder_SetSecurityDescriptor(ITaskFolder *iface, BSTR sddl, LONG flags)
382 FIXME("%p,%s,%x: stub\n", iface, debugstr_w(sddl), flags);
383 return E_NOTIMPL;
386 static const ITaskFolderVtbl TaskFolder_vtbl =
388 TaskFolder_QueryInterface,
389 TaskFolder_AddRef,
390 TaskFolder_Release,
391 TaskFolder_GetTypeInfoCount,
392 TaskFolder_GetTypeInfo,
393 TaskFolder_GetIDsOfNames,
394 TaskFolder_Invoke,
395 TaskFolder_get_Name,
396 TaskFolder_get_Path,
397 TaskFolder_GetFolder,
398 TaskFolder_GetFolders,
399 TaskFolder_CreateFolder,
400 TaskFolder_DeleteFolder,
401 TaskFolder_GetTask,
402 TaskFolder_GetTasks,
403 TaskFolder_DeleteTask,
404 TaskFolder_RegisterTask,
405 TaskFolder_RegisterTaskDefinition,
406 TaskFolder_GetSecurityDescriptor,
407 TaskFolder_SetSecurityDescriptor
410 HRESULT TaskFolder_create(const WCHAR *parent, const WCHAR *path, ITaskFolder **obj, BOOL create)
412 TaskFolder *folder;
413 WCHAR *folder_path;
414 HRESULT hr;
416 if (path)
418 int len = lstrlenW(path);
419 if (len && path[len - 1] == '\\') return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
422 folder_path = get_full_path(parent, path);
423 if (!folder_path) return E_OUTOFMEMORY;
425 if (create)
427 hr = SchRpcCreateFolder(folder_path, NULL, 0);
429 else
431 DWORD start_index, count, i;
432 TASK_NAMES names;
434 start_index = 0;
435 names = NULL;
436 hr = SchRpcEnumFolders(folder_path, 0, &start_index, 0, &count, &names);
437 if (hr == S_OK)
439 for (i = 0; i < count; i++)
440 MIDL_user_free(names[i]);
441 MIDL_user_free(names);
443 else
445 if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
446 hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
450 if (FAILED(hr))
452 heap_free(folder_path);
453 return hr;
456 folder = heap_alloc(sizeof(*folder));
457 if (!folder)
459 heap_free(folder_path);
460 return E_OUTOFMEMORY;
463 folder->ITaskFolder_iface.lpVtbl = &TaskFolder_vtbl;
464 folder->ref = 1;
465 folder->path = folder_path;
466 *obj = &folder->ITaskFolder_iface;
468 TRACE("created %p\n", *obj);
470 return S_OK;