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/unicode.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(taskschd
);
38 ITaskFolder ITaskFolder_iface
;
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
);
61 TRACE("destroying %p\n", iface
);
62 heap_free(folder
->path
);
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
);
84 FIXME("interface %s is not implemented\n", debugstr_guid(riid
));
89 static HRESULT WINAPI
TaskFolder_GetTypeInfoCount(ITaskFolder
*iface
, UINT
*count
)
91 FIXME("%p,%p: stub\n", iface
, count
);
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
);
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
);
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
);
116 static HRESULT WINAPI
TaskFolder_get_Name(ITaskFolder
*iface
, BSTR
*name
)
118 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
121 TRACE("%p,%p\n", iface
, name
);
123 if (!name
) return E_POINTER
;
125 p_name
= strrchrW(folder
->path
, '\\');
127 p_name
= folder
->path
;
129 if (p_name
[1] != 0) p_name
++;
131 *name
= SysAllocString(p_name
);
132 if (!*name
) return E_OUTOFMEMORY
;
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
;
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
;
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
;
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
);
200 ITaskFolder_Release(tmp_folder
);
205 WCHAR
*get_full_path(const WCHAR
*parent
, const WCHAR
*path
)
207 static const WCHAR bslash
[] = { '\\', 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
;
222 strcpyW(folder_path
, parent
);
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
);
236 strcatW(folder_path
, bslash
);
241 static HRESULT WINAPI
TaskFolder_DeleteFolder(ITaskFolder
*iface
, BSTR name
, LONG flags
)
243 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
247 TRACE("%p,%s,%x\n", iface
, debugstr_w(name
), flags
);
249 if (!name
|| !*name
) return E_ACCESSDENIED
;
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
);
262 static HRESULT WINAPI
TaskFolder_GetTask(ITaskFolder
*iface
, BSTR name
, IRegisteredTask
**task
)
264 TaskFolder
*folder
= impl_from_ITaskFolder(iface
);
265 ITaskDefinition
*taskdef
;
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
);
277 ITaskDefinition_Release(taskdef
);
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
);
298 TRACE("%p,%s,%x\n", iface
, debugstr_w(name
), flags
);
300 if (!name
|| !*name
) return E_ACCESSDENIED
;
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
);
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
;
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
= ®task
;
329 hr
= TaskDefinition_create(&taskdef
);
330 if (hr
!= S_OK
) return hr
;
332 hr
= ITaskDefinition_put_XmlText(taskdef
, xml
);
334 hr
= RegisteredTask_create(folder
->path
, name
, taskdef
, flags
, logon
, task
, TRUE
);
337 ITaskDefinition_Release(taskdef
);
340 IRegisteredTask_Release(regtask
);
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
;
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
= ®task
;
364 ITaskDefinition_AddRef(definition
);
365 hr
= RegisteredTask_create(folder
->path
, name
, definition
, flags
, logon
, task
, TRUE
);
367 ITaskDefinition_Release(definition
);
370 IRegisteredTask_Release(regtask
);
375 static HRESULT WINAPI
TaskFolder_GetSecurityDescriptor(ITaskFolder
*iface
, LONG info
, BSTR
*sddl
)
377 FIXME("%p,%x,%p: stub\n", iface
, info
, sddl
);
381 static HRESULT WINAPI
TaskFolder_SetSecurityDescriptor(ITaskFolder
*iface
, BSTR sddl
, LONG flags
)
383 FIXME("%p,%s,%x: stub\n", iface
, debugstr_w(sddl
), flags
);
387 static const ITaskFolderVtbl TaskFolder_vtbl
=
389 TaskFolder_QueryInterface
,
392 TaskFolder_GetTypeInfoCount
,
393 TaskFolder_GetTypeInfo
,
394 TaskFolder_GetIDsOfNames
,
398 TaskFolder_GetFolder
,
399 TaskFolder_GetFolders
,
400 TaskFolder_CreateFolder
,
401 TaskFolder_DeleteFolder
,
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
)
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
;
428 hr
= SchRpcCreateFolder(folder_path
, NULL
, 0);
432 DWORD start_index
, count
, i
;
437 hr
= SchRpcEnumFolders(folder_path
, 0, &start_index
, 0, &count
, &names
);
440 for (i
= 0; i
< count
; i
++)
441 MIDL_user_free(names
[i
]);
442 MIDL_user_free(names
);
446 if (hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
))
447 hr
= HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
);
453 heap_free(folder_path
);
457 folder
= heap_alloc(sizeof(*folder
));
460 heap_free(folder_path
);
461 return E_OUTOFMEMORY
;
464 folder
->ITaskFolder_iface
.lpVtbl
= &TaskFolder_vtbl
;
466 folder
->path
= folder_path
;
467 *obj
= &folder
->ITaskFolder_iface
;
469 TRACE("created %p\n", *obj
);