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
29 #include "taskschd_private.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(taskschd
);
37 ITaskFolder ITaskFolder_iface
;
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
);
60 TRACE("destroying %p\n", iface
);
61 heap_free(folder
->path
);
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
);
83 FIXME("interface %s is not implemented\n", debugstr_guid(riid
));
88 static HRESULT WINAPI
TaskFolder_GetTypeInfoCount(ITaskFolder
*iface
, UINT
*count
)
90 FIXME("%p,%p: stub\n", iface
, count
);
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
);
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
);
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
);
115 static HRESULT WINAPI
TaskFolder_get_Name(ITaskFolder
*iface
, BSTR
*name
)
117 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
120 TRACE("%p,%p\n", iface
, name
);
122 if (!name
) return E_POINTER
;
124 p_name
= wcsrchr(folder
->path
, '\\');
126 p_name
= folder
->path
;
128 if (p_name
[1] != 0) p_name
++;
130 *name
= SysAllocString(p_name
);
131 if (!*name
) return E_OUTOFMEMORY
;
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
;
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
;
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
;
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
);
199 ITaskFolder_Release(tmp_folder
);
204 WCHAR
*get_full_path(const WCHAR
*parent
, const WCHAR
*path
)
209 if (path
) len
= lstrlenW(path
);
211 if (parent
) len
+= lstrlenW(parent
);
213 /* +1 if parent is not '\' terminated */
214 folder_path
= heap_alloc((len
+ 2) * sizeof(WCHAR
));
215 if (!folder_path
) return NULL
;
220 lstrcpyW(folder_path
, parent
);
224 len
= lstrlenW(folder_path
);
225 if (!len
|| folder_path
[len
- 1] != '\\')
226 lstrcatW(folder_path
, L
"\\");
228 while (*path
== '\\') path
++;
229 lstrcatW(folder_path
, path
);
232 len
= lstrlenW(folder_path
);
234 lstrcatW(folder_path
, L
"\\");
239 static HRESULT WINAPI
TaskFolder_DeleteFolder(ITaskFolder
*iface
, BSTR name
, LONG flags
)
241 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
245 TRACE("%p,%s,%x\n", iface
, debugstr_w(name
), flags
);
247 if (!name
|| !*name
) return E_ACCESSDENIED
;
250 FIXME("unsupported flags %x\n", flags
);
252 folder_path
= get_full_path(folder
->path
, name
);
253 if (!folder_path
) return E_OUTOFMEMORY
;
255 hr
= SchRpcDelete(folder_path
, 0);
256 heap_free(folder_path
);
260 static HRESULT WINAPI
TaskFolder_GetTask(ITaskFolder
*iface
, BSTR name
, IRegisteredTask
**task
)
262 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
263 ITaskDefinition
*taskdef
;
266 TRACE("%p,%s,%p\n", iface
, debugstr_w(name
), task
);
268 if (!task
) return E_POINTER
;
270 hr
= TaskDefinition_create(&taskdef
);
271 if (hr
!= S_OK
) return hr
;
273 hr
= RegisteredTask_create(folder
->path
, name
, taskdef
, 0, 0, task
, FALSE
);
275 ITaskDefinition_Release(taskdef
);
279 static HRESULT WINAPI
TaskFolder_GetTasks(ITaskFolder
*iface
, LONG flags
, IRegisteredTaskCollection
**tasks
)
281 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
283 TRACE("%p,%x,%p: stub\n", iface
, flags
, tasks
);
285 if (!tasks
) return E_POINTER
;
287 return RegisteredTaskCollection_create(folder
->path
, tasks
);
290 static HRESULT WINAPI
TaskFolder_DeleteTask(ITaskFolder
*iface
, BSTR name
, LONG flags
)
292 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
296 TRACE("%p,%s,%x\n", iface
, debugstr_w(name
), flags
);
298 if (!name
|| !*name
) return E_ACCESSDENIED
;
301 FIXME("unsupported flags %x\n", flags
);
303 folder_path
= get_full_path(folder
->path
, name
);
304 if (!folder_path
) return E_OUTOFMEMORY
;
306 hr
= SchRpcDelete(folder_path
, 0);
307 heap_free(folder_path
);
311 static HRESULT WINAPI
TaskFolder_RegisterTask(ITaskFolder
*iface
, BSTR name
, BSTR xml
, LONG flags
,
312 VARIANT user
, VARIANT password
, TASK_LOGON_TYPE logon
,
313 VARIANT sddl
, IRegisteredTask
**task
)
315 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
316 IRegisteredTask
*regtask
= NULL
;
317 ITaskDefinition
*taskdef
;
320 TRACE("%p,%s,%s,%x,%s,%s,%d,%s,%p\n", iface
, debugstr_w(name
), debugstr_w(xml
), flags
,
321 debugstr_variant(&user
), debugstr_variant(&password
), logon
, debugstr_variant(&sddl
), task
);
323 if (!xml
) return HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
);
325 if (!task
) task
= ®task
;
327 hr
= TaskDefinition_create(&taskdef
);
328 if (hr
!= S_OK
) return hr
;
330 hr
= ITaskDefinition_put_XmlText(taskdef
, xml
);
332 hr
= RegisteredTask_create(folder
->path
, name
, taskdef
, flags
, logon
, task
, TRUE
);
335 ITaskDefinition_Release(taskdef
);
338 IRegisteredTask_Release(regtask
);
343 static HRESULT WINAPI
TaskFolder_RegisterTaskDefinition(ITaskFolder
*iface
, BSTR name
, ITaskDefinition
*definition
, LONG flags
,
344 VARIANT user
, VARIANT password
, TASK_LOGON_TYPE logon
,
345 VARIANT sddl
, IRegisteredTask
**task
)
347 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
348 IRegisteredTask
*regtask
= NULL
;
351 FIXME("%p,%s,%p,%x,%s,%s,%d,%s,%p: stub\n", iface
, debugstr_w(name
), definition
, flags
,
352 debugstr_variant(&user
), debugstr_variant(&password
), logon
, debugstr_variant(&sddl
), task
);
354 if (!is_variant_null(&sddl
))
355 FIXME("security descriptor %s is ignored\n", debugstr_variant(&sddl
));
357 if (!is_variant_null(&user
) || !is_variant_null(&password
))
358 FIXME("user/password are ignored\n");
360 if (!task
) task
= ®task
;
362 ITaskDefinition_AddRef(definition
);
363 hr
= RegisteredTask_create(folder
->path
, name
, definition
, flags
, logon
, task
, TRUE
);
365 ITaskDefinition_Release(definition
);
368 IRegisteredTask_Release(regtask
);
373 static HRESULT WINAPI
TaskFolder_GetSecurityDescriptor(ITaskFolder
*iface
, LONG info
, BSTR
*sddl
)
375 FIXME("%p,%x,%p: stub\n", iface
, info
, sddl
);
379 static HRESULT WINAPI
TaskFolder_SetSecurityDescriptor(ITaskFolder
*iface
, BSTR sddl
, LONG flags
)
381 FIXME("%p,%s,%x: stub\n", iface
, debugstr_w(sddl
), flags
);
385 static const ITaskFolderVtbl TaskFolder_vtbl
=
387 TaskFolder_QueryInterface
,
390 TaskFolder_GetTypeInfoCount
,
391 TaskFolder_GetTypeInfo
,
392 TaskFolder_GetIDsOfNames
,
396 TaskFolder_GetFolder
,
397 TaskFolder_GetFolders
,
398 TaskFolder_CreateFolder
,
399 TaskFolder_DeleteFolder
,
402 TaskFolder_DeleteTask
,
403 TaskFolder_RegisterTask
,
404 TaskFolder_RegisterTaskDefinition
,
405 TaskFolder_GetSecurityDescriptor
,
406 TaskFolder_SetSecurityDescriptor
409 HRESULT
TaskFolder_create(const WCHAR
*parent
, const WCHAR
*path
, ITaskFolder
**obj
, BOOL create
)
417 int len
= lstrlenW(path
);
418 if (len
&& path
[len
- 1] == '\\') return HRESULT_FROM_WIN32(ERROR_INVALID_NAME
);
421 folder_path
= get_full_path(parent
, path
);
422 if (!folder_path
) return E_OUTOFMEMORY
;
426 hr
= SchRpcCreateFolder(folder_path
, NULL
, 0);
430 DWORD start_index
, count
, i
;
435 hr
= SchRpcEnumFolders(folder_path
, 0, &start_index
, 0, &count
, &names
);
438 for (i
= 0; i
< count
; i
++)
439 MIDL_user_free(names
[i
]);
440 MIDL_user_free(names
);
444 if (hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
))
445 hr
= HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
);
451 heap_free(folder_path
);
455 folder
= heap_alloc(sizeof(*folder
));
458 heap_free(folder_path
);
459 return E_OUTOFMEMORY
;
462 folder
->ITaskFolder_iface
.lpVtbl
= &TaskFolder_vtbl
;
464 folder
->path
= folder_path
;
465 *obj
= &folder
->ITaskFolder_iface
;
467 TRACE("created %p\n", *obj
);