include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / programs / schtasks / schtasks.c
blobc9434801db8a3c6fbb09d8d3333894e31cf1191f
1 /*
2 * Copyright 2012 Detlef Riekenberg
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 #define COBJMACROS
21 #include "initguid.h"
22 #include "taskschd.h"
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(schtasks);
28 static ITaskFolder *get_tasks_root_folder(void)
30 ITaskService *service;
31 ITaskFolder *root;
32 VARIANT empty;
33 HRESULT hres;
35 hres = CoCreateInstance(&CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER,
36 &IID_ITaskService, (void**)&service);
37 if (FAILED(hres))
38 return NULL;
40 V_VT(&empty) = VT_EMPTY;
41 hres = ITaskService_Connect(service, empty, empty, empty, empty);
42 if (FAILED(hres)) {
43 FIXME("Connect failed: %08lx\n", hres);
44 return NULL;
47 hres = ITaskService_GetFolder(service, NULL, &root);
48 ITaskService_Release(service);
49 if (FAILED(hres)) {
50 FIXME("GetFolder failed: %08lx\n", hres);
51 return NULL;
54 return root;
57 static IRegisteredTask *get_registered_task(const WCHAR *name)
59 IRegisteredTask *registered_task;
60 ITaskFolder *root;
61 BSTR str;
62 HRESULT hres;
64 root = get_tasks_root_folder();
65 if (!root)
66 return NULL;
68 str = SysAllocString(name);
69 hres = ITaskFolder_GetTask(root, str, &registered_task);
70 SysFreeString(str);
71 ITaskFolder_Release(root);
72 if (FAILED(hres)) {
73 FIXME("GetTask failed: %08lx\n", hres);
74 return NULL;
77 return registered_task;
80 static BSTR read_file_to_bstr(const WCHAR *file_name)
82 LARGE_INTEGER file_size;
83 DWORD read_size, size;
84 unsigned char *data;
85 HANDLE file;
86 BOOL r = FALSE;
87 BSTR ret;
89 file = CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL,
90 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
91 if (file == INVALID_HANDLE_VALUE) {
92 FIXME("Could not open file\n");
93 return NULL;
96 if (!GetFileSizeEx(file, &file_size) || !file_size.QuadPart) {
97 FIXME("Empty file\n");
98 CloseHandle(file);
99 return NULL;
102 data = HeapAlloc(GetProcessHeap(), 0, file_size.QuadPart);
103 if (data)
104 r = ReadFile(file, data, file_size.QuadPart, &read_size, NULL);
105 CloseHandle(file);
106 if (!r) {
107 FIXME("Read failed\n");
108 HeapFree(GetProcessHeap(), 0, data);
109 return NULL;
112 if (read_size > 2 && data[0] == 0xff && data[1] == 0xfe) { /* UTF-16 BOM */
113 ret = SysAllocStringLen((const WCHAR *)(data + 2), (read_size - 2) / sizeof(WCHAR));
114 }else {
115 size = MultiByteToWideChar(CP_ACP, 0, (const char *)data, read_size, NULL, 0);
116 ret = SysAllocStringLen(NULL, size);
117 if (ret)
118 MultiByteToWideChar(CP_ACP, 0, (const char *)data, read_size, ret, size);
120 HeapFree(GetProcessHeap(), 0, data);
122 return ret;
125 static int change_command(int argc, WCHAR *argv[])
127 BOOL have_option = FALSE, enable = FALSE;
128 const WCHAR *task_name = NULL;
129 IRegisteredTask *task;
130 HRESULT hres;
132 while (argc) {
133 if (!wcsicmp(argv[0], L"/tn")) {
134 if (argc < 2) {
135 FIXME("Missing /tn value\n");
136 return 1;
139 if (task_name) {
140 FIXME("Duplicated /tn argument\n");
141 return 1;
144 task_name = argv[1];
145 argc -= 2;
146 argv += 2;
147 } else if (!wcsicmp(argv[0], L"/enable")) {
148 enable = TRUE;
149 have_option = TRUE;
150 argc--;
151 argv++;
152 } else if (!wcsicmp(argv[0], L"/tr")) {
153 if (argc < 2) {
154 FIXME("Missing /tr value\n");
155 return 1;
158 FIXME("Unsupported /tr option %s\n", debugstr_w(argv[1]));
159 have_option = TRUE;
160 argc -= 2;
161 argv += 2;
162 }else {
163 FIXME("Unsupported arguments %s\n", debugstr_w(argv[0]));
164 return 1;
168 if (!task_name) {
169 FIXME("Missing /tn option\n");
170 return 1;
173 if (!have_option) {
174 FIXME("Missing change options\n");
175 return 1;
178 task = get_registered_task(task_name);
179 if (!task)
180 return 1;
182 if (enable) {
183 hres = IRegisteredTask_put_Enabled(task, VARIANT_TRUE);
184 if (FAILED(hres)) {
185 IRegisteredTask_Release(task);
186 FIXME("put_Enabled failed: %08lx\n", hres);
187 return 1;
191 IRegisteredTask_Release(task);
192 return 0;
195 static int create_command(int argc, WCHAR *argv[])
197 const WCHAR *task_name = NULL, *xml_file = NULL;
198 ITaskFolder *root = NULL;
199 LONG flags = TASK_CREATE;
200 IRegisteredTask *task;
201 VARIANT empty;
202 BSTR str, xml;
203 HRESULT hres;
205 while (argc) {
206 if (!wcsicmp(argv[0], L"/xml")) {
207 if (argc < 2) {
208 FIXME("Missing /xml value\n");
209 return 1;
212 if (xml_file) {
213 FIXME("Duplicated /xml argument\n");
214 return 1;
217 xml_file = argv[1];
218 argc -= 2;
219 argv += 2;
220 } else if (!wcsicmp(argv[0], L"/tn")) {
221 if (argc < 2) {
222 FIXME("Missing /tn value\n");
223 return 1;
226 if (task_name) {
227 FIXME("Duplicated /tn argument\n");
228 return 1;
231 task_name = argv[1];
232 argc -= 2;
233 argv += 2;
234 } else if (!wcsicmp(argv[0], L"/f")) {
235 flags = TASK_CREATE_OR_UPDATE;
236 argc--;
237 argv++;
238 } else if (!wcsicmp(argv[0], L"/ru")) {
239 if (argc < 2) {
240 FIXME("Missing /ru value\n");
241 return 1;
244 FIXME("Unsupported /ru option %s\n", debugstr_w(argv[1]));
245 argc -= 2;
246 argv += 2;
247 }else {
248 FIXME("Unsupported argument %s\n", debugstr_w(argv[0]));
249 return 1;
253 if (!task_name) {
254 FIXME("Missing /tn argument\n");
255 return 1;
258 if (!xml_file) {
259 FIXME("Missing /xml argument\n");
260 return E_FAIL;
263 xml = read_file_to_bstr(xml_file);
264 if (!xml)
265 return 1;
267 root = get_tasks_root_folder();
268 if (!root) {
269 SysFreeString(xml);
270 return 1;
273 V_VT(&empty) = VT_EMPTY;
274 str = SysAllocString(task_name);
275 hres = ITaskFolder_RegisterTask(root, str, xml, flags, empty, empty,
276 TASK_LOGON_NONE, empty, &task);
277 SysFreeString(str);
278 SysFreeString(xml);
279 ITaskFolder_Release(root);
280 if (FAILED(hres))
281 return 1;
283 IRegisteredTask_Release(task);
284 return 0;
287 static int delete_command(int argc, WCHAR *argv[])
289 const WCHAR *task_name = NULL;
290 ITaskFolder *root = NULL;
291 BSTR str;
292 HRESULT hres;
294 while (argc) {
295 if (!wcsicmp(argv[0], L"/f")) {
296 TRACE("force opt\n");
297 argc--;
298 argv++;
299 } else if (!wcsicmp(argv[0], L"/tn")) {
300 if (argc < 2) {
301 FIXME("Missing /tn value\n");
302 return 1;
305 if (task_name) {
306 FIXME("Duplicated /tn argument\n");
307 return 1;
310 task_name = argv[1];
311 argc -= 2;
312 argv += 2;
313 }else {
314 FIXME("Unsupported argument %s\n", debugstr_w(argv[0]));
315 return 1;
319 if (!task_name) {
320 FIXME("Missing /tn argument\n");
321 return 1;
324 root = get_tasks_root_folder();
325 if (!root)
326 return 1;
328 str = SysAllocString(task_name);
329 hres = ITaskFolder_DeleteTask(root, str, 0);
330 SysFreeString(str);
331 ITaskFolder_Release(root);
332 if (FAILED(hres))
333 return 1;
335 return 0;
338 int __cdecl wmain(int argc, WCHAR *argv[])
340 int i, ret = 0;
342 for (i = 0; i < argc; i++)
343 TRACE(" %s", wine_dbgstr_w(argv[i]));
344 TRACE("\n");
346 CoInitialize(NULL);
348 if (argc < 2)
349 FIXME("Print current tasks state\n");
350 else if (!wcsicmp(argv[1], L"/change"))
351 ret = change_command(argc - 2, argv + 2);
352 else if (!wcsicmp(argv[1], L"/create"))
353 ret = create_command(argc - 2, argv + 2);
354 else if (!wcsicmp(argv[1], L"/delete"))
355 ret = delete_command(argc - 2, argv + 2);
356 else
357 FIXME("Unsupported command %s\n", debugstr_w(argv[1]));
359 CoUninitialize();
360 return ret;