Release 0.9.61.
[wine/gsoc-2012-control.git] / dlls / advapi32 / service.c
bloba1407dd521c37045b13a0345350a8539bae1bb46
1 /*
2 * Win32 advapi functions
4 * Copyright 1995 Sven Verdoolaege
5 * Copyright 2005 Mike McCormack
6 * Copyright 2007 Rolf Kalbermatter
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <string.h>
28 #include <time.h>
29 #include <assert.h>
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winsvc.h"
34 #include "winerror.h"
35 #include "winreg.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
38 #include "winternl.h"
39 #include "lmcons.h"
40 #include "lmserver.h"
42 #include "svcctl.h"
44 #include "wine/exception.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(service);
48 static const WCHAR szLocalSystem[] = {'L','o','c','a','l','S','y','s','t','e','m',0};
49 static const WCHAR szServiceManagerKey[] = { 'S','y','s','t','e','m','\\',
50 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
51 'S','e','r','v','i','c','e','s',0 };
52 static const WCHAR szSCMLock[] = {'A','D','V','A','P','I','_','S','C','M',
53 'L','O','C','K',0};
55 void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t len)
57 return HeapAlloc(GetProcessHeap(), 0, len);
60 void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr)
62 HeapFree(GetProcessHeap(), 0, ptr);
65 static const GENERIC_MAPPING scm_generic = {
66 (STANDARD_RIGHTS_READ | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS),
67 (STANDARD_RIGHTS_WRITE | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_MODIFY_BOOT_CONFIG),
68 (STANDARD_RIGHTS_EXECUTE | SC_MANAGER_CONNECT | SC_MANAGER_LOCK),
69 SC_MANAGER_ALL_ACCESS
72 static const GENERIC_MAPPING svc_generic = {
73 (STANDARD_RIGHTS_READ | SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_INTERROGATE | SERVICE_ENUMERATE_DEPENDENTS),
74 (STANDARD_RIGHTS_WRITE | SERVICE_CHANGE_CONFIG),
75 (STANDARD_RIGHTS_EXECUTE | SERVICE_START | SERVICE_STOP | SERVICE_PAUSE_CONTINUE | SERVICE_USER_DEFINED_CONTROL),
76 SERVICE_ALL_ACCESS
79 typedef struct service_data_t
81 LPHANDLER_FUNCTION_EX handler;
82 LPVOID context;
83 HANDLE thread;
84 BOOL unicode : 1;
85 union {
86 LPSERVICE_MAIN_FUNCTIONA a;
87 LPSERVICE_MAIN_FUNCTIONW w;
88 } proc;
89 LPWSTR args;
90 WCHAR name[1];
91 } service_data;
93 static CRITICAL_SECTION service_cs;
94 static CRITICAL_SECTION_DEBUG service_cs_debug =
96 0, 0, &service_cs,
97 { &service_cs_debug.ProcessLocksList,
98 &service_cs_debug.ProcessLocksList },
99 0, 0, { (DWORD_PTR)(__FILE__ ": service_cs") }
101 static CRITICAL_SECTION service_cs = { &service_cs_debug, -1, 0, 0, 0, 0 };
103 static service_data **services;
104 static unsigned int nb_services;
105 static HANDLE service_event;
107 extern HANDLE __wine_make_process_system(void);
109 /******************************************************************************
110 * SC_HANDLEs
113 #define MAX_SERVICE_NAME 256
115 typedef enum { SC_HTYPE_MANAGER, SC_HTYPE_SERVICE } SC_HANDLE_TYPE;
117 struct sc_handle;
118 typedef VOID (*sc_handle_destructor)(struct sc_handle *);
120 struct sc_handle
122 SC_HANDLE_TYPE htype;
123 DWORD ref_count;
124 sc_handle_destructor destroy;
125 SC_RPC_HANDLE server_handle; /* server-side handle */
128 struct sc_manager /* service control manager handle */
130 struct sc_handle hdr;
131 HKEY hkey; /* handle to services database in the registry */
132 DWORD dwAccess;
135 struct sc_service /* service handle */
137 struct sc_handle hdr;
138 HKEY hkey; /* handle to service entry in the registry (under hkey) */
139 DWORD dwAccess;
140 struct sc_manager *scm; /* pointer to SCM handle */
141 WCHAR name[1];
144 static void *sc_handle_alloc(SC_HANDLE_TYPE htype, DWORD size,
145 sc_handle_destructor destroy)
147 struct sc_handle *hdr;
149 hdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
150 if (hdr)
152 hdr->htype = htype;
153 hdr->ref_count = 1;
154 hdr->destroy = destroy;
156 TRACE("sc_handle type=%d -> %p\n", htype, hdr);
157 return hdr;
160 static void *sc_handle_get_handle_data(SC_HANDLE handle, DWORD htype)
162 struct sc_handle *hdr = (struct sc_handle *) handle;
164 if (!hdr)
165 return NULL;
166 if (hdr->htype != htype)
167 return NULL;
168 return hdr;
171 static void sc_handle_free(struct sc_handle* hdr)
173 if (!hdr)
174 return;
175 if (--hdr->ref_count)
176 return;
177 hdr->destroy(hdr);
178 HeapFree(GetProcessHeap(), 0, hdr);
181 static void sc_handle_destroy_manager(struct sc_handle *handle)
183 struct sc_manager *mgr = (struct sc_manager*) handle;
185 TRACE("destroying SC Manager %p\n", mgr);
186 if (mgr->hkey)
187 RegCloseKey(mgr->hkey);
190 static void sc_handle_destroy_service(struct sc_handle *handle)
192 struct sc_service *svc = (struct sc_service*) handle;
194 TRACE("destroying service %p\n", svc);
195 if (svc->hkey)
196 RegCloseKey(svc->hkey);
197 svc->hkey = NULL;
198 sc_handle_free(&svc->scm->hdr);
199 svc->scm = NULL;
202 /******************************************************************************
203 * String management functions (same behaviour as strdup)
204 * NOTE: the caller of those functions is responsible for calling HeapFree
205 * in order to release the memory allocated by those functions.
207 static inline LPWSTR SERV_dup( LPCSTR str )
209 UINT len;
210 LPWSTR wstr;
212 if( !str )
213 return NULL;
214 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
215 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
216 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
217 return wstr;
220 static inline LPWSTR SERV_dupmulti(LPCSTR str)
222 UINT len = 0, n = 0;
223 LPWSTR wstr;
225 if( !str )
226 return NULL;
227 do {
228 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
229 n += (strlen( &str[n] ) + 1);
230 } while (str[n]);
231 len++;
232 n++;
234 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
235 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
236 return wstr;
239 static inline DWORD multisz_cb(LPCWSTR wmultisz)
241 const WCHAR *wptr = wmultisz;
243 if (wmultisz == NULL)
244 return 0;
246 while (*wptr)
247 wptr += lstrlenW(wptr)+1;
248 return (wptr - wmultisz + 1)*sizeof(WCHAR);
251 /******************************************************************************
252 * RPC connection with services.exe
255 handle_t __RPC_USER MACHINE_HANDLEW_bind(MACHINE_HANDLEW MachineName)
257 WCHAR transport[] = SVCCTL_TRANSPORT;
258 WCHAR endpoint[] = SVCCTL_ENDPOINT;
259 RPC_WSTR binding_str;
260 RPC_STATUS status;
261 handle_t rpc_handle;
263 status = RpcStringBindingComposeW(NULL, transport, (RPC_WSTR)MachineName, endpoint, NULL, &binding_str);
264 if (status != RPC_S_OK)
266 ERR("RpcStringBindingComposeW failed (%d)\n", (DWORD)status);
267 return NULL;
270 status = RpcBindingFromStringBindingW(binding_str, &rpc_handle);
271 RpcStringFreeW(&binding_str);
273 if (status != RPC_S_OK)
275 ERR("Couldn't connect to services.exe: error code %u\n", (DWORD)status);
276 return NULL;
279 return rpc_handle;
282 void __RPC_USER MACHINE_HANDLEW_unbind(MACHINE_HANDLEW MachineName, handle_t h)
284 RpcBindingFree(&h);
287 static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *eptr)
289 return I_RpcExceptionFilter(eptr->ExceptionRecord->ExceptionCode);
292 static DWORD map_exception_code(DWORD exception_code)
294 switch (exception_code)
296 case RPC_X_NULL_REF_POINTER:
297 case RPC_X_ENUM_VALUE_OUT_OF_RANGE:
298 case RPC_X_BYTE_COUNT_TOO_SMALL:
299 return ERROR_INVALID_PARAMETER;
300 default:
301 return exception_code;
305 /******************************************************************************
306 * Service IPC functions
308 static LPWSTR service_get_pipe_name(void)
310 static const WCHAR format[] = { '\\','\\','.','\\','p','i','p','e','\\',
311 'n','e','t','\\','N','t','C','o','n','t','r','o','l','P','i','p','e','%','u',0};
312 static const WCHAR service_current_key_str[] = { 'S','Y','S','T','E','M','\\',
313 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
314 'C','o','n','t','r','o','l','\\',
315 'S','e','r','v','i','c','e','C','u','r','r','e','n','t',0};
316 LPWSTR name;
317 DWORD len;
318 HKEY service_current_key;
319 DWORD service_current;
320 LONG ret;
321 DWORD type;
323 ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, service_current_key_str, 0,
324 KEY_QUERY_VALUE, &service_current_key);
325 if (ret != ERROR_SUCCESS)
326 return NULL;
327 len = sizeof(service_current);
328 ret = RegQueryValueExW(service_current_key, NULL, NULL, &type,
329 (BYTE *)&service_current, &len);
330 RegCloseKey(service_current_key);
331 if (ret != ERROR_SUCCESS || type != REG_DWORD)
332 return NULL;
333 len = sizeof(format)/sizeof(WCHAR) + 10 /* strlenW("4294967295") */;
334 name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
335 if (!name)
336 return NULL;
337 snprintfW(name, len, format, service_current);
338 return name;
341 static HANDLE service_open_pipe(void)
343 LPWSTR szPipe = service_get_pipe_name();
344 HANDLE handle = INVALID_HANDLE_VALUE;
346 do {
347 handle = CreateFileW(szPipe, GENERIC_READ|GENERIC_WRITE,
348 0, NULL, OPEN_ALWAYS, 0, NULL);
349 if (handle != INVALID_HANDLE_VALUE)
350 break;
351 if (GetLastError() != ERROR_PIPE_BUSY)
352 break;
353 } while (WaitNamedPipeW(szPipe, NMPWAIT_WAIT_FOREVER));
354 HeapFree(GetProcessHeap(), 0, szPipe);
356 return handle;
359 /******************************************************************************
360 * service_thread
362 * Call into the main service routine provided by StartServiceCtrlDispatcher.
364 static DWORD WINAPI service_thread(LPVOID arg)
366 service_data *info = arg;
367 LPWSTR str = info->args;
368 DWORD argc = 0, len = 0;
370 TRACE("%p\n", arg);
372 while (str[len])
374 len += strlenW(&str[len]) + 1;
375 argc++;
378 if (!argc)
380 if (info->unicode)
381 info->proc.w(0, NULL);
382 else
383 info->proc.a(0, NULL);
384 return 0;
387 if (info->unicode)
389 LPWSTR *argv, p;
391 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPWSTR));
392 for (argc=0, p=str; *p; p += strlenW(p) + 1)
393 argv[argc++] = p;
394 argv[argc] = NULL;
396 info->proc.w(argc, argv);
397 HeapFree(GetProcessHeap(), 0, argv);
399 else
401 LPSTR strA, *argv, p;
402 DWORD lenA;
404 lenA = WideCharToMultiByte(CP_ACP,0, str, len, NULL, 0, NULL, NULL);
405 strA = HeapAlloc(GetProcessHeap(), 0, lenA);
406 WideCharToMultiByte(CP_ACP,0, str, len, strA, lenA, NULL, NULL);
408 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPSTR));
409 for (argc=0, p=strA; *p; p += strlen(p) + 1)
410 argv[argc++] = p;
411 argv[argc] = NULL;
413 info->proc.a(argc, argv);
414 HeapFree(GetProcessHeap(), 0, argv);
415 HeapFree(GetProcessHeap(), 0, strA);
417 return 0;
420 /******************************************************************************
421 * service_handle_start
423 static BOOL service_handle_start(HANDLE pipe, service_data *service, DWORD count)
425 DWORD read = 0, result = 0;
426 LPWSTR args;
427 BOOL r;
429 TRACE("%p %p %d\n", pipe, service, count);
431 args = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
432 r = ReadFile(pipe, args, count*sizeof(WCHAR), &read, NULL);
433 if (!r || count!=read/sizeof(WCHAR) || args[count-1])
435 ERR("pipe read failed r = %d count = %d read = %d args[n-1]=%s\n",
436 r, count, read, debugstr_wn(args, count));
437 goto end;
440 if (service->thread)
442 WARN("service is not stopped\n");
443 result = ERROR_SERVICE_ALREADY_RUNNING;
444 goto end;
447 HeapFree(GetProcessHeap(), 0, service->args);
448 service->args = args;
449 args = NULL;
450 service->thread = CreateThread( NULL, 0, service_thread,
451 service, 0, NULL );
452 SetEvent( service_event ); /* notify the main loop */
454 end:
455 HeapFree(GetProcessHeap(), 0, args);
456 WriteFile( pipe, &result, sizeof result, &read, NULL );
458 return TRUE;
461 /******************************************************************************
462 * service_handle_control
464 static BOOL service_handle_control(HANDLE pipe, service_data *service,
465 DWORD dwControl)
467 DWORD count, ret = ERROR_INVALID_SERVICE_CONTROL;
469 TRACE("received control %d\n", dwControl);
471 if (service->handler)
472 ret = service->handler(dwControl, 0, NULL, service->context);
473 return WriteFile(pipe, &ret, sizeof ret, &count, NULL);
476 /******************************************************************************
477 * service_control_dispatcher
479 static DWORD WINAPI service_control_dispatcher(LPVOID arg)
481 service_data *service = arg;
482 HANDLE pipe;
484 TRACE("%p %s\n", service, debugstr_w(service->name));
486 pipe = service_open_pipe();
488 if (pipe==INVALID_HANDLE_VALUE)
490 ERR("failed to create pipe for %s, error = %d\n",
491 debugstr_w(service->name), GetLastError());
492 return 0;
495 /* dispatcher loop */
496 while (1)
498 BOOL r;
499 DWORD count, req[2] = {0,0};
501 r = ReadFile( pipe, &req, sizeof req, &count, NULL );
502 if (!r)
504 if (GetLastError() != ERROR_BROKEN_PIPE)
505 ERR( "pipe read failed error %u\n", GetLastError() );
506 break;
508 if (count != sizeof(req))
510 ERR( "partial pipe read %u\n", count );
511 break;
514 /* handle the request */
515 switch (req[0])
517 case WINESERV_STARTINFO:
518 service_handle_start(pipe, service, req[1]);
519 break;
520 case WINESERV_SENDCONTROL:
521 service_handle_control(pipe, service, req[1]);
522 break;
523 default:
524 ERR("received invalid command %d length %d\n", req[0], req[1]);
528 CloseHandle(pipe);
529 return 1;
532 /******************************************************************************
533 * service_run_threads
535 static BOOL service_run_threads(void)
537 DWORD i, n, ret;
538 HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
539 UINT wait_services[MAXIMUM_WAIT_OBJECTS];
541 service_event = CreateEventW( NULL, FALSE, FALSE, NULL );
543 wait_handles[0] = __wine_make_process_system();
544 wait_handles[1] = service_event;
546 TRACE("Starting %d pipe listener threads. Services running as process %d\n",
547 nb_services, GetCurrentProcessId());
549 EnterCriticalSection( &service_cs );
550 for (i = 0; i < nb_services; i++)
551 CloseHandle( CreateThread( NULL, 0, service_control_dispatcher, services[i], 0, NULL ));
552 LeaveCriticalSection( &service_cs );
554 /* wait for all the threads to pack up and exit */
555 for (;;)
557 EnterCriticalSection( &service_cs );
558 for (i = 0, n = 2; i < nb_services && n < MAXIMUM_WAIT_OBJECTS; i++)
560 if (!services[i]->thread) continue;
561 wait_services[n] = i;
562 wait_handles[n++] = services[i]->thread;
564 LeaveCriticalSection( &service_cs );
566 ret = WaitForMultipleObjects( n, wait_handles, FALSE, INFINITE );
567 if (!ret) /* system process event */
569 TRACE( "last user process exited, shutting down\n" );
570 /* FIXME: we should maybe send a shutdown control to running services */
571 ExitProcess(0);
573 else if (ret == 1)
575 continue; /* rebuild the list */
577 else if (ret < n)
579 services[wait_services[ret]]->thread = 0;
580 CloseHandle( wait_handles[ret] );
581 if (n == 3) return TRUE; /* it was the last running thread */
583 else return FALSE;
587 /******************************************************************************
588 * StartServiceCtrlDispatcherA [ADVAPI32.@]
590 * See StartServiceCtrlDispatcherW.
592 BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent )
594 service_data *info;
595 unsigned int i;
596 BOOL ret = TRUE;
598 TRACE("%p\n", servent);
600 if (nb_services)
602 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
603 return FALSE;
605 while (servent[nb_services].lpServiceName) nb_services++;
606 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
608 for (i = 0; i < nb_services; i++)
610 DWORD len = MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, NULL, 0);
611 DWORD sz = FIELD_OFFSET( service_data, name[len] );
612 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
613 MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, info->name, len);
614 info->proc.a = servent[i].lpServiceProc;
615 info->unicode = FALSE;
616 services[i] = info;
619 service_run_threads();
621 return ret;
624 /******************************************************************************
625 * StartServiceCtrlDispatcherW [ADVAPI32.@]
627 * Connects a process containing one or more services to the service control
628 * manager.
630 * PARAMS
631 * servent [I] A list of the service names and service procedures
633 * RETURNS
634 * Success: TRUE.
635 * Failure: FALSE.
637 BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent )
639 service_data *info;
640 unsigned int i;
641 BOOL ret = TRUE;
643 TRACE("%p\n", servent);
645 if (nb_services)
647 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
648 return FALSE;
650 while (servent[nb_services].lpServiceName) nb_services++;
651 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
653 for (i = 0; i < nb_services; i++)
655 DWORD len = strlenW(servent[i].lpServiceName) + 1;
656 DWORD sz = FIELD_OFFSET( service_data, name[len] );
657 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
658 strcpyW(info->name, servent[i].lpServiceName);
659 info->proc.w = servent[i].lpServiceProc;
660 info->unicode = TRUE;
661 services[i] = info;
664 service_run_threads();
666 return ret;
669 /******************************************************************************
670 * LockServiceDatabase [ADVAPI32.@]
672 SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
674 struct sc_manager *hscm;
675 SC_RPC_LOCK hLock = NULL;
676 DWORD err;
678 TRACE("%p\n",hSCManager);
680 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
681 if (!hscm)
683 SetLastError( ERROR_INVALID_HANDLE );
684 return NULL;
687 __TRY
689 err = svcctl_LockServiceDatabase(hscm->hdr.server_handle, &hLock);
691 __EXCEPT(rpc_filter)
693 err = map_exception_code(GetExceptionCode());
695 __ENDTRY
696 if (err != ERROR_SUCCESS)
698 SetLastError(err);
699 return NULL;
701 return hLock;
704 /******************************************************************************
705 * UnlockServiceDatabase [ADVAPI32.@]
707 BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock)
709 DWORD err;
710 SC_RPC_LOCK hRpcLock = ScLock;
712 TRACE("%p\n",ScLock);
714 __TRY
716 err = svcctl_UnlockServiceDatabase(&hRpcLock);
718 __EXCEPT(rpc_filter)
720 err = map_exception_code(GetExceptionCode());
722 __ENDTRY
723 if (err != ERROR_SUCCESS)
725 SetLastError(err);
726 return FALSE;
728 return TRUE;
731 /******************************************************************************
732 * SetServiceStatus [ADVAPI32.@]
734 * PARAMS
735 * hService []
736 * lpStatus []
738 BOOL WINAPI
739 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
741 struct sc_service *hsvc;
742 DWORD err;
744 TRACE("%p %x %x %x %x %x %x %x\n", hService,
745 lpStatus->dwServiceType, lpStatus->dwCurrentState,
746 lpStatus->dwControlsAccepted, lpStatus->dwWin32ExitCode,
747 lpStatus->dwServiceSpecificExitCode, lpStatus->dwCheckPoint,
748 lpStatus->dwWaitHint);
750 hsvc = sc_handle_get_handle_data((SC_HANDLE)hService, SC_HTYPE_SERVICE);
751 if (!hsvc)
753 SetLastError( ERROR_INVALID_HANDLE );
754 return FALSE;
757 __TRY
759 err = svcctl_SetServiceStatus( hsvc->hdr.server_handle, lpStatus );
761 __EXCEPT(rpc_filter)
763 err = map_exception_code(GetExceptionCode());
765 __ENDTRY
766 if (err != ERROR_SUCCESS)
768 SetLastError(err);
769 return FALSE;
772 if (lpStatus->dwCurrentState == SERVICE_STOPPED)
773 CloseServiceHandle((SC_HANDLE)hService);
775 return TRUE;
779 /******************************************************************************
780 * OpenSCManagerA [ADVAPI32.@]
782 * Establish a connection to the service control manager and open its database.
784 * PARAMS
785 * lpMachineName [I] Pointer to machine name string
786 * lpDatabaseName [I] Pointer to database name string
787 * dwDesiredAccess [I] Type of access
789 * RETURNS
790 * Success: A Handle to the service control manager database
791 * Failure: NULL
793 SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
794 DWORD dwDesiredAccess )
796 LPWSTR lpMachineNameW, lpDatabaseNameW;
797 SC_HANDLE ret;
799 lpMachineNameW = SERV_dup(lpMachineName);
800 lpDatabaseNameW = SERV_dup(lpDatabaseName);
801 ret = OpenSCManagerW(lpMachineNameW, lpDatabaseNameW, dwDesiredAccess);
802 HeapFree(GetProcessHeap(), 0, lpDatabaseNameW);
803 HeapFree(GetProcessHeap(), 0, lpMachineNameW);
804 return ret;
807 /******************************************************************************
808 * OpenSCManagerW [ADVAPI32.@]
810 * See OpenSCManagerA.
812 SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
813 DWORD dwDesiredAccess )
815 struct sc_manager *manager;
816 HKEY hReg;
817 LONG r;
818 DWORD new_mask = dwDesiredAccess;
820 TRACE("(%s,%s,0x%08x)\n", debugstr_w(lpMachineName),
821 debugstr_w(lpDatabaseName), dwDesiredAccess);
823 manager = sc_handle_alloc( SC_HTYPE_MANAGER, sizeof (struct sc_manager),
824 sc_handle_destroy_manager );
825 if (!manager)
826 return NULL;
828 __TRY
830 r = svcctl_OpenSCManagerW(lpMachineName, lpDatabaseName, dwDesiredAccess, &manager->hdr.server_handle);
832 __EXCEPT(rpc_filter)
834 r = map_exception_code(GetExceptionCode());
836 __ENDTRY
837 if (r!=ERROR_SUCCESS)
838 goto error;
840 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg);
841 if (r!=ERROR_SUCCESS)
842 goto error;
844 r = RegCreateKeyW(hReg, szServiceManagerKey, &manager->hkey);
845 RegCloseKey( hReg );
846 if (r!=ERROR_SUCCESS)
847 goto error;
849 RtlMapGenericMask(&new_mask, &scm_generic);
850 manager->dwAccess = new_mask;
851 TRACE("returning %p (access : 0x%08x)\n", manager, manager->dwAccess);
853 return (SC_HANDLE) &manager->hdr;
855 error:
856 sc_handle_free( &manager->hdr );
857 SetLastError( r);
858 return NULL;
861 /******************************************************************************
862 * ControlService [ADVAPI32.@]
864 * Send a control code to a service.
866 * PARAMS
867 * hService [I] Handle of the service control manager database
868 * dwControl [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
869 * lpServiceStatus [O] Destination for the status of the service, if available
871 * RETURNS
872 * Success: TRUE.
873 * Failure: FALSE.
875 * BUGS
876 * Unlike M$' implementation, control requests are not serialized and may be
877 * processed asynchronously.
879 BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl,
880 LPSERVICE_STATUS lpServiceStatus )
882 struct sc_service *hsvc;
883 DWORD err;
885 TRACE("%p %d %p\n", hService, dwControl, lpServiceStatus);
887 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
888 if (!hsvc)
890 SetLastError( ERROR_INVALID_HANDLE );
891 return FALSE;
894 __TRY
896 err = svcctl_ControlService(hsvc->hdr.server_handle, dwControl, lpServiceStatus);
898 __EXCEPT(rpc_filter)
900 err = map_exception_code(GetExceptionCode());
902 __ENDTRY
903 if (err != ERROR_SUCCESS)
905 SetLastError(err);
906 return FALSE;
909 return TRUE;
912 /******************************************************************************
913 * CloseServiceHandle [ADVAPI32.@]
915 * Close a handle to a service or the service control manager database.
917 * PARAMS
918 * hSCObject [I] Handle to service or service control manager database
920 * RETURNS
921 * Success: TRUE
922 * Failure: FALSE
924 BOOL WINAPI
925 CloseServiceHandle( SC_HANDLE hSCObject )
927 struct sc_handle *obj;
928 DWORD err;
930 TRACE("%p\n", hSCObject);
931 if (hSCObject == NULL)
933 SetLastError(ERROR_INVALID_HANDLE);
934 return FALSE;
937 obj = (struct sc_handle *)hSCObject;
938 __TRY
940 err = svcctl_CloseServiceHandle(&obj->server_handle);
942 __EXCEPT(rpc_filter)
944 err = map_exception_code(GetExceptionCode());
946 __ENDTRY
947 sc_handle_free( obj );
949 if (err != ERROR_SUCCESS)
951 SetLastError(err);
952 return FALSE;
954 return TRUE;
958 /******************************************************************************
959 * OpenServiceA [ADVAPI32.@]
961 * Open a handle to a service.
963 * PARAMS
964 * hSCManager [I] Handle of the service control manager database
965 * lpServiceName [I] Name of the service to open
966 * dwDesiredAccess [I] Access required to the service
968 * RETURNS
969 * Success: Handle to the service
970 * Failure: NULL
972 SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
973 DWORD dwDesiredAccess )
975 LPWSTR lpServiceNameW;
976 SC_HANDLE ret;
978 TRACE("%p %s %d\n", hSCManager, debugstr_a(lpServiceName), dwDesiredAccess);
980 lpServiceNameW = SERV_dup(lpServiceName);
981 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
982 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
983 return ret;
987 /******************************************************************************
988 * OpenServiceW [ADVAPI32.@]
990 * See OpenServiceA.
992 SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
993 DWORD dwDesiredAccess)
995 struct sc_manager *hscm;
996 struct sc_service *hsvc;
997 DWORD err;
998 DWORD len;
999 DWORD new_mask = dwDesiredAccess;
1001 TRACE("%p %s %d\n", hSCManager, debugstr_w(lpServiceName), dwDesiredAccess);
1003 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
1004 if (!hscm)
1006 SetLastError( ERROR_INVALID_HANDLE );
1007 return FALSE;
1010 if (!lpServiceName)
1012 SetLastError(ERROR_INVALID_ADDRESS);
1013 return NULL;
1016 len = strlenW(lpServiceName)+1;
1017 hsvc = sc_handle_alloc( SC_HTYPE_SERVICE,
1018 sizeof (struct sc_service) + len*sizeof(WCHAR),
1019 sc_handle_destroy_service );
1020 if (!hsvc)
1022 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1023 return NULL;
1025 strcpyW( hsvc->name, lpServiceName );
1027 /* add reference to SCM handle */
1028 hscm->hdr.ref_count++;
1029 hsvc->scm = hscm;
1031 __TRY
1033 err = svcctl_OpenServiceW(hscm->hdr.server_handle, lpServiceName, dwDesiredAccess, &hsvc->hdr.server_handle);
1035 __EXCEPT(rpc_filter)
1037 err = map_exception_code(GetExceptionCode());
1039 __ENDTRY
1041 if (err != ERROR_SUCCESS)
1043 sc_handle_free(&hsvc->hdr);
1044 SetLastError(err);
1045 return NULL;
1048 /* for parts of advapi32 not using services.exe yet */
1049 RtlMapGenericMask(&new_mask, &svc_generic);
1050 hsvc->dwAccess = new_mask;
1052 err = RegOpenKeyExW( hscm->hkey, lpServiceName, 0, KEY_ALL_ACCESS, &hsvc->hkey );
1053 if (err != ERROR_SUCCESS)
1054 ERR("Shouldn't hapen - service key for service validated by services.exe doesn't exist\n");
1056 TRACE("returning %p\n",hsvc);
1058 return (SC_HANDLE) &hsvc->hdr;
1061 /******************************************************************************
1062 * CreateServiceW [ADVAPI32.@]
1064 SC_HANDLE WINAPI
1065 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1066 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
1067 DWORD dwServiceType, DWORD dwStartType,
1068 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1069 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
1070 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
1071 LPCWSTR lpPassword )
1073 struct sc_manager *hscm;
1074 struct sc_service *hsvc = NULL;
1075 DWORD new_mask = dwDesiredAccess;
1076 DWORD len, err;
1077 SIZE_T passwdlen;
1079 TRACE("%p %s %s\n", hSCManager,
1080 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
1082 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
1083 if (!hscm)
1085 SetLastError( ERROR_INVALID_HANDLE );
1086 return NULL;
1089 if (!lpServiceName || !lpBinaryPathName)
1091 SetLastError(ERROR_INVALID_ADDRESS);
1092 return NULL;
1095 if (lpPassword)
1096 passwdlen = (strlenW(lpPassword) + 1) * sizeof(WCHAR);
1097 else
1098 passwdlen = 0;
1100 len = strlenW(lpServiceName)+1;
1101 len = sizeof (struct sc_service) + len*sizeof(WCHAR);
1102 hsvc = sc_handle_alloc( SC_HTYPE_SERVICE, len, sc_handle_destroy_service );
1103 if( !hsvc )
1105 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1106 return NULL;
1108 lstrcpyW( hsvc->name, lpServiceName );
1110 hsvc->scm = hscm;
1111 hscm->hdr.ref_count++;
1113 __TRY
1115 err = svcctl_CreateServiceW(hscm->hdr.server_handle, lpServiceName,
1116 lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1117 lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, (LPBYTE)lpDependencies,
1118 multisz_cb(lpDependencies), lpServiceStartName, (LPBYTE)lpPassword, passwdlen,
1119 &hsvc->hdr.server_handle);
1121 __EXCEPT(rpc_filter)
1123 err = map_exception_code(GetExceptionCode());
1125 __ENDTRY
1127 if (err != ERROR_SUCCESS)
1129 SetLastError(err);
1130 sc_handle_free(&hsvc->hdr);
1131 return NULL;
1134 /* for parts of advapi32 not using services.exe yet */
1135 err = RegOpenKeyW(hscm->hkey, lpServiceName, &hsvc->hkey);
1136 if (err != ERROR_SUCCESS)
1137 WINE_ERR("Couldn't open key that should have been created by services.exe\n");
1139 RtlMapGenericMask(&new_mask, &svc_generic);
1140 hsvc->dwAccess = new_mask;
1142 return (SC_HANDLE) &hsvc->hdr;
1146 /******************************************************************************
1147 * CreateServiceA [ADVAPI32.@]
1149 SC_HANDLE WINAPI
1150 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1151 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
1152 DWORD dwServiceType, DWORD dwStartType,
1153 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1154 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
1155 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
1156 LPCSTR lpPassword )
1158 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
1159 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
1160 SC_HANDLE r;
1162 TRACE("%p %s %s\n", hSCManager,
1163 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
1165 lpServiceNameW = SERV_dup( lpServiceName );
1166 lpDisplayNameW = SERV_dup( lpDisplayName );
1167 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
1168 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
1169 lpDependenciesW = SERV_dupmulti( lpDependencies );
1170 lpServiceStartNameW = SERV_dup( lpServiceStartName );
1171 lpPasswordW = SERV_dup( lpPassword );
1173 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
1174 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1175 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
1176 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
1178 HeapFree( GetProcessHeap(), 0, lpServiceNameW );
1179 HeapFree( GetProcessHeap(), 0, lpDisplayNameW );
1180 HeapFree( GetProcessHeap(), 0, lpBinaryPathNameW );
1181 HeapFree( GetProcessHeap(), 0, lpLoadOrderGroupW );
1182 HeapFree( GetProcessHeap(), 0, lpDependenciesW );
1183 HeapFree( GetProcessHeap(), 0, lpServiceStartNameW );
1184 HeapFree( GetProcessHeap(), 0, lpPasswordW );
1186 return r;
1190 /******************************************************************************
1191 * DeleteService [ADVAPI32.@]
1193 * Delete a service from the service control manager database.
1195 * PARAMS
1196 * hService [I] Handle of the service to delete
1198 * RETURNS
1199 * Success: TRUE
1200 * Failure: FALSE
1202 BOOL WINAPI DeleteService( SC_HANDLE hService )
1204 struct sc_service *hsvc;
1205 DWORD err;
1207 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1208 if (!hsvc)
1210 SetLastError( ERROR_INVALID_HANDLE );
1211 return FALSE;
1214 __TRY
1216 err = svcctl_DeleteService(hsvc->hdr.server_handle);
1218 __EXCEPT(rpc_filter)
1220 err = map_exception_code(GetExceptionCode());
1222 __ENDTRY
1223 if (err != 0)
1225 SetLastError(err);
1226 return FALSE;
1229 /* Close the key to the service */
1230 RegCloseKey(hsvc->hkey);
1231 hsvc->hkey = NULL;
1232 return TRUE;
1236 /******************************************************************************
1237 * StartServiceA [ADVAPI32.@]
1239 * Start a service
1241 * PARAMS
1242 * hService [I] Handle of service
1243 * dwNumServiceArgs [I] Number of arguments
1244 * lpServiceArgVectors [I] Address of array of argument strings
1246 * NOTES
1247 * - NT implements this function using an obscure RPC call.
1248 * - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
1249 * to get things like "%SystemRoot%\\System32\\service.exe" to load.
1250 * - This will only work for shared address space. How should the service
1251 * args be transferred when address spaces are separated?
1252 * - Can only start one service at a time.
1253 * - Has no concept of privilege.
1255 * RETURNS
1256 * Success: TRUE.
1257 * Failure: FALSE
1259 BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
1260 LPCSTR *lpServiceArgVectors )
1262 LPWSTR *lpwstr=NULL;
1263 unsigned int i;
1264 BOOL r;
1266 TRACE("(%p,%d,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
1268 if (dwNumServiceArgs)
1269 lpwstr = HeapAlloc( GetProcessHeap(), 0,
1270 dwNumServiceArgs*sizeof(LPWSTR) );
1272 for(i=0; i<dwNumServiceArgs; i++)
1273 lpwstr[i]=SERV_dup(lpServiceArgVectors[i]);
1275 r = StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
1277 if (dwNumServiceArgs)
1279 for(i=0; i<dwNumServiceArgs; i++)
1280 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
1281 HeapFree(GetProcessHeap(), 0, lpwstr);
1284 return r;
1288 /******************************************************************************
1289 * StartServiceW [ADVAPI32.@]
1291 * See StartServiceA.
1293 BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs,
1294 LPCWSTR *lpServiceArgVectors)
1296 struct sc_service *hsvc;
1297 DWORD err;
1299 TRACE("%p %d %p\n", hService, dwNumServiceArgs, lpServiceArgVectors);
1301 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1302 if (!hsvc)
1304 SetLastError(ERROR_INVALID_HANDLE);
1305 return FALSE;
1308 __TRY
1310 err = svcctl_StartServiceW(hsvc->hdr.server_handle, dwNumServiceArgs, lpServiceArgVectors);
1312 __EXCEPT(rpc_filter)
1314 err = map_exception_code(GetExceptionCode());
1316 __ENDTRY
1317 if (err != ERROR_SUCCESS)
1319 SetLastError(err);
1320 return FALSE;
1323 return TRUE;
1326 /******************************************************************************
1327 * QueryServiceStatus [ADVAPI32.@]
1329 * PARAMS
1330 * hService [I] Handle to service to get information about
1331 * lpservicestatus [O] buffer to receive the status information for the service
1334 BOOL WINAPI QueryServiceStatus(SC_HANDLE hService,
1335 LPSERVICE_STATUS lpservicestatus)
1337 SERVICE_STATUS_PROCESS SvcStatusData;
1338 BOOL ret;
1339 DWORD dummy;
1341 TRACE("%p %p\n", hService, lpservicestatus);
1343 ret = QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&SvcStatusData,
1344 sizeof(SERVICE_STATUS_PROCESS), &dummy);
1345 if (ret) memcpy(lpservicestatus, &SvcStatusData, sizeof(SERVICE_STATUS)) ;
1346 return ret;
1350 /******************************************************************************
1351 * QueryServiceStatusEx [ADVAPI32.@]
1353 * Get information about a service.
1355 * PARAMS
1356 * hService [I] Handle to service to get information about
1357 * InfoLevel [I] Level of information to get
1358 * lpBuffer [O] Destination for requested information
1359 * cbBufSize [I] Size of lpBuffer in bytes
1360 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
1362 * RETURNS
1363 * Success: TRUE
1364 * FAILURE: FALSE
1366 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
1367 LPBYTE lpBuffer, DWORD cbBufSize,
1368 LPDWORD pcbBytesNeeded)
1370 struct sc_service *hsvc;
1371 DWORD err;
1373 TRACE("%p %d %p %d %p\n", hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1375 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1376 if (!hsvc)
1378 SetLastError( ERROR_INVALID_HANDLE );
1379 return FALSE;
1382 __TRY
1384 err = svcctl_QueryServiceStatusEx(hsvc->hdr.server_handle, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1386 __EXCEPT(rpc_filter)
1388 err = map_exception_code(GetExceptionCode());
1390 __ENDTRY
1391 if (err != ERROR_SUCCESS)
1393 SetLastError(err);
1394 return FALSE;
1397 return TRUE;
1400 /******************************************************************************
1401 * QueryServiceConfigA [ADVAPI32.@]
1403 BOOL WINAPI QueryServiceConfigA( SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA config,
1404 DWORD size, LPDWORD needed )
1406 DWORD n;
1407 LPSTR p, buffer;
1408 BOOL ret;
1409 QUERY_SERVICE_CONFIGW *configW;
1411 TRACE("%p %p %d %p\n", hService, config, size, needed);
1413 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, 2 * size )))
1415 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1416 return FALSE;
1418 configW = (QUERY_SERVICE_CONFIGW *)buffer;
1419 ret = QueryServiceConfigW( hService, configW, 2 * size, needed );
1420 if (!ret) goto done;
1422 config->dwServiceType = configW->dwServiceType;
1423 config->dwStartType = configW->dwStartType;
1424 config->dwErrorControl = configW->dwErrorControl;
1425 config->lpBinaryPathName = NULL;
1426 config->lpLoadOrderGroup = NULL;
1427 config->dwTagId = configW->dwTagId;
1428 config->lpDependencies = NULL;
1429 config->lpServiceStartName = NULL;
1430 config->lpDisplayName = NULL;
1432 p = (LPSTR)(config + 1);
1433 n = size - sizeof(*config);
1434 ret = FALSE;
1436 #define MAP_STR(str) \
1437 do { \
1438 if (configW->str) \
1440 DWORD sz = WideCharToMultiByte( CP_ACP, 0, configW->str, -1, p, n, NULL, NULL ); \
1441 if (!sz) goto done; \
1442 config->str = p; \
1443 p += sz; \
1444 n -= sz; \
1446 } while (0)
1448 MAP_STR( lpBinaryPathName );
1449 MAP_STR( lpLoadOrderGroup );
1450 MAP_STR( lpDependencies );
1451 MAP_STR( lpServiceStartName );
1452 MAP_STR( lpDisplayName );
1453 #undef MAP_STR
1455 *needed = p - (LPSTR)config;
1456 ret = TRUE;
1458 done:
1459 HeapFree( GetProcessHeap(), 0, buffer );
1460 return ret;
1463 static DWORD move_string_to_buffer(BYTE **buf, LPWSTR *string_ptr)
1465 DWORD cb;
1467 if (!*string_ptr)
1469 cb = sizeof(WCHAR);
1470 memset(*buf, 0, cb);
1472 else
1474 cb = (strlenW(*string_ptr) + 1)*sizeof(WCHAR);
1475 memcpy(*buf, *string_ptr, cb);
1476 MIDL_user_free(*string_ptr);
1479 *string_ptr = (LPWSTR)*buf;
1480 *buf += cb;
1482 return cb;
1485 static DWORD size_string(LPWSTR string)
1487 return (string ? (strlenW(string) + 1)*sizeof(WCHAR) : sizeof(WCHAR));
1490 /******************************************************************************
1491 * QueryServiceConfigW [ADVAPI32.@]
1493 BOOL WINAPI
1494 QueryServiceConfigW( SC_HANDLE hService,
1495 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1496 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1498 QUERY_SERVICE_CONFIGW config;
1499 struct sc_service *hsvc;
1500 DWORD total;
1501 DWORD err;
1502 BYTE *bufpos;
1504 TRACE("%p %p %d %p\n", hService, lpServiceConfig,
1505 cbBufSize, pcbBytesNeeded);
1507 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1508 if (!hsvc)
1510 SetLastError( ERROR_INVALID_HANDLE );
1511 return FALSE;
1514 memset(&config, 0, sizeof(config));
1516 __TRY
1518 err = svcctl_QueryServiceConfigW(hsvc->hdr.server_handle, &config);
1520 __EXCEPT(rpc_filter)
1522 err = map_exception_code(GetExceptionCode());
1524 __ENDTRY
1526 if (err != ERROR_SUCCESS)
1528 TRACE("services.exe: error %u\n", err);
1529 SetLastError(err);
1530 return FALSE;
1533 /* calculate the size required first */
1534 total = sizeof (QUERY_SERVICE_CONFIGW);
1535 total += size_string(config.lpBinaryPathName);
1536 total += size_string(config.lpLoadOrderGroup);
1537 total += size_string(config.lpDependencies);
1538 total += size_string(config.lpServiceStartName);
1539 total += size_string(config.lpDisplayName);
1541 *pcbBytesNeeded = total;
1543 /* if there's not enough memory, return an error */
1544 if( total > cbBufSize )
1546 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1547 MIDL_user_free(config.lpBinaryPathName);
1548 MIDL_user_free(config.lpLoadOrderGroup);
1549 MIDL_user_free(config.lpDependencies);
1550 MIDL_user_free(config.lpServiceStartName);
1551 MIDL_user_free(config.lpDisplayName);
1552 return FALSE;
1555 *lpServiceConfig = config;
1556 bufpos = ((BYTE *)lpServiceConfig) + sizeof(QUERY_SERVICE_CONFIGW);
1557 move_string_to_buffer(&bufpos, &lpServiceConfig->lpBinaryPathName);
1558 move_string_to_buffer(&bufpos, &lpServiceConfig->lpLoadOrderGroup);
1559 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDependencies);
1560 move_string_to_buffer(&bufpos, &lpServiceConfig->lpServiceStartName);
1561 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDisplayName);
1563 if (bufpos - (LPBYTE)lpServiceConfig > cbBufSize)
1564 ERR("Buffer overflow!\n");
1566 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1567 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1568 TRACE("Dependencies = %s\n", debugstr_w(lpServiceConfig->lpDependencies) );
1569 TRACE("Service account name = %s\n", debugstr_w(lpServiceConfig->lpServiceStartName) );
1570 TRACE("Display name = %s\n", debugstr_w(lpServiceConfig->lpDisplayName) );
1572 return TRUE;
1575 /******************************************************************************
1576 * QueryServiceConfig2A [ADVAPI32.@]
1578 * Note
1579 * observed under win2k:
1580 * The functions QueryServiceConfig2A and QueryServiceConfig2W return the same
1581 * required buffer size (in byte) at least for dwLevel SERVICE_CONFIG_DESCRIPTION
1583 BOOL WINAPI QueryServiceConfig2A(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1584 DWORD size, LPDWORD needed)
1586 BOOL ret;
1587 LPBYTE bufferW = NULL;
1589 if(buffer && size)
1590 bufferW = HeapAlloc( GetProcessHeap(), 0, size);
1592 ret = QueryServiceConfig2W(hService, dwLevel, bufferW, size, needed);
1593 if(!ret) goto cleanup;
1595 switch(dwLevel) {
1596 case SERVICE_CONFIG_DESCRIPTION:
1597 { LPSERVICE_DESCRIPTIONA configA = (LPSERVICE_DESCRIPTIONA) buffer;
1598 LPSERVICE_DESCRIPTIONW configW = (LPSERVICE_DESCRIPTIONW) bufferW;
1599 if (configW->lpDescription) {
1600 DWORD sz;
1601 configA->lpDescription = (LPSTR)(configA + 1);
1602 sz = WideCharToMultiByte( CP_ACP, 0, configW->lpDescription, -1,
1603 configA->lpDescription, size - sizeof(SERVICE_DESCRIPTIONA), NULL, NULL );
1604 if (!sz) {
1605 FIXME("WideCharToMultiByte failed for configW->lpDescription\n");
1606 ret = FALSE;
1607 configA->lpDescription = NULL;
1610 else configA->lpDescription = NULL;
1612 break;
1613 default:
1614 FIXME("conversation W->A not implemented for level %d\n", dwLevel);
1615 ret = FALSE;
1618 cleanup:
1619 HeapFree( GetProcessHeap(), 0, bufferW);
1620 return ret;
1623 /******************************************************************************
1624 * QueryServiceConfig2W [ADVAPI32.@]
1626 BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1627 DWORD size, LPDWORD needed)
1629 DWORD sz, type;
1630 HKEY hKey;
1631 LONG r;
1632 struct sc_service *hsvc;
1634 if(dwLevel != SERVICE_CONFIG_DESCRIPTION) {
1635 if((dwLevel == SERVICE_CONFIG_DELAYED_AUTO_START_INFO) ||
1636 (dwLevel == SERVICE_CONFIG_FAILURE_ACTIONS) ||
1637 (dwLevel == SERVICE_CONFIG_FAILURE_ACTIONS_FLAG) ||
1638 (dwLevel == SERVICE_CONFIG_PRESHUTDOWN_INFO) ||
1639 (dwLevel == SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO) ||
1640 (dwLevel == SERVICE_CONFIG_SERVICE_SID_INFO))
1641 FIXME("Level %d not implemented\n", dwLevel);
1642 SetLastError(ERROR_INVALID_LEVEL);
1643 return FALSE;
1645 if(!needed || (!buffer && size)) {
1646 SetLastError(ERROR_INVALID_ADDRESS);
1647 return FALSE;
1650 TRACE("%p 0x%d %p 0x%d %p\n", hService, dwLevel, buffer, size, needed);
1652 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1653 if (!hsvc)
1655 SetLastError(ERROR_INVALID_HANDLE);
1656 return FALSE;
1658 hKey = hsvc->hkey;
1660 switch(dwLevel) {
1661 case SERVICE_CONFIG_DESCRIPTION: {
1662 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
1663 LPSERVICE_DESCRIPTIONW config = (LPSERVICE_DESCRIPTIONW) buffer;
1664 LPBYTE strbuf = NULL;
1665 *needed = sizeof (SERVICE_DESCRIPTIONW);
1666 sz = size - *needed;
1667 if(config && (*needed <= size))
1668 strbuf = (LPBYTE) (config + 1);
1669 r = RegQueryValueExW( hKey, szDescription, 0, &type, strbuf, &sz );
1670 if((r == ERROR_SUCCESS) && ( type != REG_SZ)) {
1671 FIXME("SERVICE_CONFIG_DESCRIPTION: don't know how to handle type %d\n", type);
1672 return FALSE;
1674 *needed += sz;
1675 if(config) {
1676 if(r == ERROR_SUCCESS)
1677 config->lpDescription = (LPWSTR) (config + 1);
1678 else
1679 config->lpDescription = NULL;
1682 break;
1684 if(*needed > size)
1685 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1687 return (*needed <= size);
1690 /******************************************************************************
1691 * EnumServicesStatusA [ADVAPI32.@]
1693 BOOL WINAPI
1694 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
1695 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
1696 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1697 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
1699 FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager,
1700 dwServiceType, dwServiceState, lpServices, cbBufSize,
1701 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
1702 SetLastError (ERROR_ACCESS_DENIED);
1703 return FALSE;
1706 /******************************************************************************
1707 * EnumServicesStatusW [ADVAPI32.@]
1709 BOOL WINAPI
1710 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
1711 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
1712 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1713 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
1715 FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager,
1716 dwServiceType, dwServiceState, lpServices, cbBufSize,
1717 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
1718 SetLastError (ERROR_ACCESS_DENIED);
1719 return FALSE;
1722 /******************************************************************************
1723 * EnumServicesStatusExA [ADVAPI32.@]
1725 BOOL WINAPI
1726 EnumServicesStatusExA(SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType,
1727 DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1728 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle, LPCSTR pszGroupName)
1730 FIXME("%p level=%d type=%x state=%x %p %x %p %p %p %s\n", hSCManager, InfoLevel,
1731 dwServiceType, dwServiceState, lpServices, cbBufSize,
1732 pcbBytesNeeded, lpServicesReturned, lpResumeHandle, debugstr_a(pszGroupName));
1733 *lpServicesReturned = 0;
1734 SetLastError (ERROR_ACCESS_DENIED);
1735 return FALSE;
1738 /******************************************************************************
1739 * EnumServicesStatusExW [ADVAPI32.@]
1741 BOOL WINAPI
1742 EnumServicesStatusExW(SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType,
1743 DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1744 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle, LPCWSTR pszGroupName)
1746 FIXME("%p level=%d type=%x state=%x %p %x %p %p %p %s\n", hSCManager, InfoLevel,
1747 dwServiceType, dwServiceState, lpServices, cbBufSize,
1748 pcbBytesNeeded, lpServicesReturned, lpResumeHandle, debugstr_w(pszGroupName));
1749 SetLastError (ERROR_ACCESS_DENIED);
1750 return FALSE;
1753 /******************************************************************************
1754 * GetServiceKeyNameA [ADVAPI32.@]
1756 BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
1757 LPSTR lpServiceName, LPDWORD lpcchBuffer )
1759 LPWSTR lpDisplayNameW, lpServiceNameW;
1760 DWORD sizeW;
1761 BOOL ret = FALSE;
1763 TRACE("%p %s %p %p\n", hSCManager,
1764 debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
1766 lpDisplayNameW = SERV_dup(lpDisplayName);
1767 if (lpServiceName)
1768 lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1769 else
1770 lpServiceNameW = NULL;
1772 sizeW = *lpcchBuffer;
1773 if (!GetServiceKeyNameW(hSCManager, lpDisplayNameW, lpServiceNameW, &sizeW))
1775 if (*lpcchBuffer && lpServiceName)
1776 lpServiceName[0] = 0;
1777 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1778 goto cleanup;
1781 if (!WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, (sizeW + 1), lpServiceName,
1782 *lpcchBuffer, NULL, NULL ))
1784 if (*lpcchBuffer && lpServiceName)
1785 lpServiceName[0] = 0;
1786 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, -1, NULL, 0, NULL, NULL);
1787 goto cleanup;
1790 /* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
1791 ret = TRUE;
1793 cleanup:
1794 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1795 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1796 return ret;
1799 /******************************************************************************
1800 * GetServiceKeyNameW [ADVAPI32.@]
1802 BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
1803 LPWSTR lpServiceName, LPDWORD lpcchBuffer )
1805 struct sc_manager *hscm;
1806 DWORD err;
1808 TRACE("%p %s %p %p\n", hSCManager,
1809 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1811 hscm = sc_handle_get_handle_data(hSCManager, SC_HTYPE_MANAGER);
1812 if (!hscm)
1814 SetLastError(ERROR_INVALID_HANDLE);
1815 return FALSE;
1818 if (!lpDisplayName)
1820 SetLastError(ERROR_INVALID_ADDRESS);
1821 return FALSE;
1824 __TRY
1826 err = svcctl_GetServiceKeyNameW(hscm->hdr.server_handle,
1827 lpDisplayName, lpServiceName, lpServiceName ? *lpcchBuffer : 0, lpcchBuffer);
1829 __EXCEPT(rpc_filter)
1831 err = map_exception_code(GetExceptionCode());
1833 __ENDTRY
1835 if (err)
1836 SetLastError(err);
1837 return err == ERROR_SUCCESS;
1840 /******************************************************************************
1841 * QueryServiceLockStatusA [ADVAPI32.@]
1843 BOOL WINAPI QueryServiceLockStatusA( SC_HANDLE hSCManager,
1844 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
1845 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1847 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1849 return FALSE;
1852 /******************************************************************************
1853 * QueryServiceLockStatusW [ADVAPI32.@]
1855 BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager,
1856 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
1857 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1859 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1861 return FALSE;
1864 /******************************************************************************
1865 * GetServiceDisplayNameA [ADVAPI32.@]
1867 BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1868 LPSTR lpDisplayName, LPDWORD lpcchBuffer)
1870 LPWSTR lpServiceNameW, lpDisplayNameW;
1871 DWORD sizeW;
1872 BOOL ret = FALSE;
1874 TRACE("%p %s %p %p\n", hSCManager,
1875 debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
1877 lpServiceNameW = SERV_dup(lpServiceName);
1878 if (lpDisplayName)
1879 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1880 else
1881 lpDisplayNameW = NULL;
1883 sizeW = *lpcchBuffer;
1884 if (!GetServiceDisplayNameW(hSCManager, lpServiceNameW, lpDisplayNameW, &sizeW))
1886 if (*lpcchBuffer && lpDisplayName)
1887 lpDisplayName[0] = 0;
1888 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1889 goto cleanup;
1892 if (!WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, (sizeW + 1), lpDisplayName,
1893 *lpcchBuffer, NULL, NULL ))
1895 if (*lpcchBuffer && lpDisplayName)
1896 lpDisplayName[0] = 0;
1897 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, -1, NULL, 0, NULL, NULL);
1898 goto cleanup;
1901 /* probably due to a bug GetServiceDisplayNameA doesn't modify lpcchBuffer on success.
1902 * (but if the function succeeded it means that is a good upper estimation of the size) */
1903 ret = TRUE;
1905 cleanup:
1906 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1907 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1908 return ret;
1911 /******************************************************************************
1912 * GetServiceDisplayNameW [ADVAPI32.@]
1914 BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1915 LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
1917 struct sc_manager *hscm;
1918 DWORD err;
1920 TRACE("%p %s %p %p\n", hSCManager,
1921 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1923 hscm = sc_handle_get_handle_data(hSCManager, SC_HTYPE_MANAGER);
1924 if (!hscm)
1926 SetLastError(ERROR_INVALID_HANDLE);
1927 return FALSE;
1930 if (!lpServiceName)
1932 SetLastError(ERROR_INVALID_ADDRESS);
1933 return FALSE;
1936 __TRY
1938 err = svcctl_GetServiceDisplayNameW(hscm->hdr.server_handle,
1939 lpServiceName, lpDisplayName, lpDisplayName ? *lpcchBuffer : 0, lpcchBuffer);
1941 __EXCEPT(rpc_filter)
1943 err = map_exception_code(GetExceptionCode());
1945 __ENDTRY
1947 if (err)
1948 SetLastError(err);
1949 return err == ERROR_SUCCESS;
1952 /******************************************************************************
1953 * ChangeServiceConfigW [ADVAPI32.@]
1955 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
1956 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1957 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
1958 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
1960 struct sc_service *hsvc;
1961 DWORD cb_pwd;
1962 DWORD err;
1964 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
1965 hService, dwServiceType, dwStartType, dwErrorControl,
1966 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
1967 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
1968 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
1970 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1971 if (!hsvc)
1973 SetLastError( ERROR_INVALID_HANDLE );
1974 return FALSE;
1977 cb_pwd = lpPassword ? (strlenW(lpPassword) + 1)*sizeof(WCHAR) : 0;
1979 __TRY
1981 err = svcctl_ChangeServiceConfigW(hsvc->hdr.server_handle, dwServiceType,
1982 dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId,
1983 (const BYTE *)lpDependencies, multisz_cb(lpDependencies), lpServiceStartName,
1984 (const BYTE *)lpPassword, cb_pwd, lpDisplayName);
1986 __EXCEPT(rpc_filter)
1988 err = map_exception_code(GetExceptionCode());
1990 __ENDTRY
1992 if (err != ERROR_SUCCESS)
1993 SetLastError(err);
1995 return err == ERROR_SUCCESS;
1998 /******************************************************************************
1999 * ChangeServiceConfigA [ADVAPI32.@]
2001 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
2002 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
2003 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
2004 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
2006 LPWSTR wBinaryPathName, wLoadOrderGroup, wDependencies;
2007 LPWSTR wServiceStartName, wPassword, wDisplayName;
2008 BOOL r;
2010 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2011 hService, dwServiceType, dwStartType, dwErrorControl,
2012 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
2013 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
2014 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
2016 wBinaryPathName = SERV_dup( lpBinaryPathName );
2017 wLoadOrderGroup = SERV_dup( lpLoadOrderGroup );
2018 wDependencies = SERV_dupmulti( lpDependencies );
2019 wServiceStartName = SERV_dup( lpServiceStartName );
2020 wPassword = SERV_dup( lpPassword );
2021 wDisplayName = SERV_dup( lpDisplayName );
2023 r = ChangeServiceConfigW( hService, dwServiceType,
2024 dwStartType, dwErrorControl, wBinaryPathName,
2025 wLoadOrderGroup, lpdwTagId, wDependencies,
2026 wServiceStartName, wPassword, wDisplayName);
2028 HeapFree( GetProcessHeap(), 0, wBinaryPathName );
2029 HeapFree( GetProcessHeap(), 0, wLoadOrderGroup );
2030 HeapFree( GetProcessHeap(), 0, wDependencies );
2031 HeapFree( GetProcessHeap(), 0, wServiceStartName );
2032 HeapFree( GetProcessHeap(), 0, wPassword );
2033 HeapFree( GetProcessHeap(), 0, wDisplayName );
2035 return r;
2038 /******************************************************************************
2039 * ChangeServiceConfig2A [ADVAPI32.@]
2041 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
2042 LPVOID lpInfo)
2044 BOOL r = FALSE;
2046 TRACE("%p %d %p\n",hService, dwInfoLevel, lpInfo);
2048 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2050 LPSERVICE_DESCRIPTIONA sd = (LPSERVICE_DESCRIPTIONA) lpInfo;
2051 SERVICE_DESCRIPTIONW sdw;
2053 sdw.lpDescription = SERV_dup( sd->lpDescription );
2055 r = ChangeServiceConfig2W( hService, dwInfoLevel, &sdw );
2057 HeapFree( GetProcessHeap(), 0, sdw.lpDescription );
2059 else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
2061 LPSERVICE_FAILURE_ACTIONSA fa = (LPSERVICE_FAILURE_ACTIONSA) lpInfo;
2062 SERVICE_FAILURE_ACTIONSW faw;
2064 faw.dwResetPeriod = fa->dwResetPeriod;
2065 faw.lpRebootMsg = SERV_dup( fa->lpRebootMsg );
2066 faw.lpCommand = SERV_dup( fa->lpCommand );
2067 faw.cActions = fa->cActions;
2068 faw.lpsaActions = fa->lpsaActions;
2070 r = ChangeServiceConfig2W( hService, dwInfoLevel, &faw );
2072 HeapFree( GetProcessHeap(), 0, faw.lpRebootMsg );
2073 HeapFree( GetProcessHeap(), 0, faw.lpCommand );
2075 else
2076 SetLastError( ERROR_INVALID_PARAMETER );
2078 return r;
2081 /******************************************************************************
2082 * ChangeServiceConfig2W [ADVAPI32.@]
2084 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
2085 LPVOID lpInfo)
2087 HKEY hKey;
2088 struct sc_service *hsvc;
2090 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
2091 if (!hsvc)
2093 SetLastError( ERROR_INVALID_HANDLE );
2094 return FALSE;
2096 hKey = hsvc->hkey;
2098 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2100 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
2101 LPSERVICE_DESCRIPTIONW sd = (LPSERVICE_DESCRIPTIONW)lpInfo;
2102 if (sd->lpDescription)
2104 TRACE("Setting Description to %s\n",debugstr_w(sd->lpDescription));
2105 if (sd->lpDescription[0] == 0)
2106 RegDeleteValueW(hKey,szDescription);
2107 else
2108 RegSetValueExW(hKey, szDescription, 0, REG_SZ,
2109 (LPVOID)sd->lpDescription,
2110 sizeof(WCHAR)*(strlenW(sd->lpDescription)+1));
2113 else
2114 FIXME("STUB: %p %d %p\n",hService, dwInfoLevel, lpInfo);
2115 return TRUE;
2118 /******************************************************************************
2119 * QueryServiceObjectSecurity [ADVAPI32.@]
2121 BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService,
2122 SECURITY_INFORMATION dwSecurityInformation,
2123 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2124 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
2126 SECURITY_DESCRIPTOR descriptor;
2127 DWORD size;
2128 BOOL succ;
2129 ACL acl;
2131 FIXME("%p %d %p %u %p - semi-stub\n", hService, dwSecurityInformation,
2132 lpSecurityDescriptor, cbBufSize, pcbBytesNeeded);
2134 if (dwSecurityInformation != DACL_SECURITY_INFORMATION)
2135 FIXME("information %d not supported\n", dwSecurityInformation);
2137 InitializeSecurityDescriptor(&descriptor, SECURITY_DESCRIPTOR_REVISION);
2139 InitializeAcl(&acl, sizeof(ACL), ACL_REVISION);
2140 SetSecurityDescriptorDacl(&descriptor, TRUE, &acl, TRUE);
2142 size = cbBufSize;
2143 succ = MakeSelfRelativeSD(&descriptor, lpSecurityDescriptor, &size);
2144 *pcbBytesNeeded = size;
2145 return succ;
2148 /******************************************************************************
2149 * SetServiceObjectSecurity [ADVAPI32.@]
2151 BOOL WINAPI SetServiceObjectSecurity(SC_HANDLE hService,
2152 SECURITY_INFORMATION dwSecurityInformation,
2153 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2155 FIXME("%p %d %p\n", hService, dwSecurityInformation, lpSecurityDescriptor);
2156 return TRUE;
2159 /******************************************************************************
2160 * SetServiceBits [ADVAPI32.@]
2162 BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus,
2163 DWORD dwServiceBits,
2164 BOOL bSetBitsOn,
2165 BOOL bUpdateImmediately)
2167 FIXME("%p %08x %x %x\n", hServiceStatus, dwServiceBits,
2168 bSetBitsOn, bUpdateImmediately);
2169 return TRUE;
2172 /* thunk for calling the RegisterServiceCtrlHandler handler function */
2173 static DWORD WINAPI ctrl_handler_thunk( DWORD control, DWORD type, void *data, void *context )
2175 LPHANDLER_FUNCTION func = context;
2177 func( control );
2178 return ERROR_SUCCESS;
2181 /******************************************************************************
2182 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
2184 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerA( LPCSTR name, LPHANDLER_FUNCTION handler )
2186 return RegisterServiceCtrlHandlerExA( name, ctrl_handler_thunk, handler );
2189 /******************************************************************************
2190 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
2192 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW( LPCWSTR name, LPHANDLER_FUNCTION handler )
2194 return RegisterServiceCtrlHandlerExW( name, ctrl_handler_thunk, handler );
2197 /******************************************************************************
2198 * RegisterServiceCtrlHandlerExA [ADVAPI32.@]
2200 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA( LPCSTR name, LPHANDLER_FUNCTION_EX handler, LPVOID context )
2202 LPWSTR nameW;
2203 SERVICE_STATUS_HANDLE ret;
2205 nameW = SERV_dup(name);
2206 ret = RegisterServiceCtrlHandlerExW( nameW, handler, context );
2207 HeapFree( GetProcessHeap(), 0, nameW );
2208 return ret;
2211 /******************************************************************************
2212 * RegisterServiceCtrlHandlerExW [ADVAPI32.@]
2214 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceName,
2215 LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext )
2217 SC_HANDLE hService;
2218 SC_HANDLE hSCM;
2219 unsigned int i;
2220 BOOL found = FALSE;
2222 TRACE("%s %p %p\n", debugstr_w(lpServiceName), lpHandlerProc, lpContext);
2224 hSCM = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT );
2225 if (!hSCM)
2226 return NULL;
2227 hService = OpenServiceW( hSCM, lpServiceName, SERVICE_SET_STATUS );
2228 CloseServiceHandle(hSCM);
2229 if (!hService)
2230 return NULL;
2232 EnterCriticalSection( &service_cs );
2233 for (i = 0; i < nb_services; i++)
2235 if(!strcmpW(lpServiceName, services[i]->name))
2237 services[i]->handler = lpHandlerProc;
2238 services[i]->context = lpContext;
2239 found = TRUE;
2240 break;
2243 LeaveCriticalSection( &service_cs );
2245 if (!found)
2247 CloseServiceHandle(hService);
2248 SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
2249 return NULL;
2252 return (SERVICE_STATUS_HANDLE)hService;
2255 /******************************************************************************
2256 * EnumDependentServicesA [ADVAPI32.@]
2258 BOOL WINAPI EnumDependentServicesA( SC_HANDLE hService, DWORD dwServiceState,
2259 LPENUM_SERVICE_STATUSA lpServices, DWORD cbBufSize,
2260 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2262 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2263 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2265 *lpServicesReturned = 0;
2266 return TRUE;
2269 /******************************************************************************
2270 * EnumDependentServicesW [ADVAPI32.@]
2272 BOOL WINAPI EnumDependentServicesW( SC_HANDLE hService, DWORD dwServiceState,
2273 LPENUM_SERVICE_STATUSW lpServices, DWORD cbBufSize,
2274 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2276 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2277 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2279 *lpServicesReturned = 0;
2280 return TRUE;