dmstyle: Remove the extraneous IUnknown from DMCommandTrack.
[wine.git] / dlls / taskschd / folder.c
blobc0eb1fb1fb056779fc7b36d9569a4c59c6403dac
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/unicode.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(taskschd);
36 typedef struct
38 ITaskFolder ITaskFolder_iface;
39 LONG ref;
40 WCHAR *path;
41 } TaskFolder;
43 static inline TaskFolder *impl_from_ITaskFolder(ITaskFolder *iface)
45 return CONTAINING_RECORD(iface, TaskFolder, ITaskFolder_iface);
48 static ULONG WINAPI TaskFolder_AddRef(ITaskFolder *iface)
50 TaskFolder *folder = impl_from_ITaskFolder(iface);
51 return InterlockedIncrement(&folder->ref);
54 static ULONG WINAPI TaskFolder_Release(ITaskFolder *iface)
56 TaskFolder *folder = impl_from_ITaskFolder(iface);
57 LONG ref = InterlockedDecrement(&folder->ref);
59 if (!ref)
61 TRACE("destroying %p\n", iface);
62 heap_free(folder->path);
63 heap_free(folder);
66 return ref;
69 static HRESULT WINAPI TaskFolder_QueryInterface(ITaskFolder *iface, REFIID riid, void **obj)
71 if (!riid || !obj) return E_INVALIDARG;
73 TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj);
75 if (IsEqualGUID(riid, &IID_ITaskFolder) ||
76 IsEqualGUID(riid, &IID_IDispatch) ||
77 IsEqualGUID(riid, &IID_IUnknown))
79 ITaskFolder_AddRef(iface);
80 *obj = iface;
81 return S_OK;
84 FIXME("interface %s is not implemented\n", debugstr_guid(riid));
85 *obj = NULL;
86 return E_NOINTERFACE;
89 static HRESULT WINAPI TaskFolder_GetTypeInfoCount(ITaskFolder *iface, UINT *count)
91 FIXME("%p,%p: stub\n", iface, count);
92 return E_NOTIMPL;
95 static HRESULT WINAPI TaskFolder_GetTypeInfo(ITaskFolder *iface, UINT index, LCID lcid, ITypeInfo **info)
97 FIXME("%p,%u,%u,%p: stub\n", iface, index, lcid, info);
98 return E_NOTIMPL;
101 static HRESULT WINAPI TaskFolder_GetIDsOfNames(ITaskFolder *iface, REFIID riid, LPOLESTR *names,
102 UINT count, LCID lcid, DISPID *dispid)
104 FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid);
105 return E_NOTIMPL;
108 static HRESULT WINAPI TaskFolder_Invoke(ITaskFolder *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags,
109 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr)
111 FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags,
112 params, result, excepinfo, argerr);
113 return E_NOTIMPL;
116 static HRESULT WINAPI TaskFolder_get_Name(ITaskFolder *iface, BSTR *name)
118 TaskFolder *folder = impl_from_ITaskFolder(iface);
119 const WCHAR *p_name;
121 TRACE("%p,%p\n", iface, name);
123 if (!name) return E_POINTER;
125 p_name = strrchrW(folder->path, '\\');
126 if (!p_name)
127 p_name = folder->path;
128 else
129 if (p_name[1] != 0) p_name++;
131 *name = SysAllocString(p_name);
132 if (!*name) return E_OUTOFMEMORY;
134 return S_OK;
137 static HRESULT WINAPI TaskFolder_get_Path(ITaskFolder *iface, BSTR *path)
139 TaskFolder *folder = impl_from_ITaskFolder(iface);
141 TRACE("%p,%p\n", iface, path);
143 if (!path) return E_POINTER;
145 *path = SysAllocString(folder->path);
146 if (!*path) return E_OUTOFMEMORY;
148 return S_OK;
151 static HRESULT WINAPI TaskFolder_GetFolder(ITaskFolder *iface, BSTR path, ITaskFolder **new_folder)
153 TaskFolder *folder = impl_from_ITaskFolder(iface);
155 TRACE("%p,%s,%p\n", iface, debugstr_w(path), folder);
157 if (!path) return E_INVALIDARG;
158 if (!new_folder) return E_POINTER;
160 return TaskFolder_create(folder->path, path, new_folder, FALSE);
163 static HRESULT WINAPI TaskFolder_GetFolders(ITaskFolder *iface, LONG flags, ITaskFolderCollection **folders)
165 TaskFolder *folder = impl_from_ITaskFolder(iface);
167 TRACE("%p,%x,%p: stub\n", iface, flags, folders);
169 if (!folders) return E_POINTER;
171 if (flags)
172 FIXME("unsupported flags %x\n", flags);
174 return TaskFolderCollection_create(folder->path, folders);
177 static inline BOOL is_variant_null(const VARIANT *var)
179 return V_VT(var) == VT_EMPTY || V_VT(var) == VT_NULL ||
180 (V_VT(var) == VT_BSTR && (V_BSTR(var) == NULL || !*V_BSTR(var)));
183 static HRESULT WINAPI TaskFolder_CreateFolder(ITaskFolder *iface, BSTR path, VARIANT sddl, ITaskFolder **new_folder)
185 TaskFolder *folder = impl_from_ITaskFolder(iface);
186 ITaskFolder *tmp_folder = NULL;
187 HRESULT hr;
189 TRACE("%p,%s,%s,%p\n", iface, debugstr_w(path), debugstr_variant(&sddl), folder);
191 if (!path) return E_INVALIDARG;
193 if (!new_folder) new_folder = &tmp_folder;
195 if (!is_variant_null(&sddl))
196 FIXME("security descriptor %s is ignored\n", debugstr_variant(&sddl));
198 hr = TaskFolder_create(folder->path, path, new_folder, TRUE);
199 if (tmp_folder)
200 ITaskFolder_Release(tmp_folder);
202 return hr;
205 WCHAR *get_full_path(const WCHAR *parent, const WCHAR *path)
207 static const WCHAR bslash[] = { '\\', 0 };
208 WCHAR *folder_path;
209 int len = 0;
211 if (path) len = strlenW(path);
213 if (parent) len += strlenW(parent);
215 /* +1 if parent is not '\' terminated */
216 folder_path = heap_alloc((len + 2) * sizeof(WCHAR));
217 if (!folder_path) return NULL;
219 folder_path[0] = 0;
221 if (parent)
222 strcpyW(folder_path, parent);
224 if (path && *path)
226 len = strlenW(folder_path);
227 if (!len || folder_path[len - 1] != '\\')
228 strcatW(folder_path, bslash);
230 while (*path == '\\') path++;
231 strcatW(folder_path, path);
234 len = strlenW(folder_path);
235 if (!len)
236 strcatW(folder_path, bslash);
238 return folder_path;
241 static HRESULT WINAPI TaskFolder_DeleteFolder(ITaskFolder *iface, BSTR name, LONG flags)
243 TaskFolder *folder = impl_from_ITaskFolder(iface);
244 WCHAR *folder_path;
245 HRESULT hr;
247 TRACE("%p,%s,%x\n", iface, debugstr_w(name), flags);
249 if (!name || !*name) return E_ACCESSDENIED;
251 if (flags)
252 FIXME("unsupported flags %x\n", flags);
254 folder_path = get_full_path(folder->path, name);
255 if (!folder_path) return E_OUTOFMEMORY;
257 hr = SchRpcDelete(folder_path, 0);
258 heap_free(folder_path);
259 return hr;
262 static HRESULT WINAPI TaskFolder_GetTask(ITaskFolder *iface, BSTR name, IRegisteredTask **task)
264 TaskFolder *folder = impl_from_ITaskFolder(iface);
265 ITaskDefinition *taskdef;
266 HRESULT hr;
268 TRACE("%p,%s,%p\n", iface, debugstr_w(name), task);
270 if (!task) return E_POINTER;
272 hr = TaskDefinition_create(&taskdef);
273 if (hr != S_OK) return hr;
275 hr = RegisteredTask_create(folder->path, name, taskdef, 0, 0, task, FALSE);
276 if (hr != S_OK)
277 ITaskDefinition_Release(taskdef);
278 return hr;
281 static HRESULT WINAPI TaskFolder_GetTasks(ITaskFolder *iface, LONG flags, IRegisteredTaskCollection **tasks)
283 TaskFolder *folder = impl_from_ITaskFolder(iface);
285 TRACE("%p,%x,%p: stub\n", iface, flags, tasks);
287 if (!tasks) return E_POINTER;
289 return RegisteredTaskCollection_create(folder->path, tasks);
292 static HRESULT WINAPI TaskFolder_DeleteTask(ITaskFolder *iface, BSTR name, LONG flags)
294 TaskFolder *folder = impl_from_ITaskFolder(iface);
295 WCHAR *folder_path;
296 HRESULT hr;
298 TRACE("%p,%s,%x\n", iface, debugstr_w(name), flags);
300 if (!name || !*name) return E_ACCESSDENIED;
302 if (flags)
303 FIXME("unsupported flags %x\n", flags);
305 folder_path = get_full_path(folder->path, name);
306 if (!folder_path) return E_OUTOFMEMORY;
308 hr = SchRpcDelete(folder_path, 0);
309 heap_free(folder_path);
310 return hr;
313 static HRESULT WINAPI TaskFolder_RegisterTask(ITaskFolder *iface, BSTR name, BSTR xml, LONG flags,
314 VARIANT user, VARIANT password, TASK_LOGON_TYPE logon,
315 VARIANT sddl, IRegisteredTask **task)
317 TaskFolder *folder = impl_from_ITaskFolder(iface);
318 IRegisteredTask *regtask = NULL;
319 ITaskDefinition *taskdef;
320 HRESULT hr;
322 TRACE("%p,%s,%s,%x,%s,%s,%d,%s,%p\n", iface, debugstr_w(name), debugstr_w(xml), flags,
323 debugstr_variant(&user), debugstr_variant(&password), logon, debugstr_variant(&sddl), task);
325 if (!xml) return HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER);
327 if (!task) task = &regtask;
329 hr = TaskDefinition_create(&taskdef);
330 if (hr != S_OK) return hr;
332 hr = ITaskDefinition_put_XmlText(taskdef, xml);
333 if (hr == S_OK)
334 hr = RegisteredTask_create(folder->path, name, taskdef, flags, logon, task, TRUE);
336 if (hr != S_OK)
337 ITaskDefinition_Release(taskdef);
339 if (regtask)
340 IRegisteredTask_Release(regtask);
342 return hr;
345 static HRESULT WINAPI TaskFolder_RegisterTaskDefinition(ITaskFolder *iface, BSTR name, ITaskDefinition *definition, LONG flags,
346 VARIANT user, VARIANT password, TASK_LOGON_TYPE logon,
347 VARIANT sddl, IRegisteredTask **task)
349 TaskFolder *folder = impl_from_ITaskFolder(iface);
350 IRegisteredTask *regtask = NULL;
351 HRESULT hr;
353 FIXME("%p,%s,%p,%x,%s,%s,%d,%s,%p: stub\n", iface, debugstr_w(name), definition, flags,
354 debugstr_variant(&user), debugstr_variant(&password), logon, debugstr_variant(&sddl), task);
356 if (!is_variant_null(&sddl))
357 FIXME("security descriptor %s is ignored\n", debugstr_variant(&sddl));
359 if (!is_variant_null(&user) || !is_variant_null(&password))
360 FIXME("user/password are ignored\n");
362 if (!task) task = &regtask;
364 ITaskDefinition_AddRef(definition);
365 hr = RegisteredTask_create(folder->path, name, definition, flags, logon, task, TRUE);
366 if (hr != S_OK)
367 ITaskDefinition_Release(definition);
369 if (regtask)
370 IRegisteredTask_Release(regtask);
372 return hr;
375 static HRESULT WINAPI TaskFolder_GetSecurityDescriptor(ITaskFolder *iface, LONG info, BSTR *sddl)
377 FIXME("%p,%x,%p: stub\n", iface, info, sddl);
378 return E_NOTIMPL;
381 static HRESULT WINAPI TaskFolder_SetSecurityDescriptor(ITaskFolder *iface, BSTR sddl, LONG flags)
383 FIXME("%p,%s,%x: stub\n", iface, debugstr_w(sddl), flags);
384 return E_NOTIMPL;
387 static const ITaskFolderVtbl TaskFolder_vtbl =
389 TaskFolder_QueryInterface,
390 TaskFolder_AddRef,
391 TaskFolder_Release,
392 TaskFolder_GetTypeInfoCount,
393 TaskFolder_GetTypeInfo,
394 TaskFolder_GetIDsOfNames,
395 TaskFolder_Invoke,
396 TaskFolder_get_Name,
397 TaskFolder_get_Path,
398 TaskFolder_GetFolder,
399 TaskFolder_GetFolders,
400 TaskFolder_CreateFolder,
401 TaskFolder_DeleteFolder,
402 TaskFolder_GetTask,
403 TaskFolder_GetTasks,
404 TaskFolder_DeleteTask,
405 TaskFolder_RegisterTask,
406 TaskFolder_RegisterTaskDefinition,
407 TaskFolder_GetSecurityDescriptor,
408 TaskFolder_SetSecurityDescriptor
411 HRESULT TaskFolder_create(const WCHAR *parent, const WCHAR *path, ITaskFolder **obj, BOOL create)
413 TaskFolder *folder;
414 WCHAR *folder_path;
415 HRESULT hr;
417 if (path)
419 int len = strlenW(path);
420 if (len && path[len - 1] == '\\') return ERROR_INVALID_NAME;
423 folder_path = get_full_path(parent, path);
424 if (!folder_path) return E_OUTOFMEMORY;
426 if (create)
428 hr = SchRpcCreateFolder(folder_path, NULL, 0);
430 else
432 DWORD start_index, count, i;
433 TASK_NAMES names;
435 start_index = 0;
436 names = NULL;
437 hr = SchRpcEnumFolders(folder_path, 0, &start_index, 0, &count, &names);
438 if (hr == S_OK)
440 for (i = 0; i < count; i++)
441 MIDL_user_free(names[i]);
442 MIDL_user_free(names);
444 else
446 if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
447 hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
451 if (FAILED(hr))
453 heap_free(folder_path);
454 return hr;
457 folder = heap_alloc(sizeof(*folder));
458 if (!folder)
460 heap_free(folder_path);
461 return E_OUTOFMEMORY;
464 folder->ITaskFolder_iface.lpVtbl = &TaskFolder_vtbl;
465 folder->ref = 1;
466 folder->path = folder_path;
467 *obj = &folder->ITaskFolder_iface;
469 TRACE("created %p\n", *obj);
471 return S_OK;