schtasks.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * Copyright 2018 Jacek Caban for CodeWeavers
  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. #define COBJMACROS
  19. #include "initguid.h"
  20. #include "taskschd.h"
  21. #include "wine/test.h"
  22. static ITaskService *service;
  23. static ITaskFolder *root;
  24. static const char xml_a[] =
  25. "<?xml version=\"1.0\"?>\n"
  26. "<Task xmlns=\"http://schemas.microsoft.com/windows/2004/02/mit/task\">\n"
  27. " <RegistrationInfo>\n"
  28. " <Description>\"Task1\"</Description>\n"
  29. " </RegistrationInfo>\n"
  30. " <Settings>\n"
  31. " <Enabled>false</Enabled>\n"
  32. " <Hidden>false</Hidden>\n"
  33. " </Settings>\n"
  34. " <Actions>\n"
  35. " <Exec>\n"
  36. " <Command>\"task1.exe\"</Command>\n"
  37. " </Exec>\n"
  38. " </Actions>\n"
  39. "</Task>\n";
  40. static WCHAR *a2w(const char *str)
  41. {
  42. WCHAR *ret;
  43. int len;
  44. if(!str)
  45. return NULL;
  46. len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
  47. ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
  48. MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
  49. return ret;
  50. }
  51. #define run_command(a) _run_command(__LINE__,a)
  52. static DWORD _run_command(unsigned line, const char *cmd)
  53. {
  54. STARTUPINFOA si = {sizeof(STARTUPINFOA)};
  55. PROCESS_INFORMATION pi;
  56. char command[1024];
  57. BOOL r;
  58. DWORD ret;
  59. si.dwFlags = STARTF_USESTDHANDLES;
  60. si.hStdInput = INVALID_HANDLE_VALUE;
  61. si.hStdOutput = INVALID_HANDLE_VALUE;
  62. si.hStdError = INVALID_HANDLE_VALUE;
  63. strcpy(command, cmd);
  64. r = CreateProcessA(NULL, command, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
  65. ok_(__FILE__,line)(r, "CreateProcess failed: %lu\n", GetLastError());
  66. if(!r) return -1;
  67. ret = WaitForSingleObject(pi.hProcess, 10000);
  68. ok_(__FILE__,line)(ret == WAIT_OBJECT_0, "wait failed\n");
  69. if (ret == WAIT_TIMEOUT)
  70. TerminateProcess(pi.hProcess, -1);
  71. r = GetExitCodeProcess(pi.hProcess, &ret);
  72. ok_(__FILE__,line)(r, "GetExitCodeProcess failed: %lu\n", GetLastError());
  73. CloseHandle(pi.hThread);
  74. CloseHandle(pi.hProcess);
  75. return ret;
  76. }
  77. #define register_task(a) _register_task(__LINE__,a)
  78. static void _register_task(unsigned line, const char *task_name_a)
  79. {
  80. IRegisteredTask *task;
  81. VARIANT empty;
  82. WCHAR *task_name, *xml;
  83. HRESULT hres;
  84. V_VT(&empty) = VT_EMPTY;
  85. task_name = a2w(task_name_a);
  86. xml = a2w(xml_a);
  87. /* make sure it's not registered */
  88. ITaskFolder_DeleteTask(root, task_name, 0);
  89. hres = ITaskFolder_RegisterTask(root, task_name, xml, TASK_CREATE, empty, empty,
  90. TASK_LOGON_NONE, empty, &task);
  91. ok_(__FILE__,line)(hres == S_OK, "RegisterTask failed: %08lx\n", hres);
  92. HeapFree(GetProcessHeap(), 0, task_name);
  93. HeapFree(GetProcessHeap(), 0, xml);
  94. IRegisteredTask_Release(task);
  95. }
  96. #define unregister_task(a) _unregister_task(__LINE__,a)
  97. static void _unregister_task(unsigned line, const char *task_name_a)
  98. {
  99. WCHAR *task_name;
  100. HRESULT hres;
  101. task_name = a2w(task_name_a);
  102. hres = ITaskFolder_DeleteTask(root, task_name, 0);
  103. ok_(__FILE__,line)(hres == S_OK, "DeleteTask failed: %08lx\n", hres);
  104. HeapFree(GetProcessHeap(), 0, task_name);
  105. }
  106. static void create_file(const char *file_name, const char *data)
  107. {
  108. HANDLE file;
  109. DWORD size;
  110. BOOL r;
  111. file = CreateFileA(file_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
  112. FILE_ATTRIBUTE_NORMAL, NULL);
  113. ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
  114. if(file == INVALID_HANDLE_VALUE)
  115. return;
  116. r = WriteFile(file, data, strlen(data), &size, NULL);
  117. ok(r, "WriteFile failed: %lu\n", GetLastError());
  118. CloseHandle(file);
  119. }
  120. static BOOL initialize_task_service(void)
  121. {
  122. VARIANT empty;
  123. HRESULT hres;
  124. hres = CoCreateInstance(&CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER,
  125. &IID_ITaskService, (void **)&service);
  126. if(hres != S_OK) {
  127. ok(hres == REGDB_E_CLASSNOTREG, "Could not create task service: %08lx\n", hres);
  128. win_skip("Task service not available\n");
  129. return FALSE;
  130. }
  131. V_VT(&empty) = VT_EMPTY;
  132. hres = ITaskService_Connect(service, empty, empty, empty, empty);
  133. ok(hres == S_OK, "Connect failed: %08lx\n", hres);
  134. hres = ITaskService_GetFolder(service, NULL, &root);
  135. ok(hres == S_OK, "GetFolder error %08lx\n", hres);
  136. return TRUE;
  137. }
  138. START_TEST(schtasks)
  139. {
  140. static WCHAR wineW[] = L"\\wine";
  141. static WCHAR wine_testW[] = L"\\wine\\test";
  142. DWORD r;
  143. CoInitialize(NULL);
  144. if(!initialize_task_service()) {
  145. CoUninitialize();
  146. return;
  147. }
  148. r = run_command("schtasks");
  149. ok(r == 0, "r = %lu\n", r);
  150. register_task("winetest");
  151. r = run_command("schtasks /change /tn winetest /enable");
  152. ok(r == 0, "r = %lu\n", r);
  153. unregister_task("winetest");
  154. r = run_command("schtasks /change /tn winetest /enable");
  155. ok(r == 1, "r = %lu\n", r);
  156. register_task("wine\\test\\winetest");
  157. r = run_command("schtasks /CHANGE /tn wine\\test\\winetest /enable");
  158. ok(r == 0, "r = %lu\n", r);
  159. r = run_command("schtasks /delete /f /tn wine\\test\\winetest");
  160. ok(r == 0, "r = %lu\n", r);
  161. r = run_command("schtasks /Change /tn wine\\test\\winetest /enable");
  162. ok(r == 1, "r = %lu\n", r);
  163. create_file("test.xml", xml_a);
  164. r = run_command("schtasks /create /xml test.xml /tn wine\\winetest");
  165. ok(r == 0, "r = %lu\n", r);
  166. r = run_command("schtasks /change /tn wine\\winetest /enable");
  167. ok(r == 0, "r = %lu\n", r);
  168. r = run_command("schtasks /create /xml test.xml /f /tn wine\\winetest");
  169. ok(r == 0, "r = %lu\n", r); /* task already exists, but /f argument provided */
  170. r = run_command("schtasks /create /xml test.xml /tn wine\\winetest");
  171. ok(r == 1, "r = %lu\n", r); /* task already exists */
  172. r = run_command("schtasks /create /tn wine\\winetest");
  173. ok(r == E_FAIL, "r = %lx\n", r); /* missing arguments */
  174. r = run_command("schtasks /Delete /f /tn wine\\winetest");
  175. ok(r == 0, "r = %lu\n", r);
  176. r = DeleteFileA("test.xml");
  177. ok(r, "DeleteFileA failed: %lu\n", GetLastError());
  178. ITaskFolder_DeleteFolder(root, wine_testW, 0);
  179. ITaskFolder_DeleteFolder(root, wineW, 0);
  180. ITaskFolder_Release(root);
  181. ITaskService_Release(service);
  182. CoUninitialize();
  183. }