advapi32: Remove some unused services functions.
[wine.git] / dlls / advapi32 / service.c
blobc95fcd9f26cd3e67b7e038d1723b6e14d07f93c2
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 <stdarg.h>
24 #include <string.h>
25 #include <time.h>
26 #include <assert.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winsvc.h"
31 #include "winerror.h"
32 #include "winreg.h"
33 #include "wine/unicode.h"
34 #include "wine/debug.h"
35 #include "winternl.h"
36 #include "lmcons.h"
37 #include "lmserver.h"
39 #include "svcctl.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(service);
43 static const WCHAR szLocalSystem[] = {'L','o','c','a','l','S','y','s','t','e','m',0};
44 static const WCHAR szServiceManagerKey[] = { 'S','y','s','t','e','m','\\',
45 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
46 'S','e','r','v','i','c','e','s',0 };
47 static const WCHAR szSCMLock[] = {'A','D','V','A','P','I','_','S','C','M',
48 'L','O','C','K',0};
50 void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t len)
52 return HeapAlloc(GetProcessHeap(), 0, len);
55 void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr)
57 HeapFree(GetProcessHeap(), 0, ptr);
60 static const GENERIC_MAPPING scm_generic = {
61 (STANDARD_RIGHTS_READ | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS),
62 (STANDARD_RIGHTS_WRITE | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_MODIFY_BOOT_CONFIG),
63 (STANDARD_RIGHTS_EXECUTE | SC_MANAGER_CONNECT | SC_MANAGER_LOCK),
64 SC_MANAGER_ALL_ACCESS
67 static const GENERIC_MAPPING svc_generic = {
68 (STANDARD_RIGHTS_READ | SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_INTERROGATE | SERVICE_ENUMERATE_DEPENDENTS),
69 (STANDARD_RIGHTS_WRITE | SERVICE_CHANGE_CONFIG),
70 (STANDARD_RIGHTS_EXECUTE | SERVICE_START | SERVICE_STOP | SERVICE_PAUSE_CONTINUE | SERVICE_USER_DEFINED_CONTROL),
71 SERVICE_ALL_ACCESS
74 typedef struct service_data_t
76 LPHANDLER_FUNCTION_EX handler;
77 LPVOID context;
78 HANDLE thread;
79 BOOL unicode : 1;
80 union {
81 LPSERVICE_MAIN_FUNCTIONA a;
82 LPSERVICE_MAIN_FUNCTIONW w;
83 } proc;
84 LPWSTR args;
85 WCHAR name[1];
86 } service_data;
88 static CRITICAL_SECTION service_cs;
89 static CRITICAL_SECTION_DEBUG service_cs_debug =
91 0, 0, &service_cs,
92 { &service_cs_debug.ProcessLocksList,
93 &service_cs_debug.ProcessLocksList },
94 0, 0, { (DWORD_PTR)(__FILE__ ": service_cs") }
96 static CRITICAL_SECTION service_cs = { &service_cs_debug, -1, 0, 0, 0, 0 };
98 static service_data **services;
99 static unsigned int nb_services;
100 static HANDLE service_event;
102 extern HANDLE __wine_make_process_system(void);
104 /******************************************************************************
105 * SC_HANDLEs
108 #define MAX_SERVICE_NAME 256
110 typedef enum { SC_HTYPE_MANAGER, SC_HTYPE_SERVICE } SC_HANDLE_TYPE;
112 struct sc_handle;
113 typedef VOID (*sc_handle_destructor)(struct sc_handle *);
115 struct sc_handle
117 SC_HANDLE_TYPE htype;
118 DWORD ref_count;
119 sc_handle_destructor destroy;
120 SC_RPC_HANDLE server_handle; /* server-side handle */
123 struct sc_manager /* service control manager handle */
125 struct sc_handle hdr;
126 HKEY hkey; /* handle to services database in the registry */
127 DWORD dwAccess;
130 struct sc_service /* service handle */
132 struct sc_handle hdr;
133 HKEY hkey; /* handle to service entry in the registry (under hkey) */
134 DWORD dwAccess;
135 struct sc_manager *scm; /* pointer to SCM handle */
136 WCHAR name[1];
139 static void *sc_handle_alloc(SC_HANDLE_TYPE htype, DWORD size,
140 sc_handle_destructor destroy)
142 struct sc_handle *hdr;
144 hdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
145 if (hdr)
147 hdr->htype = htype;
148 hdr->ref_count = 1;
149 hdr->destroy = destroy;
151 TRACE("sc_handle type=%d -> %p\n", htype, hdr);
152 return hdr;
155 static void *sc_handle_get_handle_data(SC_HANDLE handle, DWORD htype)
157 struct sc_handle *hdr = (struct sc_handle *) handle;
159 if (!hdr)
160 return NULL;
161 if (hdr->htype != htype)
162 return NULL;
163 return hdr;
166 static void sc_handle_free(struct sc_handle* hdr)
168 if (!hdr)
169 return;
170 if (--hdr->ref_count)
171 return;
172 hdr->destroy(hdr);
173 HeapFree(GetProcessHeap(), 0, hdr);
176 static void sc_handle_destroy_manager(struct sc_handle *handle)
178 struct sc_manager *mgr = (struct sc_manager*) handle;
180 TRACE("destroying SC Manager %p\n", mgr);
181 if (mgr->hkey)
182 RegCloseKey(mgr->hkey);
185 static void sc_handle_destroy_service(struct sc_handle *handle)
187 struct sc_service *svc = (struct sc_service*) handle;
189 TRACE("destroying service %p\n", svc);
190 if (svc->hkey)
191 RegCloseKey(svc->hkey);
192 svc->hkey = NULL;
193 sc_handle_free(&svc->scm->hdr);
194 svc->scm = NULL;
197 /******************************************************************************
198 * String management functions (same behaviour as strdup)
199 * NOTE: the caller of those functions is responsible for calling HeapFree
200 * in order to release the memory allocated by those functions.
202 static inline LPWSTR SERV_dup( LPCSTR str )
204 UINT len;
205 LPWSTR wstr;
207 if( !str )
208 return NULL;
209 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
210 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
211 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
212 return wstr;
215 static inline LPWSTR SERV_dupmulti(LPCSTR str)
217 UINT len = 0, n = 0;
218 LPWSTR wstr;
220 if( !str )
221 return NULL;
222 do {
223 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
224 n += (strlen( &str[n] ) + 1);
225 } while (str[n]);
226 len++;
227 n++;
229 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
230 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
231 return wstr;
234 static inline DWORD multisz_cb(LPCWSTR wmultisz)
236 const WCHAR *wptr = wmultisz;
238 if (wmultisz == NULL)
239 return 0;
241 while (*wptr)
242 wptr += lstrlenW(wptr)+1;
243 return (wptr - wmultisz + 1)*sizeof(WCHAR);
246 /******************************************************************************
247 * RPC connection with servies.exe
250 static BOOL check_services_exe(void)
252 static const WCHAR svcctl_started_event[] = SVCCTL_STARTED_EVENT;
253 HANDLE hEvent = OpenEventW(SYNCHRONIZE, FALSE, svcctl_started_event);
254 if (hEvent == NULL) /* need to start services.exe */
256 static const WCHAR services[] = {'\\','s','e','r','v','i','c','e','s','.','e','x','e',0};
257 PROCESS_INFORMATION out;
258 STARTUPINFOW si;
259 HANDLE wait_handles[2];
260 WCHAR path[MAX_PATH];
262 if (!GetSystemDirectoryW(path, MAX_PATH - strlenW(services)))
263 return FALSE;
264 strcatW(path, services);
265 ZeroMemory(&si, sizeof(si));
266 si.cb = sizeof(si);
267 if (!CreateProcessW(path, path, NULL, NULL, FALSE, 0, NULL, NULL, &si, &out))
269 ERR("Couldn't start services.exe: error %u\n", GetLastError());
270 return FALSE;
272 CloseHandle(out.hThread);
274 hEvent = CreateEventW(NULL, TRUE, FALSE, svcctl_started_event);
275 wait_handles[0] = hEvent;
276 wait_handles[1] = out.hProcess;
278 /* wait for the event to become available or the process to exit */
279 if ((WaitForMultipleObjects(2, wait_handles, FALSE, INFINITE)) == WAIT_OBJECT_0 + 1)
281 DWORD exit_code;
282 GetExitCodeProcess(out.hProcess, &exit_code);
283 ERR("Unexpected termination of services.exe - exit code %d\n", exit_code);
284 CloseHandle(out.hProcess);
285 CloseHandle(hEvent);
286 return FALSE;
289 TRACE("services.exe started successfully\n");
290 CloseHandle(out.hProcess);
291 CloseHandle(hEvent);
292 return TRUE;
295 TRACE("Waiting for services.exe to be available\n");
296 WaitForSingleObject(hEvent, INFINITE);
297 TRACE("Services.exe are available\n");
298 CloseHandle(hEvent);
300 return TRUE;
303 handle_t __RPC_USER MACHINE_HANDLEW_bind(MACHINE_HANDLEW MachineName)
305 WCHAR transport[] = SVCCTL_TRANSPORT;
306 WCHAR endpoint[] = SVCCTL_ENDPOINT;
307 LPWSTR server_copy = NULL;
308 RPC_WSTR binding_str;
309 RPC_STATUS status;
310 handle_t rpc_handle;
312 /* unlike Windows we start services.exe on demand. We start it always as
313 * checking if this is our address can be tricky */
314 if (!check_services_exe())
315 return NULL;
317 status = RpcStringBindingComposeW(NULL, transport, (RPC_WSTR)MachineName, endpoint, NULL, &binding_str);
318 HeapFree(GetProcessHeap(), 0, server_copy);
319 if (status != RPC_S_OK)
321 ERR("RpcStringBindingComposeW failed (%d)\n", (DWORD)status);
322 return NULL;
325 status = RpcBindingFromStringBindingW(binding_str, &rpc_handle);
326 RpcStringFreeW(&binding_str);
328 if (status != RPC_S_OK)
330 ERR("Couldn't connect to services.exe: error code %u\n", (DWORD)status);
331 return NULL;
334 return rpc_handle;
337 void __RPC_USER MACHINE_HANDLEW_unbind(MACHINE_HANDLEW MachineName, handle_t h)
339 RpcBindingFree(&h);
342 /******************************************************************************
343 * Service IPC functions
345 static LPWSTR service_get_pipe_name(void)
347 static const WCHAR format[] = { '\\','\\','.','\\','p','i','p','e','\\',
348 'n','e','t','\\','N','t','C','o','n','t','r','o','l','P','i','p','e','%','u',0};
349 static const WCHAR service_current_key_str[] = { 'S','Y','S','T','E','M','\\',
350 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
351 'C','o','n','t','r','o','l','\\',
352 'S','e','r','v','i','c','e','C','u','r','r','e','n','t',0};
353 LPWSTR name;
354 DWORD len;
355 HKEY service_current_key;
356 DWORD service_current;
357 LONG ret;
358 DWORD type;
360 ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, service_current_key_str, 0,
361 KEY_QUERY_VALUE, &service_current_key);
362 if (ret != ERROR_SUCCESS)
363 return NULL;
364 len = sizeof(service_current);
365 ret = RegQueryValueExW(service_current_key, NULL, NULL, &type,
366 (BYTE *)&service_current, &len);
367 RegCloseKey(service_current_key);
368 if (ret != ERROR_SUCCESS || type != REG_DWORD)
369 return NULL;
370 len = sizeof(format)/sizeof(WCHAR) + 10 /* strlenW("4294967295") */;
371 name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
372 if (!name)
373 return NULL;
374 snprintfW(name, len, format, service_current);
375 return name;
378 static HANDLE service_open_pipe(void)
380 LPWSTR szPipe = service_get_pipe_name();
381 HANDLE handle = INVALID_HANDLE_VALUE;
383 do {
384 handle = CreateFileW(szPipe, GENERIC_READ|GENERIC_WRITE,
385 0, NULL, OPEN_ALWAYS, 0, NULL);
386 if (handle != INVALID_HANDLE_VALUE)
387 break;
388 if (GetLastError() != ERROR_PIPE_BUSY)
389 break;
390 } while (WaitNamedPipeW(szPipe, NMPWAIT_WAIT_FOREVER));
391 HeapFree(GetProcessHeap(), 0, szPipe);
393 return handle;
396 /******************************************************************************
397 * service_thread
399 * Call into the main service routine provided by StartServiceCtrlDispatcher.
401 static DWORD WINAPI service_thread(LPVOID arg)
403 service_data *info = arg;
404 LPWSTR str = info->args;
405 DWORD argc = 0, len = 0;
407 TRACE("%p\n", arg);
409 while (str[len])
411 len += strlenW(&str[len]) + 1;
412 argc++;
415 if (!argc)
417 if (info->unicode)
418 info->proc.w(0, NULL);
419 else
420 info->proc.a(0, NULL);
421 return 0;
424 if (info->unicode)
426 LPWSTR *argv, p;
428 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPWSTR));
429 for (argc=0, p=str; *p; p += strlenW(p) + 1)
430 argv[argc++] = p;
431 argv[argc] = NULL;
433 info->proc.w(argc, argv);
434 HeapFree(GetProcessHeap(), 0, argv);
436 else
438 LPSTR strA, *argv, p;
439 DWORD lenA;
441 lenA = WideCharToMultiByte(CP_ACP,0, str, len, NULL, 0, NULL, NULL);
442 strA = HeapAlloc(GetProcessHeap(), 0, lenA);
443 WideCharToMultiByte(CP_ACP,0, str, len, strA, lenA, NULL, NULL);
445 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPSTR));
446 for (argc=0, p=strA; *p; p += strlen(p) + 1)
447 argv[argc++] = p;
448 argv[argc] = NULL;
450 info->proc.a(argc, argv);
451 HeapFree(GetProcessHeap(), 0, argv);
452 HeapFree(GetProcessHeap(), 0, strA);
454 return 0;
457 /******************************************************************************
458 * service_handle_start
460 static BOOL service_handle_start(HANDLE pipe, service_data *service, DWORD count)
462 DWORD read = 0, result = 0;
463 LPWSTR args;
464 BOOL r;
466 TRACE("%p %p %d\n", pipe, service, count);
468 args = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
469 r = ReadFile(pipe, args, count*sizeof(WCHAR), &read, NULL);
470 if (!r || count!=read/sizeof(WCHAR) || args[count-1])
472 ERR("pipe read failed r = %d count = %d read = %d args[n-1]=%s\n",
473 r, count, read, debugstr_wn(args, count));
474 goto end;
477 if (service->thread)
479 WARN("service is not stopped\n");
480 result = ERROR_SERVICE_ALREADY_RUNNING;
481 goto end;
484 HeapFree(GetProcessHeap(), 0, service->args);
485 service->args = args;
486 args = NULL;
487 service->thread = CreateThread( NULL, 0, service_thread,
488 service, 0, NULL );
489 SetEvent( service_event ); /* notify the main loop */
491 end:
492 HeapFree(GetProcessHeap(), 0, args);
493 WriteFile( pipe, &result, sizeof result, &read, NULL );
495 return TRUE;
498 /******************************************************************************
499 * service_handle_control
501 static BOOL service_handle_control(HANDLE pipe, service_data *service,
502 DWORD dwControl)
504 DWORD count, ret = ERROR_INVALID_SERVICE_CONTROL;
506 TRACE("received control %d\n", dwControl);
508 if (service->handler)
509 ret = service->handler(dwControl, 0, NULL, service->context);
510 return WriteFile(pipe, &ret, sizeof ret, &count, NULL);
513 /******************************************************************************
514 * service_control_dispatcher
516 static DWORD WINAPI service_control_dispatcher(LPVOID arg)
518 service_data *service = arg;
519 HANDLE pipe;
521 TRACE("%p %s\n", service, debugstr_w(service->name));
523 pipe = service_open_pipe();
525 if (pipe==INVALID_HANDLE_VALUE)
527 ERR("failed to create pipe for %s, error = %d\n",
528 debugstr_w(service->name), GetLastError());
529 return 0;
532 /* dispatcher loop */
533 while (1)
535 BOOL r;
536 DWORD count, req[2] = {0,0};
538 r = ReadFile( pipe, &req, sizeof req, &count, NULL );
539 if (!r)
541 if (GetLastError() != ERROR_BROKEN_PIPE)
542 ERR( "pipe read failed error %u\n", GetLastError() );
543 break;
545 if (count != sizeof(req))
547 ERR( "partial pipe read %u\n", count );
548 break;
551 /* handle the request */
552 switch (req[0])
554 case WINESERV_STARTINFO:
555 service_handle_start(pipe, service, req[1]);
556 break;
557 case WINESERV_SENDCONTROL:
558 service_handle_control(pipe, service, req[1]);
559 break;
560 default:
561 ERR("received invalid command %d length %d\n", req[0], req[1]);
565 CloseHandle(pipe);
566 return 1;
569 /******************************************************************************
570 * service_run_threads
572 static BOOL service_run_threads(void)
574 DWORD i, n, ret;
575 HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
576 UINT wait_services[MAXIMUM_WAIT_OBJECTS];
578 service_event = CreateEventW( NULL, FALSE, FALSE, NULL );
580 wait_handles[0] = __wine_make_process_system();
581 wait_handles[1] = service_event;
583 TRACE("Starting %d pipe listener threads. Services running as process %d\n",
584 nb_services, GetCurrentProcessId());
586 EnterCriticalSection( &service_cs );
587 for (i = 0; i < nb_services; i++)
588 CloseHandle( CreateThread( NULL, 0, service_control_dispatcher, services[i], 0, NULL ));
589 LeaveCriticalSection( &service_cs );
591 /* wait for all the threads to pack up and exit */
592 for (;;)
594 EnterCriticalSection( &service_cs );
595 for (i = 0, n = 2; i < nb_services && n < MAXIMUM_WAIT_OBJECTS; i++)
597 if (!services[i]->thread) continue;
598 wait_services[n] = i;
599 wait_handles[n++] = services[i]->thread;
601 LeaveCriticalSection( &service_cs );
603 ret = WaitForMultipleObjects( n, wait_handles, FALSE, INFINITE );
604 if (!ret) /* system process event */
606 TRACE( "last user process exited, shutting down\n" );
607 /* FIXME: we should maybe send a shutdown control to running services */
608 ExitProcess(0);
610 else if (ret == 1)
612 continue; /* rebuild the list */
614 else if (ret < n)
616 services[wait_services[ret]]->thread = 0;
617 CloseHandle( wait_handles[ret] );
618 if (n == 3) return TRUE; /* it was the last running thread */
620 else return FALSE;
624 /******************************************************************************
625 * StartServiceCtrlDispatcherA [ADVAPI32.@]
627 * See StartServiceCtrlDispatcherW.
629 BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent )
631 service_data *info;
632 unsigned int i;
633 BOOL ret = TRUE;
635 TRACE("%p\n", servent);
637 if (nb_services)
639 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
640 return FALSE;
642 while (servent[nb_services].lpServiceName) nb_services++;
643 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
645 for (i = 0; i < nb_services; i++)
647 DWORD len = MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, NULL, 0);
648 DWORD sz = FIELD_OFFSET( service_data, name[len] );
649 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
650 MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, info->name, len);
651 info->proc.a = servent[i].lpServiceProc;
652 info->unicode = FALSE;
653 services[i] = info;
656 service_run_threads();
658 return ret;
661 /******************************************************************************
662 * StartServiceCtrlDispatcherW [ADVAPI32.@]
664 * Connects a process containing one or more services to the service control
665 * manager.
667 * PARAMS
668 * servent [I] A list of the service names and service procedures
670 * RETURNS
671 * Success: TRUE.
672 * Failure: FALSE.
674 BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent )
676 service_data *info;
677 unsigned int i;
678 BOOL ret = TRUE;
680 TRACE("%p\n", servent);
682 if (nb_services)
684 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
685 return FALSE;
687 while (servent[nb_services].lpServiceName) nb_services++;
688 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
690 for (i = 0; i < nb_services; i++)
692 DWORD len = strlenW(servent[i].lpServiceName) + 1;
693 DWORD sz = FIELD_OFFSET( service_data, name[len] );
694 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
695 strcpyW(info->name, servent[i].lpServiceName);
696 info->proc.w = servent[i].lpServiceProc;
697 info->unicode = TRUE;
698 services[i] = info;
701 service_run_threads();
703 return ret;
706 /******************************************************************************
707 * LockServiceDatabase [ADVAPI32.@]
709 SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
711 struct sc_manager *hscm;
712 SC_RPC_LOCK hLock;
713 DWORD err;
715 TRACE("%p\n",hSCManager);
717 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
718 if (!hscm)
720 SetLastError( ERROR_INVALID_HANDLE );
721 return NULL;
724 err = svcctl_LockServiceDatabase(hscm->hdr.server_handle, &hLock);
725 if (err != ERROR_SUCCESS)
727 SetLastError(err);
728 return NULL;
730 return hLock;
733 /******************************************************************************
734 * UnlockServiceDatabase [ADVAPI32.@]
736 BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock)
738 DWORD err;
739 SC_RPC_LOCK hRpcLock = ScLock;
741 TRACE("%p\n",ScLock);
743 err = svcctl_UnlockServiceDatabase(&hRpcLock);
744 if (err != ERROR_SUCCESS)
746 SetLastError(err);
747 return FALSE;
749 return TRUE;
752 /******************************************************************************
753 * SetServiceStatus [ADVAPI32.@]
755 * PARAMS
756 * hService []
757 * lpStatus []
759 BOOL WINAPI
760 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
762 struct sc_service *hsvc;
763 DWORD err;
765 TRACE("%p %x %x %x %x %x %x %x\n", hService,
766 lpStatus->dwServiceType, lpStatus->dwCurrentState,
767 lpStatus->dwControlsAccepted, lpStatus->dwWin32ExitCode,
768 lpStatus->dwServiceSpecificExitCode, lpStatus->dwCheckPoint,
769 lpStatus->dwWaitHint);
771 hsvc = sc_handle_get_handle_data((SC_HANDLE)hService, SC_HTYPE_SERVICE);
772 if (!hsvc)
774 SetLastError( ERROR_INVALID_HANDLE );
775 return FALSE;
778 err = svcctl_SetServiceStatus( hsvc->hdr.server_handle, lpStatus );
779 if (err != ERROR_SUCCESS)
781 SetLastError(err);
782 return FALSE;
785 if (lpStatus->dwCurrentState == SERVICE_STOPPED)
786 CloseServiceHandle((SC_HANDLE)hService);
788 return TRUE;
792 /******************************************************************************
793 * OpenSCManagerA [ADVAPI32.@]
795 * Establish a connection to the service control manager and open its database.
797 * PARAMS
798 * lpMachineName [I] Pointer to machine name string
799 * lpDatabaseName [I] Pointer to database name string
800 * dwDesiredAccess [I] Type of access
802 * RETURNS
803 * Success: A Handle to the service control manager database
804 * Failure: NULL
806 SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
807 DWORD dwDesiredAccess )
809 LPWSTR lpMachineNameW, lpDatabaseNameW;
810 SC_HANDLE ret;
812 lpMachineNameW = SERV_dup(lpMachineName);
813 lpDatabaseNameW = SERV_dup(lpDatabaseName);
814 ret = OpenSCManagerW(lpMachineNameW, lpDatabaseNameW, dwDesiredAccess);
815 HeapFree(GetProcessHeap(), 0, lpDatabaseNameW);
816 HeapFree(GetProcessHeap(), 0, lpMachineNameW);
817 return ret;
820 /******************************************************************************
821 * OpenSCManagerW [ADVAPI32.@]
823 * See OpenSCManagerA.
825 SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
826 DWORD dwDesiredAccess )
828 struct sc_manager *manager;
829 HKEY hReg;
830 LONG r;
831 DWORD new_mask = dwDesiredAccess;
833 TRACE("(%s,%s,0x%08x)\n", debugstr_w(lpMachineName),
834 debugstr_w(lpDatabaseName), dwDesiredAccess);
836 manager = sc_handle_alloc( SC_HTYPE_MANAGER, sizeof (struct sc_manager),
837 sc_handle_destroy_manager );
838 if (!manager)
839 return NULL;
841 r = svcctl_OpenSCManagerW(lpMachineName, lpDatabaseName, dwDesiredAccess, &manager->hdr.server_handle);
842 if (r!=ERROR_SUCCESS)
843 goto error;
845 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg);
846 if (r!=ERROR_SUCCESS)
847 goto error;
849 r = RegCreateKeyW(hReg, szServiceManagerKey, &manager->hkey);
850 RegCloseKey( hReg );
851 if (r!=ERROR_SUCCESS)
852 goto error;
854 RtlMapGenericMask(&new_mask, &scm_generic);
855 manager->dwAccess = new_mask;
856 TRACE("returning %p (access : 0x%08x)\n", manager, manager->dwAccess);
858 return (SC_HANDLE) &manager->hdr;
860 error:
861 sc_handle_free( &manager->hdr );
862 SetLastError( r);
863 return NULL;
866 /******************************************************************************
867 * ControlService [ADVAPI32.@]
869 * Send a control code to a service.
871 * PARAMS
872 * hService [I] Handle of the service control manager database
873 * dwControl [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
874 * lpServiceStatus [O] Destination for the status of the service, if available
876 * RETURNS
877 * Success: TRUE.
878 * Failure: FALSE.
880 * BUGS
881 * Unlike M$' implementation, control requests are not serialized and may be
882 * processed asynchronously.
884 BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl,
885 LPSERVICE_STATUS lpServiceStatus )
887 struct sc_service *hsvc;
888 DWORD err;
890 TRACE("%p %d %p\n", hService, dwControl, lpServiceStatus);
892 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
893 if (!hsvc)
895 SetLastError( ERROR_INVALID_HANDLE );
896 return FALSE;
899 err = svcctl_ControlService(hsvc->hdr.server_handle, dwControl, lpServiceStatus);
900 if (err != ERROR_SUCCESS)
902 SetLastError(err);
903 return FALSE;
906 return TRUE;
909 /******************************************************************************
910 * CloseServiceHandle [ADVAPI32.@]
912 * Close a handle to a service or the service control manager database.
914 * PARAMS
915 * hSCObject [I] Handle to service or service control manager database
917 * RETURNS
918 * Success: TRUE
919 * Failure: FALSE
921 BOOL WINAPI
922 CloseServiceHandle( SC_HANDLE hSCObject )
924 struct sc_handle *obj;
925 DWORD err;
927 TRACE("%p\n", hSCObject);
928 if (hSCObject == NULL)
930 SetLastError(ERROR_INVALID_HANDLE);
931 return FALSE;
934 obj = (struct sc_handle *)hSCObject;
935 err = svcctl_CloseServiceHandle(&obj->server_handle);
936 sc_handle_free( obj );
938 if (err != ERROR_SUCCESS)
940 SetLastError(err);
941 return FALSE;
943 return TRUE;
947 /******************************************************************************
948 * OpenServiceA [ADVAPI32.@]
950 * Open a handle to a service.
952 * PARAMS
953 * hSCManager [I] Handle of the service control manager database
954 * lpServiceName [I] Name of the service to open
955 * dwDesiredAccess [I] Access required to the service
957 * RETURNS
958 * Success: Handle to the service
959 * Failure: NULL
961 SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
962 DWORD dwDesiredAccess )
964 LPWSTR lpServiceNameW;
965 SC_HANDLE ret;
967 TRACE("%p %s %d\n", hSCManager, debugstr_a(lpServiceName), dwDesiredAccess);
969 lpServiceNameW = SERV_dup(lpServiceName);
970 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
971 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
972 return ret;
976 /******************************************************************************
977 * OpenServiceW [ADVAPI32.@]
979 * See OpenServiceA.
981 SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
982 DWORD dwDesiredAccess)
984 struct sc_manager *hscm;
985 struct sc_service *hsvc;
986 DWORD err;
987 DWORD len;
988 DWORD new_mask = dwDesiredAccess;
990 TRACE("%p %s %d\n", hSCManager, debugstr_w(lpServiceName), dwDesiredAccess);
992 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
993 if (!hscm)
995 SetLastError( ERROR_INVALID_HANDLE );
996 return FALSE;
999 if (!lpServiceName)
1001 SetLastError(ERROR_INVALID_ADDRESS);
1002 return NULL;
1005 len = strlenW(lpServiceName)+1;
1006 hsvc = sc_handle_alloc( SC_HTYPE_SERVICE,
1007 sizeof (struct sc_service) + len*sizeof(WCHAR),
1008 sc_handle_destroy_service );
1009 if (!hsvc)
1011 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1012 return NULL;
1014 strcpyW( hsvc->name, lpServiceName );
1016 /* add reference to SCM handle */
1017 hscm->hdr.ref_count++;
1018 hsvc->scm = hscm;
1020 err = svcctl_OpenServiceW(hscm->hdr.server_handle, lpServiceName, dwDesiredAccess, &hsvc->hdr.server_handle);
1022 if (err != ERROR_SUCCESS)
1024 sc_handle_free(&hsvc->hdr);
1025 SetLastError(err);
1026 return NULL;
1029 /* for parts of advapi32 not using services.exe yet */
1030 RtlMapGenericMask(&new_mask, &svc_generic);
1031 hsvc->dwAccess = new_mask;
1033 err = RegOpenKeyExW( hscm->hkey, lpServiceName, 0, KEY_ALL_ACCESS, &hsvc->hkey );
1034 if (err != ERROR_SUCCESS)
1035 ERR("Shouldn't hapen - service key for service validated by services.exe doesn't exist\n");
1037 TRACE("returning %p\n",hsvc);
1039 return (SC_HANDLE) &hsvc->hdr;
1042 /******************************************************************************
1043 * CreateServiceW [ADVAPI32.@]
1045 SC_HANDLE WINAPI
1046 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1047 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
1048 DWORD dwServiceType, DWORD dwStartType,
1049 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1050 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
1051 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
1052 LPCWSTR lpPassword )
1054 struct sc_manager *hscm;
1055 struct sc_service *hsvc = NULL;
1056 DWORD new_mask = dwDesiredAccess;
1057 DWORD len, err;
1058 SIZE_T passwdlen;
1060 TRACE("%p %s %s\n", hSCManager,
1061 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
1063 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
1064 if (!hscm)
1066 SetLastError( ERROR_INVALID_HANDLE );
1067 return NULL;
1070 if (!lpServiceName || !lpBinaryPathName)
1072 SetLastError(ERROR_INVALID_ADDRESS);
1073 return NULL;
1076 if (lpPassword)
1077 passwdlen = (strlenW(lpPassword) + 1) * sizeof(WCHAR);
1078 else
1079 passwdlen = 0;
1081 len = strlenW(lpServiceName)+1;
1082 len = sizeof (struct sc_service) + len*sizeof(WCHAR);
1083 hsvc = sc_handle_alloc( SC_HTYPE_SERVICE, len, sc_handle_destroy_service );
1084 if( !hsvc )
1086 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1087 return NULL;
1089 lstrcpyW( hsvc->name, lpServiceName );
1091 hsvc->scm = hscm;
1092 hscm->hdr.ref_count++;
1094 err = svcctl_CreateServiceW(hscm->hdr.server_handle, lpServiceName,
1095 lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1096 lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, (LPBYTE)lpDependencies,
1097 multisz_cb(lpDependencies), lpServiceStartName, (LPBYTE)lpPassword, passwdlen,
1098 &hsvc->hdr.server_handle);
1100 if (err != ERROR_SUCCESS)
1102 SetLastError(err);
1103 sc_handle_free(&hsvc->hdr);
1104 return NULL;
1107 /* for parts of advapi32 not using services.exe yet */
1108 err = RegOpenKeyW(hscm->hkey, lpServiceName, &hsvc->hkey);
1109 if (err != ERROR_SUCCESS)
1110 WINE_ERR("Couldn't open key that should have been created by services.exe\n");
1112 RtlMapGenericMask(&new_mask, &svc_generic);
1113 hsvc->dwAccess = new_mask;
1115 return (SC_HANDLE) &hsvc->hdr;
1119 /******************************************************************************
1120 * CreateServiceA [ADVAPI32.@]
1122 SC_HANDLE WINAPI
1123 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1124 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
1125 DWORD dwServiceType, DWORD dwStartType,
1126 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1127 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
1128 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
1129 LPCSTR lpPassword )
1131 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
1132 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
1133 SC_HANDLE r;
1135 TRACE("%p %s %s\n", hSCManager,
1136 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
1138 lpServiceNameW = SERV_dup( lpServiceName );
1139 lpDisplayNameW = SERV_dup( lpDisplayName );
1140 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
1141 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
1142 lpDependenciesW = SERV_dupmulti( lpDependencies );
1143 lpServiceStartNameW = SERV_dup( lpServiceStartName );
1144 lpPasswordW = SERV_dup( lpPassword );
1146 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
1147 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1148 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
1149 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
1151 HeapFree( GetProcessHeap(), 0, lpServiceNameW );
1152 HeapFree( GetProcessHeap(), 0, lpDisplayNameW );
1153 HeapFree( GetProcessHeap(), 0, lpBinaryPathNameW );
1154 HeapFree( GetProcessHeap(), 0, lpLoadOrderGroupW );
1155 HeapFree( GetProcessHeap(), 0, lpDependenciesW );
1156 HeapFree( GetProcessHeap(), 0, lpServiceStartNameW );
1157 HeapFree( GetProcessHeap(), 0, lpPasswordW );
1159 return r;
1163 /******************************************************************************
1164 * DeleteService [ADVAPI32.@]
1166 * Delete a service from the service control manager database.
1168 * PARAMS
1169 * hService [I] Handle of the service to delete
1171 * RETURNS
1172 * Success: TRUE
1173 * Failure: FALSE
1175 BOOL WINAPI DeleteService( SC_HANDLE hService )
1177 struct sc_service *hsvc;
1178 DWORD err;
1180 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1181 if (!hsvc)
1183 SetLastError( ERROR_INVALID_HANDLE );
1184 return FALSE;
1187 err = svcctl_DeleteService(hsvc->hdr.server_handle);
1188 if (err != 0)
1190 SetLastError(err);
1191 return FALSE;
1194 /* Close the key to the service */
1195 RegCloseKey(hsvc->hkey);
1196 hsvc->hkey = NULL;
1197 return TRUE;
1201 /******************************************************************************
1202 * StartServiceA [ADVAPI32.@]
1204 * Start a service
1206 * PARAMS
1207 * hService [I] Handle of service
1208 * dwNumServiceArgs [I] Number of arguments
1209 * lpServiceArgVectors [I] Address of array of argument strings
1211 * NOTES
1212 * - NT implements this function using an obscure RPC call.
1213 * - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
1214 * to get things like "%SystemRoot%\\System32\\service.exe" to load.
1215 * - This will only work for shared address space. How should the service
1216 * args be transferred when address spaces are separated?
1217 * - Can only start one service at a time.
1218 * - Has no concept of privilege.
1220 * RETURNS
1221 * Success: TRUE.
1222 * Failure: FALSE
1224 BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
1225 LPCSTR *lpServiceArgVectors )
1227 LPWSTR *lpwstr=NULL;
1228 unsigned int i;
1229 BOOL r;
1231 TRACE("(%p,%d,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
1233 if (dwNumServiceArgs)
1234 lpwstr = HeapAlloc( GetProcessHeap(), 0,
1235 dwNumServiceArgs*sizeof(LPWSTR) );
1237 for(i=0; i<dwNumServiceArgs; i++)
1238 lpwstr[i]=SERV_dup(lpServiceArgVectors[i]);
1240 r = StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
1242 if (dwNumServiceArgs)
1244 for(i=0; i<dwNumServiceArgs; i++)
1245 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
1246 HeapFree(GetProcessHeap(), 0, lpwstr);
1249 return r;
1253 /******************************************************************************
1254 * StartServiceW [ADVAPI32.@]
1256 * See StartServiceA.
1258 BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs,
1259 LPCWSTR *lpServiceArgVectors)
1261 struct sc_service *hsvc;
1262 DWORD err;
1264 TRACE("%p %d %p\n", hService, dwNumServiceArgs, lpServiceArgVectors);
1266 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1267 if (!hsvc)
1269 SetLastError(ERROR_INVALID_HANDLE);
1270 return FALSE;
1273 err = svcctl_StartServiceW(hsvc->hdr.server_handle, dwNumServiceArgs, lpServiceArgVectors);
1274 if (err != ERROR_SUCCESS)
1276 SetLastError(err);
1277 return FALSE;
1280 return TRUE;
1283 /******************************************************************************
1284 * QueryServiceStatus [ADVAPI32.@]
1286 * PARAMS
1287 * hService [I] Handle to service to get information about
1288 * lpservicestatus [O] buffer to receive the status information for the service
1291 BOOL WINAPI QueryServiceStatus(SC_HANDLE hService,
1292 LPSERVICE_STATUS lpservicestatus)
1294 SERVICE_STATUS_PROCESS SvcStatusData;
1295 BOOL ret;
1296 DWORD dummy;
1298 TRACE("%p %p\n", hService, lpservicestatus);
1300 ret = QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&SvcStatusData,
1301 sizeof(SERVICE_STATUS_PROCESS), &dummy);
1302 if (ret) memcpy(lpservicestatus, &SvcStatusData, sizeof(SERVICE_STATUS)) ;
1303 return ret;
1307 /******************************************************************************
1308 * QueryServiceStatusEx [ADVAPI32.@]
1310 * Get information about a service.
1312 * PARAMS
1313 * hService [I] Handle to service to get information about
1314 * InfoLevel [I] Level of information to get
1315 * lpBuffer [O] Destination for requested information
1316 * cbBufSize [I] Size of lpBuffer in bytes
1317 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
1319 * RETURNS
1320 * Success: TRUE
1321 * FAILURE: FALSE
1323 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
1324 LPBYTE lpBuffer, DWORD cbBufSize,
1325 LPDWORD pcbBytesNeeded)
1327 struct sc_service *hsvc;
1328 DWORD err;
1330 TRACE("%p %d %p %d %p\n", hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1332 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1333 if (!hsvc)
1335 SetLastError( ERROR_INVALID_HANDLE );
1336 return FALSE;
1339 err = svcctl_QueryServiceStatusEx(hsvc->hdr.server_handle, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1340 if (err != ERROR_SUCCESS)
1342 SetLastError(err);
1343 return FALSE;
1346 return TRUE;
1349 /******************************************************************************
1350 * QueryServiceConfigA [ADVAPI32.@]
1352 BOOL WINAPI QueryServiceConfigA( SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA config,
1353 DWORD size, LPDWORD needed )
1355 DWORD n;
1356 LPSTR p, buffer;
1357 BOOL ret;
1358 QUERY_SERVICE_CONFIGW *configW;
1360 TRACE("%p %p %d %p\n", hService, config, size, needed);
1362 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, 2 * size )))
1364 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1365 return FALSE;
1367 configW = (QUERY_SERVICE_CONFIGW *)buffer;
1368 ret = QueryServiceConfigW( hService, configW, 2 * size, needed );
1369 if (!ret) goto done;
1371 config->dwServiceType = configW->dwServiceType;
1372 config->dwStartType = configW->dwStartType;
1373 config->dwErrorControl = configW->dwErrorControl;
1374 config->lpBinaryPathName = NULL;
1375 config->lpLoadOrderGroup = NULL;
1376 config->dwTagId = configW->dwTagId;
1377 config->lpDependencies = NULL;
1378 config->lpServiceStartName = NULL;
1379 config->lpDisplayName = NULL;
1381 p = (LPSTR)(config + 1);
1382 n = size - sizeof(*config);
1383 ret = FALSE;
1385 #define MAP_STR(str) \
1386 do { \
1387 if (configW->str) \
1389 DWORD sz = WideCharToMultiByte( CP_ACP, 0, configW->str, -1, p, n, NULL, NULL ); \
1390 if (!sz) goto done; \
1391 config->str = p; \
1392 p += sz; \
1393 n -= sz; \
1395 } while (0)
1397 MAP_STR( lpBinaryPathName );
1398 MAP_STR( lpLoadOrderGroup );
1399 MAP_STR( lpDependencies );
1400 MAP_STR( lpServiceStartName );
1401 MAP_STR( lpDisplayName );
1402 #undef MAP_STR
1404 *needed = p - (LPSTR)config;
1405 ret = TRUE;
1407 done:
1408 HeapFree( GetProcessHeap(), 0, buffer );
1409 return ret;
1412 static DWORD move_string_to_buffer(BYTE **buf, LPWSTR *string_ptr)
1414 DWORD cb;
1415 WCHAR empty_str[] = {0};
1417 if (!*string_ptr)
1418 *string_ptr = empty_str;
1420 cb = (strlenW(*string_ptr) + 1)*sizeof(WCHAR);
1422 memcpy(*buf, *string_ptr, cb);
1423 MIDL_user_free(*string_ptr);
1424 *string_ptr = (LPWSTR)*buf;
1425 *buf += cb;
1427 return cb;
1430 static DWORD size_string(LPWSTR string)
1432 return (string ? (strlenW(string) + 1)*sizeof(WCHAR) : sizeof(WCHAR));
1435 /******************************************************************************
1436 * QueryServiceConfigW [ADVAPI32.@]
1438 BOOL WINAPI
1439 QueryServiceConfigW( SC_HANDLE hService,
1440 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1441 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1443 QUERY_SERVICE_CONFIGW config;
1444 struct sc_service *hsvc;
1445 DWORD total;
1446 DWORD err;
1447 BYTE *bufpos;
1449 TRACE("%p %p %d %p\n", hService, lpServiceConfig,
1450 cbBufSize, pcbBytesNeeded);
1452 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1453 if (!hsvc)
1455 SetLastError( ERROR_INVALID_HANDLE );
1456 return FALSE;
1459 memset(&config, 0, sizeof(config));
1461 if ((err = svcctl_QueryServiceConfigW(hsvc->hdr.server_handle, &config)) != 0)
1463 TRACE("services.exe: error %u\n", err);
1464 SetLastError(err);
1465 return FALSE;
1468 /* calculate the size required first */
1469 total = sizeof (QUERY_SERVICE_CONFIGW);
1470 total += size_string(config.lpBinaryPathName);
1471 total += size_string(config.lpLoadOrderGroup);
1472 total += size_string(config.lpDependencies);
1473 total += size_string(config.lpServiceStartName);
1474 total += size_string(config.lpDisplayName);
1476 *pcbBytesNeeded = total;
1478 /* if there's not enough memory, return an error */
1479 if( total > cbBufSize )
1481 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1482 MIDL_user_free(config.lpBinaryPathName);
1483 MIDL_user_free(config.lpLoadOrderGroup);
1484 MIDL_user_free(config.lpDependencies);
1485 MIDL_user_free(config.lpServiceStartName);
1486 MIDL_user_free(config.lpDisplayName);
1487 return FALSE;
1490 *lpServiceConfig = config;
1491 bufpos = ((BYTE *)lpServiceConfig) + sizeof(QUERY_SERVICE_CONFIGW);
1492 move_string_to_buffer(&bufpos, &lpServiceConfig->lpBinaryPathName);
1493 move_string_to_buffer(&bufpos, &lpServiceConfig->lpLoadOrderGroup);
1494 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDependencies);
1495 move_string_to_buffer(&bufpos, &lpServiceConfig->lpServiceStartName);
1496 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDisplayName);
1498 if (bufpos - (LPBYTE)lpServiceConfig > cbBufSize)
1499 ERR("Buffer overflow!\n");
1501 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1502 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1503 TRACE("Dependencies = %s\n", debugstr_w(lpServiceConfig->lpDependencies) );
1504 TRACE("Service account name = %s\n", debugstr_w(lpServiceConfig->lpServiceStartName) );
1505 TRACE("Display name = %s\n", debugstr_w(lpServiceConfig->lpDisplayName) );
1507 return TRUE;
1510 /******************************************************************************
1511 * QueryServiceConfig2A [ADVAPI32.@]
1513 * Note
1514 * observed under win2k:
1515 * The functions QueryServiceConfig2A and QueryServiceConfig2W return the same
1516 * required buffer size (in byte) at least for dwLevel SERVICE_CONFIG_DESCRIPTION
1518 BOOL WINAPI QueryServiceConfig2A(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1519 DWORD size, LPDWORD needed)
1521 BOOL ret;
1522 LPBYTE bufferW = NULL;
1524 if(buffer && size)
1525 bufferW = HeapAlloc( GetProcessHeap(), 0, size);
1527 ret = QueryServiceConfig2W(hService, dwLevel, bufferW, size, needed);
1528 if(!ret) goto cleanup;
1530 switch(dwLevel) {
1531 case SERVICE_CONFIG_DESCRIPTION:
1532 { LPSERVICE_DESCRIPTIONA configA = (LPSERVICE_DESCRIPTIONA) buffer;
1533 LPSERVICE_DESCRIPTIONW configW = (LPSERVICE_DESCRIPTIONW) bufferW;
1534 if (configW->lpDescription) {
1535 DWORD sz;
1536 configA->lpDescription = (LPSTR)(configA + 1);
1537 sz = WideCharToMultiByte( CP_ACP, 0, configW->lpDescription, -1,
1538 configA->lpDescription, size - sizeof(SERVICE_DESCRIPTIONA), NULL, NULL );
1539 if (!sz) {
1540 FIXME("WideCharToMultiByte failed for configW->lpDescription\n");
1541 ret = FALSE;
1542 configA->lpDescription = NULL;
1545 else configA->lpDescription = NULL;
1547 break;
1548 default:
1549 FIXME("conversation W->A not implemented for level %d\n", dwLevel);
1550 ret = FALSE;
1553 cleanup:
1554 HeapFree( GetProcessHeap(), 0, bufferW);
1555 return ret;
1558 /******************************************************************************
1559 * QueryServiceConfig2W [ADVAPI32.@]
1561 BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1562 DWORD size, LPDWORD needed)
1564 DWORD sz, type;
1565 HKEY hKey;
1566 LONG r;
1567 struct sc_service *hsvc;
1569 if(dwLevel != SERVICE_CONFIG_DESCRIPTION) {
1570 if((dwLevel == SERVICE_CONFIG_DELAYED_AUTO_START_INFO) ||
1571 (dwLevel == SERVICE_CONFIG_FAILURE_ACTIONS) ||
1572 (dwLevel == SERVICE_CONFIG_FAILURE_ACTIONS_FLAG) ||
1573 (dwLevel == SERVICE_CONFIG_PRESHUTDOWN_INFO) ||
1574 (dwLevel == SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO) ||
1575 (dwLevel == SERVICE_CONFIG_SERVICE_SID_INFO))
1576 FIXME("Level %d not implemented\n", dwLevel);
1577 SetLastError(ERROR_INVALID_LEVEL);
1578 return FALSE;
1580 if(!needed || (!buffer && size)) {
1581 SetLastError(ERROR_INVALID_ADDRESS);
1582 return FALSE;
1585 TRACE("%p 0x%d %p 0x%d %p\n", hService, dwLevel, buffer, size, needed);
1587 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1588 if (!hsvc)
1590 SetLastError(ERROR_INVALID_HANDLE);
1591 return FALSE;
1593 hKey = hsvc->hkey;
1595 switch(dwLevel) {
1596 case SERVICE_CONFIG_DESCRIPTION: {
1597 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
1598 LPSERVICE_DESCRIPTIONW config = (LPSERVICE_DESCRIPTIONW) buffer;
1599 LPBYTE strbuf = NULL;
1600 *needed = sizeof (SERVICE_DESCRIPTIONW);
1601 sz = size - *needed;
1602 if(config && (*needed <= size))
1603 strbuf = (LPBYTE) (config + 1);
1604 r = RegQueryValueExW( hKey, szDescription, 0, &type, strbuf, &sz );
1605 if((r == ERROR_SUCCESS) && ( type != REG_SZ)) {
1606 FIXME("SERVICE_CONFIG_DESCRIPTION: don't know how to handle type %d\n", type);
1607 return FALSE;
1609 *needed += sz;
1610 if(config) {
1611 if(r == ERROR_SUCCESS)
1612 config->lpDescription = (LPWSTR) (config + 1);
1613 else
1614 config->lpDescription = NULL;
1617 break;
1619 if(*needed > size)
1620 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1622 return (*needed <= size);
1625 /******************************************************************************
1626 * EnumServicesStatusA [ADVAPI32.@]
1628 BOOL WINAPI
1629 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
1630 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
1631 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1632 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
1634 FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager,
1635 dwServiceType, dwServiceState, lpServices, cbBufSize,
1636 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
1637 SetLastError (ERROR_ACCESS_DENIED);
1638 return FALSE;
1641 /******************************************************************************
1642 * EnumServicesStatusW [ADVAPI32.@]
1644 BOOL WINAPI
1645 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
1646 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
1647 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1648 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
1650 FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager,
1651 dwServiceType, dwServiceState, lpServices, cbBufSize,
1652 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
1653 SetLastError (ERROR_ACCESS_DENIED);
1654 return FALSE;
1657 /******************************************************************************
1658 * EnumServicesStatusExA [ADVAPI32.@]
1660 BOOL WINAPI
1661 EnumServicesStatusExA(SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType,
1662 DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1663 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle, LPCSTR pszGroupName)
1665 FIXME("%p level=%d type=%x state=%x %p %x %p %p %p %s\n", hSCManager, InfoLevel,
1666 dwServiceType, dwServiceState, lpServices, cbBufSize,
1667 pcbBytesNeeded, lpServicesReturned, lpResumeHandle, debugstr_a(pszGroupName));
1668 *lpServicesReturned = 0;
1669 SetLastError (ERROR_ACCESS_DENIED);
1670 return FALSE;
1673 /******************************************************************************
1674 * EnumServicesStatusExW [ADVAPI32.@]
1676 BOOL WINAPI
1677 EnumServicesStatusExW(SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType,
1678 DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1679 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle, LPCWSTR pszGroupName)
1681 FIXME("%p level=%d type=%x state=%x %p %x %p %p %p %s\n", hSCManager, InfoLevel,
1682 dwServiceType, dwServiceState, lpServices, cbBufSize,
1683 pcbBytesNeeded, lpServicesReturned, lpResumeHandle, debugstr_w(pszGroupName));
1684 SetLastError (ERROR_ACCESS_DENIED);
1685 return FALSE;
1688 /******************************************************************************
1689 * GetServiceKeyNameA [ADVAPI32.@]
1691 BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
1692 LPSTR lpServiceName, LPDWORD lpcchBuffer )
1694 LPWSTR lpDisplayNameW, lpServiceNameW;
1695 DWORD sizeW;
1696 BOOL ret = FALSE;
1698 TRACE("%p %s %p %p\n", hSCManager,
1699 debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
1701 lpDisplayNameW = SERV_dup(lpDisplayName);
1702 if (lpServiceName)
1703 lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1704 else
1705 lpServiceNameW = NULL;
1707 sizeW = *lpcchBuffer;
1708 if (!GetServiceKeyNameW(hSCManager, lpDisplayNameW, lpServiceNameW, &sizeW))
1710 if (*lpcchBuffer && lpServiceName)
1711 lpServiceName[0] = 0;
1712 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1713 goto cleanup;
1716 if (!WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, (sizeW + 1), lpServiceName,
1717 *lpcchBuffer, NULL, NULL ))
1719 if (*lpcchBuffer && lpServiceName)
1720 lpServiceName[0] = 0;
1721 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, -1, NULL, 0, NULL, NULL);
1722 goto cleanup;
1725 /* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
1726 ret = TRUE;
1728 cleanup:
1729 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1730 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1731 return ret;
1734 /******************************************************************************
1735 * GetServiceKeyNameW [ADVAPI32.@]
1737 BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
1738 LPWSTR lpServiceName, LPDWORD lpcchBuffer )
1740 struct sc_manager *hscm;
1741 DWORD err;
1743 TRACE("%p %s %p %p\n", hSCManager,
1744 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1746 hscm = sc_handle_get_handle_data(hSCManager, SC_HTYPE_MANAGER);
1747 if (!hscm)
1749 SetLastError(ERROR_INVALID_HANDLE);
1750 return FALSE;
1753 if (!lpDisplayName)
1755 SetLastError(ERROR_INVALID_ADDRESS);
1756 return FALSE;
1759 err = svcctl_GetServiceKeyNameW(hscm->hdr.server_handle,
1760 lpDisplayName, lpServiceName, lpServiceName ? *lpcchBuffer : 0, lpcchBuffer);
1762 if (err)
1763 SetLastError(err);
1764 return err == ERROR_SUCCESS;
1767 /******************************************************************************
1768 * QueryServiceLockStatusA [ADVAPI32.@]
1770 BOOL WINAPI QueryServiceLockStatusA( SC_HANDLE hSCManager,
1771 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
1772 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1774 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1776 return FALSE;
1779 /******************************************************************************
1780 * QueryServiceLockStatusW [ADVAPI32.@]
1782 BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager,
1783 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
1784 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1786 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1788 return FALSE;
1791 /******************************************************************************
1792 * GetServiceDisplayNameA [ADVAPI32.@]
1794 BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1795 LPSTR lpDisplayName, LPDWORD lpcchBuffer)
1797 LPWSTR lpServiceNameW, lpDisplayNameW;
1798 DWORD sizeW;
1799 BOOL ret = FALSE;
1801 TRACE("%p %s %p %p\n", hSCManager,
1802 debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
1804 lpServiceNameW = SERV_dup(lpServiceName);
1805 if (lpDisplayName)
1806 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1807 else
1808 lpDisplayNameW = NULL;
1810 sizeW = *lpcchBuffer;
1811 if (!GetServiceDisplayNameW(hSCManager, lpServiceNameW, lpDisplayNameW, &sizeW))
1813 if (*lpcchBuffer && lpDisplayName)
1814 lpDisplayName[0] = 0;
1815 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1816 goto cleanup;
1819 if (!WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, (sizeW + 1), lpDisplayName,
1820 *lpcchBuffer, NULL, NULL ))
1822 if (*lpcchBuffer && lpDisplayName)
1823 lpDisplayName[0] = 0;
1824 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, -1, NULL, 0, NULL, NULL);
1825 goto cleanup;
1828 /* probably due to a bug GetServiceDisplayNameA doesn't modify lpcchBuffer on success.
1829 * (but if the function succeeded it means that is a good upper estimation of the size) */
1830 ret = TRUE;
1832 cleanup:
1833 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1834 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1835 return ret;
1838 /******************************************************************************
1839 * GetServiceDisplayNameW [ADVAPI32.@]
1841 BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1842 LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
1844 struct sc_manager *hscm;
1845 DWORD err;
1847 TRACE("%p %s %p %p\n", hSCManager,
1848 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1850 hscm = sc_handle_get_handle_data(hSCManager, SC_HTYPE_MANAGER);
1851 if (!hscm)
1853 SetLastError(ERROR_INVALID_HANDLE);
1854 return FALSE;
1857 if (!lpServiceName)
1859 SetLastError(ERROR_INVALID_ADDRESS);
1860 return FALSE;
1863 err = svcctl_GetServiceDisplayNameW(hscm->hdr.server_handle,
1864 lpServiceName, lpDisplayName, lpDisplayName ? *lpcchBuffer : 0, lpcchBuffer);
1866 if (err)
1867 SetLastError(err);
1868 return err == ERROR_SUCCESS;
1871 /******************************************************************************
1872 * ChangeServiceConfigW [ADVAPI32.@]
1874 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
1875 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1876 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
1877 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
1879 struct sc_service *hsvc;
1880 DWORD cb_pwd;
1881 DWORD err;
1883 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
1884 hService, dwServiceType, dwStartType, dwErrorControl,
1885 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
1886 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
1887 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
1889 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1890 if (!hsvc)
1892 SetLastError( ERROR_INVALID_HANDLE );
1893 return FALSE;
1896 cb_pwd = lpPassword ? (strlenW(lpPassword) + 1)*sizeof(WCHAR) : 0;
1898 err = svcctl_ChangeServiceConfigW(hsvc->hdr.server_handle, dwServiceType,
1899 dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId,
1900 (const BYTE *)lpDependencies, multisz_cb(lpDependencies), lpServiceStartName,
1901 (const BYTE *)lpPassword, cb_pwd, lpDisplayName);
1903 if (err != ERROR_SUCCESS)
1904 SetLastError(err);
1906 return err == ERROR_SUCCESS;
1909 /******************************************************************************
1910 * ChangeServiceConfigA [ADVAPI32.@]
1912 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
1913 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1914 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
1915 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
1917 LPWSTR wBinaryPathName, wLoadOrderGroup, wDependencies;
1918 LPWSTR wServiceStartName, wPassword, wDisplayName;
1919 BOOL r;
1921 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
1922 hService, dwServiceType, dwStartType, dwErrorControl,
1923 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
1924 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
1925 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
1927 wBinaryPathName = SERV_dup( lpBinaryPathName );
1928 wLoadOrderGroup = SERV_dup( lpLoadOrderGroup );
1929 wDependencies = SERV_dupmulti( lpDependencies );
1930 wServiceStartName = SERV_dup( lpServiceStartName );
1931 wPassword = SERV_dup( lpPassword );
1932 wDisplayName = SERV_dup( lpDisplayName );
1934 r = ChangeServiceConfigW( hService, dwServiceType,
1935 dwStartType, dwErrorControl, wBinaryPathName,
1936 wLoadOrderGroup, lpdwTagId, wDependencies,
1937 wServiceStartName, wPassword, wDisplayName);
1939 HeapFree( GetProcessHeap(), 0, wBinaryPathName );
1940 HeapFree( GetProcessHeap(), 0, wLoadOrderGroup );
1941 HeapFree( GetProcessHeap(), 0, wDependencies );
1942 HeapFree( GetProcessHeap(), 0, wServiceStartName );
1943 HeapFree( GetProcessHeap(), 0, wPassword );
1944 HeapFree( GetProcessHeap(), 0, wDisplayName );
1946 return r;
1949 /******************************************************************************
1950 * ChangeServiceConfig2A [ADVAPI32.@]
1952 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
1953 LPVOID lpInfo)
1955 BOOL r = FALSE;
1957 TRACE("%p %d %p\n",hService, dwInfoLevel, lpInfo);
1959 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
1961 LPSERVICE_DESCRIPTIONA sd = (LPSERVICE_DESCRIPTIONA) lpInfo;
1962 SERVICE_DESCRIPTIONW sdw;
1964 sdw.lpDescription = SERV_dup( sd->lpDescription );
1966 r = ChangeServiceConfig2W( hService, dwInfoLevel, &sdw );
1968 HeapFree( GetProcessHeap(), 0, sdw.lpDescription );
1970 else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
1972 LPSERVICE_FAILURE_ACTIONSA fa = (LPSERVICE_FAILURE_ACTIONSA) lpInfo;
1973 SERVICE_FAILURE_ACTIONSW faw;
1975 faw.dwResetPeriod = fa->dwResetPeriod;
1976 faw.lpRebootMsg = SERV_dup( fa->lpRebootMsg );
1977 faw.lpCommand = SERV_dup( fa->lpCommand );
1978 faw.cActions = fa->cActions;
1979 faw.lpsaActions = fa->lpsaActions;
1981 r = ChangeServiceConfig2W( hService, dwInfoLevel, &faw );
1983 HeapFree( GetProcessHeap(), 0, faw.lpRebootMsg );
1984 HeapFree( GetProcessHeap(), 0, faw.lpCommand );
1986 else
1987 SetLastError( ERROR_INVALID_PARAMETER );
1989 return r;
1992 /******************************************************************************
1993 * ChangeServiceConfig2W [ADVAPI32.@]
1995 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
1996 LPVOID lpInfo)
1998 HKEY hKey;
1999 struct sc_service *hsvc;
2001 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
2002 if (!hsvc)
2004 SetLastError( ERROR_INVALID_HANDLE );
2005 return FALSE;
2007 hKey = hsvc->hkey;
2009 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2011 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
2012 LPSERVICE_DESCRIPTIONW sd = (LPSERVICE_DESCRIPTIONW)lpInfo;
2013 if (sd->lpDescription)
2015 TRACE("Setting Description to %s\n",debugstr_w(sd->lpDescription));
2016 if (sd->lpDescription[0] == 0)
2017 RegDeleteValueW(hKey,szDescription);
2018 else
2019 RegSetValueExW(hKey, szDescription, 0, REG_SZ,
2020 (LPVOID)sd->lpDescription,
2021 sizeof(WCHAR)*(strlenW(sd->lpDescription)+1));
2024 else
2025 FIXME("STUB: %p %d %p\n",hService, dwInfoLevel, lpInfo);
2026 return TRUE;
2029 /******************************************************************************
2030 * QueryServiceObjectSecurity [ADVAPI32.@]
2032 BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService,
2033 SECURITY_INFORMATION dwSecurityInformation,
2034 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2035 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
2037 SECURITY_DESCRIPTOR descriptor;
2038 DWORD size;
2039 BOOL succ;
2040 ACL acl;
2042 FIXME("%p %d %p %u %p - semi-stub\n", hService, dwSecurityInformation,
2043 lpSecurityDescriptor, cbBufSize, pcbBytesNeeded);
2045 if (dwSecurityInformation != DACL_SECURITY_INFORMATION)
2046 FIXME("information %d not supported\n", dwSecurityInformation);
2048 InitializeSecurityDescriptor(&descriptor, SECURITY_DESCRIPTOR_REVISION);
2050 InitializeAcl(&acl, sizeof(ACL), ACL_REVISION);
2051 SetSecurityDescriptorDacl(&descriptor, TRUE, &acl, TRUE);
2053 size = cbBufSize;
2054 succ = MakeSelfRelativeSD(&descriptor, lpSecurityDescriptor, &size);
2055 *pcbBytesNeeded = size;
2056 return succ;
2059 /******************************************************************************
2060 * SetServiceObjectSecurity [ADVAPI32.@]
2062 BOOL WINAPI SetServiceObjectSecurity(SC_HANDLE hService,
2063 SECURITY_INFORMATION dwSecurityInformation,
2064 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2066 FIXME("%p %d %p\n", hService, dwSecurityInformation, lpSecurityDescriptor);
2067 return TRUE;
2070 /******************************************************************************
2071 * SetServiceBits [ADVAPI32.@]
2073 BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus,
2074 DWORD dwServiceBits,
2075 BOOL bSetBitsOn,
2076 BOOL bUpdateImmediately)
2078 FIXME("%p %08x %x %x\n", hServiceStatus, dwServiceBits,
2079 bSetBitsOn, bUpdateImmediately);
2080 return TRUE;
2083 /* thunk for calling the RegisterServiceCtrlHandler handler function */
2084 static DWORD WINAPI ctrl_handler_thunk( DWORD control, DWORD type, void *data, void *context )
2086 LPHANDLER_FUNCTION func = context;
2088 func( control );
2089 return ERROR_SUCCESS;
2092 /******************************************************************************
2093 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
2095 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerA( LPCSTR name, LPHANDLER_FUNCTION handler )
2097 return RegisterServiceCtrlHandlerExA( name, ctrl_handler_thunk, handler );
2100 /******************************************************************************
2101 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
2103 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW( LPCWSTR name, LPHANDLER_FUNCTION handler )
2105 return RegisterServiceCtrlHandlerExW( name, ctrl_handler_thunk, handler );
2108 /******************************************************************************
2109 * RegisterServiceCtrlHandlerExA [ADVAPI32.@]
2111 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA( LPCSTR name, LPHANDLER_FUNCTION_EX handler, LPVOID context )
2113 LPWSTR nameW;
2114 SERVICE_STATUS_HANDLE ret;
2116 nameW = SERV_dup(name);
2117 ret = RegisterServiceCtrlHandlerExW( nameW, handler, context );
2118 HeapFree( GetProcessHeap(), 0, nameW );
2119 return ret;
2122 /******************************************************************************
2123 * RegisterServiceCtrlHandlerExW [ADVAPI32.@]
2125 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceName,
2126 LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext )
2128 SC_HANDLE hService;
2129 SC_HANDLE hSCM;
2130 unsigned int i;
2131 BOOL found = FALSE;
2133 TRACE("%s %p %p\n", debugstr_w(lpServiceName), lpHandlerProc, lpContext);
2135 hSCM = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT );
2136 if (!hSCM)
2137 return NULL;
2138 hService = OpenServiceW( hSCM, lpServiceName, SERVICE_SET_STATUS );
2139 CloseServiceHandle(hSCM);
2140 if (!hService)
2141 return NULL;
2143 EnterCriticalSection( &service_cs );
2144 for (i = 0; i < nb_services; i++)
2146 if(!strcmpW(lpServiceName, services[i]->name))
2148 services[i]->handler = lpHandlerProc;
2149 services[i]->context = lpContext;
2150 found = TRUE;
2151 break;
2154 LeaveCriticalSection( &service_cs );
2156 if (!found)
2158 CloseServiceHandle(hService);
2159 SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
2160 return NULL;
2163 return (SERVICE_STATUS_HANDLE)hService;
2166 /******************************************************************************
2167 * EnumDependentServicesA [ADVAPI32.@]
2169 BOOL WINAPI EnumDependentServicesA( SC_HANDLE hService, DWORD dwServiceState,
2170 LPENUM_SERVICE_STATUSA lpServices, DWORD cbBufSize,
2171 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2173 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2174 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2176 *lpServicesReturned = 0;
2177 return TRUE;
2180 /******************************************************************************
2181 * EnumDependentServicesW [ADVAPI32.@]
2183 BOOL WINAPI EnumDependentServicesW( SC_HANDLE hService, DWORD dwServiceState,
2184 LPENUM_SERVICE_STATUSW lpServices, DWORD cbBufSize,
2185 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2187 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2188 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2190 *lpServicesReturned = 0;
2191 return TRUE;