push 9bfdf186dc6a237cd7f58f0ee2ef677e81617b1d
[wine/hacks.git] / dlls / advapi32 / service.c
blobda2b81f163a838b1d581d34bae93206c712ed5c7
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 szServiceManagerKey[] = { 'S','y','s','t','e','m','\\',
49 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
50 'S','e','r','v','i','c','e','s',0 };
52 void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t len)
54 return HeapAlloc(GetProcessHeap(), 0, len);
57 void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr)
59 HeapFree(GetProcessHeap(), 0, ptr);
62 static const GENERIC_MAPPING scm_generic = {
63 (STANDARD_RIGHTS_READ | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS),
64 (STANDARD_RIGHTS_WRITE | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_MODIFY_BOOT_CONFIG),
65 (STANDARD_RIGHTS_EXECUTE | SC_MANAGER_CONNECT | SC_MANAGER_LOCK),
66 SC_MANAGER_ALL_ACCESS
69 static const GENERIC_MAPPING svc_generic = {
70 (STANDARD_RIGHTS_READ | SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_INTERROGATE | SERVICE_ENUMERATE_DEPENDENTS),
71 (STANDARD_RIGHTS_WRITE | SERVICE_CHANGE_CONFIG),
72 (STANDARD_RIGHTS_EXECUTE | SERVICE_START | SERVICE_STOP | SERVICE_PAUSE_CONTINUE | SERVICE_USER_DEFINED_CONTROL),
73 SERVICE_ALL_ACCESS
76 typedef struct service_data_t
78 LPHANDLER_FUNCTION_EX handler;
79 LPVOID context;
80 HANDLE thread;
81 SC_HANDLE handle;
82 BOOL unicode : 1;
83 union {
84 LPSERVICE_MAIN_FUNCTIONA a;
85 LPSERVICE_MAIN_FUNCTIONW w;
86 } proc;
87 LPWSTR args;
88 WCHAR name[1];
89 } service_data;
91 static CRITICAL_SECTION service_cs;
92 static CRITICAL_SECTION_DEBUG service_cs_debug =
94 0, 0, &service_cs,
95 { &service_cs_debug.ProcessLocksList,
96 &service_cs_debug.ProcessLocksList },
97 0, 0, { (DWORD_PTR)(__FILE__ ": service_cs") }
99 static CRITICAL_SECTION service_cs = { &service_cs_debug, -1, 0, 0, 0, 0 };
101 static service_data **services;
102 static unsigned int nb_services;
103 static HANDLE service_event;
105 extern HANDLE __wine_make_process_system(void);
107 /******************************************************************************
108 * SC_HANDLEs
111 #define MAX_SERVICE_NAME 256
113 typedef enum { SC_HTYPE_MANAGER, SC_HTYPE_SERVICE } SC_HANDLE_TYPE;
115 struct sc_handle;
116 typedef VOID (*sc_handle_destructor)(struct sc_handle *);
118 struct sc_handle
120 SC_HANDLE_TYPE htype;
121 DWORD ref_count;
122 sc_handle_destructor destroy;
123 SC_RPC_HANDLE server_handle; /* server-side handle */
126 struct sc_manager /* service control manager handle */
128 struct sc_handle hdr;
129 HKEY hkey; /* handle to services database in the registry */
130 DWORD dwAccess;
133 struct sc_service /* service handle */
135 struct sc_handle hdr;
136 HKEY hkey; /* handle to service entry in the registry (under hkey) */
137 DWORD dwAccess;
138 struct sc_manager *scm; /* pointer to SCM handle */
139 WCHAR name[1];
142 static void *sc_handle_alloc(SC_HANDLE_TYPE htype, DWORD size,
143 sc_handle_destructor destroy)
145 struct sc_handle *hdr;
147 hdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
148 if (hdr)
150 hdr->htype = htype;
151 hdr->ref_count = 1;
152 hdr->destroy = destroy;
154 TRACE("sc_handle type=%d -> %p\n", htype, hdr);
155 return hdr;
158 static void *sc_handle_get_handle_data(SC_HANDLE handle, DWORD htype)
160 struct sc_handle *hdr = (struct sc_handle *) handle;
162 if (!hdr)
163 return NULL;
164 if (hdr->htype != htype)
165 return NULL;
166 return hdr;
169 static void sc_handle_free(struct sc_handle* hdr)
171 if (!hdr)
172 return;
173 if (--hdr->ref_count)
174 return;
175 hdr->destroy(hdr);
176 HeapFree(GetProcessHeap(), 0, hdr);
179 static void sc_handle_destroy_manager(struct sc_handle *handle)
181 struct sc_manager *mgr = (struct sc_manager*) handle;
183 TRACE("destroying SC Manager %p\n", mgr);
184 if (mgr->hkey)
185 RegCloseKey(mgr->hkey);
188 static void sc_handle_destroy_service(struct sc_handle *handle)
190 struct sc_service *svc = (struct sc_service*) handle;
192 TRACE("destroying service %p\n", svc);
193 if (svc->hkey)
194 RegCloseKey(svc->hkey);
195 svc->hkey = NULL;
196 sc_handle_free(&svc->scm->hdr);
197 svc->scm = NULL;
200 /******************************************************************************
201 * String management functions (same behaviour as strdup)
202 * NOTE: the caller of those functions is responsible for calling HeapFree
203 * in order to release the memory allocated by those functions.
205 static inline LPWSTR SERV_dup( LPCSTR str )
207 UINT len;
208 LPWSTR wstr;
210 if( !str )
211 return NULL;
212 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
213 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
214 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
215 return wstr;
218 static inline LPWSTR SERV_dupmulti(LPCSTR str)
220 UINT len = 0, n = 0;
221 LPWSTR wstr;
223 if( !str )
224 return NULL;
225 do {
226 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
227 n += (strlen( &str[n] ) + 1);
228 } while (str[n]);
229 len++;
230 n++;
232 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
233 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
234 return wstr;
237 static inline DWORD multisz_cb(LPCWSTR wmultisz)
239 const WCHAR *wptr = wmultisz;
241 if (wmultisz == NULL)
242 return 0;
244 while (*wptr)
245 wptr += lstrlenW(wptr)+1;
246 return (wptr - wmultisz + 1)*sizeof(WCHAR);
249 /******************************************************************************
250 * RPC connection with services.exe
253 handle_t __RPC_USER MACHINE_HANDLEW_bind(MACHINE_HANDLEW MachineName)
255 WCHAR transport[] = SVCCTL_TRANSPORT;
256 WCHAR endpoint[] = SVCCTL_ENDPOINT;
257 RPC_WSTR binding_str;
258 RPC_STATUS status;
259 handle_t rpc_handle;
261 status = RpcStringBindingComposeW(NULL, transport, (RPC_WSTR)MachineName, endpoint, NULL, &binding_str);
262 if (status != RPC_S_OK)
264 ERR("RpcStringBindingComposeW failed (%d)\n", (DWORD)status);
265 return NULL;
268 status = RpcBindingFromStringBindingW(binding_str, &rpc_handle);
269 RpcStringFreeW(&binding_str);
271 if (status != RPC_S_OK)
273 ERR("Couldn't connect to services.exe: error code %u\n", (DWORD)status);
274 return NULL;
277 return rpc_handle;
280 void __RPC_USER MACHINE_HANDLEW_unbind(MACHINE_HANDLEW MachineName, handle_t h)
282 RpcBindingFree(&h);
285 static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *eptr)
287 return I_RpcExceptionFilter(eptr->ExceptionRecord->ExceptionCode);
290 static DWORD map_exception_code(DWORD exception_code)
292 switch (exception_code)
294 case RPC_X_NULL_REF_POINTER:
295 case RPC_X_ENUM_VALUE_OUT_OF_RANGE:
296 case RPC_X_BYTE_COUNT_TOO_SMALL:
297 return ERROR_INVALID_PARAMETER;
298 default:
299 return exception_code;
303 /******************************************************************************
304 * Service IPC functions
306 static LPWSTR service_get_pipe_name(void)
308 static const WCHAR format[] = { '\\','\\','.','\\','p','i','p','e','\\',
309 'n','e','t','\\','N','t','C','o','n','t','r','o','l','P','i','p','e','%','u',0};
310 static const WCHAR service_current_key_str[] = { 'S','Y','S','T','E','M','\\',
311 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
312 'C','o','n','t','r','o','l','\\',
313 'S','e','r','v','i','c','e','C','u','r','r','e','n','t',0};
314 LPWSTR name;
315 DWORD len;
316 HKEY service_current_key;
317 DWORD service_current;
318 LONG ret;
319 DWORD type;
321 ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, service_current_key_str, 0,
322 KEY_QUERY_VALUE, &service_current_key);
323 if (ret != ERROR_SUCCESS)
324 return NULL;
325 len = sizeof(service_current);
326 ret = RegQueryValueExW(service_current_key, NULL, NULL, &type,
327 (BYTE *)&service_current, &len);
328 RegCloseKey(service_current_key);
329 if (ret != ERROR_SUCCESS || type != REG_DWORD)
330 return NULL;
331 len = sizeof(format)/sizeof(WCHAR) + 10 /* strlenW("4294967295") */;
332 name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
333 if (!name)
334 return NULL;
335 snprintfW(name, len, format, service_current);
336 return name;
339 static HANDLE service_open_pipe(void)
341 LPWSTR szPipe = service_get_pipe_name();
342 HANDLE handle = INVALID_HANDLE_VALUE;
344 do {
345 handle = CreateFileW(szPipe, GENERIC_READ|GENERIC_WRITE,
346 0, NULL, OPEN_ALWAYS, 0, NULL);
347 if (handle != INVALID_HANDLE_VALUE)
348 break;
349 if (GetLastError() != ERROR_PIPE_BUSY)
350 break;
351 } while (WaitNamedPipeW(szPipe, NMPWAIT_WAIT_FOREVER));
352 HeapFree(GetProcessHeap(), 0, szPipe);
354 return handle;
357 static service_data *find_service_by_name( const WCHAR *name )
359 unsigned int i;
361 if (nb_services == 1) /* only one service (FIXME: should depend on OWN_PROCESS etc.) */
362 return services[0];
363 for (i = 0; i < nb_services; i++)
364 if (!strcmpiW( name, services[i]->name )) return services[i];
365 return NULL;
368 /******************************************************************************
369 * service_thread
371 * Call into the main service routine provided by StartServiceCtrlDispatcher.
373 static DWORD WINAPI service_thread(LPVOID arg)
375 service_data *info = arg;
376 LPWSTR str = info->args;
377 DWORD argc = 0, len = 0;
379 TRACE("%p\n", arg);
381 while (str[len])
383 len += strlenW(&str[len]) + 1;
384 argc++;
386 len++;
388 if (info->unicode)
390 LPWSTR *argv, p;
392 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPWSTR));
393 for (argc=0, p=str; *p; p += strlenW(p) + 1)
394 argv[argc++] = p;
395 argv[argc] = NULL;
397 info->proc.w(argc, argv);
398 HeapFree(GetProcessHeap(), 0, argv);
400 else
402 LPSTR strA, *argv, p;
403 DWORD lenA;
405 lenA = WideCharToMultiByte(CP_ACP,0, str, len, NULL, 0, NULL, NULL);
406 strA = HeapAlloc(GetProcessHeap(), 0, lenA);
407 WideCharToMultiByte(CP_ACP,0, str, len, strA, lenA, NULL, NULL);
409 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPSTR));
410 for (argc=0, p=strA; *p; p += strlen(p) + 1)
411 argv[argc++] = p;
412 argv[argc] = NULL;
414 info->proc.a(argc, argv);
415 HeapFree(GetProcessHeap(), 0, argv);
416 HeapFree(GetProcessHeap(), 0, strA);
418 return 0;
421 /******************************************************************************
422 * service_handle_start
424 static DWORD service_handle_start(service_data *service, const WCHAR *data, DWORD count)
426 TRACE("%s argsize %u\n", debugstr_w(service->name), count);
428 if (service->thread)
430 WARN("service is not stopped\n");
431 return ERROR_SERVICE_ALREADY_RUNNING;
434 HeapFree(GetProcessHeap(), 0, service->args);
435 service->args = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
436 memcpy( service->args, data, count * sizeof(WCHAR) );
437 service->thread = CreateThread( NULL, 0, service_thread,
438 service, 0, NULL );
439 SetEvent( service_event ); /* notify the main loop */
440 return 0;
443 /******************************************************************************
444 * service_handle_control
446 static DWORD service_handle_control(service_data *service, DWORD dwControl)
448 DWORD ret = ERROR_INVALID_SERVICE_CONTROL;
450 TRACE("%s control %u\n", debugstr_w(service->name), dwControl);
452 if (service->handler)
453 ret = service->handler(dwControl, 0, NULL, service->context);
454 return ret;
457 /******************************************************************************
458 * service_control_dispatcher
460 static DWORD WINAPI service_control_dispatcher(LPVOID arg)
462 SC_HANDLE manager;
463 HANDLE pipe;
465 if (!(manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT )))
467 ERR("failed to open service manager error %u\n", GetLastError());
468 return 0;
471 pipe = service_open_pipe();
473 if (pipe==INVALID_HANDLE_VALUE)
475 ERR("failed to create control pipe error = %d\n", GetLastError());
476 return 0;
479 /* dispatcher loop */
480 while (1)
482 service_data *service;
483 service_start_info info;
484 WCHAR *data = NULL;
485 BOOL r;
486 DWORD data_size = 0, count, result;
488 r = ReadFile( pipe, &info, FIELD_OFFSET(service_start_info,data), &count, NULL );
489 if (!r)
491 if (GetLastError() != ERROR_BROKEN_PIPE)
492 ERR( "pipe read failed error %u\n", GetLastError() );
493 break;
495 if (count != FIELD_OFFSET(service_start_info,data))
497 ERR( "partial pipe read %u\n", count );
498 break;
500 if (count < info.total_size)
502 data_size = info.total_size - FIELD_OFFSET(service_start_info,data);
503 data = HeapAlloc( GetProcessHeap(), 0, data_size );
504 r = ReadFile( pipe, data, data_size, &count, NULL );
505 if (!r)
507 if (GetLastError() != ERROR_BROKEN_PIPE)
508 ERR( "pipe read failed error %u\n", GetLastError() );
509 break;
511 if (count != data_size)
513 ERR( "partial pipe read %u/%u\n", count, data_size );
514 break;
518 /* find the service */
520 if (!(service = find_service_by_name( data )))
522 FIXME( "got request %u for unknown service %s\n", info.cmd, debugstr_w(data));
523 result = ERROR_INVALID_PARAMETER;
524 goto done;
527 TRACE( "got request %u for service %s\n", info.cmd, debugstr_w(data) );
529 /* handle the request */
530 switch (info.cmd)
532 case WINESERV_STARTINFO:
533 if (!service->handle)
535 if (!(service->handle = OpenServiceW( manager, data, SERVICE_SET_STATUS )))
536 FIXME( "failed to open service %s\n", debugstr_w(data) );
538 result = service_handle_start(service, data + info.name_size,
539 data_size / sizeof(WCHAR) - info.name_size );
540 break;
541 case WINESERV_SENDCONTROL:
542 result = service_handle_control(service, info.control);
543 break;
544 default:
545 ERR("received invalid command %u\n", info.cmd);
546 result = ERROR_INVALID_PARAMETER;
547 break;
550 done:
551 WriteFile(pipe, &result, sizeof(result), &count, NULL);
552 HeapFree( GetProcessHeap(), 0, data );
555 CloseHandle(pipe);
556 CloseServiceHandle( manager );
557 return 1;
560 /******************************************************************************
561 * service_run_main_thread
563 static BOOL service_run_main_thread(void)
565 DWORD i, n, ret;
566 HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
567 UINT wait_services[MAXIMUM_WAIT_OBJECTS];
569 service_event = CreateEventW( NULL, FALSE, FALSE, NULL );
571 /* FIXME: service_control_dispatcher should be merged into the main thread */
572 wait_handles[0] = __wine_make_process_system();
573 wait_handles[1] = CreateThread( NULL, 0, service_control_dispatcher, NULL, 0, NULL );
574 wait_handles[2] = service_event;
576 TRACE("Starting %d services running as process %d\n",
577 nb_services, GetCurrentProcessId());
579 /* wait for all the threads to pack up and exit */
580 for (;;)
582 EnterCriticalSection( &service_cs );
583 for (i = 0, n = 3; i < nb_services && n < MAXIMUM_WAIT_OBJECTS; i++)
585 if (!services[i]->thread) continue;
586 wait_services[n] = i;
587 wait_handles[n++] = services[i]->thread;
589 LeaveCriticalSection( &service_cs );
591 ret = WaitForMultipleObjects( n, wait_handles, FALSE, INFINITE );
592 if (!ret) /* system process event */
594 TRACE( "last user process exited, shutting down\n" );
595 /* FIXME: we should maybe send a shutdown control to running services */
596 ExitProcess(0);
598 else if (ret == 1)
600 TRACE( "control dispatcher exited, shutting down\n" );
601 /* FIXME: we should maybe send a shutdown control to running services */
602 ExitProcess(0);
604 else if (ret == 2)
606 continue; /* rebuild the list */
608 else if (ret < n)
610 services[wait_services[ret]]->thread = 0;
611 CloseHandle( wait_handles[ret] );
612 if (n == 4) return TRUE; /* it was the last running thread */
614 else return FALSE;
618 /******************************************************************************
619 * StartServiceCtrlDispatcherA [ADVAPI32.@]
621 * See StartServiceCtrlDispatcherW.
623 BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent )
625 service_data *info;
626 unsigned int i;
627 BOOL ret = TRUE;
629 TRACE("%p\n", servent);
631 if (nb_services)
633 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
634 return FALSE;
636 while (servent[nb_services].lpServiceName) nb_services++;
637 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
639 for (i = 0; i < nb_services; i++)
641 DWORD len = MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, NULL, 0);
642 DWORD sz = FIELD_OFFSET( service_data, name[len] );
643 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
644 MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, info->name, len);
645 info->proc.a = servent[i].lpServiceProc;
646 info->unicode = FALSE;
647 services[i] = info;
650 service_run_main_thread();
652 return ret;
655 /******************************************************************************
656 * StartServiceCtrlDispatcherW [ADVAPI32.@]
658 * Connects a process containing one or more services to the service control
659 * manager.
661 * PARAMS
662 * servent [I] A list of the service names and service procedures
664 * RETURNS
665 * Success: TRUE.
666 * Failure: FALSE.
668 BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent )
670 service_data *info;
671 unsigned int i;
672 BOOL ret = TRUE;
674 TRACE("%p\n", servent);
676 if (nb_services)
678 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
679 return FALSE;
681 while (servent[nb_services].lpServiceName) nb_services++;
682 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
684 for (i = 0; i < nb_services; i++)
686 DWORD len = strlenW(servent[i].lpServiceName) + 1;
687 DWORD sz = FIELD_OFFSET( service_data, name[len] );
688 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
689 strcpyW(info->name, servent[i].lpServiceName);
690 info->proc.w = servent[i].lpServiceProc;
691 info->unicode = TRUE;
692 services[i] = info;
695 service_run_main_thread();
697 return ret;
700 /******************************************************************************
701 * LockServiceDatabase [ADVAPI32.@]
703 SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
705 struct sc_manager *hscm;
706 SC_RPC_LOCK hLock = NULL;
707 DWORD err;
709 TRACE("%p\n",hSCManager);
711 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
712 if (!hscm)
714 SetLastError( ERROR_INVALID_HANDLE );
715 return NULL;
718 __TRY
720 err = svcctl_LockServiceDatabase(hscm->hdr.server_handle, &hLock);
722 __EXCEPT(rpc_filter)
724 err = map_exception_code(GetExceptionCode());
726 __ENDTRY
727 if (err != ERROR_SUCCESS)
729 SetLastError(err);
730 return NULL;
732 return hLock;
735 /******************************************************************************
736 * UnlockServiceDatabase [ADVAPI32.@]
738 BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock)
740 DWORD err;
741 SC_RPC_LOCK hRpcLock = ScLock;
743 TRACE("%p\n",ScLock);
745 __TRY
747 err = svcctl_UnlockServiceDatabase(&hRpcLock);
749 __EXCEPT(rpc_filter)
751 err = map_exception_code(GetExceptionCode());
753 __ENDTRY
754 if (err != ERROR_SUCCESS)
756 SetLastError(err);
757 return FALSE;
759 return TRUE;
762 /******************************************************************************
763 * SetServiceStatus [ADVAPI32.@]
765 * PARAMS
766 * hService []
767 * lpStatus []
769 BOOL WINAPI
770 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
772 struct sc_service *hsvc;
773 DWORD err;
775 TRACE("%p %x %x %x %x %x %x %x\n", hService,
776 lpStatus->dwServiceType, lpStatus->dwCurrentState,
777 lpStatus->dwControlsAccepted, lpStatus->dwWin32ExitCode,
778 lpStatus->dwServiceSpecificExitCode, lpStatus->dwCheckPoint,
779 lpStatus->dwWaitHint);
781 hsvc = sc_handle_get_handle_data((SC_HANDLE)hService, SC_HTYPE_SERVICE);
782 if (!hsvc)
784 SetLastError( ERROR_INVALID_HANDLE );
785 return FALSE;
788 __TRY
790 err = svcctl_SetServiceStatus( hsvc->hdr.server_handle, lpStatus );
792 __EXCEPT(rpc_filter)
794 err = map_exception_code(GetExceptionCode());
796 __ENDTRY
797 if (err != ERROR_SUCCESS)
799 SetLastError(err);
800 return FALSE;
803 if (lpStatus->dwCurrentState == SERVICE_STOPPED)
804 CloseServiceHandle((SC_HANDLE)hService);
806 return TRUE;
810 /******************************************************************************
811 * OpenSCManagerA [ADVAPI32.@]
813 * Establish a connection to the service control manager and open its database.
815 * PARAMS
816 * lpMachineName [I] Pointer to machine name string
817 * lpDatabaseName [I] Pointer to database name string
818 * dwDesiredAccess [I] Type of access
820 * RETURNS
821 * Success: A Handle to the service control manager database
822 * Failure: NULL
824 SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
825 DWORD dwDesiredAccess )
827 LPWSTR lpMachineNameW, lpDatabaseNameW;
828 SC_HANDLE ret;
830 lpMachineNameW = SERV_dup(lpMachineName);
831 lpDatabaseNameW = SERV_dup(lpDatabaseName);
832 ret = OpenSCManagerW(lpMachineNameW, lpDatabaseNameW, dwDesiredAccess);
833 HeapFree(GetProcessHeap(), 0, lpDatabaseNameW);
834 HeapFree(GetProcessHeap(), 0, lpMachineNameW);
835 return ret;
838 /******************************************************************************
839 * OpenSCManagerW [ADVAPI32.@]
841 * See OpenSCManagerA.
843 SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
844 DWORD dwDesiredAccess )
846 struct sc_manager *manager;
847 HKEY hReg;
848 LONG r;
849 DWORD new_mask = dwDesiredAccess;
851 TRACE("(%s,%s,0x%08x)\n", debugstr_w(lpMachineName),
852 debugstr_w(lpDatabaseName), dwDesiredAccess);
854 manager = sc_handle_alloc( SC_HTYPE_MANAGER, sizeof (struct sc_manager),
855 sc_handle_destroy_manager );
856 if (!manager)
857 return NULL;
859 __TRY
861 r = svcctl_OpenSCManagerW(lpMachineName, lpDatabaseName, dwDesiredAccess, &manager->hdr.server_handle);
863 __EXCEPT(rpc_filter)
865 r = map_exception_code(GetExceptionCode());
867 __ENDTRY
868 if (r!=ERROR_SUCCESS)
869 goto error;
871 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg);
872 if (r!=ERROR_SUCCESS)
873 goto error;
875 r = RegCreateKeyW(hReg, szServiceManagerKey, &manager->hkey);
876 RegCloseKey( hReg );
877 if (r!=ERROR_SUCCESS)
878 goto error;
880 RtlMapGenericMask(&new_mask, &scm_generic);
881 manager->dwAccess = new_mask;
882 TRACE("returning %p (access : 0x%08x)\n", manager, manager->dwAccess);
884 return (SC_HANDLE) &manager->hdr;
886 error:
887 sc_handle_free( &manager->hdr );
888 SetLastError( r);
889 return NULL;
892 /******************************************************************************
893 * ControlService [ADVAPI32.@]
895 * Send a control code to a service.
897 * PARAMS
898 * hService [I] Handle of the service control manager database
899 * dwControl [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
900 * lpServiceStatus [O] Destination for the status of the service, if available
902 * RETURNS
903 * Success: TRUE.
904 * Failure: FALSE.
906 * BUGS
907 * Unlike M$' implementation, control requests are not serialized and may be
908 * processed asynchronously.
910 BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl,
911 LPSERVICE_STATUS lpServiceStatus )
913 struct sc_service *hsvc;
914 DWORD err;
916 TRACE("%p %d %p\n", hService, dwControl, lpServiceStatus);
918 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
919 if (!hsvc)
921 SetLastError( ERROR_INVALID_HANDLE );
922 return FALSE;
925 __TRY
927 err = svcctl_ControlService(hsvc->hdr.server_handle, dwControl, lpServiceStatus);
929 __EXCEPT(rpc_filter)
931 err = map_exception_code(GetExceptionCode());
933 __ENDTRY
934 if (err != ERROR_SUCCESS)
936 SetLastError(err);
937 return FALSE;
940 return TRUE;
943 /******************************************************************************
944 * CloseServiceHandle [ADVAPI32.@]
946 * Close a handle to a service or the service control manager database.
948 * PARAMS
949 * hSCObject [I] Handle to service or service control manager database
951 * RETURNS
952 * Success: TRUE
953 * Failure: FALSE
955 BOOL WINAPI
956 CloseServiceHandle( SC_HANDLE hSCObject )
958 struct sc_handle *obj;
959 DWORD err;
961 TRACE("%p\n", hSCObject);
962 if (hSCObject == NULL)
964 SetLastError(ERROR_INVALID_HANDLE);
965 return FALSE;
968 obj = (struct sc_handle *)hSCObject;
969 __TRY
971 err = svcctl_CloseServiceHandle(&obj->server_handle);
973 __EXCEPT(rpc_filter)
975 err = map_exception_code(GetExceptionCode());
977 __ENDTRY
978 sc_handle_free( obj );
980 if (err != ERROR_SUCCESS)
982 SetLastError(err);
983 return FALSE;
985 return TRUE;
989 /******************************************************************************
990 * OpenServiceA [ADVAPI32.@]
992 * Open a handle to a service.
994 * PARAMS
995 * hSCManager [I] Handle of the service control manager database
996 * lpServiceName [I] Name of the service to open
997 * dwDesiredAccess [I] Access required to the service
999 * RETURNS
1000 * Success: Handle to the service
1001 * Failure: NULL
1003 SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1004 DWORD dwDesiredAccess )
1006 LPWSTR lpServiceNameW;
1007 SC_HANDLE ret;
1009 TRACE("%p %s %d\n", hSCManager, debugstr_a(lpServiceName), dwDesiredAccess);
1011 lpServiceNameW = SERV_dup(lpServiceName);
1012 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
1013 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1014 return ret;
1018 /******************************************************************************
1019 * OpenServiceW [ADVAPI32.@]
1021 * See OpenServiceA.
1023 SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1024 DWORD dwDesiredAccess)
1026 struct sc_manager *hscm;
1027 struct sc_service *hsvc;
1028 DWORD err;
1029 DWORD len;
1030 DWORD new_mask = dwDesiredAccess;
1032 TRACE("%p %s %d\n", hSCManager, debugstr_w(lpServiceName), dwDesiredAccess);
1034 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
1035 if (!hscm)
1037 SetLastError( ERROR_INVALID_HANDLE );
1038 return FALSE;
1041 if (!lpServiceName)
1043 SetLastError(ERROR_INVALID_ADDRESS);
1044 return NULL;
1047 len = strlenW(lpServiceName)+1;
1048 hsvc = sc_handle_alloc( SC_HTYPE_SERVICE,
1049 sizeof (struct sc_service) + len*sizeof(WCHAR),
1050 sc_handle_destroy_service );
1051 if (!hsvc)
1053 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1054 return NULL;
1056 strcpyW( hsvc->name, lpServiceName );
1058 /* add reference to SCM handle */
1059 hscm->hdr.ref_count++;
1060 hsvc->scm = hscm;
1062 __TRY
1064 err = svcctl_OpenServiceW(hscm->hdr.server_handle, lpServiceName, dwDesiredAccess, &hsvc->hdr.server_handle);
1066 __EXCEPT(rpc_filter)
1068 err = map_exception_code(GetExceptionCode());
1070 __ENDTRY
1072 if (err != ERROR_SUCCESS)
1074 sc_handle_free(&hsvc->hdr);
1075 SetLastError(err);
1076 return NULL;
1079 /* for parts of advapi32 not using services.exe yet */
1080 RtlMapGenericMask(&new_mask, &svc_generic);
1081 hsvc->dwAccess = new_mask;
1083 err = RegOpenKeyExW( hscm->hkey, lpServiceName, 0, KEY_ALL_ACCESS, &hsvc->hkey );
1084 if (err != ERROR_SUCCESS)
1085 ERR("Shouldn't hapen - service key for service validated by services.exe doesn't exist\n");
1087 TRACE("returning %p\n",hsvc);
1089 return (SC_HANDLE) &hsvc->hdr;
1092 /******************************************************************************
1093 * CreateServiceW [ADVAPI32.@]
1095 SC_HANDLE WINAPI
1096 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1097 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
1098 DWORD dwServiceType, DWORD dwStartType,
1099 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1100 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
1101 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
1102 LPCWSTR lpPassword )
1104 struct sc_manager *hscm;
1105 struct sc_service *hsvc = NULL;
1106 DWORD new_mask = dwDesiredAccess;
1107 DWORD len, err;
1108 SIZE_T passwdlen;
1110 TRACE("%p %s %s\n", hSCManager,
1111 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
1113 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
1114 if (!hscm)
1116 SetLastError( ERROR_INVALID_HANDLE );
1117 return NULL;
1120 if (!lpServiceName || !lpBinaryPathName)
1122 SetLastError(ERROR_INVALID_ADDRESS);
1123 return NULL;
1126 if (lpPassword)
1127 passwdlen = (strlenW(lpPassword) + 1) * sizeof(WCHAR);
1128 else
1129 passwdlen = 0;
1131 len = strlenW(lpServiceName)+1;
1132 len = sizeof (struct sc_service) + len*sizeof(WCHAR);
1133 hsvc = sc_handle_alloc( SC_HTYPE_SERVICE, len, sc_handle_destroy_service );
1134 if( !hsvc )
1136 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1137 return NULL;
1139 lstrcpyW( hsvc->name, lpServiceName );
1141 hsvc->scm = hscm;
1142 hscm->hdr.ref_count++;
1144 __TRY
1146 err = svcctl_CreateServiceW(hscm->hdr.server_handle, lpServiceName,
1147 lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1148 lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, (LPBYTE)lpDependencies,
1149 multisz_cb(lpDependencies), lpServiceStartName, (LPBYTE)lpPassword, passwdlen,
1150 &hsvc->hdr.server_handle);
1152 __EXCEPT(rpc_filter)
1154 err = map_exception_code(GetExceptionCode());
1156 __ENDTRY
1158 if (err != ERROR_SUCCESS)
1160 SetLastError(err);
1161 sc_handle_free(&hsvc->hdr);
1162 return NULL;
1165 /* for parts of advapi32 not using services.exe yet */
1166 err = RegOpenKeyW(hscm->hkey, lpServiceName, &hsvc->hkey);
1167 if (err != ERROR_SUCCESS)
1168 WINE_ERR("Couldn't open key that should have been created by services.exe\n");
1170 RtlMapGenericMask(&new_mask, &svc_generic);
1171 hsvc->dwAccess = new_mask;
1173 return (SC_HANDLE) &hsvc->hdr;
1177 /******************************************************************************
1178 * CreateServiceA [ADVAPI32.@]
1180 SC_HANDLE WINAPI
1181 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1182 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
1183 DWORD dwServiceType, DWORD dwStartType,
1184 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1185 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
1186 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
1187 LPCSTR lpPassword )
1189 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
1190 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
1191 SC_HANDLE r;
1193 TRACE("%p %s %s\n", hSCManager,
1194 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
1196 lpServiceNameW = SERV_dup( lpServiceName );
1197 lpDisplayNameW = SERV_dup( lpDisplayName );
1198 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
1199 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
1200 lpDependenciesW = SERV_dupmulti( lpDependencies );
1201 lpServiceStartNameW = SERV_dup( lpServiceStartName );
1202 lpPasswordW = SERV_dup( lpPassword );
1204 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
1205 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1206 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
1207 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
1209 HeapFree( GetProcessHeap(), 0, lpServiceNameW );
1210 HeapFree( GetProcessHeap(), 0, lpDisplayNameW );
1211 HeapFree( GetProcessHeap(), 0, lpBinaryPathNameW );
1212 HeapFree( GetProcessHeap(), 0, lpLoadOrderGroupW );
1213 HeapFree( GetProcessHeap(), 0, lpDependenciesW );
1214 HeapFree( GetProcessHeap(), 0, lpServiceStartNameW );
1215 HeapFree( GetProcessHeap(), 0, lpPasswordW );
1217 return r;
1221 /******************************************************************************
1222 * DeleteService [ADVAPI32.@]
1224 * Delete a service from the service control manager database.
1226 * PARAMS
1227 * hService [I] Handle of the service to delete
1229 * RETURNS
1230 * Success: TRUE
1231 * Failure: FALSE
1233 BOOL WINAPI DeleteService( SC_HANDLE hService )
1235 struct sc_service *hsvc;
1236 DWORD err;
1238 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1239 if (!hsvc)
1241 SetLastError( ERROR_INVALID_HANDLE );
1242 return FALSE;
1245 __TRY
1247 err = svcctl_DeleteService(hsvc->hdr.server_handle);
1249 __EXCEPT(rpc_filter)
1251 err = map_exception_code(GetExceptionCode());
1253 __ENDTRY
1254 if (err != 0)
1256 SetLastError(err);
1257 return FALSE;
1260 /* Close the key to the service */
1261 RegCloseKey(hsvc->hkey);
1262 hsvc->hkey = NULL;
1263 return TRUE;
1267 /******************************************************************************
1268 * StartServiceA [ADVAPI32.@]
1270 * Start a service
1272 * PARAMS
1273 * hService [I] Handle of service
1274 * dwNumServiceArgs [I] Number of arguments
1275 * lpServiceArgVectors [I] Address of array of argument strings
1277 * NOTES
1278 * - NT implements this function using an obscure RPC call.
1279 * - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
1280 * to get things like "%SystemRoot%\\System32\\service.exe" to load.
1281 * - This will only work for shared address space. How should the service
1282 * args be transferred when address spaces are separated?
1283 * - Can only start one service at a time.
1284 * - Has no concept of privilege.
1286 * RETURNS
1287 * Success: TRUE.
1288 * Failure: FALSE
1290 BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
1291 LPCSTR *lpServiceArgVectors )
1293 LPWSTR *lpwstr=NULL;
1294 unsigned int i;
1295 BOOL r;
1297 TRACE("(%p,%d,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
1299 if (dwNumServiceArgs)
1300 lpwstr = HeapAlloc( GetProcessHeap(), 0,
1301 dwNumServiceArgs*sizeof(LPWSTR) );
1303 for(i=0; i<dwNumServiceArgs; i++)
1304 lpwstr[i]=SERV_dup(lpServiceArgVectors[i]);
1306 r = StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
1308 if (dwNumServiceArgs)
1310 for(i=0; i<dwNumServiceArgs; i++)
1311 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
1312 HeapFree(GetProcessHeap(), 0, lpwstr);
1315 return r;
1319 /******************************************************************************
1320 * StartServiceW [ADVAPI32.@]
1322 * See StartServiceA.
1324 BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs,
1325 LPCWSTR *lpServiceArgVectors)
1327 struct sc_service *hsvc;
1328 DWORD err;
1330 TRACE("%p %d %p\n", hService, dwNumServiceArgs, lpServiceArgVectors);
1332 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1333 if (!hsvc)
1335 SetLastError(ERROR_INVALID_HANDLE);
1336 return FALSE;
1339 __TRY
1341 err = svcctl_StartServiceW(hsvc->hdr.server_handle, dwNumServiceArgs, lpServiceArgVectors);
1343 __EXCEPT(rpc_filter)
1345 err = map_exception_code(GetExceptionCode());
1347 __ENDTRY
1348 if (err != ERROR_SUCCESS)
1350 SetLastError(err);
1351 return FALSE;
1354 return TRUE;
1357 /******************************************************************************
1358 * QueryServiceStatus [ADVAPI32.@]
1360 * PARAMS
1361 * hService [I] Handle to service to get information about
1362 * lpservicestatus [O] buffer to receive the status information for the service
1365 BOOL WINAPI QueryServiceStatus(SC_HANDLE hService,
1366 LPSERVICE_STATUS lpservicestatus)
1368 SERVICE_STATUS_PROCESS SvcStatusData;
1369 BOOL ret;
1370 DWORD dummy;
1372 TRACE("%p %p\n", hService, lpservicestatus);
1374 ret = QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&SvcStatusData,
1375 sizeof(SERVICE_STATUS_PROCESS), &dummy);
1376 if (ret) memcpy(lpservicestatus, &SvcStatusData, sizeof(SERVICE_STATUS)) ;
1377 return ret;
1381 /******************************************************************************
1382 * QueryServiceStatusEx [ADVAPI32.@]
1384 * Get information about a service.
1386 * PARAMS
1387 * hService [I] Handle to service to get information about
1388 * InfoLevel [I] Level of information to get
1389 * lpBuffer [O] Destination for requested information
1390 * cbBufSize [I] Size of lpBuffer in bytes
1391 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
1393 * RETURNS
1394 * Success: TRUE
1395 * FAILURE: FALSE
1397 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
1398 LPBYTE lpBuffer, DWORD cbBufSize,
1399 LPDWORD pcbBytesNeeded)
1401 struct sc_service *hsvc;
1402 DWORD err;
1404 TRACE("%p %d %p %d %p\n", hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1406 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1407 if (!hsvc)
1409 SetLastError( ERROR_INVALID_HANDLE );
1410 return FALSE;
1413 __TRY
1415 err = svcctl_QueryServiceStatusEx(hsvc->hdr.server_handle, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1417 __EXCEPT(rpc_filter)
1419 err = map_exception_code(GetExceptionCode());
1421 __ENDTRY
1422 if (err != ERROR_SUCCESS)
1424 SetLastError(err);
1425 return FALSE;
1428 return TRUE;
1431 /******************************************************************************
1432 * QueryServiceConfigA [ADVAPI32.@]
1434 BOOL WINAPI QueryServiceConfigA( SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA config,
1435 DWORD size, LPDWORD needed )
1437 DWORD n;
1438 LPSTR p, buffer;
1439 BOOL ret;
1440 QUERY_SERVICE_CONFIGW *configW;
1442 TRACE("%p %p %d %p\n", hService, config, size, needed);
1444 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, 2 * size )))
1446 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1447 return FALSE;
1449 configW = (QUERY_SERVICE_CONFIGW *)buffer;
1450 ret = QueryServiceConfigW( hService, configW, 2 * size, needed );
1451 if (!ret) goto done;
1453 config->dwServiceType = configW->dwServiceType;
1454 config->dwStartType = configW->dwStartType;
1455 config->dwErrorControl = configW->dwErrorControl;
1456 config->lpBinaryPathName = NULL;
1457 config->lpLoadOrderGroup = NULL;
1458 config->dwTagId = configW->dwTagId;
1459 config->lpDependencies = NULL;
1460 config->lpServiceStartName = NULL;
1461 config->lpDisplayName = NULL;
1463 p = (LPSTR)(config + 1);
1464 n = size - sizeof(*config);
1465 ret = FALSE;
1467 #define MAP_STR(str) \
1468 do { \
1469 if (configW->str) \
1471 DWORD sz = WideCharToMultiByte( CP_ACP, 0, configW->str, -1, p, n, NULL, NULL ); \
1472 if (!sz) goto done; \
1473 config->str = p; \
1474 p += sz; \
1475 n -= sz; \
1477 } while (0)
1479 MAP_STR( lpBinaryPathName );
1480 MAP_STR( lpLoadOrderGroup );
1481 MAP_STR( lpDependencies );
1482 MAP_STR( lpServiceStartName );
1483 MAP_STR( lpDisplayName );
1484 #undef MAP_STR
1486 *needed = p - (LPSTR)config;
1487 ret = TRUE;
1489 done:
1490 HeapFree( GetProcessHeap(), 0, buffer );
1491 return ret;
1494 static DWORD move_string_to_buffer(BYTE **buf, LPWSTR *string_ptr)
1496 DWORD cb;
1498 if (!*string_ptr)
1500 cb = sizeof(WCHAR);
1501 memset(*buf, 0, cb);
1503 else
1505 cb = (strlenW(*string_ptr) + 1)*sizeof(WCHAR);
1506 memcpy(*buf, *string_ptr, cb);
1507 MIDL_user_free(*string_ptr);
1510 *string_ptr = (LPWSTR)*buf;
1511 *buf += cb;
1513 return cb;
1516 static DWORD size_string(LPWSTR string)
1518 return (string ? (strlenW(string) + 1)*sizeof(WCHAR) : sizeof(WCHAR));
1521 /******************************************************************************
1522 * QueryServiceConfigW [ADVAPI32.@]
1524 BOOL WINAPI
1525 QueryServiceConfigW( SC_HANDLE hService,
1526 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1527 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1529 QUERY_SERVICE_CONFIGW config;
1530 struct sc_service *hsvc;
1531 DWORD total;
1532 DWORD err;
1533 BYTE *bufpos;
1535 TRACE("%p %p %d %p\n", hService, lpServiceConfig,
1536 cbBufSize, pcbBytesNeeded);
1538 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1539 if (!hsvc)
1541 SetLastError( ERROR_INVALID_HANDLE );
1542 return FALSE;
1545 memset(&config, 0, sizeof(config));
1547 __TRY
1549 err = svcctl_QueryServiceConfigW(hsvc->hdr.server_handle, &config);
1551 __EXCEPT(rpc_filter)
1553 err = map_exception_code(GetExceptionCode());
1555 __ENDTRY
1557 if (err != ERROR_SUCCESS)
1559 TRACE("services.exe: error %u\n", err);
1560 SetLastError(err);
1561 return FALSE;
1564 /* calculate the size required first */
1565 total = sizeof (QUERY_SERVICE_CONFIGW);
1566 total += size_string(config.lpBinaryPathName);
1567 total += size_string(config.lpLoadOrderGroup);
1568 total += size_string(config.lpDependencies);
1569 total += size_string(config.lpServiceStartName);
1570 total += size_string(config.lpDisplayName);
1572 *pcbBytesNeeded = total;
1574 /* if there's not enough memory, return an error */
1575 if( total > cbBufSize )
1577 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1578 MIDL_user_free(config.lpBinaryPathName);
1579 MIDL_user_free(config.lpLoadOrderGroup);
1580 MIDL_user_free(config.lpDependencies);
1581 MIDL_user_free(config.lpServiceStartName);
1582 MIDL_user_free(config.lpDisplayName);
1583 return FALSE;
1586 *lpServiceConfig = config;
1587 bufpos = ((BYTE *)lpServiceConfig) + sizeof(QUERY_SERVICE_CONFIGW);
1588 move_string_to_buffer(&bufpos, &lpServiceConfig->lpBinaryPathName);
1589 move_string_to_buffer(&bufpos, &lpServiceConfig->lpLoadOrderGroup);
1590 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDependencies);
1591 move_string_to_buffer(&bufpos, &lpServiceConfig->lpServiceStartName);
1592 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDisplayName);
1594 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1595 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1596 TRACE("Dependencies = %s\n", debugstr_w(lpServiceConfig->lpDependencies) );
1597 TRACE("Service account name = %s\n", debugstr_w(lpServiceConfig->lpServiceStartName) );
1598 TRACE("Display name = %s\n", debugstr_w(lpServiceConfig->lpDisplayName) );
1600 return TRUE;
1603 /******************************************************************************
1604 * QueryServiceConfig2A [ADVAPI32.@]
1606 * Note
1607 * observed under win2k:
1608 * The functions QueryServiceConfig2A and QueryServiceConfig2W return the same
1609 * required buffer size (in byte) at least for dwLevel SERVICE_CONFIG_DESCRIPTION
1611 BOOL WINAPI QueryServiceConfig2A(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1612 DWORD size, LPDWORD needed)
1614 BOOL ret;
1615 LPBYTE bufferW = NULL;
1617 if(buffer && size)
1618 bufferW = HeapAlloc( GetProcessHeap(), 0, size);
1620 ret = QueryServiceConfig2W(hService, dwLevel, bufferW, size, needed);
1621 if(!ret) goto cleanup;
1623 switch(dwLevel) {
1624 case SERVICE_CONFIG_DESCRIPTION:
1625 { LPSERVICE_DESCRIPTIONA configA = (LPSERVICE_DESCRIPTIONA) buffer;
1626 LPSERVICE_DESCRIPTIONW configW = (LPSERVICE_DESCRIPTIONW) bufferW;
1627 if (configW->lpDescription) {
1628 DWORD sz;
1629 configA->lpDescription = (LPSTR)(configA + 1);
1630 sz = WideCharToMultiByte( CP_ACP, 0, configW->lpDescription, -1,
1631 configA->lpDescription, size - sizeof(SERVICE_DESCRIPTIONA), NULL, NULL );
1632 if (!sz) {
1633 FIXME("WideCharToMultiByte failed for configW->lpDescription\n");
1634 ret = FALSE;
1635 configA->lpDescription = NULL;
1638 else configA->lpDescription = NULL;
1640 break;
1641 default:
1642 FIXME("conversation W->A not implemented for level %d\n", dwLevel);
1643 ret = FALSE;
1646 cleanup:
1647 HeapFree( GetProcessHeap(), 0, bufferW);
1648 return ret;
1651 /******************************************************************************
1652 * QueryServiceConfig2W [ADVAPI32.@]
1654 BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1655 DWORD size, LPDWORD needed)
1657 DWORD sz, type;
1658 HKEY hKey;
1659 LONG r;
1660 struct sc_service *hsvc;
1662 if(dwLevel != SERVICE_CONFIG_DESCRIPTION) {
1663 if((dwLevel == SERVICE_CONFIG_DELAYED_AUTO_START_INFO) ||
1664 (dwLevel == SERVICE_CONFIG_FAILURE_ACTIONS) ||
1665 (dwLevel == SERVICE_CONFIG_FAILURE_ACTIONS_FLAG) ||
1666 (dwLevel == SERVICE_CONFIG_PRESHUTDOWN_INFO) ||
1667 (dwLevel == SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO) ||
1668 (dwLevel == SERVICE_CONFIG_SERVICE_SID_INFO))
1669 FIXME("Level %d not implemented\n", dwLevel);
1670 SetLastError(ERROR_INVALID_LEVEL);
1671 return FALSE;
1673 if(!needed || (!buffer && size)) {
1674 SetLastError(ERROR_INVALID_ADDRESS);
1675 return FALSE;
1678 TRACE("%p 0x%d %p 0x%d %p\n", hService, dwLevel, buffer, size, needed);
1680 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1681 if (!hsvc)
1683 SetLastError(ERROR_INVALID_HANDLE);
1684 return FALSE;
1686 hKey = hsvc->hkey;
1688 switch(dwLevel) {
1689 case SERVICE_CONFIG_DESCRIPTION: {
1690 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
1691 LPSERVICE_DESCRIPTIONW config = (LPSERVICE_DESCRIPTIONW) buffer;
1692 LPBYTE strbuf = NULL;
1693 *needed = sizeof (SERVICE_DESCRIPTIONW);
1694 sz = size - *needed;
1695 if(config && (*needed <= size))
1696 strbuf = (LPBYTE) (config + 1);
1697 r = RegQueryValueExW( hKey, szDescription, 0, &type, strbuf, &sz );
1698 if((r == ERROR_SUCCESS) && ( type != REG_SZ)) {
1699 FIXME("SERVICE_CONFIG_DESCRIPTION: don't know how to handle type %d\n", type);
1700 return FALSE;
1702 *needed += sz;
1703 if(config) {
1704 if(r == ERROR_SUCCESS)
1705 config->lpDescription = (LPWSTR) (config + 1);
1706 else
1707 config->lpDescription = NULL;
1710 break;
1712 if(*needed > size)
1713 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1715 return (*needed <= size);
1718 /******************************************************************************
1719 * EnumServicesStatusA [ADVAPI32.@]
1721 BOOL WINAPI
1722 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
1723 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
1724 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1725 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
1727 FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager,
1728 dwServiceType, dwServiceState, lpServices, cbBufSize,
1729 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
1730 SetLastError (ERROR_ACCESS_DENIED);
1731 return FALSE;
1734 /******************************************************************************
1735 * EnumServicesStatusW [ADVAPI32.@]
1737 BOOL WINAPI
1738 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
1739 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
1740 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1741 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
1743 FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager,
1744 dwServiceType, dwServiceState, lpServices, cbBufSize,
1745 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
1746 SetLastError (ERROR_ACCESS_DENIED);
1747 return FALSE;
1750 /******************************************************************************
1751 * EnumServicesStatusExA [ADVAPI32.@]
1753 BOOL WINAPI
1754 EnumServicesStatusExA(SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType,
1755 DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1756 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle, LPCSTR pszGroupName)
1758 FIXME("%p level=%d type=%x state=%x %p %x %p %p %p %s\n", hSCManager, InfoLevel,
1759 dwServiceType, dwServiceState, lpServices, cbBufSize,
1760 pcbBytesNeeded, lpServicesReturned, lpResumeHandle, debugstr_a(pszGroupName));
1761 if (lpServicesReturned) *lpServicesReturned = 0;
1762 SetLastError (ERROR_ACCESS_DENIED);
1763 return FALSE;
1766 /******************************************************************************
1767 * EnumServicesStatusExW [ADVAPI32.@]
1769 BOOL WINAPI
1770 EnumServicesStatusExW(SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType,
1771 DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1772 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle, LPCWSTR pszGroupName)
1774 FIXME("%p level=%d type=%x state=%x %p %x %p %p %p %s\n", hSCManager, InfoLevel,
1775 dwServiceType, dwServiceState, lpServices, cbBufSize,
1776 pcbBytesNeeded, lpServicesReturned, lpResumeHandle, debugstr_w(pszGroupName));
1777 SetLastError (ERROR_ACCESS_DENIED);
1778 return FALSE;
1781 /******************************************************************************
1782 * GetServiceKeyNameA [ADVAPI32.@]
1784 BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
1785 LPSTR lpServiceName, LPDWORD lpcchBuffer )
1787 LPWSTR lpDisplayNameW, lpServiceNameW;
1788 DWORD sizeW;
1789 BOOL ret = FALSE;
1791 TRACE("%p %s %p %p\n", hSCManager,
1792 debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
1794 lpDisplayNameW = SERV_dup(lpDisplayName);
1795 if (lpServiceName)
1796 lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1797 else
1798 lpServiceNameW = NULL;
1800 sizeW = *lpcchBuffer;
1801 if (!GetServiceKeyNameW(hSCManager, lpDisplayNameW, lpServiceNameW, &sizeW))
1803 if (lpServiceName && *lpcchBuffer)
1804 lpServiceName[0] = 0;
1805 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1806 goto cleanup;
1809 if (!WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, (sizeW + 1), lpServiceName,
1810 *lpcchBuffer, NULL, NULL ))
1812 if (*lpcchBuffer && lpServiceName)
1813 lpServiceName[0] = 0;
1814 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, -1, NULL, 0, NULL, NULL);
1815 goto cleanup;
1818 /* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
1819 ret = TRUE;
1821 cleanup:
1822 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1823 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1824 return ret;
1827 /******************************************************************************
1828 * GetServiceKeyNameW [ADVAPI32.@]
1830 BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
1831 LPWSTR lpServiceName, LPDWORD lpcchBuffer )
1833 struct sc_manager *hscm;
1834 DWORD err;
1836 TRACE("%p %s %p %p\n", hSCManager,
1837 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1839 hscm = sc_handle_get_handle_data(hSCManager, SC_HTYPE_MANAGER);
1840 if (!hscm)
1842 SetLastError(ERROR_INVALID_HANDLE);
1843 return FALSE;
1846 if (!lpDisplayName)
1848 SetLastError(ERROR_INVALID_ADDRESS);
1849 return FALSE;
1852 __TRY
1854 err = svcctl_GetServiceKeyNameW(hscm->hdr.server_handle,
1855 lpDisplayName, lpServiceName, lpServiceName ? *lpcchBuffer : 0, lpcchBuffer);
1857 __EXCEPT(rpc_filter)
1859 err = map_exception_code(GetExceptionCode());
1861 __ENDTRY
1863 if (err)
1864 SetLastError(err);
1865 return err == ERROR_SUCCESS;
1868 /******************************************************************************
1869 * QueryServiceLockStatusA [ADVAPI32.@]
1871 BOOL WINAPI QueryServiceLockStatusA( SC_HANDLE hSCManager,
1872 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
1873 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1875 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1877 return FALSE;
1880 /******************************************************************************
1881 * QueryServiceLockStatusW [ADVAPI32.@]
1883 BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager,
1884 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
1885 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1887 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1889 return FALSE;
1892 /******************************************************************************
1893 * GetServiceDisplayNameA [ADVAPI32.@]
1895 BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1896 LPSTR lpDisplayName, LPDWORD lpcchBuffer)
1898 LPWSTR lpServiceNameW, lpDisplayNameW;
1899 DWORD sizeW;
1900 BOOL ret = FALSE;
1902 TRACE("%p %s %p %p\n", hSCManager,
1903 debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
1905 lpServiceNameW = SERV_dup(lpServiceName);
1906 if (lpDisplayName)
1907 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1908 else
1909 lpDisplayNameW = NULL;
1911 sizeW = *lpcchBuffer;
1912 if (!GetServiceDisplayNameW(hSCManager, lpServiceNameW, lpDisplayNameW, &sizeW))
1914 if (lpDisplayName && *lpcchBuffer)
1915 lpDisplayName[0] = 0;
1916 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1917 goto cleanup;
1920 if (!WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, (sizeW + 1), lpDisplayName,
1921 *lpcchBuffer, NULL, NULL ))
1923 if (*lpcchBuffer && lpDisplayName)
1924 lpDisplayName[0] = 0;
1925 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, -1, NULL, 0, NULL, NULL);
1926 goto cleanup;
1929 /* probably due to a bug GetServiceDisplayNameA doesn't modify lpcchBuffer on success.
1930 * (but if the function succeeded it means that is a good upper estimation of the size) */
1931 ret = TRUE;
1933 cleanup:
1934 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1935 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1936 return ret;
1939 /******************************************************************************
1940 * GetServiceDisplayNameW [ADVAPI32.@]
1942 BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1943 LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
1945 struct sc_manager *hscm;
1946 DWORD err;
1948 TRACE("%p %s %p %p\n", hSCManager,
1949 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1951 hscm = sc_handle_get_handle_data(hSCManager, SC_HTYPE_MANAGER);
1952 if (!hscm)
1954 SetLastError(ERROR_INVALID_HANDLE);
1955 return FALSE;
1958 if (!lpServiceName)
1960 SetLastError(ERROR_INVALID_ADDRESS);
1961 return FALSE;
1964 __TRY
1966 err = svcctl_GetServiceDisplayNameW(hscm->hdr.server_handle,
1967 lpServiceName, lpDisplayName, lpDisplayName ? *lpcchBuffer : 0, lpcchBuffer);
1969 __EXCEPT(rpc_filter)
1971 err = map_exception_code(GetExceptionCode());
1973 __ENDTRY
1975 if (err)
1976 SetLastError(err);
1977 return err == ERROR_SUCCESS;
1980 /******************************************************************************
1981 * ChangeServiceConfigW [ADVAPI32.@]
1983 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
1984 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1985 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
1986 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
1988 struct sc_service *hsvc;
1989 DWORD cb_pwd;
1990 DWORD err;
1992 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
1993 hService, dwServiceType, dwStartType, dwErrorControl,
1994 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
1995 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
1996 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
1998 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1999 if (!hsvc)
2001 SetLastError( ERROR_INVALID_HANDLE );
2002 return FALSE;
2005 cb_pwd = lpPassword ? (strlenW(lpPassword) + 1)*sizeof(WCHAR) : 0;
2007 __TRY
2009 err = svcctl_ChangeServiceConfigW(hsvc->hdr.server_handle, dwServiceType,
2010 dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId,
2011 (const BYTE *)lpDependencies, multisz_cb(lpDependencies), lpServiceStartName,
2012 (const BYTE *)lpPassword, cb_pwd, lpDisplayName);
2014 __EXCEPT(rpc_filter)
2016 err = map_exception_code(GetExceptionCode());
2018 __ENDTRY
2020 if (err != ERROR_SUCCESS)
2021 SetLastError(err);
2023 return err == ERROR_SUCCESS;
2026 /******************************************************************************
2027 * ChangeServiceConfigA [ADVAPI32.@]
2029 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
2030 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
2031 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
2032 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
2034 LPWSTR wBinaryPathName, wLoadOrderGroup, wDependencies;
2035 LPWSTR wServiceStartName, wPassword, wDisplayName;
2036 BOOL r;
2038 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2039 hService, dwServiceType, dwStartType, dwErrorControl,
2040 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
2041 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
2042 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
2044 wBinaryPathName = SERV_dup( lpBinaryPathName );
2045 wLoadOrderGroup = SERV_dup( lpLoadOrderGroup );
2046 wDependencies = SERV_dupmulti( lpDependencies );
2047 wServiceStartName = SERV_dup( lpServiceStartName );
2048 wPassword = SERV_dup( lpPassword );
2049 wDisplayName = SERV_dup( lpDisplayName );
2051 r = ChangeServiceConfigW( hService, dwServiceType,
2052 dwStartType, dwErrorControl, wBinaryPathName,
2053 wLoadOrderGroup, lpdwTagId, wDependencies,
2054 wServiceStartName, wPassword, wDisplayName);
2056 HeapFree( GetProcessHeap(), 0, wBinaryPathName );
2057 HeapFree( GetProcessHeap(), 0, wLoadOrderGroup );
2058 HeapFree( GetProcessHeap(), 0, wDependencies );
2059 HeapFree( GetProcessHeap(), 0, wServiceStartName );
2060 HeapFree( GetProcessHeap(), 0, wPassword );
2061 HeapFree( GetProcessHeap(), 0, wDisplayName );
2063 return r;
2066 /******************************************************************************
2067 * ChangeServiceConfig2A [ADVAPI32.@]
2069 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
2070 LPVOID lpInfo)
2072 BOOL r = FALSE;
2074 TRACE("%p %d %p\n",hService, dwInfoLevel, lpInfo);
2076 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2078 LPSERVICE_DESCRIPTIONA sd = (LPSERVICE_DESCRIPTIONA) lpInfo;
2079 SERVICE_DESCRIPTIONW sdw;
2081 sdw.lpDescription = SERV_dup( sd->lpDescription );
2083 r = ChangeServiceConfig2W( hService, dwInfoLevel, &sdw );
2085 HeapFree( GetProcessHeap(), 0, sdw.lpDescription );
2087 else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
2089 LPSERVICE_FAILURE_ACTIONSA fa = (LPSERVICE_FAILURE_ACTIONSA) lpInfo;
2090 SERVICE_FAILURE_ACTIONSW faw;
2092 faw.dwResetPeriod = fa->dwResetPeriod;
2093 faw.lpRebootMsg = SERV_dup( fa->lpRebootMsg );
2094 faw.lpCommand = SERV_dup( fa->lpCommand );
2095 faw.cActions = fa->cActions;
2096 faw.lpsaActions = fa->lpsaActions;
2098 r = ChangeServiceConfig2W( hService, dwInfoLevel, &faw );
2100 HeapFree( GetProcessHeap(), 0, faw.lpRebootMsg );
2101 HeapFree( GetProcessHeap(), 0, faw.lpCommand );
2103 else
2104 SetLastError( ERROR_INVALID_PARAMETER );
2106 return r;
2109 /******************************************************************************
2110 * ChangeServiceConfig2W [ADVAPI32.@]
2112 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
2113 LPVOID lpInfo)
2115 HKEY hKey;
2116 struct sc_service *hsvc;
2118 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
2119 if (!hsvc)
2121 SetLastError( ERROR_INVALID_HANDLE );
2122 return FALSE;
2124 hKey = hsvc->hkey;
2126 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2128 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
2129 LPSERVICE_DESCRIPTIONW sd = (LPSERVICE_DESCRIPTIONW)lpInfo;
2130 if (sd->lpDescription)
2132 TRACE("Setting Description to %s\n",debugstr_w(sd->lpDescription));
2133 if (sd->lpDescription[0] == 0)
2134 RegDeleteValueW(hKey,szDescription);
2135 else
2136 RegSetValueExW(hKey, szDescription, 0, REG_SZ,
2137 (LPVOID)sd->lpDescription,
2138 sizeof(WCHAR)*(strlenW(sd->lpDescription)+1));
2141 else
2142 FIXME("STUB: %p %d %p\n",hService, dwInfoLevel, lpInfo);
2143 return TRUE;
2146 /******************************************************************************
2147 * QueryServiceObjectSecurity [ADVAPI32.@]
2149 BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService,
2150 SECURITY_INFORMATION dwSecurityInformation,
2151 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2152 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
2154 SECURITY_DESCRIPTOR descriptor;
2155 DWORD size;
2156 BOOL succ;
2157 ACL acl;
2159 FIXME("%p %d %p %u %p - semi-stub\n", hService, dwSecurityInformation,
2160 lpSecurityDescriptor, cbBufSize, pcbBytesNeeded);
2162 if (dwSecurityInformation != DACL_SECURITY_INFORMATION)
2163 FIXME("information %d not supported\n", dwSecurityInformation);
2165 InitializeSecurityDescriptor(&descriptor, SECURITY_DESCRIPTOR_REVISION);
2167 InitializeAcl(&acl, sizeof(ACL), ACL_REVISION);
2168 SetSecurityDescriptorDacl(&descriptor, TRUE, &acl, TRUE);
2170 size = cbBufSize;
2171 succ = MakeSelfRelativeSD(&descriptor, lpSecurityDescriptor, &size);
2172 *pcbBytesNeeded = size;
2173 return succ;
2176 /******************************************************************************
2177 * SetServiceObjectSecurity [ADVAPI32.@]
2179 BOOL WINAPI SetServiceObjectSecurity(SC_HANDLE hService,
2180 SECURITY_INFORMATION dwSecurityInformation,
2181 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2183 FIXME("%p %d %p\n", hService, dwSecurityInformation, lpSecurityDescriptor);
2184 return TRUE;
2187 /******************************************************************************
2188 * SetServiceBits [ADVAPI32.@]
2190 BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus,
2191 DWORD dwServiceBits,
2192 BOOL bSetBitsOn,
2193 BOOL bUpdateImmediately)
2195 FIXME("%p %08x %x %x\n", hServiceStatus, dwServiceBits,
2196 bSetBitsOn, bUpdateImmediately);
2197 return TRUE;
2200 /* thunk for calling the RegisterServiceCtrlHandler handler function */
2201 static DWORD WINAPI ctrl_handler_thunk( DWORD control, DWORD type, void *data, void *context )
2203 LPHANDLER_FUNCTION func = context;
2205 func( control );
2206 return ERROR_SUCCESS;
2209 /******************************************************************************
2210 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
2212 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerA( LPCSTR name, LPHANDLER_FUNCTION handler )
2214 return RegisterServiceCtrlHandlerExA( name, ctrl_handler_thunk, handler );
2217 /******************************************************************************
2218 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
2220 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW( LPCWSTR name, LPHANDLER_FUNCTION handler )
2222 return RegisterServiceCtrlHandlerExW( name, ctrl_handler_thunk, handler );
2225 /******************************************************************************
2226 * RegisterServiceCtrlHandlerExA [ADVAPI32.@]
2228 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA( LPCSTR name, LPHANDLER_FUNCTION_EX handler, LPVOID context )
2230 LPWSTR nameW;
2231 SERVICE_STATUS_HANDLE ret;
2233 nameW = SERV_dup(name);
2234 ret = RegisterServiceCtrlHandlerExW( nameW, handler, context );
2235 HeapFree( GetProcessHeap(), 0, nameW );
2236 return ret;
2239 /******************************************************************************
2240 * RegisterServiceCtrlHandlerExW [ADVAPI32.@]
2242 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceName,
2243 LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext )
2245 service_data *service;
2246 SC_HANDLE hService = 0;
2247 BOOL found = FALSE;
2249 TRACE("%s %p %p\n", debugstr_w(lpServiceName), lpHandlerProc, lpContext);
2251 EnterCriticalSection( &service_cs );
2252 if ((service = find_service_by_name( lpServiceName )))
2254 service->handler = lpHandlerProc;
2255 service->context = lpContext;
2256 hService = service->handle;
2257 found = TRUE;
2259 LeaveCriticalSection( &service_cs );
2261 if (!found) SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
2263 return (SERVICE_STATUS_HANDLE)hService;
2266 /******************************************************************************
2267 * EnumDependentServicesA [ADVAPI32.@]
2269 BOOL WINAPI EnumDependentServicesA( SC_HANDLE hService, DWORD dwServiceState,
2270 LPENUM_SERVICE_STATUSA lpServices, DWORD cbBufSize,
2271 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2273 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2274 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2276 *lpServicesReturned = 0;
2277 return TRUE;
2280 /******************************************************************************
2281 * EnumDependentServicesW [ADVAPI32.@]
2283 BOOL WINAPI EnumDependentServicesW( SC_HANDLE hService, DWORD dwServiceState,
2284 LPENUM_SERVICE_STATUSW lpServices, DWORD cbBufSize,
2285 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2287 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2288 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2290 *lpServicesReturned = 0;
2291 return TRUE;