~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/advapi32/service.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * Win32 advapi functions
  3  *
  4  * Copyright 1995 Sven Verdoolaege
  5  * Copyright 2005 Mike McCormack
  6  * Copyright 2007 Rolf Kalbermatter
  7  *
  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.
 12  *
 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.
 17  *
 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
 21  */
 22 
 23 #include "config.h"
 24 #include "wine/port.h"
 25 
 26 #include <stdarg.h>
 27 #include <string.h>
 28 #include <time.h>
 29 #include <assert.h>
 30 
 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"
 41 
 42 #include "svcctl.h"
 43 
 44 #include "wine/exception.h"
 45 
 46 WINE_DEFAULT_DEBUG_CHANNEL(service);
 47 
 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 };
 51 
 52 void  __RPC_FAR * __RPC_USER MIDL_user_allocate(SIZE_T len)
 53 {
 54     return HeapAlloc(GetProcessHeap(), 0, len);
 55 }
 56 
 57 void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr)
 58 {
 59     HeapFree(GetProcessHeap(), 0, ptr);
 60 }
 61 
 62 typedef struct service_data_t
 63 {
 64     LPHANDLER_FUNCTION_EX handler;
 65     LPVOID context;
 66     HANDLE thread;
 67     SC_HANDLE handle;
 68     BOOL unicode : 1;
 69     union {
 70         LPSERVICE_MAIN_FUNCTIONA a;
 71         LPSERVICE_MAIN_FUNCTIONW w;
 72     } proc;
 73     LPWSTR args;
 74     WCHAR name[1];
 75 } service_data;
 76 
 77 static CRITICAL_SECTION service_cs;
 78 static CRITICAL_SECTION_DEBUG service_cs_debug =
 79 {
 80     0, 0, &service_cs,
 81     { &service_cs_debug.ProcessLocksList, 
 82       &service_cs_debug.ProcessLocksList },
 83       0, 0, { (DWORD_PTR)(__FILE__ ": service_cs") }
 84 };
 85 static CRITICAL_SECTION service_cs = { &service_cs_debug, -1, 0, 0, 0, 0 };
 86 
 87 static service_data **services;
 88 static unsigned int nb_services;
 89 static HANDLE service_event;
 90 
 91 extern HANDLE CDECL __wine_make_process_system(void);
 92 
 93 /******************************************************************************
 94  * String management functions (same behaviour as strdup)
 95  * NOTE: the caller of those functions is responsible for calling HeapFree
 96  * in order to release the memory allocated by those functions.
 97  */
 98 static inline LPWSTR SERV_dup( LPCSTR str )
 99 {
100     UINT len;
101     LPWSTR wstr;
102 
103     if( !str )
104         return NULL;
105     len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
106     wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
107     MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
108     return wstr;
109 }
110 
111 static inline LPWSTR SERV_dupmulti(LPCSTR str)
112 {
113     UINT len = 0, n = 0;
114     LPWSTR wstr;
115 
116     if( !str )
117         return NULL;
118     do {
119         len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
120         n += (strlen( &str[n] ) + 1);
121     } while (str[n]);
122     len++;
123     n++;
124 
125     wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
126     MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
127     return wstr;
128 }
129 
130 static inline DWORD multisz_cb(LPCWSTR wmultisz)
131 {
132     const WCHAR *wptr = wmultisz;
133 
134     if (wmultisz == NULL)
135         return 0;
136 
137     while (*wptr)
138         wptr += lstrlenW(wptr)+1;
139     return (wptr - wmultisz + 1)*sizeof(WCHAR);
140 }
141 
142 /******************************************************************************
143  * RPC connection with services.exe
144  */
145 
146 handle_t __RPC_USER MACHINE_HANDLEW_bind(MACHINE_HANDLEW MachineName)
147 {
148     WCHAR transport[] = SVCCTL_TRANSPORT;
149     WCHAR endpoint[] = SVCCTL_ENDPOINT;
150     RPC_WSTR binding_str;
151     RPC_STATUS status;
152     handle_t rpc_handle;
153 
154     status = RpcStringBindingComposeW(NULL, transport, (RPC_WSTR)MachineName, endpoint, NULL, &binding_str);
155     if (status != RPC_S_OK)
156     {
157         ERR("RpcStringBindingComposeW failed (%d)\n", (DWORD)status);
158         return NULL;
159     }
160 
161     status = RpcBindingFromStringBindingW(binding_str, &rpc_handle);
162     RpcStringFreeW(&binding_str);
163 
164     if (status != RPC_S_OK)
165     {
166         ERR("Couldn't connect to services.exe: error code %u\n", (DWORD)status);
167         return NULL;
168     }
169 
170     return rpc_handle;
171 }
172 
173 void __RPC_USER MACHINE_HANDLEW_unbind(MACHINE_HANDLEW MachineName, handle_t h)
174 {
175     RpcBindingFree(&h);
176 }
177 
178 static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *eptr)
179 {
180     return I_RpcExceptionFilter(eptr->ExceptionRecord->ExceptionCode);
181 }
182 
183 static DWORD map_exception_code(DWORD exception_code)
184 {
185     switch (exception_code)
186     {
187     case RPC_X_NULL_REF_POINTER:
188         return ERROR_INVALID_ADDRESS;
189     case RPC_X_ENUM_VALUE_OUT_OF_RANGE:
190     case RPC_X_BYTE_COUNT_TOO_SMALL:
191         return ERROR_INVALID_PARAMETER;
192     case RPC_S_INVALID_BINDING:
193     case RPC_X_SS_IN_NULL_CONTEXT:
194         return ERROR_INVALID_HANDLE;
195     default:
196         return exception_code;
197     }
198 }
199 
200 /******************************************************************************
201  * Service IPC functions
202  */
203 static LPWSTR service_get_pipe_name(void)
204 {
205     static const WCHAR format[] = { '\\','\\','.','\\','p','i','p','e','\\',
206         'n','e','t','\\','N','t','C','o','n','t','r','o','l','P','i','p','e','%','u',0};
207     static const WCHAR service_current_key_str[] = { 'S','Y','S','T','E','M','\\',
208         'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
209         'C','o','n','t','r','o','l','\\',
210         'S','e','r','v','i','c','e','C','u','r','r','e','n','t',0};
211     LPWSTR name;
212     DWORD len;
213     HKEY service_current_key;
214     DWORD service_current;
215     LONG ret;
216     DWORD type;
217 
218     ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, service_current_key_str, 0,
219         KEY_QUERY_VALUE, &service_current_key);
220     if (ret != ERROR_SUCCESS)
221         return NULL;
222     len = sizeof(service_current);
223     ret = RegQueryValueExW(service_current_key, NULL, NULL, &type,
224         (BYTE *)&service_current, &len);
225     RegCloseKey(service_current_key);
226     if (ret != ERROR_SUCCESS || type != REG_DWORD)
227         return NULL;
228     len = sizeof(format)/sizeof(WCHAR) + 10 /* strlenW("4294967295") */;
229     name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
230     if (!name)
231         return NULL;
232     snprintfW(name, len, format, service_current);
233     return name;
234 }
235 
236 static HANDLE service_open_pipe(void)
237 {
238     LPWSTR szPipe = service_get_pipe_name();
239     HANDLE handle = INVALID_HANDLE_VALUE;
240 
241     do {
242         handle = CreateFileW(szPipe, GENERIC_READ|GENERIC_WRITE,
243                          0, NULL, OPEN_ALWAYS, 0, NULL);
244         if (handle != INVALID_HANDLE_VALUE)
245             break;
246         if (GetLastError() != ERROR_PIPE_BUSY)
247             break;
248     } while (WaitNamedPipeW(szPipe, NMPWAIT_WAIT_FOREVER));
249     HeapFree(GetProcessHeap(), 0, szPipe);
250 
251     return handle;
252 }
253 
254 static service_data *find_service_by_name( const WCHAR *name )
255 {
256     unsigned int i;
257 
258     if (nb_services == 1)  /* only one service (FIXME: should depend on OWN_PROCESS etc.) */
259         return services[0];
260     for (i = 0; i < nb_services; i++)
261         if (!strcmpiW( name, services[i]->name )) return services[i];
262     return NULL;
263 }
264 
265 /******************************************************************************
266  * service_thread
267  *
268  * Call into the main service routine provided by StartServiceCtrlDispatcher.
269  */
270 static DWORD WINAPI service_thread(LPVOID arg)
271 {
272     service_data *info = arg;
273     LPWSTR str = info->args;
274     DWORD argc = 0, len = 0;
275 
276     TRACE("%p\n", arg);
277 
278     while (str[len])
279     {
280         len += strlenW(&str[len]) + 1;
281         argc++;
282     }
283     len++;
284 
285     if (info->unicode)
286     {
287         LPWSTR *argv, p;
288 
289         argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPWSTR));
290         for (argc=0, p=str; *p; p += strlenW(p) + 1)
291             argv[argc++] = p;
292         argv[argc] = NULL;
293 
294         info->proc.w(argc, argv);
295         HeapFree(GetProcessHeap(), 0, argv);
296     }
297     else
298     {
299         LPSTR strA, *argv, p;
300         DWORD lenA;
301         
302         lenA = WideCharToMultiByte(CP_ACP,0, str, len, NULL, 0, NULL, NULL);
303         strA = HeapAlloc(GetProcessHeap(), 0, lenA);
304         WideCharToMultiByte(CP_ACP,0, str, len, strA, lenA, NULL, NULL);
305 
306         argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPSTR));
307         for (argc=0, p=strA; *p; p += strlen(p) + 1)
308             argv[argc++] = p;
309         argv[argc] = NULL;
310 
311         info->proc.a(argc, argv);
312         HeapFree(GetProcessHeap(), 0, argv);
313         HeapFree(GetProcessHeap(), 0, strA);
314     }
315     return 0;
316 }
317 
318 /******************************************************************************
319  * service_handle_start
320  */
321 static DWORD service_handle_start(service_data *service, const WCHAR *data, DWORD count)
322 {
323     TRACE("%s argsize %u\n", debugstr_w(service->name), count);
324 
325     if (service->thread)
326     {
327         WARN("service is not stopped\n");
328         return ERROR_SERVICE_ALREADY_RUNNING;
329     }
330 
331     HeapFree(GetProcessHeap(), 0, service->args);
332     service->args = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
333     memcpy( service->args, data, count * sizeof(WCHAR) );
334     service->thread = CreateThread( NULL, 0, service_thread,
335                                     service, 0, NULL );
336     SetEvent( service_event );  /* notify the main loop */
337     return 0;
338 }
339 
340 /******************************************************************************
341  * service_handle_control
342  */
343 static DWORD service_handle_control(service_data *service, DWORD dwControl)
344 {
345     DWORD ret = ERROR_INVALID_SERVICE_CONTROL;
346 
347     TRACE("%s control %u\n", debugstr_w(service->name), dwControl);
348 
349     if (service->handler)
350         ret = service->handler(dwControl, 0, NULL, service->context);
351     return ret;
352 }
353 
354 /******************************************************************************
355  * service_control_dispatcher
356  */
357 static DWORD WINAPI service_control_dispatcher(LPVOID arg)
358 {
359     SC_HANDLE manager;
360     HANDLE pipe;
361 
362     if (!(manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT )))
363     {
364         ERR("failed to open service manager error %u\n", GetLastError());
365         return 0;
366     }
367 
368     pipe = service_open_pipe();
369 
370     if (pipe==INVALID_HANDLE_VALUE)
371     {
372         ERR("failed to create control pipe error = %d\n", GetLastError());
373         return 0;
374     }
375 
376     /* dispatcher loop */
377     while (1)
378     {
379         service_data *service;
380         service_start_info info;
381         WCHAR *data = NULL;
382         BOOL r;
383         DWORD data_size = 0, count, result;
384 
385         r = ReadFile( pipe, &info, FIELD_OFFSET(service_start_info,data), &count, NULL );
386         if (!r)
387         {
388             if (GetLastError() != ERROR_BROKEN_PIPE)
389                 ERR( "pipe read failed error %u\n", GetLastError() );
390             break;
391         }
392         if (count != FIELD_OFFSET(service_start_info,data))
393         {
394             ERR( "partial pipe read %u\n", count );
395             break;
396         }
397         if (count < info.total_size)
398         {
399             data_size = info.total_size - FIELD_OFFSET(service_start_info,data);
400             data = HeapAlloc( GetProcessHeap(), 0, data_size );
401             r = ReadFile( pipe, data, data_size, &count, NULL );
402             if (!r)
403             {
404                 if (GetLastError() != ERROR_BROKEN_PIPE)
405                     ERR( "pipe read failed error %u\n", GetLastError() );
406                 break;
407             }
408             if (count != data_size)
409             {
410                 ERR( "partial pipe read %u/%u\n", count, data_size );
411                 break;
412             }
413         }
414 
415         /* find the service */
416 
417         if (!(service = find_service_by_name( data )))
418         {
419             FIXME( "got request %u for unknown service %s\n", info.cmd, debugstr_w(data));
420             result = ERROR_INVALID_PARAMETER;
421             goto done;
422         }
423 
424         TRACE( "got request %u for service %s\n", info.cmd, debugstr_w(data) );
425 
426         /* handle the request */
427         switch (info.cmd)
428         {
429         case WINESERV_STARTINFO:
430             if (!service->handle)
431             {
432                 if (!(service->handle = OpenServiceW( manager, data, SERVICE_SET_STATUS )))
433                     FIXME( "failed to open service %s\n", debugstr_w(data) );
434             }
435             result = service_handle_start(service, data + info.name_size,
436                                           data_size / sizeof(WCHAR) - info.name_size );
437             break;
438         case WINESERV_SENDCONTROL:
439             result = service_handle_control(service, info.control);
440             break;
441         default:
442             ERR("received invalid command %u\n", info.cmd);
443             result = ERROR_INVALID_PARAMETER;
444             break;
445         }
446 
447     done:
448         WriteFile(pipe, &result, sizeof(result), &count, NULL);
449         HeapFree( GetProcessHeap(), 0, data );
450     }
451 
452     CloseHandle(pipe);
453     CloseServiceHandle( manager );
454     return 1;
455 }
456 
457 /******************************************************************************
458  * service_run_main_thread
459  */
460 static BOOL service_run_main_thread(void)
461 {
462     DWORD i, n, ret;
463     HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
464     UINT wait_services[MAXIMUM_WAIT_OBJECTS];
465 
466     service_event = CreateEventW( NULL, FALSE, FALSE, NULL );
467 
468     /* FIXME: service_control_dispatcher should be merged into the main thread */
469     wait_handles[0] = __wine_make_process_system();
470     wait_handles[1] = CreateThread( NULL, 0, service_control_dispatcher, NULL, 0, NULL );
471     wait_handles[2] = service_event;
472 
473     TRACE("Starting %d services running as process %d\n",
474           nb_services, GetCurrentProcessId());
475 
476     /* wait for all the threads to pack up and exit */
477     for (;;)
478     {
479         EnterCriticalSection( &service_cs );
480         for (i = 0, n = 3; i < nb_services && n < MAXIMUM_WAIT_OBJECTS; i++)
481         {
482             if (!services[i]->thread) continue;
483             wait_services[n] = i;
484             wait_handles[n++] = services[i]->thread;
485         }
486         LeaveCriticalSection( &service_cs );
487 
488         ret = WaitForMultipleObjects( n, wait_handles, FALSE, INFINITE );
489         if (!ret)  /* system process event */
490         {
491             TRACE( "last user process exited, shutting down\n" );
492             /* FIXME: we should maybe send a shutdown control to running services */
493             ExitProcess(0);
494         }
495         else if (ret == 1)
496         {
497             TRACE( "control dispatcher exited, shutting down\n" );
498             /* FIXME: we should maybe send a shutdown control to running services */
499             ExitProcess(0);
500         }
501         else if (ret == 2)
502         {
503             continue;  /* rebuild the list */
504         }
505         else if (ret < n)
506         {
507             services[wait_services[ret]]->thread = 0;
508             CloseHandle( wait_handles[ret] );
509             if (n == 4) return TRUE; /* it was the last running thread */
510         }
511         else return FALSE;
512     }
513 }
514 
515 /******************************************************************************
516  * StartServiceCtrlDispatcherA [ADVAPI32.@]
517  *
518  * See StartServiceCtrlDispatcherW.
519  */
520 BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent )
521 {
522     service_data *info;
523     unsigned int i;
524     BOOL ret = TRUE;
525 
526     TRACE("%p\n", servent);
527 
528     if (nb_services)
529     {
530         SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
531         return FALSE;
532     }
533     while (servent[nb_services].lpServiceName) nb_services++;
534     services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
535 
536     for (i = 0; i < nb_services; i++)
537     {
538         DWORD len = MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, NULL, 0);
539         DWORD sz = FIELD_OFFSET( service_data, name[len] );
540         info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
541         MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, info->name, len);
542         info->proc.a = servent[i].lpServiceProc;
543         info->unicode = FALSE;
544         services[i] = info;
545     }
546 
547     service_run_main_thread();
548 
549     return ret;
550 }
551 
552 /******************************************************************************
553  * StartServiceCtrlDispatcherW [ADVAPI32.@]
554  *
555  *  Connects a process containing one or more services to the service control
556  * manager.
557  *
558  * PARAMS
559  *   servent [I]  A list of the service names and service procedures
560  *
561  * RETURNS
562  *  Success: TRUE.
563  *  Failure: FALSE.
564  */
565 BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent )
566 {
567     service_data *info;
568     unsigned int i;
569     BOOL ret = TRUE;
570 
571     TRACE("%p\n", servent);
572 
573     if (nb_services)
574     {
575         SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
576         return FALSE;
577     }
578     while (servent[nb_services].lpServiceName) nb_services++;
579     services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
580 
581     for (i = 0; i < nb_services; i++)
582     {
583         DWORD len = strlenW(servent[i].lpServiceName) + 1;
584         DWORD sz = FIELD_OFFSET( service_data, name[len] );
585         info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
586         strcpyW(info->name, servent[i].lpServiceName);
587         info->proc.w = servent[i].lpServiceProc;
588         info->unicode = TRUE;
589         services[i] = info;
590     }
591 
592     service_run_main_thread();
593 
594     return ret;
595 }
596 
597 /******************************************************************************
598  * LockServiceDatabase  [ADVAPI32.@]
599  */
600 SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
601 {
602     SC_RPC_LOCK hLock = NULL;
603     DWORD err;
604 
605     TRACE("%p\n",hSCManager);
606 
607     __TRY
608     {
609         err = svcctl_LockServiceDatabase(hSCManager, &hLock);
610     }
611     __EXCEPT(rpc_filter)
612     {
613         err = map_exception_code(GetExceptionCode());
614     }
615     __ENDTRY
616     if (err != ERROR_SUCCESS)
617     {
618         SetLastError(err);
619         return NULL;
620     }
621     return hLock;
622 }
623 
624 /******************************************************************************
625  * UnlockServiceDatabase  [ADVAPI32.@]
626  */
627 BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock)
628 {
629     DWORD err;
630     SC_RPC_LOCK hRpcLock = ScLock;
631 
632     TRACE("%p\n",ScLock);
633 
634     __TRY
635     {
636         err = svcctl_UnlockServiceDatabase(&hRpcLock);
637     }
638     __EXCEPT(rpc_filter)
639     {
640         err = map_exception_code(GetExceptionCode());
641     }
642     __ENDTRY
643     if (err != ERROR_SUCCESS)
644     {
645         SetLastError(err);
646         return FALSE;
647     }
648     return TRUE;
649 }
650 
651 /******************************************************************************
652  * SetServiceStatus [ADVAPI32.@]
653  *
654  * PARAMS
655  *   hService []
656  *   lpStatus []
657  */
658 BOOL WINAPI
659 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
660 {
661     DWORD err;
662 
663     TRACE("%p %x %x %x %x %x %x %x\n", hService,
664           lpStatus->dwServiceType, lpStatus->dwCurrentState,
665           lpStatus->dwControlsAccepted, lpStatus->dwWin32ExitCode,
666           lpStatus->dwServiceSpecificExitCode, lpStatus->dwCheckPoint,
667           lpStatus->dwWaitHint);
668 
669     __TRY
670     {
671         err = svcctl_SetServiceStatus( hService, lpStatus );
672     }
673     __EXCEPT(rpc_filter)
674     {
675         err = map_exception_code(GetExceptionCode());
676     }
677     __ENDTRY
678     if (err != ERROR_SUCCESS)
679     {
680         SetLastError(err);
681         return FALSE;
682     }
683 
684     if (lpStatus->dwCurrentState == SERVICE_STOPPED)
685         CloseServiceHandle((SC_HANDLE)hService);
686 
687     return TRUE;
688 }
689 
690 
691 /******************************************************************************
692  * OpenSCManagerA [ADVAPI32.@]
693  *
694  * Establish a connection to the service control manager and open its database.
695  *
696  * PARAMS
697  *   lpMachineName   [I] Pointer to machine name string
698  *   lpDatabaseName  [I] Pointer to database name string
699  *   dwDesiredAccess [I] Type of access
700  *
701  * RETURNS
702  *   Success: A Handle to the service control manager database
703  *   Failure: NULL
704  */
705 SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
706                                  DWORD dwDesiredAccess )
707 {
708     LPWSTR lpMachineNameW, lpDatabaseNameW;
709     SC_HANDLE ret;
710 
711     lpMachineNameW = SERV_dup(lpMachineName);
712     lpDatabaseNameW = SERV_dup(lpDatabaseName);
713     ret = OpenSCManagerW(lpMachineNameW, lpDatabaseNameW, dwDesiredAccess);
714     HeapFree(GetProcessHeap(), 0, lpDatabaseNameW);
715     HeapFree(GetProcessHeap(), 0, lpMachineNameW);
716     return ret;
717 }
718 
719 /******************************************************************************
720  * OpenSCManagerW [ADVAPI32.@]
721  *
722  * See OpenSCManagerA.
723  */
724 SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
725                                  DWORD dwDesiredAccess )
726 {
727     SC_HANDLE handle;
728     LONG r;
729 
730     TRACE("(%s,%s,0x%08x)\n", debugstr_w(lpMachineName),
731           debugstr_w(lpDatabaseName), dwDesiredAccess);
732 
733     __TRY
734     {
735         r = svcctl_OpenSCManagerW(lpMachineName, lpDatabaseName, dwDesiredAccess, (SC_RPC_HANDLE *)&handle);
736     }
737     __EXCEPT(rpc_filter)
738     {
739         r = map_exception_code(GetExceptionCode());
740     }
741     __ENDTRY
742 
743     if (r!=ERROR_SUCCESS)
744     {
745         SetLastError( r );
746         handle = 0;
747     }
748 
749     TRACE("returning %p\n", handle);
750     return handle;
751 }
752 
753 /******************************************************************************
754  * ControlService [ADVAPI32.@]
755  *
756  * Send a control code to a service.
757  *
758  * PARAMS
759  *   hService        [I] Handle of the service control manager database
760  *   dwControl       [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
761  *   lpServiceStatus [O] Destination for the status of the service, if available
762  *
763  * RETURNS
764  *   Success: TRUE.
765  *   Failure: FALSE.
766  *
767  * BUGS
768  *   Unlike M$' implementation, control requests are not serialized and may be
769  *   processed asynchronously.
770  */
771 BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl,
772                             LPSERVICE_STATUS lpServiceStatus )
773 {
774     DWORD err;
775 
776     TRACE("%p %d %p\n", hService, dwControl, lpServiceStatus);
777 
778     __TRY
779     {
780         err = svcctl_ControlService(hService, dwControl, lpServiceStatus);
781     }
782     __EXCEPT(rpc_filter)
783     {
784         err = map_exception_code(GetExceptionCode());
785     }
786     __ENDTRY
787     if (err != ERROR_SUCCESS)
788     {
789         SetLastError(err);
790         return FALSE;
791     }
792 
793     return TRUE;
794 }
795 
796 /******************************************************************************
797  * CloseServiceHandle [ADVAPI32.@]
798  * 
799  * Close a handle to a service or the service control manager database.
800  *
801  * PARAMS
802  *   hSCObject [I] Handle to service or service control manager database
803  *
804  * RETURNS
805  *  Success: TRUE
806  *  Failure: FALSE
807  */
808 BOOL WINAPI
809 CloseServiceHandle( SC_HANDLE hSCObject )
810 {
811     DWORD err;
812 
813     TRACE("%p\n", hSCObject);
814 
815     __TRY
816     {
817         err = svcctl_CloseServiceHandle((SC_RPC_HANDLE *)&hSCObject);
818     }
819     __EXCEPT(rpc_filter)
820     {
821         err = map_exception_code(GetExceptionCode());
822     }
823     __ENDTRY
824 
825     if (err != ERROR_SUCCESS)
826     {
827         SetLastError(err);
828         return FALSE;
829     }
830     return TRUE;
831 }
832 
833 
834 /******************************************************************************
835  * OpenServiceA [ADVAPI32.@]
836  *
837  * Open a handle to a service.
838  *
839  * PARAMS
840  *   hSCManager      [I] Handle of the service control manager database
841  *   lpServiceName   [I] Name of the service to open
842  *   dwDesiredAccess [I] Access required to the service
843  *
844  * RETURNS
845  *    Success: Handle to the service
846  *    Failure: NULL
847  */
848 SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
849                                DWORD dwDesiredAccess )
850 {
851     LPWSTR lpServiceNameW;
852     SC_HANDLE ret;
853 
854     TRACE("%p %s %d\n", hSCManager, debugstr_a(lpServiceName), dwDesiredAccess);
855 
856     lpServiceNameW = SERV_dup(lpServiceName);
857     ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
858     HeapFree(GetProcessHeap(), 0, lpServiceNameW);
859     return ret;
860 }
861 
862 
863 /******************************************************************************
864  * OpenServiceW [ADVAPI32.@]
865  *
866  * See OpenServiceA.
867  */
868 SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
869                                DWORD dwDesiredAccess)
870 {
871     SC_HANDLE handle;
872     DWORD err;
873 
874     TRACE("%p %s %d\n", hSCManager, debugstr_w(lpServiceName), dwDesiredAccess);
875 
876     if (!hSCManager)
877     {
878         SetLastError( ERROR_INVALID_HANDLE );
879         return 0;
880     }
881 
882     __TRY
883     {
884         err = svcctl_OpenServiceW(hSCManager, lpServiceName, dwDesiredAccess, (SC_RPC_HANDLE *)&handle);
885     }
886     __EXCEPT(rpc_filter)
887     {
888         err = map_exception_code(GetExceptionCode());
889     }
890     __ENDTRY
891 
892     if (err != ERROR_SUCCESS)
893     {
894         SetLastError(err);
895         handle = 0;
896     }
897 
898     TRACE("returning %p\n",handle);
899     return handle;
900 }
901 
902 /******************************************************************************
903  * CreateServiceW [ADVAPI32.@]
904  */
905 SC_HANDLE WINAPI
906 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
907                   LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
908                   DWORD dwServiceType, DWORD dwStartType,
909                   DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
910                   LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
911                   LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
912                   LPCWSTR lpPassword )
913 {
914     SC_HANDLE handle;
915     DWORD err;
916     SIZE_T passwdlen;
917 
918     TRACE("%p %s %s\n", hSCManager, 
919           debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
920 
921     if (!hSCManager)
922     {
923         SetLastError( ERROR_INVALID_HANDLE );
924         return 0;
925     }
926 
927     if (lpPassword)
928         passwdlen = (strlenW(lpPassword) + 1) * sizeof(WCHAR);
929     else
930         passwdlen = 0;
931 
932     __TRY
933     {
934         err = svcctl_CreateServiceW(hSCManager, lpServiceName,
935                 lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
936                 lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, (LPBYTE)lpDependencies,
937                 multisz_cb(lpDependencies), lpServiceStartName, (LPBYTE)lpPassword, passwdlen,
938                 (SC_RPC_HANDLE *)&handle);
939     }
940     __EXCEPT(rpc_filter)
941     {
942         err = map_exception_code(GetExceptionCode());
943     }
944     __ENDTRY
945 
946     if (err != ERROR_SUCCESS)
947     {
948         SetLastError(err);
949         handle = 0;
950     }
951     return handle;
952 }
953 
954 
955 /******************************************************************************
956  * CreateServiceA [ADVAPI32.@]
957  */
958 SC_HANDLE WINAPI
959 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
960                   LPCSTR lpDisplayName, DWORD dwDesiredAccess,
961                   DWORD dwServiceType, DWORD dwStartType,
962                   DWORD dwErrorControl, LPCSTR lpBinaryPathName,
963                   LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
964                   LPCSTR lpDependencies, LPCSTR lpServiceStartName,
965                   LPCSTR lpPassword )
966 {
967     LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
968         lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
969     SC_HANDLE r;
970 
971     TRACE("%p %s %s\n", hSCManager,
972           debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
973 
974     lpServiceNameW = SERV_dup( lpServiceName );
975     lpDisplayNameW = SERV_dup( lpDisplayName );
976     lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
977     lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
978     lpDependenciesW = SERV_dupmulti( lpDependencies );
979     lpServiceStartNameW = SERV_dup( lpServiceStartName );
980     lpPasswordW = SERV_dup( lpPassword );
981 
982     r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
983             dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
984             lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
985             lpDependenciesW, lpServiceStartNameW, lpPasswordW );
986 
987     HeapFree( GetProcessHeap(), 0, lpServiceNameW );
988     HeapFree( GetProcessHeap(), 0, lpDisplayNameW );
989     HeapFree( GetProcessHeap(), 0, lpBinaryPathNameW );
990     HeapFree( GetProcessHeap(), 0, lpLoadOrderGroupW );
991     HeapFree( GetProcessHeap(), 0, lpDependenciesW );
992     HeapFree( GetProcessHeap(), 0, lpServiceStartNameW );
993     HeapFree( GetProcessHeap(), 0, lpPasswordW );
994 
995     return r;
996 }
997 
998 
999 /******************************************************************************
1000  * DeleteService [ADVAPI32.@]
1001  *
1002  * Delete a service from the service control manager database.
1003  *
1004  * PARAMS
1005  *    hService [I] Handle of the service to delete
1006  *
1007  * RETURNS
1008  *  Success: TRUE
1009  *  Failure: FALSE
1010  */
1011 BOOL WINAPI DeleteService( SC_HANDLE hService )
1012 {
1013     DWORD err;
1014 
1015     __TRY
1016     {
1017         err = svcctl_DeleteService(hService);
1018     }
1019     __EXCEPT(rpc_filter)
1020     {
1021         err = map_exception_code(GetExceptionCode());
1022     }
1023     __ENDTRY
1024     if (err != 0)
1025     {
1026         SetLastError(err);
1027         return FALSE;
1028     }
1029 
1030     return TRUE;
1031 }
1032 
1033 
1034 /******************************************************************************
1035  * StartServiceA [ADVAPI32.@]
1036  *
1037  * Start a service
1038  *
1039  * PARAMS
1040  *   hService            [I] Handle of service
1041  *   dwNumServiceArgs    [I] Number of arguments
1042  *   lpServiceArgVectors [I] Address of array of argument strings
1043  *
1044  * NOTES
1045  *  - NT implements this function using an obscure RPC call.
1046  *  - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
1047  *    to get things like "%SystemRoot%\\System32\\service.exe" to load.
1048  *  - This will only work for shared address space. How should the service
1049  *    args be transferred when address spaces are separated?
1050  *  - Can only start one service at a time.
1051  *  - Has no concept of privilege.
1052  *
1053  * RETURNS
1054  *   Success: TRUE.
1055  *   Failure: FALSE
1056  */
1057 BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
1058                            LPCSTR *lpServiceArgVectors )
1059 {
1060     LPWSTR *lpwstr=NULL;
1061     unsigned int i;
1062     BOOL r;
1063 
1064     TRACE("(%p,%d,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
1065 
1066     if (dwNumServiceArgs)
1067         lpwstr = HeapAlloc( GetProcessHeap(), 0,
1068                                    dwNumServiceArgs*sizeof(LPWSTR) );
1069 
1070     for(i=0; i<dwNumServiceArgs; i++)
1071         lpwstr[i]=SERV_dup(lpServiceArgVectors[i]);
1072 
1073     r = StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
1074 
1075     if (dwNumServiceArgs)
1076     {
1077         for(i=0; i<dwNumServiceArgs; i++)
1078             HeapFree(GetProcessHeap(), 0, lpwstr[i]);
1079         HeapFree(GetProcessHeap(), 0, lpwstr);
1080     }
1081 
1082     return r;
1083 }
1084 
1085 
1086 /******************************************************************************
1087  * StartServiceW [ADVAPI32.@]
1088  * 
1089  * See StartServiceA.
1090  */
1091 BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs,
1092                           LPCWSTR *lpServiceArgVectors)
1093 {
1094     DWORD err;
1095 
1096     TRACE("%p %d %p\n", hService, dwNumServiceArgs, lpServiceArgVectors);
1097 
1098     __TRY
1099     {
1100         err = svcctl_StartServiceW(hService, dwNumServiceArgs, lpServiceArgVectors);
1101     }
1102     __EXCEPT(rpc_filter)
1103     {
1104         err = map_exception_code(GetExceptionCode());
1105     }
1106     __ENDTRY
1107     if (err != ERROR_SUCCESS)
1108     {
1109         SetLastError(err);
1110         return FALSE;
1111     }
1112 
1113     return TRUE;
1114 }
1115 
1116 /******************************************************************************
1117  * QueryServiceStatus [ADVAPI32.@]
1118  *
1119  * PARAMS
1120  *   hService        [I] Handle to service to get information about
1121  *   lpservicestatus [O] buffer to receive the status information for the service
1122  *
1123  */
1124 BOOL WINAPI QueryServiceStatus(SC_HANDLE hService,
1125                                LPSERVICE_STATUS lpservicestatus)
1126 {
1127     SERVICE_STATUS_PROCESS SvcStatusData;
1128     BOOL ret;
1129     DWORD dummy;
1130 
1131     TRACE("%p %p\n", hService, lpservicestatus);
1132 
1133     ret = QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&SvcStatusData,
1134                                 sizeof(SERVICE_STATUS_PROCESS), &dummy);
1135     if (ret) memcpy(lpservicestatus, &SvcStatusData, sizeof(SERVICE_STATUS)) ;
1136     return ret;
1137 }
1138 
1139 
1140 /******************************************************************************
1141  * QueryServiceStatusEx [ADVAPI32.@]
1142  *
1143  * Get information about a service.
1144  *
1145  * PARAMS
1146  *   hService       [I] Handle to service to get information about
1147  *   InfoLevel      [I] Level of information to get
1148  *   lpBuffer       [O] Destination for requested information
1149  *   cbBufSize      [I] Size of lpBuffer in bytes
1150  *   pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
1151  *
1152  * RETURNS
1153  *  Success: TRUE
1154  *  FAILURE: FALSE
1155  */
1156 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
1157                         LPBYTE lpBuffer, DWORD cbBufSize,
1158                         LPDWORD pcbBytesNeeded)
1159 {
1160     DWORD err;
1161 
1162     TRACE("%p %d %p %d %p\n", hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1163 
1164     __TRY
1165     {
1166         err = svcctl_QueryServiceStatusEx(hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1167     }
1168     __EXCEPT(rpc_filter)
1169     {
1170         err = map_exception_code(GetExceptionCode());
1171     }
1172     __ENDTRY
1173     if (err != ERROR_SUCCESS)
1174     {
1175         SetLastError(err);
1176         return FALSE;
1177     }
1178 
1179     return TRUE;
1180 }
1181 
1182 /******************************************************************************
1183  * QueryServiceConfigA [ADVAPI32.@]
1184  */
1185 BOOL WINAPI QueryServiceConfigA( SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA config,
1186                                  DWORD size, LPDWORD needed )
1187 {
1188     DWORD n;
1189     LPSTR p, buffer;
1190     BOOL ret;
1191     QUERY_SERVICE_CONFIGW *configW;
1192 
1193     TRACE("%p %p %d %p\n", hService, config, size, needed);
1194 
1195     if (!(buffer = HeapAlloc( GetProcessHeap(), 0, 2 * size )))
1196     {
1197         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1198         return FALSE;
1199     }
1200     configW = (QUERY_SERVICE_CONFIGW *)buffer;
1201     ret = QueryServiceConfigW( hService, configW, 2 * size, needed );
1202     if (!ret) goto done;
1203 
1204     config->dwServiceType      = configW->dwServiceType;
1205     config->dwStartType        = configW->dwStartType;
1206     config->dwErrorControl     = configW->dwErrorControl;
1207     config->lpBinaryPathName   = NULL;
1208     config->lpLoadOrderGroup   = NULL;
1209     config->dwTagId            = configW->dwTagId;
1210     config->lpDependencies     = NULL;
1211     config->lpServiceStartName = NULL;
1212     config->lpDisplayName      = NULL;
1213 
1214     p = (LPSTR)(config + 1);
1215     n = size - sizeof(*config);
1216     ret = FALSE;
1217 
1218 #define MAP_STR(str) \
1219     do { \
1220         if (configW->str) \
1221         { \
1222             DWORD sz = WideCharToMultiByte( CP_ACP, 0, configW->str, -1, p, n, NULL, NULL ); \
1223             if (!sz) goto done; \
1224             config->str = p; \
1225             p += sz; \
1226             n -= sz; \
1227         } \
1228     } while (0)
1229 
1230     MAP_STR( lpBinaryPathName );
1231     MAP_STR( lpLoadOrderGroup );
1232     MAP_STR( lpDependencies );
1233     MAP_STR( lpServiceStartName );
1234     MAP_STR( lpDisplayName );
1235 #undef MAP_STR
1236 
1237     *needed = p - (LPSTR)config;
1238     ret = TRUE;
1239 
1240 done:
1241     HeapFree( GetProcessHeap(), 0, buffer );
1242     return ret;
1243 }
1244 
1245 static DWORD move_string_to_buffer(BYTE **buf, LPWSTR *string_ptr)
1246 {
1247     DWORD cb;
1248 
1249     if (!*string_ptr)
1250     {
1251         cb = sizeof(WCHAR);
1252         memset(*buf, 0, cb);
1253     }
1254     else
1255     {
1256         cb = (strlenW(*string_ptr) + 1)*sizeof(WCHAR);
1257         memcpy(*buf, *string_ptr, cb);
1258         MIDL_user_free(*string_ptr);
1259     }
1260 
1261     *string_ptr = (LPWSTR)*buf;
1262     *buf += cb;
1263 
1264     return cb;
1265 }
1266 
1267 static DWORD size_string(LPWSTR string)
1268 {
1269     return (string ? (strlenW(string) + 1)*sizeof(WCHAR) : sizeof(WCHAR));
1270 }
1271 
1272 /******************************************************************************
1273  * QueryServiceConfigW [ADVAPI32.@]
1274  */
1275 BOOL WINAPI 
1276 QueryServiceConfigW( SC_HANDLE hService,
1277                      LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1278                      DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1279 {
1280     QUERY_SERVICE_CONFIGW config;
1281     DWORD total;
1282     DWORD err;
1283     BYTE *bufpos;
1284 
1285     TRACE("%p %p %d %p\n", hService, lpServiceConfig,
1286            cbBufSize, pcbBytesNeeded);
1287 
1288     memset(&config, 0, sizeof(config));
1289 
1290     __TRY
1291     {
1292         err = svcctl_QueryServiceConfigW(hService, &config);
1293     }
1294     __EXCEPT(rpc_filter)
1295     {
1296         err = map_exception_code(GetExceptionCode());
1297     }
1298     __ENDTRY
1299 
1300     if (err != ERROR_SUCCESS)
1301     {
1302         TRACE("services.exe: error %u\n", err);
1303         SetLastError(err);
1304         return FALSE;
1305     }
1306 
1307     /* calculate the size required first */
1308     total = sizeof (QUERY_SERVICE_CONFIGW);
1309     total += size_string(config.lpBinaryPathName);
1310     total += size_string(config.lpLoadOrderGroup);
1311     total += size_string(config.lpDependencies);
1312     total += size_string(config.lpServiceStartName);
1313     total += size_string(config.lpDisplayName);
1314 
1315     *pcbBytesNeeded = total;
1316 
1317     /* if there's not enough memory, return an error */
1318     if( total > cbBufSize )
1319     {
1320         SetLastError( ERROR_INSUFFICIENT_BUFFER );
1321         MIDL_user_free(config.lpBinaryPathName);
1322         MIDL_user_free(config.lpLoadOrderGroup);
1323         MIDL_user_free(config.lpDependencies);
1324         MIDL_user_free(config.lpServiceStartName);
1325         MIDL_user_free(config.lpDisplayName);
1326         return FALSE;
1327     }
1328 
1329     *lpServiceConfig = config;
1330     bufpos = ((BYTE *)lpServiceConfig) + sizeof(QUERY_SERVICE_CONFIGW);
1331     move_string_to_buffer(&bufpos, &lpServiceConfig->lpBinaryPathName);
1332     move_string_to_buffer(&bufpos, &lpServiceConfig->lpLoadOrderGroup);
1333     move_string_to_buffer(&bufpos, &lpServiceConfig->lpDependencies);
1334     move_string_to_buffer(&bufpos, &lpServiceConfig->lpServiceStartName);
1335     move_string_to_buffer(&bufpos, &lpServiceConfig->lpDisplayName);
1336 
1337     TRACE("Image path           = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1338     TRACE("Group                = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1339     TRACE("Dependencies         = %s\n", debugstr_w(lpServiceConfig->lpDependencies) );
1340     TRACE("Service account name = %s\n", debugstr_w(lpServiceConfig->lpServiceStartName) );
1341     TRACE("Display name         = %s\n", debugstr_w(lpServiceConfig->lpDisplayName) );
1342 
1343     return TRUE;
1344 }
1345 
1346 /******************************************************************************
1347  * QueryServiceConfig2A [ADVAPI32.@]
1348  *
1349  * Note
1350  *   observed under win2k:
1351  *   The functions QueryServiceConfig2A and QueryServiceConfig2W return the same
1352  *   required buffer size (in byte) at least for dwLevel SERVICE_CONFIG_DESCRIPTION
1353  */
1354 BOOL WINAPI QueryServiceConfig2A(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1355                                  DWORD size, LPDWORD needed)
1356 {
1357     BOOL ret;
1358     LPBYTE bufferW = NULL;
1359 
1360     if(buffer && size)
1361         bufferW = HeapAlloc( GetProcessHeap(), 0, size);
1362 
1363     ret = QueryServiceConfig2W(hService, dwLevel, bufferW, size, needed);
1364     if(!ret) goto cleanup;
1365 
1366     switch(dwLevel) {
1367         case SERVICE_CONFIG_DESCRIPTION:
1368             if (buffer && bufferW) {
1369                 LPSERVICE_DESCRIPTIONA configA = (LPSERVICE_DESCRIPTIONA) buffer;
1370                 LPSERVICE_DESCRIPTIONW configW = (LPSERVICE_DESCRIPTIONW) bufferW;
1371                 if (configW->lpDescription && (size > sizeof(SERVICE_DESCRIPTIONA))) {
1372                     DWORD sz;
1373                     configA->lpDescription = (LPSTR)(configA + 1);
1374                     sz = WideCharToMultiByte( CP_ACP, 0, configW->lpDescription, -1,
1375                              configA->lpDescription, size - sizeof(SERVICE_DESCRIPTIONA), NULL, NULL );
1376                     if (!sz) {
1377                         FIXME("WideCharToMultiByte failed for configW->lpDescription\n");
1378                         ret = FALSE;
1379                         configA->lpDescription = NULL;
1380                     }
1381                 }
1382                 else configA->lpDescription = NULL;
1383             }
1384             break;
1385         default:
1386             FIXME("conversation W->A not implemented for level %d\n", dwLevel);
1387             ret = FALSE;
1388             break;
1389     }
1390 
1391 cleanup:
1392     HeapFree( GetProcessHeap(), 0, bufferW);
1393     return ret;
1394 }
1395 
1396 /******************************************************************************
1397  * QueryServiceConfig2W [ADVAPI32.@]
1398  */
1399 BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1400                                  DWORD size, LPDWORD needed)
1401 {
1402     DWORD err;
1403 
1404     if(dwLevel != SERVICE_CONFIG_DESCRIPTION) {
1405         if((dwLevel == SERVICE_CONFIG_DELAYED_AUTO_START_INFO) ||
1406            (dwLevel == SERVICE_CONFIG_FAILURE_ACTIONS) ||
1407            (dwLevel == SERVICE_CONFIG_FAILURE_ACTIONS_FLAG) ||
1408            (dwLevel == SERVICE_CONFIG_PRESHUTDOWN_INFO) ||
1409            (dwLevel == SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO) ||
1410            (dwLevel == SERVICE_CONFIG_SERVICE_SID_INFO))
1411             FIXME("Level %d not implemented\n", dwLevel);
1412         SetLastError(ERROR_INVALID_LEVEL);
1413         return FALSE;
1414     }
1415 
1416     if(!buffer && size) {
1417         SetLastError(ERROR_INVALID_ADDRESS);
1418         return FALSE;
1419     }
1420 
1421     TRACE("%p 0x%d %p 0x%d %p\n", hService, dwLevel, buffer, size, needed);
1422 
1423     __TRY
1424     {
1425         err = svcctl_QueryServiceConfig2W(hService, dwLevel, buffer, size, needed);
1426     }
1427     __EXCEPT(rpc_filter)
1428     {
1429         err = map_exception_code(GetExceptionCode());
1430     }
1431     __ENDTRY
1432 
1433     if (err != ERROR_SUCCESS)
1434     {
1435         SetLastError( err );
1436         return FALSE;
1437     }
1438 
1439     switch (dwLevel)
1440     {
1441     case SERVICE_CONFIG_DESCRIPTION:
1442         if (buffer)
1443         {
1444             SERVICE_DESCRIPTIONW *descr = (SERVICE_DESCRIPTIONW *)buffer;
1445             if (descr->lpDescription)  /* make it an absolute pointer */
1446                 descr->lpDescription = (WCHAR *)(buffer + (ULONG_PTR)descr->lpDescription);
1447             break;
1448         }
1449     }
1450 
1451     return TRUE;
1452 }
1453 
1454 /******************************************************************************
1455  * EnumServicesStatusA [ADVAPI32.@]
1456  */
1457 BOOL WINAPI
1458 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
1459                      DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
1460                      DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1461                      LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
1462 {
1463     FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager,
1464           dwServiceType, dwServiceState, lpServices, cbBufSize,
1465           pcbBytesNeeded, lpServicesReturned,  lpResumeHandle);
1466     SetLastError (ERROR_ACCESS_DENIED);
1467     return FALSE;
1468 }
1469 
1470 /******************************************************************************
1471  * EnumServicesStatusW [ADVAPI32.@]
1472  */
1473 BOOL WINAPI
1474 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
1475                      DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
1476                      DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1477                      LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
1478 {
1479     FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager,
1480           dwServiceType, dwServiceState, lpServices, cbBufSize,
1481           pcbBytesNeeded, lpServicesReturned,  lpResumeHandle);
1482     SetLastError (ERROR_ACCESS_DENIED);
1483     return FALSE;
1484 }
1485 
1486 /******************************************************************************
1487  * EnumServicesStatusExA [ADVAPI32.@]
1488  */
1489 BOOL WINAPI
1490 EnumServicesStatusExA(SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType,
1491                       DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1492                       LPDWORD lpServicesReturned, LPDWORD lpResumeHandle, LPCSTR pszGroupName)
1493 {
1494     FIXME("%p level=%d type=%x state=%x %p %x %p %p %p %s\n", hSCManager, InfoLevel,
1495           dwServiceType, dwServiceState, lpServices, cbBufSize,
1496           pcbBytesNeeded, lpServicesReturned,  lpResumeHandle, debugstr_a(pszGroupName));
1497     if (lpServicesReturned) *lpServicesReturned = 0;
1498     SetLastError (ERROR_ACCESS_DENIED);
1499     return FALSE;
1500 }
1501 
1502 /******************************************************************************
1503  * EnumServicesStatusExW [ADVAPI32.@]
1504  */
1505 BOOL WINAPI
1506 EnumServicesStatusExW(SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType,
1507                       DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1508                       LPDWORD lpServicesReturned, LPDWORD lpResumeHandle, LPCWSTR pszGroupName)
1509 {
1510     FIXME("%p level=%d type=%x state=%x %p %x %p %p %p %s\n", hSCManager, InfoLevel,
1511           dwServiceType, dwServiceState, lpServices, cbBufSize,
1512           pcbBytesNeeded, lpServicesReturned,  lpResumeHandle, debugstr_w(pszGroupName));
1513     SetLastError (ERROR_ACCESS_DENIED);
1514     return FALSE;
1515 }
1516 
1517 /******************************************************************************
1518  * GetServiceKeyNameA [ADVAPI32.@]
1519  */
1520 BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
1521                                 LPSTR lpServiceName, LPDWORD lpcchBuffer )
1522 {
1523     LPWSTR lpDisplayNameW, lpServiceNameW;
1524     DWORD sizeW;
1525     BOOL ret = FALSE;
1526 
1527     TRACE("%p %s %p %p\n", hSCManager,
1528           debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
1529 
1530     lpDisplayNameW = SERV_dup(lpDisplayName);
1531     if (lpServiceName)
1532         lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1533     else
1534         lpServiceNameW = NULL;
1535 
1536     sizeW = *lpcchBuffer;
1537     if (!GetServiceKeyNameW(hSCManager, lpDisplayNameW, lpServiceNameW, &sizeW))
1538     {
1539         if (lpServiceName && *lpcchBuffer)
1540             lpServiceName[0] = 0;
1541         *lpcchBuffer = sizeW*2;  /* we can only provide an upper estimation of string length */
1542         goto cleanup;
1543     }
1544 
1545     if (!WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, (sizeW + 1), lpServiceName,
1546                         *lpcchBuffer, NULL, NULL ))
1547     {
1548         if (*lpcchBuffer && lpServiceName)
1549             lpServiceName[0] = 0;
1550         *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, -1, NULL, 0, NULL, NULL);
1551         goto cleanup;
1552     }
1553 
1554     /* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
1555     ret = TRUE;
1556 
1557 cleanup:
1558     HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1559     HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1560     return ret;
1561 }
1562 
1563 /******************************************************************************
1564  * GetServiceKeyNameW [ADVAPI32.@]
1565  */
1566 BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
1567                                 LPWSTR lpServiceName, LPDWORD lpcchBuffer )
1568 {
1569     DWORD err;
1570     WCHAR buffer[2];
1571 
1572     TRACE("%p %s %p %p\n", hSCManager,
1573           debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1574 
1575     if (!hSCManager)
1576     {
1577         SetLastError( ERROR_INVALID_HANDLE );
1578         return 0;
1579     }
1580 
1581     /* provide a buffer if the caller didn't */
1582     if (!lpServiceName || *lpcchBuffer < 2)
1583     {
1584         lpServiceName = buffer;
1585         /* A size of 1 would be enough, but tests show that Windows returns 2,
1586          * probably because of a WCHAR/bytes mismatch in their code.
1587          */
1588         *lpcchBuffer = 2;
1589     }
1590 
1591     __TRY
1592     {
1593         err = svcctl_GetServiceKeyNameW(hSCManager, lpDisplayName, lpServiceName,
1594                                         *lpcchBuffer, lpcchBuffer);
1595     }
1596     __EXCEPT(rpc_filter)
1597     {
1598         err = map_exception_code(GetExceptionCode());
1599     }
1600     __ENDTRY
1601 
1602     if (err)
1603         SetLastError(err);
1604     return err == ERROR_SUCCESS;
1605 }
1606 
1607 /******************************************************************************
1608  * QueryServiceLockStatusA [ADVAPI32.@]
1609  */
1610 BOOL WINAPI QueryServiceLockStatusA( SC_HANDLE hSCManager,
1611                                      LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
1612                                      DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1613 {
1614     FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1615 
1616     return FALSE;
1617 }
1618 
1619 /******************************************************************************
1620  * QueryServiceLockStatusW [ADVAPI32.@]
1621  */
1622 BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager,
1623                                      LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
1624                                      DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1625 {
1626     FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1627 
1628     return FALSE;
1629 }
1630 
1631 /******************************************************************************
1632  * GetServiceDisplayNameA  [ADVAPI32.@]
1633  */
1634 BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1635   LPSTR lpDisplayName, LPDWORD lpcchBuffer)
1636 {
1637     LPWSTR lpServiceNameW, lpDisplayNameW;
1638     DWORD sizeW;
1639     BOOL ret = FALSE;
1640 
1641     TRACE("%p %s %p %p\n", hSCManager,
1642           debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
1643 
1644     lpServiceNameW = SERV_dup(lpServiceName);
1645     if (lpDisplayName)
1646         lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1647     else
1648         lpDisplayNameW = NULL;
1649 
1650     sizeW = *lpcchBuffer;
1651     if (!GetServiceDisplayNameW(hSCManager, lpServiceNameW, lpDisplayNameW, &sizeW))
1652     {
1653         if (lpDisplayName && *lpcchBuffer)
1654             lpDisplayName[0] = 0;
1655         *lpcchBuffer = sizeW*2;  /* we can only provide an upper estimation of string length */
1656         goto cleanup;
1657     }
1658 
1659     if (!WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, (sizeW + 1), lpDisplayName,
1660                         *lpcchBuffer, NULL, NULL ))
1661     {
1662         if (*lpcchBuffer && lpDisplayName)
1663             lpDisplayName[0] = 0;
1664         *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, -1, NULL, 0, NULL, NULL);
1665         goto cleanup;
1666     }
1667 
1668     /* probably due to a bug GetServiceDisplayNameA doesn't modify lpcchBuffer on success.
1669      * (but if the function succeeded it means that is a good upper estimation of the size) */
1670     ret = TRUE;
1671 
1672 cleanup:
1673     HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1674     HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1675     return ret;
1676 }
1677 
1678 /******************************************************************************
1679  * GetServiceDisplayNameW  [ADVAPI32.@]
1680  */
1681 BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1682   LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
1683 {
1684     DWORD err;
1685     WCHAR buffer[2];
1686 
1687     TRACE("%p %s %p %p\n", hSCManager,
1688           debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1689 
1690     if (!hSCManager)
1691     {
1692         SetLastError( ERROR_INVALID_HANDLE );
1693         return 0;
1694     }
1695 
1696     /* provide a buffer if the caller didn't */
1697     if (!lpDisplayName || *lpcchBuffer < 2)
1698     {
1699         lpDisplayName = buffer;
1700         /* A size of 1 would be enough, but tests show that Windows returns 2,
1701          * probably because of a WCHAR/bytes mismatch in their code.
1702          */
1703         *lpcchBuffer = 2;
1704     }
1705 
1706     __TRY
1707     {
1708         err = svcctl_GetServiceDisplayNameW(hSCManager, lpServiceName, lpDisplayName,
1709                                             *lpcchBuffer, lpcchBuffer);
1710     }
1711     __EXCEPT(rpc_filter)
1712     {
1713         err = map_exception_code(GetExceptionCode());
1714     }
1715     __ENDTRY
1716 
1717     if (err)
1718         SetLastError(err);
1719     return err == ERROR_SUCCESS;
1720 }
1721 
1722 /******************************************************************************
1723  * ChangeServiceConfigW  [ADVAPI32.@]
1724  */
1725 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
1726   DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1727   LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
1728   LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
1729 {
1730     DWORD cb_pwd;
1731     DWORD err;
1732 
1733     TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
1734           hService, dwServiceType, dwStartType, dwErrorControl, 
1735           debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
1736           lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
1737           debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
1738 
1739     cb_pwd = lpPassword ? (strlenW(lpPassword) + 1)*sizeof(WCHAR) : 0;
1740 
1741     __TRY
1742     {
1743         err = svcctl_ChangeServiceConfigW(hService, dwServiceType,
1744                 dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId,
1745                 (const BYTE *)lpDependencies, multisz_cb(lpDependencies), lpServiceStartName,
1746                 (const BYTE *)lpPassword, cb_pwd, lpDisplayName);
1747     }
1748     __EXCEPT(rpc_filter)
1749     {
1750         err = map_exception_code(GetExceptionCode());
1751     }
1752     __ENDTRY
1753 
1754     if (err != ERROR_SUCCESS)
1755         SetLastError(err);
1756 
1757     return err == ERROR_SUCCESS;
1758 }
1759 
1760 /******************************************************************************
1761  * ChangeServiceConfigA  [ADVAPI32.@]
1762  */
1763 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
1764   DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1765   LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
1766   LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
1767 {
1768     LPWSTR wBinaryPathName, wLoadOrderGroup, wDependencies;
1769     LPWSTR wServiceStartName, wPassword, wDisplayName;
1770     BOOL r;
1771 
1772     TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
1773           hService, dwServiceType, dwStartType, dwErrorControl, 
1774           debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
1775           lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
1776           debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
1777 
1778     wBinaryPathName = SERV_dup( lpBinaryPathName );
1779     wLoadOrderGroup = SERV_dup( lpLoadOrderGroup );
1780     wDependencies = SERV_dupmulti( lpDependencies );
1781     wServiceStartName = SERV_dup( lpServiceStartName );
1782     wPassword = SERV_dup( lpPassword );
1783     wDisplayName = SERV_dup( lpDisplayName );
1784 
1785     r = ChangeServiceConfigW( hService, dwServiceType,
1786             dwStartType, dwErrorControl, wBinaryPathName,
1787             wLoadOrderGroup, lpdwTagId, wDependencies,
1788             wServiceStartName, wPassword, wDisplayName);
1789 
1790     HeapFree( GetProcessHeap(), 0, wBinaryPathName );
1791     HeapFree( GetProcessHeap(), 0, wLoadOrderGroup );
1792     HeapFree( GetProcessHeap(), 0, wDependencies );
1793     HeapFree( GetProcessHeap(), 0, wServiceStartName );
1794     HeapFree( GetProcessHeap(), 0, wPassword );
1795     HeapFree( GetProcessHeap(), 0, wDisplayName );
1796 
1797     return r;
1798 }
1799 
1800 /******************************************************************************
1801  * ChangeServiceConfig2A  [ADVAPI32.@]
1802  */
1803 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel, 
1804     LPVOID lpInfo)
1805 {
1806     BOOL r = FALSE;
1807 
1808     TRACE("%p %d %p\n",hService, dwInfoLevel, lpInfo);
1809 
1810     if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
1811     {
1812         LPSERVICE_DESCRIPTIONA sd = lpInfo;
1813         SERVICE_DESCRIPTIONW sdw;
1814 
1815         sdw.lpDescription = SERV_dup( sd->lpDescription );
1816 
1817         r = ChangeServiceConfig2W( hService, dwInfoLevel, &sdw );
1818 
1819         HeapFree( GetProcessHeap(), 0, sdw.lpDescription );
1820     }
1821     else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
1822     {
1823         LPSERVICE_FAILURE_ACTIONSA fa = lpInfo;
1824         SERVICE_FAILURE_ACTIONSW faw;
1825 
1826         faw.dwResetPeriod = fa->dwResetPeriod;
1827         faw.lpRebootMsg = SERV_dup( fa->lpRebootMsg );
1828         faw.lpCommand = SERV_dup( fa->lpCommand );
1829         faw.cActions = fa->cActions;
1830         faw.lpsaActions = fa->lpsaActions;
1831 
1832         r = ChangeServiceConfig2W( hService, dwInfoLevel, &faw );
1833 
1834         HeapFree( GetProcessHeap(), 0, faw.lpRebootMsg );
1835         HeapFree( GetProcessHeap(), 0, faw.lpCommand );
1836     }
1837     else
1838         SetLastError( ERROR_INVALID_PARAMETER );
1839 
1840     return r;
1841 }
1842 
1843 /******************************************************************************
1844  * ChangeServiceConfig2W  [ADVAPI32.@]
1845  */
1846 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel, 
1847     LPVOID lpInfo)
1848 {
1849     DWORD err;
1850 
1851     __TRY
1852     {
1853         err = svcctl_ChangeServiceConfig2W( hService, dwInfoLevel, lpInfo );
1854     }
1855     __EXCEPT(rpc_filter)
1856     {
1857         err = map_exception_code(GetExceptionCode());
1858     }
1859     __ENDTRY
1860 
1861     if (err != ERROR_SUCCESS)
1862         SetLastError(err);
1863 
1864     return err == ERROR_SUCCESS;
1865 }
1866 
1867 /******************************************************************************
1868  * QueryServiceObjectSecurity [ADVAPI32.@]
1869  */
1870 BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService,
1871        SECURITY_INFORMATION dwSecurityInformation,
1872        PSECURITY_DESCRIPTOR lpSecurityDescriptor,
1873        DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1874 {
1875     SECURITY_DESCRIPTOR descriptor;
1876     DWORD size;
1877     BOOL succ;
1878     ACL acl;
1879 
1880     FIXME("%p %d %p %u %p - semi-stub\n", hService, dwSecurityInformation,
1881           lpSecurityDescriptor, cbBufSize, pcbBytesNeeded);
1882 
1883     if (dwSecurityInformation != DACL_SECURITY_INFORMATION)
1884         FIXME("information %d not supported\n", dwSecurityInformation);
1885 
1886     InitializeSecurityDescriptor(&descriptor, SECURITY_DESCRIPTOR_REVISION);
1887 
1888     InitializeAcl(&acl, sizeof(ACL), ACL_REVISION);
1889     SetSecurityDescriptorDacl(&descriptor, TRUE, &acl, TRUE);
1890 
1891     size = cbBufSize;
1892     succ = MakeSelfRelativeSD(&descriptor, lpSecurityDescriptor, &size);
1893     *pcbBytesNeeded = size;
1894     return succ;
1895 }
1896 
1897 /******************************************************************************
1898  * SetServiceObjectSecurity [ADVAPI32.@]
1899  */
1900 BOOL WINAPI SetServiceObjectSecurity(SC_HANDLE hService,
1901        SECURITY_INFORMATION dwSecurityInformation,
1902        PSECURITY_DESCRIPTOR lpSecurityDescriptor)
1903 {
1904     FIXME("%p %d %p\n", hService, dwSecurityInformation, lpSecurityDescriptor);
1905     return TRUE;
1906 }
1907 
1908 /******************************************************************************
1909  * SetServiceBits [ADVAPI32.@]
1910  */
1911 BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus,
1912         DWORD dwServiceBits,
1913         BOOL bSetBitsOn,
1914         BOOL bUpdateImmediately)
1915 {
1916     FIXME("%p %08x %x %x\n", hServiceStatus, dwServiceBits,
1917           bSetBitsOn, bUpdateImmediately);
1918     return TRUE;
1919 }
1920 
1921 /* thunk for calling the RegisterServiceCtrlHandler handler function */
1922 static DWORD WINAPI ctrl_handler_thunk( DWORD control, DWORD type, void *data, void *context )
1923 {
1924     LPHANDLER_FUNCTION func = context;
1925 
1926     func( control );
1927     return ERROR_SUCCESS;
1928 }
1929 
1930 /******************************************************************************
1931  * RegisterServiceCtrlHandlerA [ADVAPI32.@]
1932  */
1933 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerA( LPCSTR name, LPHANDLER_FUNCTION handler )
1934 {
1935     return RegisterServiceCtrlHandlerExA( name, ctrl_handler_thunk, handler );
1936 }
1937 
1938 /******************************************************************************
1939  * RegisterServiceCtrlHandlerW [ADVAPI32.@]
1940  */
1941 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW( LPCWSTR name, LPHANDLER_FUNCTION handler )
1942 {
1943     return RegisterServiceCtrlHandlerExW( name, ctrl_handler_thunk, handler );
1944 }
1945 
1946 /******************************************************************************
1947  * RegisterServiceCtrlHandlerExA [ADVAPI32.@]
1948  */
1949 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA( LPCSTR name, LPHANDLER_FUNCTION_EX handler, LPVOID context )
1950 {
1951     LPWSTR nameW;
1952     SERVICE_STATUS_HANDLE ret;
1953 
1954     nameW = SERV_dup(name);
1955     ret = RegisterServiceCtrlHandlerExW( nameW, handler, context );
1956     HeapFree( GetProcessHeap(), 0, nameW );
1957     return ret;
1958 }
1959 
1960 /******************************************************************************
1961  * RegisterServiceCtrlHandlerExW [ADVAPI32.@]
1962  */
1963 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceName,
1964         LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext )
1965 {
1966     service_data *service;
1967     SC_HANDLE hService = 0;
1968     BOOL found = FALSE;
1969 
1970     TRACE("%s %p %p\n", debugstr_w(lpServiceName), lpHandlerProc, lpContext);
1971 
1972     EnterCriticalSection( &service_cs );
1973     if ((service = find_service_by_name( lpServiceName )))
1974     {
1975         service->handler = lpHandlerProc;
1976         service->context = lpContext;
1977         hService = service->handle;
1978         found = TRUE;
1979     }
1980     LeaveCriticalSection( &service_cs );
1981 
1982     if (!found) SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
1983 
1984     return (SERVICE_STATUS_HANDLE)hService;
1985 }
1986 
1987 /******************************************************************************
1988  * EnumDependentServicesA [ADVAPI32.@]
1989  */
1990 BOOL WINAPI EnumDependentServicesA( SC_HANDLE hService, DWORD dwServiceState,
1991                                     LPENUM_SERVICE_STATUSA lpServices, DWORD cbBufSize,
1992         LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
1993 {
1994     FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
1995           lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
1996 
1997     *lpServicesReturned = 0;
1998     return TRUE;
1999 }
2000 
2001 /******************************************************************************
2002  * EnumDependentServicesW [ADVAPI32.@]
2003  */
2004 BOOL WINAPI EnumDependentServicesW( SC_HANDLE hService, DWORD dwServiceState,
2005                                     LPENUM_SERVICE_STATUSW lpServices, DWORD cbBufSize,
2006                                     LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2007 {
2008     FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2009           lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2010 
2011     *lpServicesReturned = 0;
2012     return TRUE;
2013 }
2014 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.