rpc.c 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170
  1. /*
  2. * Services.exe - RPC functions
  3. *
  4. * Copyright 2007 Google (Mikolaj Zalewski)
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  19. */
  20. #define WIN32_LEAN_AND_MEAN
  21. #define NONAMELESSSTRUCT
  22. #define NONAMELESSUNION
  23. #include <stdarg.h>
  24. #include <windows.h>
  25. #include <winternl.h>
  26. #include <winsvc.h>
  27. #include <ntsecapi.h>
  28. #include <rpc.h>
  29. #include "wine/list.h"
  30. #include "wine/debug.h"
  31. #include "services.h"
  32. #include "svcctl.h"
  33. WINE_DEFAULT_DEBUG_CHANNEL(service);
  34. static const GENERIC_MAPPING g_scm_generic =
  35. {
  36. (STANDARD_RIGHTS_READ | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS),
  37. (STANDARD_RIGHTS_WRITE | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_MODIFY_BOOT_CONFIG),
  38. (STANDARD_RIGHTS_EXECUTE | SC_MANAGER_CONNECT | SC_MANAGER_LOCK),
  39. SC_MANAGER_ALL_ACCESS
  40. };
  41. static const GENERIC_MAPPING g_svc_generic =
  42. {
  43. (STANDARD_RIGHTS_READ | SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_INTERROGATE | SERVICE_ENUMERATE_DEPENDENTS),
  44. (STANDARD_RIGHTS_WRITE | SERVICE_CHANGE_CONFIG),
  45. (STANDARD_RIGHTS_EXECUTE | SERVICE_START | SERVICE_STOP | SERVICE_PAUSE_CONTINUE | SERVICE_USER_DEFINED_CONTROL),
  46. SERVICE_ALL_ACCESS
  47. };
  48. typedef enum
  49. {
  50. SC_HTYPE_DONT_CARE = 0,
  51. SC_HTYPE_MANAGER,
  52. SC_HTYPE_SERVICE,
  53. SC_HTYPE_NOTIFY
  54. } SC_HANDLE_TYPE;
  55. struct sc_handle
  56. {
  57. SC_HANDLE_TYPE type;
  58. DWORD access;
  59. };
  60. struct sc_manager_handle /* service control manager handle */
  61. {
  62. struct sc_handle hdr;
  63. struct scmdatabase *db;
  64. };
  65. struct sc_notify_handle
  66. {
  67. struct sc_handle hdr;
  68. HANDLE event;
  69. DWORD notify_mask;
  70. LONG ref;
  71. SC_RPC_NOTIFY_PARAMS_LIST *params_list;
  72. };
  73. struct sc_service_handle /* service handle */
  74. {
  75. struct sc_handle hdr;
  76. struct list entry;
  77. BOOL status_notified;
  78. struct service_entry *service_entry;
  79. struct sc_notify_handle *notify;
  80. };
  81. static void sc_notify_retain(struct sc_notify_handle *notify)
  82. {
  83. InterlockedIncrement(&notify->ref);
  84. }
  85. static void sc_notify_release(struct sc_notify_handle *notify)
  86. {
  87. ULONG r = InterlockedDecrement(&notify->ref);
  88. if (r == 0)
  89. {
  90. CloseHandle(notify->event);
  91. HeapFree(GetProcessHeap(), 0, notify->params_list);
  92. HeapFree(GetProcessHeap(), 0, notify);
  93. }
  94. }
  95. struct sc_lock
  96. {
  97. struct scmdatabase *db;
  98. };
  99. static const WCHAR emptyW[] = {0};
  100. static PTP_CLEANUP_GROUP cleanup_group;
  101. HANDLE exit_event;
  102. static void CALLBACK group_cancel_callback(void *object, void *userdata)
  103. {
  104. struct process_entry *process = object;
  105. release_process(process);
  106. }
  107. static void CALLBACK terminate_callback(TP_CALLBACK_INSTANCE *instance, void *context,
  108. TP_WAIT *wait, TP_WAIT_RESULT result)
  109. {
  110. struct process_entry *process = context;
  111. if (result == WAIT_TIMEOUT) process_terminate(process);
  112. release_process(process);
  113. CloseThreadpoolWait(wait);
  114. }
  115. static void terminate_after_timeout(struct process_entry *process, DWORD timeout)
  116. {
  117. TP_CALLBACK_ENVIRON environment;
  118. LARGE_INTEGER timestamp;
  119. TP_WAIT *wait;
  120. FILETIME ft;
  121. memset(&environment, 0, sizeof(environment));
  122. environment.Version = 1;
  123. environment.CleanupGroup = cleanup_group;
  124. environment.CleanupGroupCancelCallback = group_cancel_callback;
  125. timestamp.QuadPart = (ULONGLONG)timeout * -10000;
  126. ft.dwLowDateTime = timestamp.u.LowPart;
  127. ft.dwHighDateTime = timestamp.u.HighPart;
  128. if ((wait = CreateThreadpoolWait(terminate_callback, grab_process(process), &environment)))
  129. SetThreadpoolWait(wait, process->process, &ft);
  130. else
  131. release_process(process);
  132. }
  133. static void CALLBACK shutdown_callback(TP_CALLBACK_INSTANCE *instance, void *context)
  134. {
  135. struct process_entry *process = context;
  136. DWORD result;
  137. result = WaitForSingleObject(process->control_mutex, 30000);
  138. if (result == WAIT_OBJECT_0)
  139. {
  140. process_send_control(process, FALSE, emptyW, SERVICE_CONTROL_STOP, NULL, 0, &result);
  141. ReleaseMutex(process->control_mutex);
  142. }
  143. release_process(process);
  144. }
  145. static void shutdown_shared_process(struct process_entry *process)
  146. {
  147. TP_CALLBACK_ENVIRON environment;
  148. struct service_entry *service;
  149. struct scmdatabase *db = process->db;
  150. scmdatabase_lock(db);
  151. LIST_FOR_EACH_ENTRY(service, &db->services, struct service_entry, entry)
  152. {
  153. if (service->process != process) continue;
  154. service->status.dwCurrentState = SERVICE_STOP_PENDING;
  155. }
  156. scmdatabase_unlock(db);
  157. memset(&environment, 0, sizeof(environment));
  158. environment.Version = 1;
  159. environment.CleanupGroup = cleanup_group;
  160. environment.CleanupGroupCancelCallback = group_cancel_callback;
  161. if (!TrySubmitThreadpoolCallback(shutdown_callback, grab_process(process), &environment))
  162. release_process(process);
  163. }
  164. static void free_service_strings(struct service_entry *old, struct service_entry *new)
  165. {
  166. QUERY_SERVICE_CONFIGW *old_cfg = &old->config;
  167. QUERY_SERVICE_CONFIGW *new_cfg = &new->config;
  168. if (old_cfg->lpBinaryPathName != new_cfg->lpBinaryPathName)
  169. HeapFree(GetProcessHeap(), 0, old_cfg->lpBinaryPathName);
  170. if (old_cfg->lpLoadOrderGroup != new_cfg->lpLoadOrderGroup)
  171. HeapFree(GetProcessHeap(), 0, old_cfg->lpLoadOrderGroup);
  172. if (old_cfg->lpServiceStartName != new_cfg->lpServiceStartName)
  173. HeapFree(GetProcessHeap(), 0, old_cfg->lpServiceStartName);
  174. if (old_cfg->lpDisplayName != new_cfg->lpDisplayName)
  175. HeapFree(GetProcessHeap(), 0, old_cfg->lpDisplayName);
  176. if (old->dependOnServices != new->dependOnServices)
  177. HeapFree(GetProcessHeap(), 0, old->dependOnServices);
  178. if (old->dependOnGroups != new->dependOnGroups)
  179. HeapFree(GetProcessHeap(), 0, old->dependOnGroups);
  180. }
  181. /* Check if the given handle is of the required type and allows the requested access. */
  182. static DWORD validate_context_handle(SC_RPC_HANDLE handle, DWORD type, DWORD needed_access, struct sc_handle **out_hdr)
  183. {
  184. struct sc_handle *hdr = handle;
  185. if (type != SC_HTYPE_DONT_CARE && hdr->type != type)
  186. {
  187. WINE_ERR("Handle is of an invalid type (%d, %d)\n", hdr->type, type);
  188. return ERROR_INVALID_HANDLE;
  189. }
  190. if ((needed_access & hdr->access) != needed_access)
  191. {
  192. WINE_ERR("Access denied - handle created with access %x, needed %x\n", hdr->access, needed_access);
  193. return ERROR_ACCESS_DENIED;
  194. }
  195. *out_hdr = hdr;
  196. return ERROR_SUCCESS;
  197. }
  198. static DWORD validate_scm_handle(SC_RPC_HANDLE handle, DWORD needed_access, struct sc_manager_handle **manager)
  199. {
  200. struct sc_handle *hdr;
  201. DWORD err = validate_context_handle(handle, SC_HTYPE_MANAGER, needed_access, &hdr);
  202. if (err == ERROR_SUCCESS)
  203. *manager = (struct sc_manager_handle *)hdr;
  204. return err;
  205. }
  206. static DWORD validate_service_handle(SC_RPC_HANDLE handle, DWORD needed_access, struct sc_service_handle **service)
  207. {
  208. struct sc_handle *hdr;
  209. DWORD err = validate_context_handle(handle, SC_HTYPE_SERVICE, needed_access, &hdr);
  210. if (err == ERROR_SUCCESS)
  211. *service = (struct sc_service_handle *)hdr;
  212. return err;
  213. }
  214. static DWORD validate_notify_handle(SC_RPC_HANDLE handle, DWORD needed_access, struct sc_notify_handle **notify)
  215. {
  216. struct sc_handle *hdr;
  217. DWORD err = validate_context_handle(handle, SC_HTYPE_NOTIFY, needed_access, &hdr);
  218. if (err == ERROR_SUCCESS)
  219. *notify = (struct sc_notify_handle *)hdr;
  220. return err;
  221. }
  222. DWORD __cdecl svcctl_OpenSCManagerW(
  223. MACHINE_HANDLEW MachineName, /* Note: this parameter is ignored */
  224. LPCWSTR DatabaseName,
  225. DWORD dwAccessMask,
  226. SC_RPC_HANDLE *handle)
  227. {
  228. struct sc_manager_handle *manager;
  229. WINE_TRACE("(%s, %s, %x)\n", wine_dbgstr_w(MachineName), wine_dbgstr_w(DatabaseName), dwAccessMask);
  230. if (DatabaseName != NULL && DatabaseName[0])
  231. {
  232. if (lstrcmpW(DatabaseName, SERVICES_FAILED_DATABASEW) == 0)
  233. return ERROR_DATABASE_DOES_NOT_EXIST;
  234. if (lstrcmpW(DatabaseName, SERVICES_ACTIVE_DATABASEW) != 0)
  235. return ERROR_INVALID_NAME;
  236. }
  237. if (!(manager = HeapAlloc(GetProcessHeap(), 0, sizeof(*manager))))
  238. return ERROR_NOT_ENOUGH_SERVER_MEMORY;
  239. manager->hdr.type = SC_HTYPE_MANAGER;
  240. if (dwAccessMask & MAXIMUM_ALLOWED)
  241. dwAccessMask |= SC_MANAGER_ALL_ACCESS;
  242. manager->hdr.access = dwAccessMask;
  243. RtlMapGenericMask(&manager->hdr.access, &g_scm_generic);
  244. manager->db = active_database;
  245. *handle = &manager->hdr;
  246. return ERROR_SUCCESS;
  247. }
  248. static void SC_RPC_HANDLE_destroy(SC_RPC_HANDLE handle)
  249. {
  250. struct sc_handle *hdr = handle;
  251. switch (hdr->type)
  252. {
  253. case SC_HTYPE_MANAGER:
  254. {
  255. struct sc_manager_handle *manager = (struct sc_manager_handle *)hdr;
  256. HeapFree(GetProcessHeap(), 0, manager);
  257. break;
  258. }
  259. case SC_HTYPE_SERVICE:
  260. {
  261. struct sc_service_handle *service = (struct sc_service_handle *)hdr;
  262. service_lock(service->service_entry);
  263. list_remove(&service->entry);
  264. if (service->notify)
  265. {
  266. SetEvent(service->notify->event);
  267. sc_notify_release(service->notify);
  268. }
  269. service_unlock(service->service_entry);
  270. release_service(service->service_entry);
  271. HeapFree(GetProcessHeap(), 0, service);
  272. break;
  273. }
  274. default:
  275. WINE_ERR("invalid handle type %d\n", hdr->type);
  276. RpcRaiseException(ERROR_INVALID_HANDLE);
  277. }
  278. }
  279. DWORD __cdecl svcctl_GetServiceDisplayNameW(
  280. SC_RPC_HANDLE hSCManager,
  281. LPCWSTR lpServiceName,
  282. WCHAR *lpBuffer,
  283. DWORD *cchBufSize)
  284. {
  285. struct sc_manager_handle *manager;
  286. struct service_entry *entry;
  287. DWORD err;
  288. WINE_TRACE("(%s, %d)\n", wine_dbgstr_w(lpServiceName), *cchBufSize);
  289. if ((err = validate_scm_handle(hSCManager, 0, &manager)) != ERROR_SUCCESS)
  290. return err;
  291. scmdatabase_lock(manager->db);
  292. entry = scmdatabase_find_service(manager->db, lpServiceName);
  293. if (entry != NULL)
  294. {
  295. LPCWSTR name;
  296. int len;
  297. name = get_display_name(entry);
  298. len = lstrlenW(name);
  299. if (len <= *cchBufSize)
  300. {
  301. err = ERROR_SUCCESS;
  302. memcpy(lpBuffer, name, (len + 1)*sizeof(*name));
  303. }
  304. else
  305. err = ERROR_INSUFFICIENT_BUFFER;
  306. *cchBufSize = len;
  307. }
  308. else
  309. err = ERROR_SERVICE_DOES_NOT_EXIST;
  310. scmdatabase_unlock(manager->db);
  311. if (err != ERROR_SUCCESS)
  312. lpBuffer[0] = 0;
  313. return err;
  314. }
  315. DWORD __cdecl svcctl_GetServiceKeyNameW(
  316. SC_RPC_HANDLE hSCManager,
  317. LPCWSTR lpServiceDisplayName,
  318. WCHAR *lpBuffer,
  319. DWORD *cchBufSize)
  320. {
  321. struct service_entry *entry;
  322. struct sc_manager_handle *manager;
  323. DWORD err;
  324. WINE_TRACE("(%s, %d)\n", wine_dbgstr_w(lpServiceDisplayName), *cchBufSize);
  325. if ((err = validate_scm_handle(hSCManager, 0, &manager)) != ERROR_SUCCESS)
  326. return err;
  327. scmdatabase_lock(manager->db);
  328. entry = scmdatabase_find_service_by_displayname(manager->db, lpServiceDisplayName);
  329. if (entry != NULL)
  330. {
  331. int len;
  332. len = lstrlenW(entry->name);
  333. if (len <= *cchBufSize)
  334. {
  335. err = ERROR_SUCCESS;
  336. memcpy(lpBuffer, entry->name, (len + 1)*sizeof(*entry->name));
  337. }
  338. else
  339. err = ERROR_INSUFFICIENT_BUFFER;
  340. *cchBufSize = len;
  341. }
  342. else
  343. err = ERROR_SERVICE_DOES_NOT_EXIST;
  344. scmdatabase_unlock(manager->db);
  345. if (err != ERROR_SUCCESS)
  346. lpBuffer[0] = 0;
  347. return err;
  348. }
  349. static DWORD create_handle_for_service(struct service_entry *entry, DWORD dwDesiredAccess, SC_RPC_HANDLE *phService)
  350. {
  351. struct sc_service_handle *service;
  352. if (!(service = HeapAlloc(GetProcessHeap(), 0, sizeof(*service))))
  353. {
  354. release_service(entry);
  355. return ERROR_NOT_ENOUGH_SERVER_MEMORY;
  356. }
  357. if (dwDesiredAccess & MAXIMUM_ALLOWED)
  358. dwDesiredAccess |= SERVICE_ALL_ACCESS;
  359. service->hdr.type = SC_HTYPE_SERVICE;
  360. service->hdr.access = dwDesiredAccess;
  361. service->notify = NULL;
  362. service->status_notified = FALSE;
  363. RtlMapGenericMask(&service->hdr.access, &g_svc_generic);
  364. service_lock(entry);
  365. service->service_entry = entry;
  366. list_add_tail(&entry->handles, &service->entry);
  367. service_unlock(entry);
  368. *phService = &service->hdr;
  369. return ERROR_SUCCESS;
  370. }
  371. DWORD __cdecl svcctl_OpenServiceW(
  372. SC_RPC_HANDLE hSCManager,
  373. LPCWSTR lpServiceName,
  374. DWORD dwDesiredAccess,
  375. SC_RPC_HANDLE *phService)
  376. {
  377. struct sc_manager_handle *manager;
  378. struct service_entry *entry;
  379. DWORD err;
  380. WINE_TRACE("(%s, 0x%x)\n", wine_dbgstr_w(lpServiceName), dwDesiredAccess);
  381. if ((err = validate_scm_handle(hSCManager, 0, &manager)) != ERROR_SUCCESS)
  382. return err;
  383. if (!validate_service_name(lpServiceName))
  384. return ERROR_INVALID_NAME;
  385. scmdatabase_lock(manager->db);
  386. entry = grab_service(scmdatabase_find_service(manager->db, lpServiceName));
  387. scmdatabase_unlock(manager->db);
  388. if (entry == NULL)
  389. return ERROR_SERVICE_DOES_NOT_EXIST;
  390. return create_handle_for_service(entry, dwDesiredAccess, phService);
  391. }
  392. static DWORD parse_dependencies(const WCHAR *dependencies, struct service_entry *entry)
  393. {
  394. WCHAR *services = NULL, *groups, *s;
  395. DWORD len, len_services = 0, len_groups = 0;
  396. const WCHAR *ptr = dependencies;
  397. if (!dependencies || !dependencies[0])
  398. {
  399. entry->dependOnServices = NULL;
  400. entry->dependOnGroups = NULL;
  401. return ERROR_SUCCESS;
  402. }
  403. while (*ptr)
  404. {
  405. len = lstrlenW(ptr) + 1;
  406. if (ptr[0] == '+' && ptr[1])
  407. len_groups += len - 1;
  408. else
  409. len_services += len;
  410. ptr += len;
  411. }
  412. if (!len_services) entry->dependOnServices = NULL;
  413. else
  414. {
  415. services = HeapAlloc(GetProcessHeap(), 0, (len_services + 1) * sizeof(WCHAR));
  416. if (!services)
  417. return ERROR_OUTOFMEMORY;
  418. s = services;
  419. ptr = dependencies;
  420. while (*ptr)
  421. {
  422. len = lstrlenW(ptr) + 1;
  423. if (*ptr != '+')
  424. {
  425. lstrcpyW(s, ptr);
  426. s += len;
  427. }
  428. ptr += len;
  429. }
  430. *s = 0;
  431. entry->dependOnServices = services;
  432. }
  433. if (!len_groups) entry->dependOnGroups = NULL;
  434. else
  435. {
  436. groups = HeapAlloc(GetProcessHeap(), 0, (len_groups + 1) * sizeof(WCHAR));
  437. if (!groups)
  438. {
  439. HeapFree(GetProcessHeap(), 0, services);
  440. return ERROR_OUTOFMEMORY;
  441. }
  442. s = groups;
  443. ptr = dependencies;
  444. while (*ptr)
  445. {
  446. len = lstrlenW(ptr) + 1;
  447. if (ptr[0] == '+' && ptr[1])
  448. {
  449. lstrcpyW(s, ptr + 1);
  450. s += len - 1;
  451. }
  452. ptr += len;
  453. }
  454. *s = 0;
  455. entry->dependOnGroups = groups;
  456. }
  457. return ERROR_SUCCESS;
  458. }
  459. static DWORD create_serviceW(
  460. SC_RPC_HANDLE hSCManager,
  461. LPCWSTR lpServiceName,
  462. LPCWSTR lpDisplayName,
  463. DWORD dwDesiredAccess,
  464. DWORD dwServiceType,
  465. DWORD dwStartType,
  466. DWORD dwErrorControl,
  467. LPCWSTR lpBinaryPathName,
  468. LPCWSTR lpLoadOrderGroup,
  469. DWORD *lpdwTagId,
  470. const BYTE *lpDependencies,
  471. DWORD dwDependenciesSize,
  472. LPCWSTR lpServiceStartName,
  473. const BYTE *lpPassword,
  474. DWORD dwPasswordSize,
  475. SC_RPC_HANDLE *phService,
  476. BOOL is_wow64)
  477. {
  478. struct service_entry *entry, *found;
  479. struct sc_manager_handle *manager;
  480. DWORD err;
  481. WINE_TRACE("(%s, %s, 0x%x, %s)\n", wine_dbgstr_w(lpServiceName), wine_dbgstr_w(lpDisplayName), dwDesiredAccess, wine_dbgstr_w(lpBinaryPathName));
  482. if ((err = validate_scm_handle(hSCManager, SC_MANAGER_CREATE_SERVICE, &manager)) != ERROR_SUCCESS)
  483. return err;
  484. if (!validate_service_name(lpServiceName))
  485. return ERROR_INVALID_NAME;
  486. if (!check_multisz((LPCWSTR)lpDependencies, dwDependenciesSize) || !lpServiceName[0] || !lpBinaryPathName[0])
  487. return ERROR_INVALID_PARAMETER;
  488. if (lpPassword)
  489. WINE_FIXME("Don't know how to add a password\n"); /* I always get ERROR_GEN_FAILURE */
  490. err = service_create(lpServiceName, &entry);
  491. if (err != ERROR_SUCCESS)
  492. return err;
  493. err = parse_dependencies((LPCWSTR)lpDependencies, entry);
  494. if (err != ERROR_SUCCESS) {
  495. free_service_entry(entry);
  496. return err;
  497. }
  498. entry->is_wow64 = is_wow64;
  499. entry->config.dwServiceType = entry->status.dwServiceType = dwServiceType;
  500. entry->config.dwStartType = dwStartType;
  501. entry->config.dwErrorControl = dwErrorControl;
  502. entry->config.lpBinaryPathName = strdupW(lpBinaryPathName);
  503. entry->config.lpLoadOrderGroup = strdupW(lpLoadOrderGroup);
  504. entry->config.lpServiceStartName = strdupW(lpServiceStartName);
  505. entry->config.lpDisplayName = strdupW(lpDisplayName);
  506. if (lpdwTagId) /* TODO: In most situations a non-NULL TagId will generate an ERROR_INVALID_PARAMETER. */
  507. entry->config.dwTagId = *lpdwTagId;
  508. else
  509. entry->config.dwTagId = 0;
  510. /* other fields NULL*/
  511. if (!validate_service_config(entry))
  512. {
  513. WINE_ERR("Invalid data while trying to create service\n");
  514. free_service_entry(entry);
  515. return ERROR_INVALID_PARAMETER;
  516. }
  517. scmdatabase_lock(manager->db);
  518. if ((found = scmdatabase_find_service(manager->db, lpServiceName)))
  519. {
  520. err = is_marked_for_delete(found) ? ERROR_SERVICE_MARKED_FOR_DELETE : ERROR_SERVICE_EXISTS;
  521. scmdatabase_unlock(manager->db);
  522. free_service_entry(entry);
  523. return err;
  524. }
  525. if (scmdatabase_find_service_by_displayname(manager->db, get_display_name(entry)))
  526. {
  527. scmdatabase_unlock(manager->db);
  528. free_service_entry(entry);
  529. return ERROR_DUPLICATE_SERVICE_NAME;
  530. }
  531. err = scmdatabase_add_service(manager->db, entry);
  532. if (err != ERROR_SUCCESS)
  533. {
  534. scmdatabase_unlock(manager->db);
  535. free_service_entry(entry);
  536. return err;
  537. }
  538. scmdatabase_unlock(manager->db);
  539. return create_handle_for_service(entry, dwDesiredAccess, phService);
  540. }
  541. DWORD __cdecl svcctl_CreateServiceW(
  542. SC_RPC_HANDLE hSCManager,
  543. LPCWSTR lpServiceName,
  544. LPCWSTR lpDisplayName,
  545. DWORD dwDesiredAccess,
  546. DWORD dwServiceType,
  547. DWORD dwStartType,
  548. DWORD dwErrorControl,
  549. LPCWSTR lpBinaryPathName,
  550. LPCWSTR lpLoadOrderGroup,
  551. DWORD *lpdwTagId,
  552. const BYTE *lpDependencies,
  553. DWORD dwDependenciesSize,
  554. LPCWSTR lpServiceStartName,
  555. const BYTE *lpPassword,
  556. DWORD dwPasswordSize,
  557. SC_RPC_HANDLE *phService)
  558. {
  559. WINE_TRACE("(%s, %s, 0x%x, %s)\n", wine_dbgstr_w(lpServiceName), wine_dbgstr_w(lpDisplayName), dwDesiredAccess, wine_dbgstr_w(lpBinaryPathName));
  560. return create_serviceW(hSCManager, lpServiceName, lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType,
  561. dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, dwDependenciesSize, lpServiceStartName,
  562. lpPassword, dwPasswordSize, phService, FALSE);
  563. }
  564. DWORD __cdecl svcctl_DeleteService(
  565. SC_RPC_HANDLE hService)
  566. {
  567. struct sc_service_handle *service;
  568. DWORD err;
  569. if ((err = validate_service_handle(hService, DELETE, &service)) != ERROR_SUCCESS)
  570. return err;
  571. service_lock(service->service_entry);
  572. if (!is_marked_for_delete(service->service_entry))
  573. err = mark_for_delete(service->service_entry);
  574. else
  575. err = ERROR_SERVICE_MARKED_FOR_DELETE;
  576. service_unlock(service->service_entry);
  577. return err;
  578. }
  579. DWORD __cdecl svcctl_QueryServiceConfigW(
  580. SC_RPC_HANDLE hService,
  581. QUERY_SERVICE_CONFIGW *config,
  582. DWORD buf_size,
  583. DWORD *needed_size)
  584. {
  585. struct sc_service_handle *service;
  586. DWORD err;
  587. WINE_TRACE("(%p)\n", config);
  588. if ((err = validate_service_handle(hService, SERVICE_QUERY_CONFIG, &service)) != 0)
  589. return err;
  590. service_lock(service->service_entry);
  591. config->dwServiceType = service->service_entry->config.dwServiceType;
  592. config->dwStartType = service->service_entry->config.dwStartType;
  593. config->dwErrorControl = service->service_entry->config.dwErrorControl;
  594. config->lpBinaryPathName = strdupW(service->service_entry->config.lpBinaryPathName);
  595. config->lpLoadOrderGroup = strdupW(service->service_entry->config.lpLoadOrderGroup);
  596. config->dwTagId = service->service_entry->config.dwTagId;
  597. config->lpDependencies = NULL; /* TODO */
  598. config->lpServiceStartName = strdupW(service->service_entry->config.lpServiceStartName);
  599. config->lpDisplayName = strdupW(service->service_entry->config.lpDisplayName);
  600. service_unlock(service->service_entry);
  601. return ERROR_SUCCESS;
  602. }
  603. DWORD __cdecl svcctl_ChangeServiceConfigW(
  604. SC_RPC_HANDLE hService,
  605. DWORD dwServiceType,
  606. DWORD dwStartType,
  607. DWORD dwErrorControl,
  608. LPCWSTR lpBinaryPathName,
  609. LPCWSTR lpLoadOrderGroup,
  610. DWORD *lpdwTagId,
  611. const BYTE *lpDependencies,
  612. DWORD dwDependenciesSize,
  613. LPCWSTR lpServiceStartName,
  614. const BYTE *lpPassword,
  615. DWORD dwPasswordSize,
  616. LPCWSTR lpDisplayName)
  617. {
  618. struct service_entry new_entry, *entry;
  619. struct sc_service_handle *service;
  620. DWORD err;
  621. WINE_TRACE("\n");
  622. if ((err = validate_service_handle(hService, SERVICE_CHANGE_CONFIG, &service)) != 0)
  623. return err;
  624. if (!check_multisz((LPCWSTR)lpDependencies, dwDependenciesSize))
  625. return ERROR_INVALID_PARAMETER;
  626. /* first check if the new configuration is correct */
  627. service_lock(service->service_entry);
  628. if (is_marked_for_delete(service->service_entry))
  629. {
  630. service_unlock(service->service_entry);
  631. return ERROR_SERVICE_MARKED_FOR_DELETE;
  632. }
  633. if (lpDisplayName != NULL &&
  634. (entry = scmdatabase_find_service_by_displayname(service->service_entry->db, lpDisplayName)) &&
  635. (entry != service->service_entry))
  636. {
  637. service_unlock(service->service_entry);
  638. return ERROR_DUPLICATE_SERVICE_NAME;
  639. }
  640. new_entry = *service->service_entry;
  641. if (dwServiceType != SERVICE_NO_CHANGE)
  642. new_entry.config.dwServiceType = dwServiceType;
  643. if (dwStartType != SERVICE_NO_CHANGE)
  644. new_entry.config.dwStartType = dwStartType;
  645. if (dwErrorControl != SERVICE_NO_CHANGE)
  646. new_entry.config.dwErrorControl = dwErrorControl;
  647. if (lpBinaryPathName != NULL)
  648. new_entry.config.lpBinaryPathName = (LPWSTR)lpBinaryPathName;
  649. if (lpLoadOrderGroup != NULL)
  650. new_entry.config.lpLoadOrderGroup = (LPWSTR)lpLoadOrderGroup;
  651. if (lpdwTagId != NULL)
  652. WINE_FIXME("Changing tag id not supported\n");
  653. if (lpServiceStartName != NULL)
  654. new_entry.config.lpServiceStartName = (LPWSTR)lpServiceStartName;
  655. if (lpPassword != NULL)
  656. WINE_FIXME("Setting password not supported\n");
  657. if (lpDisplayName != NULL)
  658. new_entry.config.lpDisplayName = (LPWSTR)lpDisplayName;
  659. err = parse_dependencies((LPCWSTR)lpDependencies, &new_entry);
  660. if (err != ERROR_SUCCESS)
  661. {
  662. service_unlock(service->service_entry);
  663. return err;
  664. }
  665. if (!validate_service_config(&new_entry))
  666. {
  667. WINE_ERR("The configuration after the change wouldn't be valid\n");
  668. service_unlock(service->service_entry);
  669. return ERROR_INVALID_PARAMETER;
  670. }
  671. /* configuration OK. The strings needs to be duplicated */
  672. if (lpBinaryPathName != NULL)
  673. new_entry.config.lpBinaryPathName = strdupW(lpBinaryPathName);
  674. if (lpLoadOrderGroup != NULL)
  675. new_entry.config.lpLoadOrderGroup = strdupW(lpLoadOrderGroup);
  676. if (lpServiceStartName != NULL)
  677. new_entry.config.lpServiceStartName = strdupW(lpServiceStartName);
  678. if (lpDisplayName != NULL)
  679. new_entry.config.lpDisplayName = strdupW(lpDisplayName);
  680. /* try to save to Registry, commit or rollback depending on success */
  681. err = save_service_config(&new_entry);
  682. if (ERROR_SUCCESS == err)
  683. {
  684. free_service_strings(service->service_entry, &new_entry);
  685. *service->service_entry = new_entry;
  686. }
  687. else free_service_strings(&new_entry, service->service_entry);
  688. service_unlock(service->service_entry);
  689. return err;
  690. }
  691. static void fill_status_process(SERVICE_STATUS_PROCESS *status, struct service_entry *service)
  692. {
  693. struct process_entry *process = service->process;
  694. memcpy(status, &service->status, sizeof(service->status));
  695. status->dwProcessId = 0;
  696. if (process && !(service->status.dwServiceType & SERVICE_DRIVER))
  697. status->dwProcessId = process->process_id;
  698. status->dwServiceFlags = 0;
  699. }
  700. static void fill_notify(struct sc_notify_handle *notify, struct service_entry *service)
  701. {
  702. SC_RPC_NOTIFY_PARAMS_LIST *list;
  703. SERVICE_NOTIFY_STATUS_CHANGE_PARAMS_2 *cparams;
  704. list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
  705. sizeof(SC_RPC_NOTIFY_PARAMS_LIST) + sizeof(SERVICE_NOTIFY_STATUS_CHANGE_PARAMS_2));
  706. if (!list)
  707. return;
  708. cparams = (SERVICE_NOTIFY_STATUS_CHANGE_PARAMS_2 *)(list + 1);
  709. cparams->dwNotifyMask = notify->notify_mask;
  710. fill_status_process(&cparams->ServiceStatus, service);
  711. cparams->dwNotificationStatus = ERROR_SUCCESS;
  712. cparams->dwNotificationTriggered = 1 << (cparams->ServiceStatus.dwCurrentState - SERVICE_STOPPED);
  713. cparams->pszServiceNames = NULL;
  714. list->cElements = 1;
  715. list->NotifyParamsArray[0].dwInfoLevel = 2;
  716. list->NotifyParamsArray[0].params = cparams;
  717. InterlockedExchangePointer((void**)&notify->params_list, list);
  718. SetEvent(notify->event);
  719. }
  720. DWORD __cdecl svcctl_SetServiceStatus(SC_RPC_HANDLE handle, SERVICE_STATUS *status)
  721. {
  722. struct sc_service_handle *service, *service_handle;
  723. struct process_entry *process;
  724. DWORD err, mask;
  725. WINE_TRACE("(%p, %p)\n", handle, status);
  726. if ((err = validate_service_handle(handle, SERVICE_SET_STATUS, &service)) != 0)
  727. return err;
  728. service_lock(service->service_entry);
  729. /* FIXME: be a bit more discriminant about what parts of the status we set
  730. * and check that fields are valid */
  731. service->service_entry->status.dwCurrentState = status->dwCurrentState;
  732. service->service_entry->status.dwControlsAccepted = status->dwControlsAccepted;
  733. service->service_entry->status.dwWin32ExitCode = status->dwWin32ExitCode;
  734. service->service_entry->status.dwServiceSpecificExitCode = status->dwServiceSpecificExitCode;
  735. service->service_entry->status.dwCheckPoint = status->dwCheckPoint;
  736. service->service_entry->status.dwWaitHint = status->dwWaitHint;
  737. SetEvent(service->service_entry->status_changed_event);
  738. if ((process = service->service_entry->process) &&
  739. status->dwCurrentState == SERVICE_STOPPED)
  740. {
  741. service->service_entry->process = NULL;
  742. if (!--process->use_count)
  743. terminate_after_timeout(process, service_kill_timeout);
  744. if (service->service_entry->shared_process && process->use_count <= 1)
  745. shutdown_shared_process(process);
  746. release_process(process);
  747. }
  748. mask = 1 << (service->service_entry->status.dwCurrentState - SERVICE_STOPPED);
  749. LIST_FOR_EACH_ENTRY(service_handle, &service->service_entry->handles, struct sc_service_handle, entry)
  750. {
  751. struct sc_notify_handle *notify = service_handle->notify;
  752. if (notify && (notify->notify_mask & mask))
  753. {
  754. fill_notify(notify, service->service_entry);
  755. sc_notify_release(notify);
  756. service_handle->notify = NULL;
  757. service_handle->status_notified = TRUE;
  758. }
  759. else
  760. service_handle->status_notified = FALSE;
  761. }
  762. service_unlock(service->service_entry);
  763. return ERROR_SUCCESS;
  764. }
  765. DWORD __cdecl svcctl_ChangeServiceConfig2W( SC_RPC_HANDLE hService, SC_RPC_CONFIG_INFOW config )
  766. {
  767. struct sc_service_handle *service;
  768. DWORD err;
  769. if ((err = validate_service_handle(hService, SERVICE_CHANGE_CONFIG, &service)) != 0)
  770. return err;
  771. switch (config.dwInfoLevel)
  772. {
  773. case SERVICE_CONFIG_DESCRIPTION:
  774. {
  775. WCHAR *descr = NULL;
  776. if (!config.descr->lpDescription)
  777. break;
  778. if (config.descr->lpDescription[0])
  779. {
  780. if (!(descr = strdupW( config.descr->lpDescription )))
  781. return ERROR_NOT_ENOUGH_MEMORY;
  782. }
  783. WINE_TRACE( "changing service %p descr to %s\n", service, wine_dbgstr_w(descr) );
  784. service_lock( service->service_entry );
  785. HeapFree( GetProcessHeap(), 0, service->service_entry->description );
  786. service->service_entry->description = descr;
  787. save_service_config( service->service_entry );
  788. service_unlock( service->service_entry );
  789. }
  790. break;
  791. case SERVICE_CONFIG_FAILURE_ACTIONS:
  792. WINE_FIXME( "SERVICE_CONFIG_FAILURE_ACTIONS not implemented: period %u msg %s cmd %s\n",
  793. config.actions->dwResetPeriod,
  794. wine_dbgstr_w(config.actions->lpRebootMsg),
  795. wine_dbgstr_w(config.actions->lpCommand) );
  796. break;
  797. case SERVICE_CONFIG_PRESHUTDOWN_INFO:
  798. WINE_TRACE( "changing service %p preshutdown timeout to %d\n",
  799. service, config.preshutdown->dwPreshutdownTimeout );
  800. service_lock( service->service_entry );
  801. service->service_entry->preshutdown_timeout = config.preshutdown->dwPreshutdownTimeout;
  802. save_service_config( service->service_entry );
  803. service_unlock( service->service_entry );
  804. break;
  805. default:
  806. WINE_FIXME("level %u not implemented\n", config.dwInfoLevel);
  807. err = ERROR_INVALID_LEVEL;
  808. break;
  809. }
  810. return err;
  811. }
  812. DWORD __cdecl svcctl_QueryServiceConfig2W( SC_RPC_HANDLE hService, DWORD level,
  813. BYTE *buffer, DWORD size, LPDWORD needed )
  814. {
  815. struct sc_service_handle *service;
  816. DWORD err;
  817. memset(buffer, 0, size);
  818. if ((err = validate_service_handle(hService, SERVICE_QUERY_STATUS, &service)) != 0)
  819. return err;
  820. switch (level)
  821. {
  822. case SERVICE_CONFIG_DESCRIPTION:
  823. {
  824. struct service_description *desc = (struct service_description *)buffer;
  825. DWORD total_size = sizeof(*desc);
  826. service_lock(service->service_entry);
  827. if (service->service_entry->description)
  828. total_size += lstrlenW(service->service_entry->description) * sizeof(WCHAR);
  829. *needed = total_size;
  830. if (size >= total_size)
  831. {
  832. if (service->service_entry->description)
  833. {
  834. lstrcpyW( desc->description, service->service_entry->description );
  835. desc->size = total_size - FIELD_OFFSET(struct service_description, description);
  836. }
  837. else
  838. {
  839. desc->description[0] = 0;
  840. desc->size = 0;
  841. }
  842. }
  843. else err = ERROR_INSUFFICIENT_BUFFER;
  844. service_unlock(service->service_entry);
  845. }
  846. break;
  847. case SERVICE_CONFIG_PRESHUTDOWN_INFO:
  848. service_lock(service->service_entry);
  849. *needed = sizeof(SERVICE_PRESHUTDOWN_INFO);
  850. if (size >= *needed)
  851. ((LPSERVICE_PRESHUTDOWN_INFO)buffer)->dwPreshutdownTimeout =
  852. service->service_entry->preshutdown_timeout;
  853. else err = ERROR_INSUFFICIENT_BUFFER;
  854. service_unlock(service->service_entry);
  855. break;
  856. default:
  857. WINE_FIXME("level %u not implemented\n", level);
  858. err = ERROR_INVALID_LEVEL;
  859. break;
  860. }
  861. return err;
  862. }
  863. DWORD __cdecl svcctl_QueryServiceStatusEx(
  864. SC_RPC_HANDLE hService,
  865. SC_STATUS_TYPE InfoLevel,
  866. BYTE *lpBuffer,
  867. DWORD cbBufSize,
  868. LPDWORD pcbBytesNeeded)
  869. {
  870. struct sc_service_handle *service;
  871. DWORD err;
  872. LPSERVICE_STATUS_PROCESS pSvcStatusData;
  873. memset(lpBuffer, 0, cbBufSize);
  874. if ((err = validate_service_handle(hService, SERVICE_QUERY_STATUS, &service)) != 0)
  875. return err;
  876. if (InfoLevel != SC_STATUS_PROCESS_INFO)
  877. return ERROR_INVALID_LEVEL;
  878. pSvcStatusData = (LPSERVICE_STATUS_PROCESS) lpBuffer;
  879. if (pSvcStatusData == NULL)
  880. return ERROR_INVALID_PARAMETER;
  881. if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
  882. {
  883. if( pcbBytesNeeded != NULL)
  884. *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
  885. return ERROR_INSUFFICIENT_BUFFER;
  886. }
  887. service_lock(service->service_entry);
  888. fill_status_process(pSvcStatusData, service->service_entry);
  889. service_unlock(service->service_entry);
  890. return ERROR_SUCCESS;
  891. }
  892. /******************************************************************************
  893. * service_accepts_control
  894. */
  895. static BOOL service_accepts_control(const struct service_entry *service, DWORD dwControl)
  896. {
  897. DWORD a = service->status.dwControlsAccepted;
  898. if (dwControl >= 128 && dwControl <= 255)
  899. return TRUE;
  900. switch (dwControl)
  901. {
  902. case SERVICE_CONTROL_INTERROGATE:
  903. return TRUE;
  904. case SERVICE_CONTROL_STOP:
  905. if (a&SERVICE_ACCEPT_STOP)
  906. return TRUE;
  907. break;
  908. case SERVICE_CONTROL_SHUTDOWN:
  909. if (a&SERVICE_ACCEPT_SHUTDOWN)
  910. return TRUE;
  911. break;
  912. case SERVICE_CONTROL_PAUSE:
  913. case SERVICE_CONTROL_CONTINUE:
  914. if (a&SERVICE_ACCEPT_PAUSE_CONTINUE)
  915. return TRUE;
  916. break;
  917. case SERVICE_CONTROL_PARAMCHANGE:
  918. if (a&SERVICE_ACCEPT_PARAMCHANGE)
  919. return TRUE;
  920. break;
  921. case SERVICE_CONTROL_NETBINDADD:
  922. case SERVICE_CONTROL_NETBINDREMOVE:
  923. case SERVICE_CONTROL_NETBINDENABLE:
  924. case SERVICE_CONTROL_NETBINDDISABLE:
  925. if (a&SERVICE_ACCEPT_NETBINDCHANGE)
  926. return TRUE;
  927. case SERVICE_CONTROL_HARDWAREPROFILECHANGE:
  928. if (a&SERVICE_ACCEPT_HARDWAREPROFILECHANGE)
  929. return TRUE;
  930. break;
  931. case SERVICE_CONTROL_POWEREVENT:
  932. if (a&SERVICE_ACCEPT_POWEREVENT)
  933. return TRUE;
  934. break;
  935. case SERVICE_CONTROL_SESSIONCHANGE:
  936. if (a&SERVICE_ACCEPT_SESSIONCHANGE)
  937. return TRUE;
  938. break;
  939. }
  940. return FALSE;
  941. }
  942. /******************************************************************************
  943. * process_send_command
  944. */
  945. static BOOL process_send_command(struct process_entry *process, const void *data, DWORD size, DWORD *result)
  946. {
  947. OVERLAPPED overlapped;
  948. DWORD count, ret;
  949. BOOL r;
  950. overlapped.u.s.Offset = 0;
  951. overlapped.u.s.OffsetHigh = 0;
  952. overlapped.hEvent = process->overlapped_event;
  953. r = WriteFile(process->control_pipe, data, size, &count, &overlapped);
  954. if (!r && GetLastError() == ERROR_IO_PENDING)
  955. {
  956. ret = WaitForSingleObject(process->overlapped_event, service_pipe_timeout);
  957. if (ret == WAIT_TIMEOUT)
  958. {
  959. WINE_ERR("sending command timed out\n");
  960. *result = ERROR_SERVICE_REQUEST_TIMEOUT;
  961. return FALSE;
  962. }
  963. r = GetOverlappedResult(process->control_pipe, &overlapped, &count, FALSE);
  964. }
  965. if (!r || count != size)
  966. {
  967. WINE_ERR("service protocol error - failed to write pipe!\n");
  968. *result = (!r ? GetLastError() : ERROR_WRITE_FAULT);
  969. return FALSE;
  970. }
  971. r = ReadFile(process->control_pipe, result, sizeof *result, &count, &overlapped);
  972. if (!r && GetLastError() == ERROR_IO_PENDING)
  973. {
  974. ret = WaitForSingleObject(process->overlapped_event, service_pipe_timeout);
  975. if (ret == WAIT_TIMEOUT)
  976. {
  977. WINE_ERR("receiving command result timed out\n");
  978. *result = ERROR_SERVICE_REQUEST_TIMEOUT;
  979. return FALSE;
  980. }
  981. r = GetOverlappedResult(process->control_pipe, &overlapped, &count, FALSE);
  982. }
  983. if (!r || count != sizeof *result)
  984. {
  985. WINE_ERR("service protocol error - failed to read pipe "
  986. "r = %d count = %d!\n", r, count);
  987. *result = (!r ? GetLastError() : ERROR_READ_FAULT);
  988. return FALSE;
  989. }
  990. return TRUE;
  991. }
  992. /******************************************************************************
  993. * process_send_control
  994. */
  995. BOOL process_send_control(struct process_entry *process, BOOL shared_process, const WCHAR *name,
  996. DWORD control, const BYTE *data, DWORD data_size, DWORD *result)
  997. {
  998. service_start_info *ssi;
  999. DWORD len;
  1000. BOOL r;
  1001. if (shared_process)
  1002. {
  1003. control |= SERVICE_CONTROL_FORWARD_FLAG;
  1004. data = (BYTE *)name;
  1005. data_size = (lstrlenW(name) + 1) * sizeof(WCHAR);
  1006. name = emptyW;
  1007. }
  1008. /* calculate how much space we need to send the startup info */
  1009. len = (lstrlenW(name) + 1) * sizeof(WCHAR) + data_size;
  1010. ssi = HeapAlloc(GetProcessHeap(),0,FIELD_OFFSET(service_start_info, data[len]));
  1011. ssi->magic = SERVICE_PROTOCOL_MAGIC;
  1012. ssi->control = control;
  1013. ssi->total_size = FIELD_OFFSET(service_start_info, data[len]);
  1014. ssi->name_size = lstrlenW(name) + 1;
  1015. lstrcpyW((WCHAR *)ssi->data, name);
  1016. if (data_size) memcpy(&ssi->data[ssi->name_size * sizeof(WCHAR)], data, data_size);
  1017. r = process_send_command(process, ssi, ssi->total_size, result);
  1018. HeapFree( GetProcessHeap(), 0, ssi );
  1019. return r;
  1020. }
  1021. DWORD __cdecl svcctl_StartServiceW(
  1022. SC_RPC_HANDLE hService,
  1023. DWORD dwNumServiceArgs,
  1024. LPCWSTR *lpServiceArgVectors)
  1025. {
  1026. struct sc_service_handle *service;
  1027. DWORD err;
  1028. WINE_TRACE("(%p, %d, %p)\n", hService, dwNumServiceArgs, lpServiceArgVectors);
  1029. if ((err = validate_service_handle(hService, SERVICE_START, &service)) != 0)
  1030. return err;
  1031. if (service->service_entry->config.dwStartType == SERVICE_DISABLED)
  1032. return ERROR_SERVICE_DISABLED;
  1033. if (!scmdatabase_lock_startup(service->service_entry->db, 3000))
  1034. return ERROR_SERVICE_DATABASE_LOCKED;
  1035. err = service_start(service->service_entry, dwNumServiceArgs, lpServiceArgVectors);
  1036. scmdatabase_unlock_startup(service->service_entry->db);
  1037. return err;
  1038. }
  1039. DWORD __cdecl svcctl_ControlService(
  1040. SC_RPC_HANDLE hService,
  1041. DWORD dwControl,
  1042. SERVICE_STATUS *lpServiceStatus)
  1043. {
  1044. DWORD access_required;
  1045. struct sc_service_handle *service;
  1046. struct process_entry *process;
  1047. BOOL shared_process;
  1048. DWORD result;
  1049. WINE_TRACE("(%p, %d, %p)\n", hService, dwControl, lpServiceStatus);
  1050. switch (dwControl)
  1051. {
  1052. case SERVICE_CONTROL_CONTINUE:
  1053. case SERVICE_CONTROL_NETBINDADD:
  1054. case SERVICE_CONTROL_NETBINDDISABLE:
  1055. case SERVICE_CONTROL_NETBINDENABLE:
  1056. case SERVICE_CONTROL_NETBINDREMOVE:
  1057. case SERVICE_CONTROL_PARAMCHANGE:
  1058. case SERVICE_CONTROL_PAUSE:
  1059. access_required = SERVICE_PAUSE_CONTINUE;
  1060. break;
  1061. case SERVICE_CONTROL_INTERROGATE:
  1062. access_required = SERVICE_INTERROGATE;
  1063. break;
  1064. case SERVICE_CONTROL_STOP:
  1065. access_required = SERVICE_STOP;
  1066. break;
  1067. default:
  1068. if (dwControl >= 128 && dwControl <= 255)
  1069. access_required = SERVICE_USER_DEFINED_CONTROL;
  1070. else
  1071. return ERROR_INVALID_PARAMETER;
  1072. }
  1073. if ((result = validate_service_handle(hService, access_required, &service)) != 0)
  1074. return result;
  1075. service_lock(service->service_entry);
  1076. result = ERROR_SUCCESS;
  1077. switch (service->service_entry->status.dwCurrentState)
  1078. {
  1079. case SERVICE_STOPPED:
  1080. result = ERROR_SERVICE_NOT_ACTIVE;
  1081. break;
  1082. case SERVICE_START_PENDING:
  1083. if (dwControl==SERVICE_CONTROL_STOP)
  1084. break;
  1085. /* fall through */
  1086. case SERVICE_STOP_PENDING:
  1087. result = ERROR_SERVICE_CANNOT_ACCEPT_CTRL;
  1088. break;
  1089. }
  1090. if (result == ERROR_SUCCESS && service->service_entry->force_shutdown)
  1091. {
  1092. result = ERROR_SERVICE_CANNOT_ACCEPT_CTRL;
  1093. if ((process = service->service_entry->process))
  1094. {
  1095. service->service_entry->process = NULL;
  1096. if (!--process->use_count) process_terminate(process);
  1097. release_process(process);
  1098. }
  1099. }
  1100. if (result != ERROR_SUCCESS)
  1101. {
  1102. if (lpServiceStatus) *lpServiceStatus = service->service_entry->status;
  1103. service_unlock(service->service_entry);
  1104. return result;
  1105. }
  1106. if (!service_accepts_control(service->service_entry, dwControl))
  1107. {
  1108. service_unlock(service->service_entry);
  1109. return ERROR_INVALID_SERVICE_CONTROL;
  1110. }
  1111. /* Remember that we tried to shutdown this service. When the service is
  1112. * still running on the second invocation, it will be forcefully killed. */
  1113. if (dwControl == SERVICE_CONTROL_STOP)
  1114. service->service_entry->force_shutdown = TRUE;
  1115. /* Hold a reference to the process while sending the command. */
  1116. process = grab_process(service->service_entry->process);
  1117. shared_process = service->service_entry->shared_process;
  1118. service_unlock(service->service_entry);
  1119. if (!process)
  1120. return ERROR_SERVICE_CANNOT_ACCEPT_CTRL;
  1121. result = WaitForSingleObject(process->control_mutex, 30000);
  1122. if (result != WAIT_OBJECT_0)
  1123. {
  1124. release_process(process);
  1125. return ERROR_SERVICE_REQUEST_TIMEOUT;
  1126. }
  1127. if (process_send_control(process, shared_process, service->service_entry->name,
  1128. dwControl, NULL, 0, &result))
  1129. result = ERROR_SUCCESS;
  1130. if (lpServiceStatus)
  1131. {
  1132. service_lock(service->service_entry);
  1133. *lpServiceStatus = service->service_entry->status;
  1134. service_unlock(service->service_entry);
  1135. }
  1136. ReleaseMutex(process->control_mutex);
  1137. release_process(process);
  1138. return result;
  1139. }
  1140. DWORD __cdecl svcctl_CloseServiceHandle(
  1141. SC_RPC_HANDLE *handle)
  1142. {
  1143. WINE_TRACE("(&%p)\n", *handle);
  1144. SC_RPC_HANDLE_destroy(*handle);
  1145. *handle = NULL;
  1146. return ERROR_SUCCESS;
  1147. }
  1148. void __RPC_USER SC_RPC_LOCK_rundown(SC_RPC_LOCK hLock)
  1149. {
  1150. }
  1151. DWORD __cdecl svcctl_LockServiceDatabase(SC_RPC_HANDLE manager, SC_RPC_LOCK *lock)
  1152. {
  1153. TRACE("(%p, %p)\n", manager, lock);
  1154. *lock = (SC_RPC_LOCK)0xdeadbeef;
  1155. return ERROR_SUCCESS;
  1156. }
  1157. DWORD __cdecl svcctl_UnlockServiceDatabase(SC_RPC_LOCK *lock)
  1158. {
  1159. TRACE("(&%p)\n", *lock);
  1160. *lock = NULL;
  1161. return ERROR_SUCCESS;
  1162. }
  1163. static BOOL map_state(DWORD state, DWORD mask)
  1164. {
  1165. switch (state)
  1166. {
  1167. case SERVICE_START_PENDING:
  1168. case SERVICE_STOP_PENDING:
  1169. case SERVICE_RUNNING:
  1170. case SERVICE_CONTINUE_PENDING:
  1171. case SERVICE_PAUSE_PENDING:
  1172. case SERVICE_PAUSED:
  1173. if (SERVICE_ACTIVE & mask) return TRUE;
  1174. break;
  1175. case SERVICE_STOPPED:
  1176. if (SERVICE_INACTIVE & mask) return TRUE;
  1177. break;
  1178. default:
  1179. WINE_ERR("unknown state %u\n", state);
  1180. break;
  1181. }
  1182. return FALSE;
  1183. }
  1184. DWORD __cdecl svcctl_EnumServicesStatusW(
  1185. SC_RPC_HANDLE hmngr,
  1186. DWORD type,
  1187. DWORD state,
  1188. BYTE *buffer,
  1189. DWORD size,
  1190. LPDWORD needed,
  1191. LPDWORD returned,
  1192. LPDWORD resume)
  1193. {
  1194. DWORD err, sz, total_size, num_services, offset;
  1195. struct sc_manager_handle *manager;
  1196. struct service_entry *service;
  1197. struct enum_service_status *s;
  1198. WINE_TRACE("(%p, 0x%x, 0x%x, %p, %u, %p, %p, %p)\n", hmngr, type, state, buffer, size, needed, returned, resume);
  1199. if (!type || !state)
  1200. return ERROR_INVALID_PARAMETER;
  1201. if ((err = validate_scm_handle(hmngr, SC_MANAGER_ENUMERATE_SERVICE, &manager)) != ERROR_SUCCESS)
  1202. return err;
  1203. if (resume)
  1204. WINE_FIXME("resume index not supported\n");
  1205. scmdatabase_lock(manager->db);
  1206. total_size = num_services = 0;
  1207. LIST_FOR_EACH_ENTRY(service, &manager->db->services, struct service_entry, entry)
  1208. {
  1209. if ((service->status.dwServiceType & type) && map_state(service->status.dwCurrentState, state))
  1210. {
  1211. total_size += sizeof(*s);
  1212. total_size += (lstrlenW(service->name) + 1) * sizeof(WCHAR);
  1213. if (service->config.lpDisplayName)
  1214. {
  1215. total_size += (lstrlenW(service->config.lpDisplayName) + 1) * sizeof(WCHAR);
  1216. }
  1217. num_services++;
  1218. }
  1219. }
  1220. *returned = 0;
  1221. *needed = total_size;
  1222. if (total_size > size)
  1223. {
  1224. scmdatabase_unlock(manager->db);
  1225. return ERROR_MORE_DATA;
  1226. }
  1227. s = (struct enum_service_status *)buffer;
  1228. offset = num_services * sizeof(struct enum_service_status);
  1229. LIST_FOR_EACH_ENTRY(service, &manager->db->services, struct service_entry, entry)
  1230. {
  1231. if ((service->status.dwServiceType & type) && map_state(service->status.dwCurrentState, state))
  1232. {
  1233. sz = (lstrlenW(service->name) + 1) * sizeof(WCHAR);
  1234. memcpy(buffer + offset, service->name, sz);
  1235. s->service_name = offset;
  1236. offset += sz;
  1237. if (!service->config.lpDisplayName) s->display_name = 0;
  1238. else
  1239. {
  1240. sz = (lstrlenW(service->config.lpDisplayName) + 1) * sizeof(WCHAR);
  1241. memcpy(buffer + offset, service->config.lpDisplayName, sz);
  1242. s->display_name = offset;
  1243. offset += sz;
  1244. }
  1245. s->service_status = service->status;
  1246. s++;
  1247. }
  1248. }
  1249. *returned = num_services;
  1250. *needed = 0;
  1251. scmdatabase_unlock(manager->db);
  1252. return ERROR_SUCCESS;
  1253. }
  1254. static struct service_entry *find_service_by_group(struct scmdatabase *db, const WCHAR *group)
  1255. {
  1256. struct service_entry *service;
  1257. LIST_FOR_EACH_ENTRY(service, &db->services, struct service_entry, entry)
  1258. {
  1259. if (service->config.lpLoadOrderGroup && !wcsicmp(group, service->config.lpLoadOrderGroup))
  1260. return service;
  1261. }
  1262. return NULL;
  1263. }
  1264. static BOOL match_group(const WCHAR *g1, const WCHAR *g2)
  1265. {
  1266. if (!g2) return TRUE;
  1267. if (!g2[0] && (!g1 || !g1[0])) return TRUE;
  1268. if (g1 && !lstrcmpW(g1, g2)) return TRUE;
  1269. return FALSE;
  1270. }
  1271. DWORD __cdecl svcctl_EnumServicesStatusExA(
  1272. SC_RPC_HANDLE scmanager,
  1273. SC_ENUM_TYPE info_level,
  1274. DWORD service_type,
  1275. DWORD service_state,
  1276. BYTE *buffer,
  1277. DWORD buf_size,
  1278. DWORD *needed_size,
  1279. DWORD *services_count,
  1280. DWORD *resume_index,
  1281. LPCSTR groupname)
  1282. {
  1283. WINE_FIXME("\n");
  1284. return ERROR_CALL_NOT_IMPLEMENTED;
  1285. }
  1286. DWORD __cdecl svcctl_EnumServicesStatusExW(
  1287. SC_RPC_HANDLE hmngr,
  1288. SC_ENUM_TYPE info_level,
  1289. DWORD type,
  1290. DWORD state,
  1291. BYTE *buffer,
  1292. DWORD size,
  1293. LPDWORD needed,
  1294. LPDWORD returned,
  1295. DWORD *resume_handle,
  1296. LPCWSTR group)
  1297. {
  1298. DWORD err, sz, total_size, num_services;
  1299. DWORD_PTR offset;
  1300. struct sc_manager_handle *manager;
  1301. struct service_entry *service;
  1302. struct enum_service_status_process *s;
  1303. WINE_TRACE("(%p, 0x%x, 0x%x, %p, %u, %p, %p, %s)\n", hmngr, type, state, buffer, size,
  1304. needed, returned, wine_dbgstr_w(group));
  1305. if (resume_handle)
  1306. FIXME("resume handle not supported\n");
  1307. if (!type || !state)
  1308. return ERROR_INVALID_PARAMETER;
  1309. if ((err = validate_scm_handle(hmngr, SC_MANAGER_ENUMERATE_SERVICE, &manager)) != ERROR_SUCCESS)
  1310. return err;
  1311. scmdatabase_lock(manager->db);
  1312. if (group && !find_service_by_group(manager->db, group))
  1313. {
  1314. scmdatabase_unlock(manager->db);
  1315. return ERROR_SERVICE_DOES_NOT_EXIST;
  1316. }
  1317. total_size = num_services = 0;
  1318. LIST_FOR_EACH_ENTRY(service, &manager->db->services, struct service_entry, entry)
  1319. {
  1320. if ((service->status.dwServiceType & type) && map_state(service->status.dwCurrentState, state)
  1321. && match_group(service->config.lpLoadOrderGroup, group))
  1322. {
  1323. total_size += sizeof(*s);
  1324. total_size += (lstrlenW(service->name) + 1) * sizeof(WCHAR);
  1325. if (service->config.lpDisplayName)
  1326. {
  1327. total_size += (lstrlenW(service->config.lpDisplayName) + 1) * sizeof(WCHAR);
  1328. }
  1329. num_services++;
  1330. }
  1331. }
  1332. *returned = 0;
  1333. *needed = total_size;
  1334. if (total_size > size)
  1335. {
  1336. scmdatabase_unlock(manager->db);
  1337. return ERROR_MORE_DATA;
  1338. }
  1339. s = (struct enum_service_status_process *)buffer;
  1340. offset = num_services * sizeof(*s);
  1341. LIST_FOR_EACH_ENTRY(service, &manager->db->services, struct service_entry, entry)
  1342. {
  1343. if ((service->status.dwServiceType & type) && map_state(service->status.dwCurrentState, state)
  1344. && match_group(service->config.lpLoadOrderGroup, group))
  1345. {
  1346. sz = (lstrlenW(service->name) + 1) * sizeof(WCHAR);
  1347. memcpy(buffer + offset, service->name, sz);
  1348. s->service_name = offset;
  1349. offset += sz;
  1350. if (!service->config.lpDisplayName) s->display_name = 0;
  1351. else
  1352. {
  1353. sz = (lstrlenW(service->config.lpDisplayName) + 1) * sizeof(WCHAR);
  1354. memcpy(buffer + offset, service->config.lpDisplayName, sz);
  1355. s->display_name = offset;
  1356. offset += sz;
  1357. }
  1358. fill_status_process(&s->service_status_process, service);
  1359. s++;
  1360. }
  1361. }
  1362. *returned = num_services;
  1363. *needed = 0;
  1364. scmdatabase_unlock(manager->db);
  1365. return ERROR_SUCCESS;
  1366. }
  1367. DWORD __cdecl svcctl_unknown43(void)
  1368. {
  1369. WINE_FIXME("\n");
  1370. return ERROR_CALL_NOT_IMPLEMENTED;
  1371. }
  1372. DWORD __cdecl svcctl_CreateServiceWOW64A(
  1373. SC_RPC_HANDLE scmanager,
  1374. LPCSTR servicename,
  1375. LPCSTR displayname,
  1376. DWORD accessmask,
  1377. DWORD service_type,
  1378. DWORD start_type,
  1379. DWORD error_control,
  1380. LPCSTR imagepath,
  1381. LPCSTR loadordergroup,
  1382. DWORD *tagid,
  1383. const BYTE *dependencies,
  1384. DWORD depend_size,
  1385. LPCSTR start_name,
  1386. const BYTE *password,
  1387. DWORD password_size,
  1388. SC_RPC_HANDLE *service)
  1389. {
  1390. WINE_FIXME("\n");
  1391. return ERROR_CALL_NOT_IMPLEMENTED;
  1392. }
  1393. DWORD __cdecl svcctl_CreateServiceWOW64W(
  1394. SC_RPC_HANDLE scmanager,
  1395. LPCWSTR servicename,
  1396. LPCWSTR displayname,
  1397. DWORD accessmask,
  1398. DWORD service_type,
  1399. DWORD start_type,
  1400. DWORD error_control,
  1401. LPCWSTR imagepath,
  1402. LPCWSTR loadordergroup,
  1403. DWORD *tagid,
  1404. const BYTE *dependencies,
  1405. DWORD depend_size,
  1406. LPCWSTR start_name,
  1407. const BYTE *password,
  1408. DWORD password_size,
  1409. SC_RPC_HANDLE *service)
  1410. {
  1411. WINE_TRACE("(%s, %s, 0x%x, %s)\n", wine_dbgstr_w(servicename), wine_dbgstr_w(displayname), accessmask, wine_dbgstr_w(imagepath));
  1412. return create_serviceW(scmanager, servicename, displayname, accessmask, service_type, start_type, error_control, imagepath,
  1413. loadordergroup, tagid, dependencies, depend_size, start_name, password, password_size, service, TRUE);
  1414. }
  1415. DWORD __cdecl svcctl_unknown46(void)
  1416. {
  1417. WINE_FIXME("\n");
  1418. return ERROR_CALL_NOT_IMPLEMENTED;
  1419. }
  1420. DWORD __cdecl svcctl_NotifyServiceStatusChange(
  1421. SC_RPC_HANDLE handle,
  1422. SC_RPC_NOTIFY_PARAMS params,
  1423. GUID *clientprocessguid,
  1424. GUID *scmprocessguid,
  1425. BOOL *createremotequeue,
  1426. SC_NOTIFY_RPC_HANDLE *hNotify)
  1427. {
  1428. DWORD err, mask;
  1429. struct sc_manager_handle *manager = NULL;
  1430. struct sc_service_handle *service = NULL;
  1431. struct sc_notify_handle *notify;
  1432. struct sc_handle *hdr = handle;
  1433. WINE_TRACE("(%p, NotifyMask: 0x%x, %p, %p, %p, %p)\n", handle,
  1434. params.params->dwNotifyMask, clientprocessguid, scmprocessguid,
  1435. createremotequeue, hNotify);
  1436. switch (hdr->type)
  1437. {
  1438. case SC_HTYPE_SERVICE:
  1439. err = validate_service_handle(handle, SERVICE_QUERY_STATUS, &service);
  1440. break;
  1441. case SC_HTYPE_MANAGER:
  1442. err = validate_scm_handle(handle, SC_MANAGER_ENUMERATE_SERVICE, &manager);
  1443. break;
  1444. default:
  1445. err = ERROR_INVALID_HANDLE;
  1446. break;
  1447. }
  1448. if (err != ERROR_SUCCESS)
  1449. return err;
  1450. if (manager)
  1451. {
  1452. WARN("Need support for service creation/deletion notifications\n");
  1453. return ERROR_CALL_NOT_IMPLEMENTED;
  1454. }
  1455. notify = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*notify));
  1456. if (!notify)
  1457. return ERROR_NOT_ENOUGH_SERVER_MEMORY;
  1458. notify->hdr.type = SC_HTYPE_NOTIFY;
  1459. notify->hdr.access = 0;
  1460. notify->event = CreateEventW(NULL, TRUE, FALSE, NULL);
  1461. notify->notify_mask = params.params->dwNotifyMask;
  1462. service_lock(service->service_entry);
  1463. if (service->notify)
  1464. {
  1465. service_unlock(service->service_entry);
  1466. sc_notify_release(notify);
  1467. return ERROR_ALREADY_REGISTERED;
  1468. }
  1469. mask = 1 << (service->service_entry->status.dwCurrentState - SERVICE_STOPPED);
  1470. if (!service->status_notified && (notify->notify_mask & mask))
  1471. {
  1472. fill_notify(notify, service->service_entry);
  1473. service->status_notified = TRUE;
  1474. }
  1475. else
  1476. {
  1477. sc_notify_retain(notify);
  1478. service->notify = notify;
  1479. }
  1480. sc_notify_retain(notify);
  1481. *hNotify = &notify->hdr;
  1482. service_unlock(service->service_entry);
  1483. return ERROR_SUCCESS;
  1484. }
  1485. DWORD __cdecl svcctl_GetNotifyResults(
  1486. SC_NOTIFY_RPC_HANDLE hNotify,
  1487. SC_RPC_NOTIFY_PARAMS_LIST **pList)
  1488. {
  1489. DWORD err;
  1490. struct sc_notify_handle *notify;
  1491. WINE_TRACE("(%p, %p)\n", hNotify, pList);
  1492. if (!pList)
  1493. return ERROR_INVALID_PARAMETER;
  1494. *pList = NULL;
  1495. if ((err = validate_notify_handle(hNotify, 0, &notify)) != 0)
  1496. return err;
  1497. sc_notify_retain(notify);
  1498. /* block until there is a result */
  1499. err = WaitForSingleObject(notify->event, INFINITE);
  1500. if (err != WAIT_OBJECT_0)
  1501. {
  1502. sc_notify_release(notify);
  1503. return err;
  1504. }
  1505. *pList = InterlockedExchangePointer((void**)&notify->params_list, NULL);
  1506. if (!*pList)
  1507. {
  1508. sc_notify_release(notify);
  1509. return ERROR_REQUEST_ABORTED;
  1510. }
  1511. sc_notify_release(notify);
  1512. return ERROR_SUCCESS;
  1513. }
  1514. DWORD __cdecl svcctl_CloseNotifyHandle(
  1515. SC_NOTIFY_RPC_HANDLE *hNotify,
  1516. BOOL *apc_fired)
  1517. {
  1518. struct sc_notify_handle *notify;
  1519. DWORD err;
  1520. WINE_TRACE("(%p, %p)\n", hNotify, apc_fired);
  1521. if ((err = validate_notify_handle(*hNotify, 0, &notify)) != 0)
  1522. return err;
  1523. sc_notify_release(notify);
  1524. return ERROR_SUCCESS;
  1525. }
  1526. DWORD __cdecl svcctl_ControlServiceExA(
  1527. SC_RPC_HANDLE service,
  1528. DWORD control,
  1529. DWORD info_level,
  1530. SC_RPC_SERVICE_CONTROL_IN_PARAMSA *in_params,
  1531. SC_RPC_SERVICE_CONTROL_OUT_PARAMSA *out_params)
  1532. {
  1533. WINE_FIXME("\n");
  1534. return ERROR_CALL_NOT_IMPLEMENTED;
  1535. }
  1536. DWORD __cdecl svcctl_ControlServiceExW(
  1537. SC_RPC_HANDLE service,
  1538. DWORD control,
  1539. DWORD info_level,
  1540. SC_RPC_SERVICE_CONTROL_IN_PARAMSW *in_params,
  1541. SC_RPC_SERVICE_CONTROL_OUT_PARAMSW *out_params)
  1542. {
  1543. WINE_FIXME("\n");
  1544. return ERROR_CALL_NOT_IMPLEMENTED;
  1545. }
  1546. DWORD __cdecl svcctl_unknown52(void)
  1547. {
  1548. WINE_FIXME("\n");
  1549. return ERROR_CALL_NOT_IMPLEMENTED;
  1550. }
  1551. DWORD __cdecl svcctl_unknown53(void)
  1552. {
  1553. WINE_FIXME("\n");
  1554. return ERROR_CALL_NOT_IMPLEMENTED;
  1555. }
  1556. DWORD __cdecl svcctl_unknown54(void)
  1557. {
  1558. WINE_FIXME("\n");
  1559. return ERROR_CALL_NOT_IMPLEMENTED;
  1560. }
  1561. DWORD __cdecl svcctl_unknown55(void)
  1562. {
  1563. WINE_FIXME("\n");
  1564. return ERROR_CALL_NOT_IMPLEMENTED;
  1565. }
  1566. DWORD __cdecl svcctl_QueryServiceConfigEx(
  1567. SC_RPC_HANDLE service,
  1568. DWORD info_level,
  1569. SC_RPC_CONFIG_INFOW *info)
  1570. {
  1571. WINE_FIXME("\n");
  1572. return ERROR_CALL_NOT_IMPLEMENTED;
  1573. }
  1574. DWORD __cdecl svcctl_QueryServiceObjectSecurity(
  1575. SC_RPC_HANDLE service,
  1576. SECURITY_INFORMATION info,
  1577. BYTE *descriptor,
  1578. DWORD buf_size,
  1579. DWORD *needed_size)
  1580. {
  1581. WINE_FIXME("\n");
  1582. return ERROR_CALL_NOT_IMPLEMENTED;
  1583. }
  1584. DWORD __cdecl svcctl_SetServiceObjectSecurity(
  1585. SC_RPC_HANDLE service,
  1586. SECURITY_INFORMATION info,
  1587. BYTE *descriptor,
  1588. DWORD buf_size)
  1589. {
  1590. WINE_FIXME("\n");
  1591. return ERROR_CALL_NOT_IMPLEMENTED;
  1592. }
  1593. DWORD __cdecl svcctl_QueryServiceStatus(
  1594. SC_RPC_HANDLE service,
  1595. SERVICE_STATUS *status)
  1596. {
  1597. WINE_FIXME("\n");
  1598. return ERROR_CALL_NOT_IMPLEMENTED;
  1599. }
  1600. DWORD __cdecl svcctl_NotifyBootConfigStatus(
  1601. SVCCTL_HANDLEW machinename,
  1602. DWORD boot_acceptable)
  1603. {
  1604. WINE_FIXME("\n");
  1605. return ERROR_CALL_NOT_IMPLEMENTED;
  1606. }
  1607. DWORD __cdecl svcctl_SCSetServiceBitsW(void)
  1608. {
  1609. WINE_FIXME("\n");
  1610. return ERROR_CALL_NOT_IMPLEMENTED;
  1611. }
  1612. DWORD __cdecl svcctl_EnumDependentServicesW(
  1613. SC_RPC_HANDLE service,
  1614. DWORD state,
  1615. BYTE *services,
  1616. DWORD buf_size,
  1617. DWORD *needed_size,
  1618. DWORD *services_ret)
  1619. {
  1620. WINE_FIXME("\n");
  1621. return ERROR_CALL_NOT_IMPLEMENTED;
  1622. }
  1623. DWORD __cdecl svcctl_QueryServiceLockStatusW(
  1624. SC_RPC_HANDLE scmanager,
  1625. QUERY_SERVICE_LOCK_STATUSW *status,
  1626. DWORD buf_size,
  1627. DWORD *needed_size)
  1628. {
  1629. WINE_FIXME("\n");
  1630. return ERROR_CALL_NOT_IMPLEMENTED;
  1631. }
  1632. DWORD __cdecl svcctl_SCSetServiceBitsA(void)
  1633. {
  1634. WINE_FIXME("\n");
  1635. return ERROR_CALL_NOT_IMPLEMENTED;
  1636. }
  1637. DWORD __cdecl svcctl_ChangeServiceConfigA(
  1638. SC_RPC_HANDLE service,
  1639. DWORD service_type,
  1640. DWORD start_type,
  1641. DWORD error_control,
  1642. LPSTR binarypath,
  1643. LPSTR loadordergroup,
  1644. DWORD *tagid,
  1645. BYTE *dependencies,
  1646. DWORD depend_size,
  1647. LPSTR startname,
  1648. BYTE *password,
  1649. DWORD password_size,
  1650. LPSTR displayname)
  1651. {
  1652. WINE_FIXME("\n");
  1653. return ERROR_CALL_NOT_IMPLEMENTED;
  1654. }
  1655. DWORD __cdecl svcctl_CreateServiceA(
  1656. SC_RPC_HANDLE scmanager,
  1657. LPCSTR servicename,
  1658. LPCSTR displayname,
  1659. DWORD desiredaccess,
  1660. DWORD service_type,
  1661. DWORD start_type,
  1662. DWORD error_control,
  1663. LPCSTR binarypath,
  1664. LPCSTR loadordergroup,
  1665. DWORD *tagid,
  1666. const BYTE *dependencies,
  1667. DWORD depend_size,
  1668. LPCSTR startname,
  1669. const BYTE *password,
  1670. DWORD password_size,
  1671. SC_RPC_HANDLE *service)
  1672. {
  1673. WINE_FIXME("\n");
  1674. return ERROR_CALL_NOT_IMPLEMENTED;
  1675. }
  1676. DWORD __cdecl svcctl_EnumDependentServicesA(
  1677. SC_RPC_HANDLE service,
  1678. DWORD state,
  1679. BYTE *services,
  1680. DWORD buf_size,
  1681. DWORD *needed_size,
  1682. DWORD *services_ret)
  1683. {
  1684. WINE_FIXME("\n");
  1685. return ERROR_CALL_NOT_IMPLEMENTED;
  1686. }
  1687. DWORD __cdecl svcctl_EnumServicesStatusA(
  1688. SC_RPC_HANDLE hmngr,
  1689. DWORD type,
  1690. DWORD state,
  1691. BYTE *buffer,
  1692. DWORD size,
  1693. DWORD *needed,
  1694. DWORD *returned,
  1695. DWORD *resume)
  1696. {
  1697. WINE_FIXME("\n");
  1698. return ERROR_CALL_NOT_IMPLEMENTED;
  1699. }
  1700. DWORD __cdecl svcctl_OpenSCManagerA(
  1701. MACHINE_HANDLEA MachineName,
  1702. LPCSTR DatabaseName,
  1703. DWORD dwAccessMask,
  1704. SC_RPC_HANDLE *handle)
  1705. {
  1706. WINE_FIXME("\n");
  1707. return ERROR_CALL_NOT_IMPLEMENTED;
  1708. }
  1709. DWORD __cdecl svcctl_OpenServiceA(
  1710. SC_RPC_HANDLE hSCManager,
  1711. LPCSTR lpServiceName,
  1712. DWORD dwDesiredAccess,
  1713. SC_RPC_HANDLE *phService)
  1714. {
  1715. WINE_FIXME("\n");
  1716. return ERROR_CALL_NOT_IMPLEMENTED;
  1717. }
  1718. DWORD __cdecl svcctl_QueryServiceConfigA(
  1719. SC_RPC_HANDLE hService,
  1720. QUERY_SERVICE_CONFIGA *config,
  1721. DWORD buf_size,
  1722. DWORD *needed_size)
  1723. {
  1724. WINE_FIXME("\n");
  1725. return ERROR_CALL_NOT_IMPLEMENTED;
  1726. }
  1727. DWORD __cdecl svcctl_QueryServiceLockStatusA(
  1728. SC_RPC_HANDLE scmanager,
  1729. QUERY_SERVICE_LOCK_STATUSA *status,
  1730. DWORD buf_size,
  1731. DWORD *needed_size)
  1732. {
  1733. WINE_FIXME("\n");
  1734. return ERROR_CALL_NOT_IMPLEMENTED;
  1735. }
  1736. DWORD __cdecl svcctl_StartServiceA(
  1737. SC_RPC_HANDLE service,
  1738. DWORD argc,
  1739. LPCSTR *args)
  1740. {
  1741. WINE_FIXME("\n");
  1742. return ERROR_CALL_NOT_IMPLEMENTED;
  1743. }
  1744. DWORD __cdecl svcctl_GetServiceDisplayNameA(
  1745. SC_RPC_HANDLE hSCManager,
  1746. LPCSTR servicename,
  1747. CHAR buffer[],
  1748. DWORD *buf_size)
  1749. {
  1750. WINE_FIXME("\n");
  1751. return ERROR_CALL_NOT_IMPLEMENTED;
  1752. }
  1753. DWORD __cdecl svcctl_GetServiceKeyNameA(
  1754. SC_RPC_HANDLE hSCManager,
  1755. LPCSTR servicename,
  1756. CHAR buffer[],
  1757. DWORD *buf_size)
  1758. {
  1759. WINE_FIXME("\n");
  1760. return ERROR_CALL_NOT_IMPLEMENTED;
  1761. }
  1762. DWORD __cdecl svcctl_GetCurrentGroupStateW(void)
  1763. {
  1764. WINE_FIXME("\n");
  1765. return ERROR_CALL_NOT_IMPLEMENTED;
  1766. }
  1767. DWORD __cdecl svcctl_EnumServiceGroupW(
  1768. SC_RPC_HANDLE scmanager,
  1769. DWORD service_type,
  1770. DWORD service_state,
  1771. BYTE *buffer,
  1772. DWORD buf_size,
  1773. DWORD *needed_size,
  1774. DWORD *returned_size,
  1775. DWORD *resume_index,
  1776. LPCWSTR groupname)
  1777. {
  1778. WINE_FIXME("\n");
  1779. return ERROR_CALL_NOT_IMPLEMENTED;
  1780. }
  1781. DWORD __cdecl svcctl_ChangeServiceConfig2A(
  1782. SC_RPC_HANDLE service,
  1783. SC_RPC_CONFIG_INFOA info)
  1784. {
  1785. WINE_FIXME("\n");
  1786. return ERROR_CALL_NOT_IMPLEMENTED;
  1787. }
  1788. DWORD __cdecl svcctl_QueryServiceConfig2A(
  1789. SC_RPC_HANDLE service,
  1790. DWORD info_level,
  1791. BYTE *buffer,
  1792. DWORD buf_size,
  1793. DWORD *needed_size)
  1794. {
  1795. WINE_FIXME("\n");
  1796. return ERROR_CALL_NOT_IMPLEMENTED;
  1797. }
  1798. DWORD RPC_Init(void)
  1799. {
  1800. WCHAR transport[] = SVCCTL_TRANSPORT;
  1801. WCHAR endpoint[] = SVCCTL_ENDPOINT;
  1802. DWORD err;
  1803. if (!(cleanup_group = CreateThreadpoolCleanupGroup()))
  1804. {
  1805. WINE_ERR("CreateThreadpoolCleanupGroup failed with error %u\n", GetLastError());
  1806. return GetLastError();
  1807. }
  1808. if ((err = RpcServerUseProtseqEpW(transport, 0, endpoint, NULL)) != ERROR_SUCCESS)
  1809. {
  1810. WINE_ERR("RpcServerUseProtseq failed with error %u\n", err);
  1811. return err;
  1812. }
  1813. if ((err = RpcServerRegisterIf(svcctl_v2_0_s_ifspec, 0, 0)) != ERROR_SUCCESS)
  1814. {
  1815. WINE_ERR("RpcServerRegisterIf failed with error %u\n", err);
  1816. return err;
  1817. }
  1818. if ((err = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE)) != ERROR_SUCCESS)
  1819. {
  1820. WINE_ERR("RpcServerListen failed with error %u\n", err);
  1821. return err;
  1822. }
  1823. NtSetInformationProcess( GetCurrentProcess(), ProcessWineMakeProcessSystem,
  1824. &exit_event, sizeof(HANDLE *) );
  1825. return ERROR_SUCCESS;
  1826. }
  1827. void RPC_Stop(void)
  1828. {
  1829. RpcMgmtStopServerListening(NULL);
  1830. RpcServerUnregisterIf(svcctl_v2_0_s_ifspec, NULL, TRUE);
  1831. RpcMgmtWaitServerListen();
  1832. CloseThreadpoolCleanupGroupMembers(cleanup_group, TRUE, NULL);
  1833. CloseThreadpoolCleanupGroup(cleanup_group);
  1834. CloseHandle(exit_event);
  1835. }
  1836. void __RPC_USER SC_RPC_HANDLE_rundown(SC_RPC_HANDLE handle)
  1837. {
  1838. SC_RPC_HANDLE_destroy(handle);
  1839. }
  1840. void __RPC_USER SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE handle)
  1841. {
  1842. }
  1843. void __RPC_FAR * __RPC_USER MIDL_user_allocate(SIZE_T len)
  1844. {
  1845. return HeapAlloc(GetProcessHeap(), 0, len);
  1846. }
  1847. void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr)
  1848. {
  1849. HeapFree(GetProcessHeap(), 0, ptr);
  1850. }