1 /* 2 * Copyright 2012 Detlef Riekenberg 3 * 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. 8 * 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. 13 * 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 17 */ 18 19 #define COBJMACROS 20 21 #include "initguid.h" 22 #include "taskschd.h" 23 24 #include "wine/debug.h" 25 #include "wine/unicode.h" 26 27 WINE_DEFAULT_DEBUG_CHANNEL(schtasks); 28 29 static const WCHAR change_optW[] = {'/','c','h','a','n','g','e',0}; 30 static const WCHAR create_optW[] = {'/','c','r','e','a','t','e',0}; 31 static const WCHAR delete_optW[] = {'/','d','e','l','e','t','e',0}; 32 static const WCHAR enable_optW[] = {'/','e','n','a','b','l','e',0}; 33 static const WCHAR f_optW[] = {'/','f',0}; 34 static const WCHAR ru_optW[] = {'/','r','u',0}; 35 static const WCHAR tn_optW[] = {'/','t','n',0}; 36 static const WCHAR tr_optW[] = {'/','t','r',0}; 37 static const WCHAR xml_optW[] = {'/','x','m','l',0}; 38 39 static ITaskFolder *get_tasks_root_folder(void) 40 { 41 ITaskService *service; 42 ITaskFolder *root; 43 VARIANT empty; 44 HRESULT hres; 45 46 hres = CoCreateInstance(&CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, 47 &IID_ITaskService, (void**)&service); 48 if (FAILED(hres)) 49 return NULL; 50 51 V_VT(&empty) = VT_EMPTY; 52 hres = ITaskService_Connect(service, empty, empty, empty, empty); 53 if (FAILED(hres)) { 54 FIXME("Connect failed: %08x\n", hres); 55 return NULL; 56 } 57 58 hres = ITaskService_GetFolder(service, NULL, &root); 59 ITaskService_Release(service); 60 if (FAILED(hres)) { 61 FIXME("GetFolder failed: %08x\n", hres); 62 return NULL; 63 } 64 65 return root; 66 } 67 68 static IRegisteredTask *get_registered_task(const WCHAR *name) 69 { 70 IRegisteredTask *registered_task; 71 ITaskFolder *root; 72 BSTR str; 73 HRESULT hres; 74 75 root = get_tasks_root_folder(); 76 if (!root) 77 return NULL; 78 79 str = SysAllocString(name); 80 hres = ITaskFolder_GetTask(root, str, ®istered_task); 81 SysFreeString(str); 82 ITaskFolder_Release(root); 83 if (FAILED(hres)) { 84 FIXME("GetTask failed: %08x\n", hres); 85 return NULL; 86 } 87 88 return registered_task; 89 } 90 91 static BSTR read_file_to_bstr(const WCHAR *file_name) 92 { 93 LARGE_INTEGER file_size; 94 DWORD read_size, size; 95 unsigned char *data; 96 HANDLE file; 97 BOOL r = FALSE; 98 BSTR ret; 99 100 file = CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, 101 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 102 if (file == INVALID_HANDLE_VALUE) { 103 FIXME("Could not open file\n"); 104 return NULL; 105 } 106 107 if (!GetFileSizeEx(file, &file_size) || !file_size.QuadPart) { 108 FIXME("Empty file\n"); 109 CloseHandle(file); 110 return NULL; 111 } 112 113 data = HeapAlloc(GetProcessHeap(), 0, file_size.QuadPart); 114 if (data) 115 r = ReadFile(file, data, file_size.QuadPart, &read_size, NULL); 116 CloseHandle(file); 117 if (!r) { 118 FIXME("Read filed\n"); 119 HeapFree(GetProcessHeap(), 0, data); 120 return NULL; 121 } 122 123 if (read_size > 2 && data[0] == 0xff && data[1] == 0xfe) { /* UTF-16 BOM */ 124 ret = SysAllocStringLen((const WCHAR *)(data + 2), (read_size - 2) / sizeof(WCHAR)); 125 }else { 126 size = MultiByteToWideChar(CP_ACP, 0, (const char *)data, read_size, NULL, 0); 127 ret = SysAllocStringLen(NULL, size); 128 if (ret) 129 MultiByteToWideChar(CP_ACP, 0, (const char *)data, read_size, ret, size); 130 } 131 HeapFree(GetProcessHeap(), 0, data); 132 133 return ret; 134 } 135 136 static int change_command(int argc, WCHAR *argv[]) 137 { 138 BOOL have_option = FALSE, enable = FALSE; 139 const WCHAR *task_name = NULL; 140 IRegisteredTask *task; 141 HRESULT hres; 142 143 while (argc) { 144 if(!strcmpiW(argv[0], tn_optW)) { 145 if (argc < 2) { 146 FIXME("Missing /tn value\n"); 147 return 1; 148 } 149 150 if (task_name) { 151 FIXME("Duplicated /tn argument\n"); 152 return 1; 153 } 154 155 task_name = argv[1]; 156 argc -= 2; 157 argv += 2; 158 }else if (!strcmpiW(argv[0], enable_optW)) { 159 enable = TRUE; 160 have_option = TRUE; 161 argc--; 162 argv++; 163 }else if (!strcmpiW(argv[0], tr_optW)) { 164 if (argc < 2) { 165 FIXME("Missing /tr value\n"); 166 return 1; 167 } 168 169 FIXME("Unsupported /tr option %s\n", debugstr_w(argv[1])); 170 have_option = TRUE; 171 argc -= 2; 172 argv += 2; 173 }else { 174 FIXME("Unsupported arguments %s\n", debugstr_w(argv[0])); 175 return 1; 176 } 177 } 178 179 if (!task_name) { 180 FIXME("Missing /tn option\n"); 181 return 1; 182 } 183 184 if (!have_option) { 185 FIXME("Missing change options\n"); 186 return 1; 187 } 188 189 task = get_registered_task(task_name); 190 if (!task) 191 return 1; 192 193 if (enable) { 194 hres = IRegisteredTask_put_Enabled(task, VARIANT_TRUE); 195 if (FAILED(hres)) { 196 IRegisteredTask_Release(task); 197 FIXME("put_Enabled failed: %08x\n", hres); 198 return 1; 199 } 200 } 201 202 IRegisteredTask_Release(task); 203 return 0; 204 } 205 206 static int create_command(int argc, WCHAR *argv[]) 207 { 208 const WCHAR *task_name = NULL, *xml_file = NULL; 209 ITaskFolder *root = NULL; 210 LONG flags = TASK_CREATE; 211 IRegisteredTask *task; 212 VARIANT empty; 213 BSTR str, xml; 214 HRESULT hres; 215 216 while (argc) { 217 if (!strcmpiW(argv[0], xml_optW)) { 218 if (argc < 2) { 219 FIXME("Missing /xml value\n"); 220 return 1; 221 } 222 223 if (xml_file) { 224 FIXME("Duplicated /xml argument\n"); 225 return 1; 226 } 227 228 xml_file = argv[1]; 229 argc -= 2; 230 argv += 2; 231 }else if(!strcmpiW(argv[0], tn_optW)) { 232 if (argc < 2) { 233 FIXME("Missing /tn value\n"); 234 return 1; 235 } 236 237 if (task_name) { 238 FIXME("Duplicated /tn argument\n"); 239 return 1; 240 } 241 242 task_name = argv[1]; 243 argc -= 2; 244 argv += 2; 245 }else if(!strcmpiW(argv[0], f_optW)) { 246 flags = TASK_CREATE_OR_UPDATE; 247 argc--; 248 argv++; 249 }else if (!strcmpiW(argv[0], ru_optW)) { 250 if (argc < 2) { 251 FIXME("Missing /ru value\n"); 252 return 1; 253 } 254 255 FIXME("Unsupported /ru option %s\n", debugstr_w(argv[1])); 256 argc -= 2; 257 argv += 2; 258 }else { 259 FIXME("Unsupported argument %s\n", debugstr_w(argv[0])); 260 return 1; 261 } 262 } 263 264 if (!task_name) { 265 FIXME("Missing /tn argument\n"); 266 return 1; 267 } 268 269 if (!xml_file) { 270 FIXME("Missing /xml argument\n"); 271 return E_FAIL; 272 } 273 274 xml = read_file_to_bstr(xml_file); 275 if (!xml) 276 return 1; 277 278 root = get_tasks_root_folder(); 279 if (!root) { 280 SysFreeString(xml); 281 return 1; 282 } 283 284 V_VT(&empty) = VT_EMPTY; 285 str = SysAllocString(task_name); 286 hres = ITaskFolder_RegisterTask(root, str, xml, flags, empty, empty, 287 TASK_LOGON_NONE, empty, &task); 288 SysFreeString(str); 289 SysFreeString(xml); 290 ITaskFolder_Release(root); 291 if (FAILED(hres)) 292 return 1; 293 294 IRegisteredTask_Release(task); 295 return 0; 296 } 297 298 static int delete_command(int argc, WCHAR *argv[]) 299 { 300 const WCHAR *task_name = NULL; 301 ITaskFolder *root = NULL; 302 BSTR str; 303 HRESULT hres; 304 305 while (argc) { 306 if (!strcmpiW(argv[0], f_optW)) { 307 TRACE("force opt\n"); 308 argc--; 309 argv++; 310 }else if(!strcmpiW(argv[0], tn_optW)) { 311 if (argc < 2) { 312 FIXME("Missing /tn value\n"); 313 return 1; 314 } 315 316 if (task_name) { 317 FIXME("Duplicated /tn argument\n"); 318 return 1; 319 } 320 321 task_name = argv[1]; 322 argc -= 2; 323 argv += 2; 324 }else { 325 FIXME("Unsupported argument %s\n", debugstr_w(argv[0])); 326 return 1; 327 } 328 } 329 330 if (!task_name) { 331 FIXME("Missing /tn argument\n"); 332 return 1; 333 } 334 335 root = get_tasks_root_folder(); 336 if (!root) 337 return 1; 338 339 str = SysAllocString(task_name); 340 hres = ITaskFolder_DeleteTask(root, str, 0); 341 SysFreeString(str); 342 ITaskFolder_Release(root); 343 if (FAILED(hres)) 344 return 1; 345 346 return 0; 347 } 348 349 int wmain(int argc, WCHAR *argv[]) 350 { 351 int i, ret = 0; 352 353 for (i = 0; i < argc; i++) 354 TRACE(" %s", wine_dbgstr_w(argv[i])); 355 TRACE("\n"); 356 357 CoInitialize(NULL); 358 359 if (argc < 2) 360 FIXME("Print current tasks state\n"); 361 else if (!strcmpiW(argv[1], change_optW)) 362 ret = change_command(argc - 2, argv + 2); 363 else if (!strcmpiW(argv[1], create_optW)) 364 ret = create_command(argc - 2, argv + 2); 365 else if (!strcmpiW(argv[1], delete_optW)) 366 ret = delete_command(argc - 2, argv + 2); 367 else 368 FIXME("Unsupported command %s\n", debugstr_w(argv[1])); 369 370 CoUninitialize(); 371 return ret; 372 } 373