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
33 #include "wine/unicode.h"
34 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(advapi
);
41 static const WCHAR szServiceManagerKey
[] = { 'S','y','s','t','e','m','\\',
42 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
43 'S','e','r','v','i','c','e','s',0 };
44 static const WCHAR szSCMLock
[] = {'A','D','V','A','P','I','_','S','C','M',
47 typedef struct service_start_info_t
54 #define WINESERV_STARTINFO 1
55 #define WINESERV_GETSTATUS 2
56 #define WINESERV_SENDCONTROL 3
57 #define WINESERV_SETPID 4
59 typedef struct service_data_t
61 struct service_data_t
*next
;
63 LPHANDLER_FUNCTION handler
;
64 LPHANDLER_FUNCTION_EX handler_ex
;
67 SERVICE_STATUS_PROCESS status
;
70 BOOL extended
: 1; /* uses handler_ex instead of handler? */
72 LPSERVICE_MAIN_FUNCTIONA a
;
73 LPSERVICE_MAIN_FUNCTIONW w
;
79 static CRITICAL_SECTION service_cs
;
80 static CRITICAL_SECTION_DEBUG service_cs_debug
=
83 { &service_cs_debug
.ProcessLocksList
,
84 &service_cs_debug
.ProcessLocksList
},
85 0, 0, { (DWORD_PTR
)(__FILE__
": service_cs") }
87 static CRITICAL_SECTION service_cs
= { &service_cs_debug
, -1, 0, 0, 0, 0 };
89 static service_data
*service_list
;
91 /******************************************************************************
95 #define MAX_SERVICE_NAME 256
97 typedef enum { SC_HTYPE_MANAGER
, SC_HTYPE_SERVICE
} SC_HANDLE_TYPE
;
100 typedef VOID (*sc_handle_destructor
)(struct sc_handle
*);
104 SC_HANDLE_TYPE htype
;
106 sc_handle_destructor destroy
;
109 struct sc_manager
/* service control manager handle */
111 struct sc_handle hdr
;
112 HKEY hkey
; /* handle to services database in the registry */
116 struct sc_service
/* service handle */
118 struct sc_handle hdr
;
119 HKEY hkey
; /* handle to service entry in the registry (under hkey) */
121 struct sc_manager
*scm
; /* pointer to SCM handle */
125 static void *sc_handle_alloc(SC_HANDLE_TYPE htype
, DWORD size
,
126 sc_handle_destructor destroy
)
128 struct sc_handle
*hdr
;
130 hdr
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
135 hdr
->destroy
= destroy
;
137 TRACE("sc_handle type=%d -> %p\n", htype
, hdr
);
141 static void *sc_handle_get_handle_data(SC_HANDLE handle
, DWORD htype
)
143 struct sc_handle
*hdr
= (struct sc_handle
*) handle
;
147 if (hdr
->htype
!= htype
)
152 static void sc_handle_free(struct sc_handle
* hdr
)
156 if (--hdr
->ref_count
)
159 HeapFree(GetProcessHeap(), 0, hdr
);
162 static void sc_handle_destroy_manager(struct sc_handle
*handle
)
164 struct sc_manager
*mgr
= (struct sc_manager
*) handle
;
166 TRACE("destroying SC Manager %p\n", mgr
);
168 RegCloseKey(mgr
->hkey
);
171 static void sc_handle_destroy_service(struct sc_handle
*handle
)
173 struct sc_service
*svc
= (struct sc_service
*) handle
;
175 TRACE("destroying service %p\n", svc
);
177 RegCloseKey(svc
->hkey
);
179 sc_handle_free(&svc
->scm
->hdr
);
183 /******************************************************************************
184 * String management functions
186 static inline LPWSTR
SERV_dup( LPCSTR str
)
193 len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
194 wstr
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof (WCHAR
) );
195 MultiByteToWideChar( CP_ACP
, 0, str
, -1, wstr
, len
);
199 static inline LPWSTR
SERV_dupmulti(LPCSTR str
)
207 len
+= MultiByteToWideChar( CP_ACP
, 0, &str
[n
], -1, NULL
, 0 );
208 n
+= (strlen( &str
[n
] ) + 1);
213 wstr
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof (WCHAR
) );
214 MultiByteToWideChar( CP_ACP
, 0, str
, n
, wstr
, len
);
218 static inline VOID
SERV_free( LPWSTR wstr
)
220 HeapFree( GetProcessHeap(), 0, wstr
);
223 /******************************************************************************
224 * registry access functions and data
226 static const WCHAR szDisplayName
[] = {
227 'D','i','s','p','l','a','y','N','a','m','e', 0 };
228 static const WCHAR szType
[] = {'T','y','p','e',0};
229 static const WCHAR szStart
[] = {'S','t','a','r','t',0};
230 static const WCHAR szError
[] = {
231 'E','r','r','o','r','C','o','n','t','r','o','l', 0};
232 static const WCHAR szImagePath
[] = {'I','m','a','g','e','P','a','t','h',0};
233 static const WCHAR szGroup
[] = {'G','r','o','u','p',0};
234 static const WCHAR szDependencies
[] = {
235 'D','e','p','e','n','d','e','n','c','i','e','s',0};
236 static const WCHAR szDependOnService
[] = {
237 'D','e','p','e','n','d','O','n','S','e','r','v','i','c','e',0};
246 static inline void service_set_value( struct reg_value
*val
,
247 DWORD type
, LPCWSTR name
, LPCVOID data
, DWORD size
)
255 static inline void service_set_dword( struct reg_value
*val
,
256 LPCWSTR name
, const DWORD
*data
)
258 service_set_value( val
, REG_DWORD
, name
, data
, sizeof (DWORD
));
261 static inline void service_set_string( struct reg_value
*val
,
262 LPCWSTR name
, LPCWSTR string
)
264 DWORD len
= (lstrlenW(string
)+1) * sizeof (WCHAR
);
265 service_set_value( val
, REG_SZ
, name
, string
, len
);
268 static inline void service_set_multi_string( struct reg_value
*val
,
269 LPCWSTR name
, LPCWSTR string
)
273 /* determine the length of a double null terminated multi string */
275 len
+= (lstrlenW( &string
[ len
] )+1);
276 } while ( string
[ len
++ ] );
278 len
*= sizeof (WCHAR
);
279 service_set_value( val
, REG_MULTI_SZ
, name
, string
, len
);
282 static inline LONG
service_write_values( HKEY hKey
,
283 const struct reg_value
*val
, int n
)
285 LONG r
= ERROR_SUCCESS
;
290 r
= RegSetValueExW(hKey
, val
[i
].name
, 0, val
[i
].type
,
291 (const BYTE
*)val
[i
].data
, val
[i
].size
);
292 if( r
!= ERROR_SUCCESS
)
298 /******************************************************************************
299 * Service IPC functions
301 static LPWSTR
service_get_pipe_name(LPCWSTR service
)
303 static const WCHAR prefix
[] = { '\\','\\','.','\\','p','i','p','e','\\',
304 '_','_','w','i','n','e','s','e','r','v','i','c','e','_',0};
308 len
= sizeof prefix
+ strlenW(service
)*sizeof(WCHAR
);
309 name
= HeapAlloc(GetProcessHeap(), 0, len
);
310 strcpyW(name
, prefix
);
311 strcatW(name
, service
);
315 static HANDLE
service_open_pipe(LPCWSTR service
)
317 LPWSTR szPipe
= service_get_pipe_name( service
);
318 HANDLE handle
= INVALID_HANDLE_VALUE
;
321 handle
= CreateFileW(szPipe
, GENERIC_READ
|GENERIC_WRITE
,
322 0, NULL
, OPEN_ALWAYS
, 0, NULL
);
323 if (handle
!= INVALID_HANDLE_VALUE
)
325 if (GetLastError() != ERROR_PIPE_BUSY
)
327 } while (WaitNamedPipeW(szPipe
, NMPWAIT_WAIT_FOREVER
));
333 /******************************************************************************
334 * service_get_event_handle
336 static HANDLE
service_get_event_handle(LPCWSTR service
)
338 static const WCHAR prefix
[] = {
339 '_','_','w','i','n','e','s','e','r','v','i','c','e','_',0};
344 len
= sizeof prefix
+ strlenW(service
)*sizeof(WCHAR
);
345 name
= HeapAlloc(GetProcessHeap(), 0, len
);
346 strcpyW(name
, prefix
);
347 strcatW(name
, service
);
348 handle
= CreateEventW(NULL
, TRUE
, FALSE
, name
);
353 /******************************************************************************
356 * Call into the main service routine provided by StartServiceCtrlDispatcher.
358 static DWORD WINAPI
service_thread(LPVOID arg
)
360 service_data
*info
= arg
;
361 LPWSTR str
= info
->args
;
362 DWORD argc
= 0, len
= 0;
368 len
+= strlenW(&str
[len
]) + 1;
375 info
->proc
.w(0, NULL
);
377 info
->proc
.a(0, NULL
);
385 argv
= HeapAlloc(GetProcessHeap(), 0, (argc
+1)*sizeof(LPWSTR
));
386 for (argc
=0, p
=str
; *p
; p
+= strlenW(p
) + 1)
390 info
->proc
.w(argc
, argv
);
391 HeapFree(GetProcessHeap(), 0, argv
);
395 LPSTR strA
, *argv
, p
;
398 lenA
= WideCharToMultiByte(CP_ACP
,0, str
, len
, NULL
, 0, NULL
, NULL
);
399 strA
= HeapAlloc(GetProcessHeap(), 0, lenA
);
400 WideCharToMultiByte(CP_ACP
,0, str
, len
, strA
, lenA
, NULL
, NULL
);
402 argv
= HeapAlloc(GetProcessHeap(), 0, (argc
+1)*sizeof(LPSTR
));
403 for (argc
=0, p
=strA
; *p
; p
+= strlen(p
) + 1)
407 info
->proc
.a(argc
, argv
);
408 HeapFree(GetProcessHeap(), 0, argv
);
409 HeapFree(GetProcessHeap(), 0, strA
);
414 /******************************************************************************
415 * service_handle_start
417 static BOOL
service_handle_start(HANDLE pipe
, service_data
*service
, DWORD count
)
419 DWORD read
= 0, result
= 0;
423 TRACE("%p %p %d\n", pipe
, service
, count
);
425 args
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
426 r
= ReadFile(pipe
, args
, count
*sizeof(WCHAR
), &read
, NULL
);
427 if (!r
|| count
!=read
/sizeof(WCHAR
) || args
[count
-1])
429 ERR("pipe read failed r = %d count = %d read = %d args[n-1]=%s\n",
430 r
, count
, read
, debugstr_wn(args
, count
));
436 ERR("service is not stopped\n");
440 SERV_free(service
->args
);
441 service
->args
= args
;
443 service
->thread
= CreateThread( NULL
, 0, service_thread
,
447 HeapFree(GetProcessHeap(), 0, args
);
448 WriteFile( pipe
, &result
, sizeof result
, &read
, NULL
);
453 /******************************************************************************
454 * service_send_start_message
456 static BOOL
service_send_start_message(HANDLE pipe
, LPCWSTR
*argv
, DWORD argc
)
458 DWORD i
, len
, count
, result
;
459 service_start_info
*ssi
;
463 TRACE("%p %p %d\n", pipe
, argv
, argc
);
465 /* calculate how much space do we need to send the startup info */
467 for (i
=0; i
<argc
; i
++)
468 len
+= strlenW(argv
[i
])+1;
470 ssi
= HeapAlloc(GetProcessHeap(),0,sizeof *ssi
+ (len
-1)*sizeof(WCHAR
));
471 ssi
->cmd
= WINESERV_STARTINFO
;
474 /* copy service args into a single buffer*/
476 for (i
=0; i
<argc
; i
++)
483 r
= WriteFile(pipe
, ssi
, sizeof *ssi
+ len
*sizeof(WCHAR
), &count
, NULL
);
485 r
= ReadFile(pipe
, &result
, sizeof result
, &count
, NULL
);
487 HeapFree(GetProcessHeap(),0,ssi
);
492 /******************************************************************************
493 * service_handle_get_status
495 static BOOL
service_handle_get_status(HANDLE pipe
, const service_data
*service
)
499 return WriteFile(pipe
, &service
->status
,
500 sizeof service
->status
, &count
, NULL
);
503 /******************************************************************************
506 static BOOL
service_get_status(HANDLE pipe
, LPSERVICE_STATUS_PROCESS status
)
508 DWORD cmd
[2], count
= 0;
511 cmd
[0] = WINESERV_GETSTATUS
;
513 r
= WriteFile( pipe
, cmd
, sizeof cmd
, &count
, NULL
);
514 if (!r
|| count
!= sizeof cmd
)
516 ERR("service protocol error - failed to write pipe!\n");
519 r
= ReadFile( pipe
, status
, sizeof *status
, &count
, NULL
);
520 if (!r
|| count
!= sizeof *status
)
521 ERR("service protocol error - failed to read pipe "
522 "r = %d count = %d!\n", r
, count
);
526 /******************************************************************************
527 * service_handle_set_processID
529 static BOOL
service_handle_set_processID(HANDLE pipe
, service_data
*service
, DWORD dwProcessId
)
531 DWORD count
, ret
= ERROR_SUCCESS
;
533 TRACE("received control %d\n", dwProcessId
);
534 service
->status
.dwProcessId
= dwProcessId
;
535 return WriteFile(pipe
, &ret
, sizeof ret
, &count
, NULL
);
538 /******************************************************************************
539 * service_set_processID
541 static BOOL
service_set_processID(HANDLE pipe
, DWORD dwprocessId
, LPDWORD dwResult
)
543 DWORD cmd
[2], count
= 0;
546 cmd
[0] = WINESERV_SETPID
;
547 cmd
[1] = dwprocessId
;
548 r
= WriteFile( pipe
, cmd
, sizeof cmd
, &count
, NULL
);
549 if (!r
|| count
!= sizeof cmd
)
551 ERR("service protocol error - failed to write pipe!\n");
554 r
= ReadFile( pipe
, dwResult
, sizeof *dwResult
, &count
, NULL
);
555 if (!r
|| count
!= sizeof *dwResult
)
556 ERR("service protocol error - failed to read pipe "
557 "r = %d count = %d!\n", r
, count
);
561 /******************************************************************************
562 * service_send_control
564 static BOOL
service_send_control(HANDLE pipe
, DWORD dwControl
, DWORD
*result
)
566 DWORD cmd
[2], count
= 0;
569 cmd
[0] = WINESERV_SENDCONTROL
;
571 r
= WriteFile(pipe
, cmd
, sizeof cmd
, &count
, NULL
);
572 if (!r
|| count
!= sizeof cmd
)
574 ERR("service protocol error - failed to write pipe!\n");
577 r
= ReadFile(pipe
, result
, sizeof *result
, &count
, NULL
);
578 if (!r
|| count
!= sizeof *result
)
579 ERR("service protocol error - failed to read pipe "
580 "r = %d count = %d!\n", r
, count
);
584 /******************************************************************************
585 * service_accepts_control
587 static BOOL
service_accepts_control(const service_data
*service
, DWORD dwControl
)
589 DWORD a
= service
->status
.dwControlsAccepted
;
593 case SERVICE_CONTROL_INTERROGATE
:
595 case SERVICE_CONTROL_STOP
:
596 if (a
&SERVICE_ACCEPT_STOP
)
599 case SERVICE_CONTROL_SHUTDOWN
:
600 if (a
&SERVICE_ACCEPT_SHUTDOWN
)
603 case SERVICE_CONTROL_PAUSE
:
604 case SERVICE_CONTROL_CONTINUE
:
605 if (a
&SERVICE_ACCEPT_PAUSE_CONTINUE
)
608 case SERVICE_CONTROL_PARAMCHANGE
:
609 if (a
&SERVICE_ACCEPT_PARAMCHANGE
)
612 case SERVICE_CONTROL_NETBINDADD
:
613 case SERVICE_CONTROL_NETBINDREMOVE
:
614 case SERVICE_CONTROL_NETBINDENABLE
:
615 case SERVICE_CONTROL_NETBINDDISABLE
:
616 if (a
&SERVICE_ACCEPT_NETBINDCHANGE
)
619 if (!service
->extended
)
623 case SERVICE_CONTROL_HARDWAREPROFILECHANGE
:
624 if (a
&SERVICE_ACCEPT_HARDWAREPROFILECHANGE
)
627 case SERVICE_CONTROL_POWEREVENT
:
628 if (a
&SERVICE_ACCEPT_POWEREVENT
)
631 case SERVICE_CONTROL_SESSIONCHANGE
:
632 if (a
&SERVICE_ACCEPT_SESSIONCHANGE
)
639 /******************************************************************************
640 * service_handle_control
642 static BOOL
service_handle_control(HANDLE pipe
, service_data
*service
,
645 DWORD count
, ret
= ERROR_INVALID_SERVICE_CONTROL
;
647 TRACE("received control %d\n", dwControl
);
649 if (service_accepts_control(service
, dwControl
))
651 if (service
->extended
&& service
->handler
.handler_ex
)
653 service
->handler
.handler_ex(dwControl
, 0, NULL
, service
->context
);
656 else if (service
->handler
.handler
)
658 service
->handler
.handler(dwControl
);
662 return WriteFile(pipe
, &ret
, sizeof ret
, &count
, NULL
);
665 /******************************************************************************
666 * service_reap_thread
668 static DWORD
service_reap_thread(service_data
*service
)
672 if (!service
->thread
)
674 GetExitCodeThread(service
->thread
, &exitcode
);
675 if (exitcode
!=STILL_ACTIVE
)
677 CloseHandle(service
->thread
);
683 /******************************************************************************
684 * service_control_dispatcher
686 static DWORD WINAPI
service_control_dispatcher(LPVOID arg
)
688 service_data
*service
= arg
;
692 TRACE("%p %s\n", service
, debugstr_w(service
->name
));
694 /* create a pipe to talk to the rest of the world with */
695 name
= service_get_pipe_name(service
->name
);
696 pipe
= CreateNamedPipeW(name
, PIPE_ACCESS_DUPLEX
,
697 PIPE_TYPE_BYTE
|PIPE_WAIT
, 1, 256, 256, 10000, NULL
);
700 /* let the process who started us know we've tried to create a pipe */
701 event
= service_get_event_handle(service
->name
);
705 if (pipe
==INVALID_HANDLE_VALUE
)
707 ERR("failed to create pipe for %s, error = %d\n",
708 debugstr_w(service
->name
), GetLastError());
712 /* dispatcher loop */
716 DWORD count
, req
[2] = {0,0};
718 r
= ConnectNamedPipe(pipe
, NULL
);
719 if (!r
&& GetLastError() != ERROR_PIPE_CONNECTED
)
721 ERR("pipe connect failed\n");
725 r
= ReadFile( pipe
, &req
, sizeof req
, &count
, NULL
);
726 if (!r
|| count
!=sizeof req
)
728 ERR("pipe read failed\n");
732 service_reap_thread(service
);
734 /* handle the request */
737 case WINESERV_STARTINFO
:
738 service_handle_start(pipe
, service
, req
[1]);
740 case WINESERV_GETSTATUS
:
741 service_handle_get_status(pipe
, service
);
743 case WINESERV_SENDCONTROL
:
744 service_handle_control(pipe
, service
, req
[1]);
746 case WINESERV_SETPID
:
747 service_handle_set_processID(pipe
, service
, req
[1]);
750 ERR("received invalid command %d length %d\n", req
[0], req
[1]);
753 FlushFileBuffers(pipe
);
754 DisconnectNamedPipe(pipe
);
761 /******************************************************************************
762 * service_run_threads
764 static BOOL
service_run_threads(void)
766 service_data
*service
;
767 DWORD count
= 0, n
= 0;
770 EnterCriticalSection( &service_cs
);
772 /* count how many services there are */
773 for (service
= service_list
; service
; service
= service
->next
)
776 TRACE("starting %d pipe listener threads\n", count
);
778 handles
= HeapAlloc(GetProcessHeap(), 0, sizeof(HANDLE
)*count
);
780 for (n
=0, service
= service_list
; service
; service
= service
->next
, n
++)
781 handles
[n
] = CreateThread( NULL
, 0, service_control_dispatcher
,
785 LeaveCriticalSection( &service_cs
);
787 /* wait for all the threads to pack up and exit */
788 WaitForMultipleObjectsEx(count
, handles
, TRUE
, INFINITE
, FALSE
);
790 HeapFree(GetProcessHeap(), 0, handles
);
795 /******************************************************************************
796 * StartServiceCtrlDispatcherA [ADVAPI32.@]
798 * See StartServiceCtrlDispatcherW.
800 BOOL WINAPI
StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA
*servent
)
806 TRACE("%p\n", servent
);
808 EnterCriticalSection( &service_cs
);
809 while (servent
->lpServiceName
)
811 LPSTR name
= servent
->lpServiceName
;
813 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0);
814 sz
= len
*sizeof(WCHAR
) + sizeof *info
;
815 info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sz
);
816 MultiByteToWideChar(CP_ACP
, 0, name
, -1, info
->name
, len
);
817 info
->proc
.a
= servent
->lpServiceProc
;
818 info
->unicode
= FALSE
;
820 /* insert into the list */
821 info
->next
= service_list
;
826 LeaveCriticalSection( &service_cs
);
828 service_run_threads();
833 /******************************************************************************
834 * StartServiceCtrlDispatcherW [ADVAPI32.@]
836 * Connects a process containing one or more services to the service control
840 * servent [I] A list of the service names and service procedures
846 BOOL WINAPI
StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW
*servent
)
852 TRACE("%p\n", servent
);
854 EnterCriticalSection( &service_cs
);
855 while (servent
->lpServiceName
)
857 LPWSTR name
= servent
->lpServiceName
;
860 sz
= len
*sizeof(WCHAR
) + sizeof *info
;
861 info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sz
);
862 strcpyW(info
->name
, name
);
863 info
->proc
.w
= servent
->lpServiceProc
;
864 info
->unicode
= TRUE
;
866 /* insert into the list */
867 info
->next
= service_list
;
872 LeaveCriticalSection( &service_cs
);
874 service_run_threads();
879 /******************************************************************************
880 * LockServiceDatabase [ADVAPI32.@]
882 SC_LOCK WINAPI
LockServiceDatabase (SC_HANDLE hSCManager
)
886 TRACE("%p\n",hSCManager
);
888 ret
= CreateSemaphoreW( NULL
, 1, 1, szSCMLock
);
889 if( ret
&& GetLastError() == ERROR_ALREADY_EXISTS
)
893 SetLastError( ERROR_SERVICE_DATABASE_LOCKED
);
896 TRACE("returning %p\n", ret
);
901 /******************************************************************************
902 * UnlockServiceDatabase [ADVAPI32.@]
904 BOOL WINAPI
UnlockServiceDatabase (SC_LOCK ScLock
)
906 TRACE("%p\n",ScLock
);
908 return CloseHandle( ScLock
);
911 /******************************************************************************
912 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
914 SERVICE_STATUS_HANDLE WINAPI
915 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName
, LPHANDLER_FUNCTION lpfHandler
)
917 LPWSTR lpServiceNameW
;
918 SERVICE_STATUS_HANDLE ret
;
920 lpServiceNameW
= SERV_dup(lpServiceName
);
921 ret
= RegisterServiceCtrlHandlerW( lpServiceNameW
, lpfHandler
);
922 SERV_free(lpServiceNameW
);
926 /******************************************************************************
927 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
933 SERVICE_STATUS_HANDLE WINAPI
RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName
,
934 LPHANDLER_FUNCTION lpfHandler
)
936 service_data
*service
;
938 EnterCriticalSection( &service_cs
);
939 for(service
= service_list
; service
; service
= service
->next
)
940 if(!strcmpW(lpServiceName
, service
->name
))
943 service
->handler
.handler
= lpfHandler
;
944 LeaveCriticalSection( &service_cs
);
946 return (SERVICE_STATUS_HANDLE
)service
;
949 /******************************************************************************
950 * SetServiceStatus [ADVAPI32.@]
957 SetServiceStatus( SERVICE_STATUS_HANDLE hService
, LPSERVICE_STATUS lpStatus
)
959 service_data
*service
;
962 TRACE("%p %x %x %x %x %x %x %x\n", hService
,
963 lpStatus
->dwServiceType
, lpStatus
->dwCurrentState
,
964 lpStatus
->dwControlsAccepted
, lpStatus
->dwWin32ExitCode
,
965 lpStatus
->dwServiceSpecificExitCode
, lpStatus
->dwCheckPoint
,
966 lpStatus
->dwWaitHint
);
968 EnterCriticalSection( &service_cs
);
969 for (service
= service_list
; service
; service
= service
->next
)
970 if(service
== (service_data
*)hService
)
974 memcpy( &service
->status
, lpStatus
, sizeof(SERVICE_STATUS
) );
975 TRACE("Set service status to %d\n",service
->status
.dwCurrentState
);
979 LeaveCriticalSection( &service_cs
);
985 /******************************************************************************
986 * OpenSCManagerA [ADVAPI32.@]
988 * Establish a connection to the service control manager and open its database.
991 * lpMachineName [I] Pointer to machine name string
992 * lpDatabaseName [I] Pointer to database name string
993 * dwDesiredAccess [I] Type of access
996 * Success: A Handle to the service control manager database
999 SC_HANDLE WINAPI
OpenSCManagerA( LPCSTR lpMachineName
, LPCSTR lpDatabaseName
,
1000 DWORD dwDesiredAccess
)
1002 LPWSTR lpMachineNameW
, lpDatabaseNameW
;
1005 lpMachineNameW
= SERV_dup(lpMachineName
);
1006 lpDatabaseNameW
= SERV_dup(lpDatabaseName
);
1007 ret
= OpenSCManagerW(lpMachineNameW
, lpDatabaseNameW
, dwDesiredAccess
);
1008 SERV_free(lpDatabaseNameW
);
1009 SERV_free(lpMachineNameW
);
1013 /******************************************************************************
1014 * OpenSCManagerW [ADVAPI32.@]
1016 * See OpenSCManagerA.
1018 SC_HANDLE WINAPI
OpenSCManagerW( LPCWSTR lpMachineName
, LPCWSTR lpDatabaseName
,
1019 DWORD dwDesiredAccess
)
1021 struct sc_manager
*manager
;
1025 TRACE("(%s,%s,0x%08x)\n", debugstr_w(lpMachineName
),
1026 debugstr_w(lpDatabaseName
), dwDesiredAccess
);
1028 if( lpDatabaseName
&& lpDatabaseName
[0] )
1030 if( strcmpiW( lpDatabaseName
, SERVICES_ACTIVE_DATABASEW
) == 0 )
1032 /* noop, all right */
1034 else if( strcmpiW( lpDatabaseName
, SERVICES_FAILED_DATABASEW
) == 0 )
1036 SetLastError( ERROR_DATABASE_DOES_NOT_EXIST
);
1041 SetLastError( ERROR_INVALID_NAME
);
1046 manager
= sc_handle_alloc( SC_HTYPE_MANAGER
, sizeof (struct sc_manager
),
1047 sc_handle_destroy_manager
);
1051 r
= RegConnectRegistryW(lpMachineName
,HKEY_LOCAL_MACHINE
,&hReg
);
1052 if (r
!=ERROR_SUCCESS
)
1055 r
= RegCreateKeyW(hReg
, szServiceManagerKey
, &manager
->hkey
);
1056 RegCloseKey( hReg
);
1057 if (r
!=ERROR_SUCCESS
)
1060 manager
->dwAccess
= dwDesiredAccess
;
1061 TRACE("returning %p\n", manager
);
1063 return (SC_HANDLE
) &manager
->hdr
;
1066 sc_handle_free( &manager
->hdr
);
1071 /******************************************************************************
1072 * ControlService [ADVAPI32.@]
1074 * Send a control code to a service.
1077 * hService [I] Handle of the service control manager database
1078 * dwControl [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
1079 * lpServiceStatus [O] Destination for the status of the service, if available
1086 * Unlike M$' implementation, control requests are not serialized and may be
1087 * processed asynchronously.
1089 BOOL WINAPI
ControlService( SC_HANDLE hService
, DWORD dwControl
,
1090 LPSERVICE_STATUS lpServiceStatus
)
1092 struct sc_service
*hsvc
;
1096 TRACE("%p %d %p\n", hService
, dwControl
, lpServiceStatus
);
1098 hsvc
= sc_handle_get_handle_data(hService
, SC_HTYPE_SERVICE
);
1101 SetLastError( ERROR_INVALID_HANDLE
);
1105 ret
= QueryServiceStatus(hService
, lpServiceStatus
);
1108 ERR("failed to query service status\n");
1109 SetLastError(ERROR_SERVICE_NOT_ACTIVE
);
1113 switch (lpServiceStatus
->dwCurrentState
)
1115 case SERVICE_STOPPED
:
1116 SetLastError(ERROR_SERVICE_NOT_ACTIVE
);
1118 case SERVICE_START_PENDING
:
1119 if (dwControl
==SERVICE_CONTROL_STOP
)
1122 case SERVICE_STOP_PENDING
:
1123 SetLastError(ERROR_SERVICE_CANNOT_ACCEPT_CTRL
);
1127 handle
= service_open_pipe(hsvc
->name
);
1128 if (handle
!=INVALID_HANDLE_VALUE
)
1130 DWORD result
= ERROR_SUCCESS
;
1131 ret
= service_send_control(handle
, dwControl
, &result
);
1132 CloseHandle(handle
);
1133 if (result
!=ERROR_SUCCESS
)
1135 SetLastError(result
);
1143 /******************************************************************************
1144 * CloseServiceHandle [ADVAPI32.@]
1146 * Close a handle to a service or the service control manager database.
1149 * hSCObject [I] Handle to service or service control manager database
1156 CloseServiceHandle( SC_HANDLE hSCObject
)
1158 TRACE("%p\n", hSCObject
);
1160 sc_handle_free( (struct sc_handle
*) hSCObject
);
1166 /******************************************************************************
1167 * OpenServiceA [ADVAPI32.@]
1169 * Open a handle to a service.
1172 * hSCManager [I] Handle of the service control manager database
1173 * lpServiceName [I] Name of the service to open
1174 * dwDesiredAccess [I] Access required to the service
1177 * Success: Handle to the service
1180 SC_HANDLE WINAPI
OpenServiceA( SC_HANDLE hSCManager
, LPCSTR lpServiceName
,
1181 DWORD dwDesiredAccess
)
1183 LPWSTR lpServiceNameW
;
1186 TRACE("%p %s %d\n", hSCManager
, debugstr_a(lpServiceName
), dwDesiredAccess
);
1188 lpServiceNameW
= SERV_dup(lpServiceName
);
1189 ret
= OpenServiceW( hSCManager
, lpServiceNameW
, dwDesiredAccess
);
1190 SERV_free(lpServiceNameW
);
1195 /******************************************************************************
1196 * OpenServiceW [ADVAPI32.@]
1200 SC_HANDLE WINAPI
OpenServiceW( SC_HANDLE hSCManager
, LPCWSTR lpServiceName
,
1201 DWORD dwDesiredAccess
)
1203 struct sc_manager
*hscm
;
1204 struct sc_service
*hsvc
;
1209 TRACE("%p %s %d\n", hSCManager
, debugstr_w(lpServiceName
), dwDesiredAccess
);
1213 SetLastError(ERROR_INVALID_ADDRESS
);
1217 hscm
= sc_handle_get_handle_data( hSCManager
, SC_HTYPE_MANAGER
);
1220 SetLastError( ERROR_INVALID_HANDLE
);
1224 r
= RegOpenKeyExW( hscm
->hkey
, lpServiceName
, 0, KEY_ALL_ACCESS
, &hKey
);
1225 if (r
!=ERROR_SUCCESS
)
1227 SetLastError( ERROR_SERVICE_DOES_NOT_EXIST
);
1231 len
= strlenW(lpServiceName
)+1;
1232 hsvc
= sc_handle_alloc( SC_HTYPE_SERVICE
,
1233 sizeof (struct sc_service
) + len
*sizeof(WCHAR
),
1234 sc_handle_destroy_service
);
1237 strcpyW( hsvc
->name
, lpServiceName
);
1239 hsvc
->dwAccess
= dwDesiredAccess
;
1241 /* add reference to SCM handle */
1242 hscm
->hdr
.ref_count
++;
1245 TRACE("returning %p\n",hsvc
);
1247 return (SC_HANDLE
) &hsvc
->hdr
;
1250 /******************************************************************************
1251 * CreateServiceW [ADVAPI32.@]
1254 CreateServiceW( SC_HANDLE hSCManager
, LPCWSTR lpServiceName
,
1255 LPCWSTR lpDisplayName
, DWORD dwDesiredAccess
,
1256 DWORD dwServiceType
, DWORD dwStartType
,
1257 DWORD dwErrorControl
, LPCWSTR lpBinaryPathName
,
1258 LPCWSTR lpLoadOrderGroup
, LPDWORD lpdwTagId
,
1259 LPCWSTR lpDependencies
, LPCWSTR lpServiceStartName
,
1260 LPCWSTR lpPassword
)
1262 struct sc_manager
*hscm
;
1263 struct sc_service
*hsvc
= NULL
;
1267 struct reg_value val
[10];
1270 TRACE("%p %s %s\n", hSCManager
,
1271 debugstr_w(lpServiceName
), debugstr_w(lpDisplayName
));
1273 hscm
= sc_handle_get_handle_data( hSCManager
, SC_HTYPE_MANAGER
);
1276 SetLastError( ERROR_INVALID_HANDLE
);
1280 r
= RegCreateKeyExW(hscm
->hkey
, lpServiceName
, 0, NULL
,
1281 REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hKey
, &dp
);
1282 if (r
!=ERROR_SUCCESS
)
1285 if (dp
!= REG_CREATED_NEW_KEY
)
1287 SetLastError(ERROR_SERVICE_EXISTS
);
1292 service_set_string( &val
[n
++], szDisplayName
, lpDisplayName
);
1294 service_set_dword( &val
[n
++], szType
, &dwServiceType
);
1295 service_set_dword( &val
[n
++], szStart
, &dwStartType
);
1296 service_set_dword( &val
[n
++], szError
, &dwErrorControl
);
1298 if( lpBinaryPathName
)
1299 service_set_string( &val
[n
++], szImagePath
, lpBinaryPathName
);
1301 if( lpLoadOrderGroup
)
1302 service_set_string( &val
[n
++], szGroup
, lpLoadOrderGroup
);
1304 if( lpDependencies
)
1305 service_set_multi_string( &val
[n
++], szDependencies
, lpDependencies
);
1308 FIXME("Don't know how to add a Password for a service.\n");
1310 if( lpServiceStartName
)
1311 service_set_string( &val
[n
++], szDependOnService
, lpServiceStartName
);
1313 r
= service_write_values( hKey
, val
, n
);
1314 if( r
!= ERROR_SUCCESS
)
1317 len
= strlenW(lpServiceName
)+1;
1318 len
= sizeof (struct sc_service
) + len
*sizeof(WCHAR
);
1319 hsvc
= sc_handle_alloc( SC_HTYPE_SERVICE
, len
, sc_handle_destroy_service
);
1322 lstrcpyW( hsvc
->name
, lpServiceName
);
1325 hscm
->hdr
.ref_count
++;
1327 return (SC_HANDLE
) &hsvc
->hdr
;
1330 RegCloseKey( hKey
);
1335 /******************************************************************************
1336 * CreateServiceA [ADVAPI32.@]
1339 CreateServiceA( SC_HANDLE hSCManager
, LPCSTR lpServiceName
,
1340 LPCSTR lpDisplayName
, DWORD dwDesiredAccess
,
1341 DWORD dwServiceType
, DWORD dwStartType
,
1342 DWORD dwErrorControl
, LPCSTR lpBinaryPathName
,
1343 LPCSTR lpLoadOrderGroup
, LPDWORD lpdwTagId
,
1344 LPCSTR lpDependencies
, LPCSTR lpServiceStartName
,
1347 LPWSTR lpServiceNameW
, lpDisplayNameW
, lpBinaryPathNameW
,
1348 lpLoadOrderGroupW
, lpDependenciesW
, lpServiceStartNameW
, lpPasswordW
;
1351 TRACE("%p %s %s\n", hSCManager
,
1352 debugstr_a(lpServiceName
), debugstr_a(lpDisplayName
));
1354 lpServiceNameW
= SERV_dup( lpServiceName
);
1355 lpDisplayNameW
= SERV_dup( lpDisplayName
);
1356 lpBinaryPathNameW
= SERV_dup( lpBinaryPathName
);
1357 lpLoadOrderGroupW
= SERV_dup( lpLoadOrderGroup
);
1358 lpDependenciesW
= SERV_dupmulti( lpDependencies
);
1359 lpServiceStartNameW
= SERV_dup( lpServiceStartName
);
1360 lpPasswordW
= SERV_dup( lpPassword
);
1362 r
= CreateServiceW( hSCManager
, lpServiceNameW
, lpDisplayNameW
,
1363 dwDesiredAccess
, dwServiceType
, dwStartType
, dwErrorControl
,
1364 lpBinaryPathNameW
, lpLoadOrderGroupW
, lpdwTagId
,
1365 lpDependenciesW
, lpServiceStartNameW
, lpPasswordW
);
1367 SERV_free( lpServiceNameW
);
1368 SERV_free( lpDisplayNameW
);
1369 SERV_free( lpBinaryPathNameW
);
1370 SERV_free( lpLoadOrderGroupW
);
1371 SERV_free( lpDependenciesW
);
1372 SERV_free( lpServiceStartNameW
);
1373 SERV_free( lpPasswordW
);
1379 /******************************************************************************
1380 * DeleteService [ADVAPI32.@]
1382 * Delete a service from the service control manager database.
1385 * hService [I] Handle of the service to delete
1391 BOOL WINAPI
DeleteService( SC_HANDLE hService
)
1393 struct sc_service
*hsvc
;
1395 WCHAR valname
[MAX_PATH
+1];
1400 hsvc
= sc_handle_get_handle_data(hService
, SC_HTYPE_SERVICE
);
1403 SetLastError( ERROR_INVALID_HANDLE
);
1409 /* Clean out the values */
1410 rc
= RegEnumValueW(hKey
, index
, valname
,&size
,0,0,0,0);
1411 while (rc
== ERROR_SUCCESS
)
1413 RegDeleteValueW(hKey
,valname
);
1416 rc
= RegEnumValueW(hKey
, index
, valname
, &size
,0,0,0,0);
1422 /* delete the key */
1423 RegDeleteKeyW(hsvc
->scm
->hkey
, hsvc
->name
);
1429 /******************************************************************************
1430 * StartServiceA [ADVAPI32.@]
1435 * hService [I] Handle of service
1436 * dwNumServiceArgs [I] Number of arguments
1437 * lpServiceArgVectors [I] Address of array of argument strings
1440 * - NT implements this function using an obscure RPC call.
1441 * - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
1442 * to get things like "%SystemRoot%\\System32\\service.exe" to load.
1443 * - This will only work for shared address space. How should the service
1444 * args be transferred when address spaces are separated?
1445 * - Can only start one service at a time.
1446 * - Has no concept of privilege.
1452 BOOL WINAPI
StartServiceA( SC_HANDLE hService
, DWORD dwNumServiceArgs
,
1453 LPCSTR
*lpServiceArgVectors
)
1455 LPWSTR
*lpwstr
=NULL
;
1459 TRACE("(%p,%d,%p)\n",hService
,dwNumServiceArgs
,lpServiceArgVectors
);
1461 if (dwNumServiceArgs
)
1462 lpwstr
= HeapAlloc( GetProcessHeap(), 0,
1463 dwNumServiceArgs
*sizeof(LPWSTR
) );
1465 for(i
=0; i
<dwNumServiceArgs
; i
++)
1466 lpwstr
[i
]=SERV_dup(lpServiceArgVectors
[i
]);
1468 r
= StartServiceW(hService
, dwNumServiceArgs
, (LPCWSTR
*)lpwstr
);
1470 if (dwNumServiceArgs
)
1472 for(i
=0; i
<dwNumServiceArgs
; i
++)
1473 SERV_free(lpwstr
[i
]);
1474 HeapFree(GetProcessHeap(), 0, lpwstr
);
1480 /******************************************************************************
1481 * service_start_process [INTERNAL]
1483 static DWORD
service_start_process(struct sc_service
*hsvc
, LPDWORD ppid
)
1485 static const WCHAR _ImagePathW
[] = {'I','m','a','g','e','P','a','t','h',0};
1486 PROCESS_INFORMATION pi
;
1488 LPWSTR path
= NULL
, str
;
1489 DWORD type
, size
, ret
, svc_type
;
1493 size
= sizeof(svc_type
);
1494 if (RegQueryValueExW(hsvc
->hkey
, szType
, NULL
, &type
, (LPBYTE
)&svc_type
, &size
) || type
!= REG_DWORD
)
1497 if (svc_type
== SERVICE_KERNEL_DRIVER
)
1499 static const WCHAR winedeviceW
[] = {'\\','w','i','n','e','d','e','v','i','c','e','.','e','x','e',' ',0};
1500 DWORD len
= GetSystemDirectoryW( NULL
, 0 ) + sizeof(winedeviceW
)/sizeof(WCHAR
) + strlenW(hsvc
->name
);
1502 if (!(path
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return FALSE
;
1503 GetSystemDirectoryW( path
, len
);
1504 lstrcatW( path
, winedeviceW
);
1505 lstrcatW( path
, hsvc
->name
);
1509 /* read the executable path from the registry */
1511 ret
= RegQueryValueExW(hsvc
->hkey
, _ImagePathW
, NULL
, &type
, NULL
, &size
);
1512 if (ret
!=ERROR_SUCCESS
)
1514 str
= HeapAlloc(GetProcessHeap(),0,size
);
1515 ret
= RegQueryValueExW(hsvc
->hkey
, _ImagePathW
, NULL
, &type
, (LPBYTE
)str
, &size
);
1516 if (ret
==ERROR_SUCCESS
)
1518 size
= ExpandEnvironmentStringsW(str
,NULL
,0);
1519 path
= HeapAlloc(GetProcessHeap(),0,size
*sizeof(WCHAR
));
1520 ExpandEnvironmentStringsW(str
,path
,size
);
1522 HeapFree(GetProcessHeap(),0,str
);
1527 /* wait for the process to start and set an event or terminate */
1528 handles
[0] = service_get_event_handle( hsvc
->name
);
1529 ZeroMemory(&si
, sizeof(STARTUPINFOW
));
1530 si
.cb
= sizeof(STARTUPINFOW
);
1531 r
= CreateProcessW(NULL
, path
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
1534 if (ppid
) *ppid
= pi
.dwProcessId
;
1536 handles
[1] = pi
.hProcess
;
1537 ret
= WaitForMultipleObjectsEx(2, handles
, FALSE
, 30000, FALSE
);
1538 if(ret
!= WAIT_OBJECT_0
)
1540 SetLastError(ERROR_IO_PENDING
);
1544 CloseHandle( pi
.hThread
);
1545 CloseHandle( pi
.hProcess
);
1547 CloseHandle( handles
[0] );
1548 HeapFree(GetProcessHeap(),0,path
);
1552 static BOOL
service_wait_for_startup(SC_HANDLE hService
)
1555 SERVICE_STATUS status
;
1558 TRACE("%p\n", hService
);
1560 for (i
=0; i
<30; i
++)
1562 status
.dwCurrentState
= 0;
1563 r
= QueryServiceStatus(hService
, &status
);
1566 if (status
.dwCurrentState
== SERVICE_RUNNING
)
1568 TRACE("Service started successfully\n");
1577 /******************************************************************************
1578 * StartServiceW [ADVAPI32.@]
1580 * See StartServiceA.
1582 BOOL WINAPI
StartServiceW(SC_HANDLE hService
, DWORD dwNumServiceArgs
,
1583 LPCWSTR
*lpServiceArgVectors
)
1585 struct sc_service
*hsvc
;
1587 DWORD dwResult
, dwProcessId
= 0;
1589 HANDLE handle
= INVALID_HANDLE_VALUE
;
1591 TRACE("%p %d %p\n", hService
, dwNumServiceArgs
, lpServiceArgVectors
);
1593 hsvc
= sc_handle_get_handle_data(hService
, SC_HTYPE_SERVICE
);
1596 SetLastError(ERROR_INVALID_HANDLE
);
1600 hLock
= LockServiceDatabase((SC_HANDLE
)hsvc
->scm
);
1604 handle
= service_open_pipe(hsvc
->name
);
1605 if (handle
==INVALID_HANDLE_VALUE
)
1607 /* start the service process */
1608 if (service_start_process(hsvc
, &dwProcessId
))
1609 handle
= service_open_pipe(hsvc
->name
);
1612 if (handle
!= INVALID_HANDLE_VALUE
)
1614 r
= service_send_start_message(handle
, lpServiceArgVectors
, dwNumServiceArgs
);
1615 CloseHandle(handle
);
1618 handle
= service_open_pipe(hsvc
->name
);
1619 if (handle
!= INVALID_HANDLE_VALUE
)
1621 service_set_processID(handle
, dwProcessId
, &dwResult
);
1622 CloseHandle(handle
);
1625 UnlockServiceDatabase( hLock
);
1627 TRACE("returning %d\n", r
);
1630 service_wait_for_startup(hService
);
1635 /******************************************************************************
1636 * QueryServiceStatus [ADVAPI32.@]
1639 * hService [I] Handle to service to get information about
1640 * lpservicestatus [O] buffer to receive the status information for the service
1643 BOOL WINAPI
QueryServiceStatus(SC_HANDLE hService
,
1644 LPSERVICE_STATUS lpservicestatus
)
1646 SERVICE_STATUS_PROCESS SvcStatusData
;
1649 TRACE("%p %p\n", hService
, lpservicestatus
);
1651 ret
= QueryServiceStatusEx(hService
, SC_STATUS_PROCESS_INFO
, (LPBYTE
)&SvcStatusData
,
1652 sizeof(SERVICE_STATUS_PROCESS
), NULL
);
1653 if (ret
) memcpy(lpservicestatus
, &SvcStatusData
, sizeof(SERVICE_STATUS
)) ;
1658 /******************************************************************************
1659 * QueryServiceStatusEx [ADVAPI32.@]
1661 * Get information about a service.
1664 * hService [I] Handle to service to get information about
1665 * InfoLevel [I] Level of information to get
1666 * lpBuffer [O] Destination for requested information
1667 * cbBufSize [I] Size of lpBuffer in bytes
1668 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
1674 BOOL WINAPI
QueryServiceStatusEx(SC_HANDLE hService
, SC_STATUS_TYPE InfoLevel
,
1675 LPBYTE lpBuffer
, DWORD cbBufSize
,
1676 LPDWORD pcbBytesNeeded
)
1678 struct sc_service
*hsvc
;
1679 DWORD size
, type
, val
;
1682 LPSERVICE_STATUS_PROCESS pSvcStatusData
;
1684 TRACE("%p %d %p %d %p\n", hService
, InfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
1686 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
1688 SetLastError( ERROR_INVALID_LEVEL
);
1692 pSvcStatusData
= (LPSERVICE_STATUS_PROCESS
) lpBuffer
;
1693 if (pSvcStatusData
== NULL
)
1695 SetLastError( ERROR_INVALID_PARAMETER
);
1699 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
1701 if( pcbBytesNeeded
!= NULL
)
1702 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
1704 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1708 hsvc
= sc_handle_get_handle_data(hService
, SC_HTYPE_SERVICE
);
1711 SetLastError( ERROR_INVALID_HANDLE
);
1715 pipe
= service_open_pipe(hsvc
->name
);
1716 if (pipe
!= INVALID_HANDLE_VALUE
)
1718 r
= service_get_status(pipe
, pSvcStatusData
);
1724 TRACE("Failed to read service status\n");
1726 /* read the service type from the registry */
1728 r
= RegQueryValueExA(hsvc
->hkey
, "Type", NULL
, &type
, (LPBYTE
)&val
, &size
);
1729 if (r
!= ERROR_SUCCESS
|| type
!= REG_DWORD
)
1732 pSvcStatusData
->dwServiceType
= val
;
1733 pSvcStatusData
->dwCurrentState
= SERVICE_STOPPED
; /* stopped */
1734 pSvcStatusData
->dwControlsAccepted
= 0;
1735 pSvcStatusData
->dwWin32ExitCode
= ERROR_SERVICE_NEVER_STARTED
;
1736 pSvcStatusData
->dwServiceSpecificExitCode
= 0;
1737 pSvcStatusData
->dwCheckPoint
= 0;
1738 pSvcStatusData
->dwWaitHint
= 0;
1743 /******************************************************************************
1744 * QueryServiceConfigA [ADVAPI32.@]
1746 BOOL WINAPI
QueryServiceConfigA( SC_HANDLE hService
, LPQUERY_SERVICE_CONFIGA config
,
1747 DWORD size
, LPDWORD needed
)
1752 QUERY_SERVICE_CONFIGW
*configW
;
1754 TRACE("%p %p %d %p\n", hService
, config
, size
, needed
);
1756 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, 2 * size
)))
1758 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1761 configW
= (QUERY_SERVICE_CONFIGW
*)buffer
;
1762 ret
= QueryServiceConfigW( hService
, configW
, 2 * size
, needed
);
1763 if (!ret
) goto done
;
1765 config
->dwServiceType
= configW
->dwServiceType
;
1766 config
->dwStartType
= configW
->dwStartType
;
1767 config
->dwErrorControl
= configW
->dwErrorControl
;
1768 config
->lpBinaryPathName
= NULL
;
1769 config
->lpLoadOrderGroup
= NULL
;
1770 config
->dwTagId
= configW
->dwTagId
;
1771 config
->lpDependencies
= NULL
;
1772 config
->lpServiceStartName
= NULL
;
1773 config
->lpDisplayName
= NULL
;
1775 p
= (LPSTR
)(config
+ 1);
1776 n
= size
- sizeof(*config
);
1779 #define MAP_STR(str) \
1783 DWORD sz = WideCharToMultiByte( CP_ACP, 0, configW->str, -1, p, n, NULL, NULL ); \
1784 if (!sz) goto done; \
1791 MAP_STR( lpBinaryPathName
);
1792 MAP_STR( lpLoadOrderGroup
);
1793 MAP_STR( lpDependencies
);
1794 MAP_STR( lpServiceStartName
);
1795 MAP_STR( lpDisplayName
);
1798 *needed
= p
- buffer
;
1802 HeapFree( GetProcessHeap(), 0, buffer
);
1806 /******************************************************************************
1807 * QueryServiceConfigW [ADVAPI32.@]
1810 QueryServiceConfigW( SC_HANDLE hService
,
1811 LPQUERY_SERVICE_CONFIGW lpServiceConfig
,
1812 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
)
1814 WCHAR str_buffer
[ MAX_PATH
];
1816 DWORD type
, val
, sz
, total
, n
;
1819 struct sc_service
*hsvc
;
1821 TRACE("%p %p %d %p\n", hService
, lpServiceConfig
,
1822 cbBufSize
, pcbBytesNeeded
);
1824 hsvc
= sc_handle_get_handle_data(hService
, SC_HTYPE_SERVICE
);
1827 SetLastError( ERROR_INVALID_HANDLE
);
1832 /* calculate the size required first */
1833 total
= sizeof (QUERY_SERVICE_CONFIGW
);
1835 sz
= sizeof(str_buffer
);
1836 r
= RegQueryValueExW( hKey
, szImagePath
, 0, &type
, (LPBYTE
) str_buffer
, &sz
);
1837 if( ( r
== ERROR_SUCCESS
) && ( type
== REG_SZ
|| type
== REG_EXPAND_SZ
) )
1839 sz
= ExpandEnvironmentStringsW(str_buffer
,NULL
,0);
1840 if( 0 == sz
) return FALSE
;
1842 total
+= sizeof(WCHAR
) * sz
;
1846 /* FIXME: set last error */
1851 r
= RegQueryValueExW( hKey
, szGroup
, 0, &type
, NULL
, &sz
);
1852 if( ( r
== ERROR_SUCCESS
) && ( type
== REG_SZ
) )
1856 r
= RegQueryValueExW( hKey
, szDependencies
, 0, &type
, NULL
, &sz
);
1857 if( ( r
== ERROR_SUCCESS
) && ( type
== REG_MULTI_SZ
) )
1860 total
+= sizeof(WCHAR
);
1863 r
= RegQueryValueExW( hKey
, szStart
, 0, &type
, NULL
, &sz
);
1864 if( ( r
== ERROR_SUCCESS
) && ( type
== REG_SZ
) )
1868 r
= RegQueryValueExW( hKey
, szDisplayName
, 0, &type
, NULL
, &sz
);
1869 if( ( r
== ERROR_SUCCESS
) && ( type
== REG_SZ
) )
1872 *pcbBytesNeeded
= total
;
1874 /* if there's not enough memory, return an error */
1875 if( total
> cbBufSize
)
1877 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1881 ZeroMemory( lpServiceConfig
, total
);
1884 r
= RegQueryValueExW( hKey
, szType
, 0, &type
, (LPBYTE
)&val
, &sz
);
1885 if( ( r
== ERROR_SUCCESS
) || ( type
== REG_DWORD
) )
1886 lpServiceConfig
->dwServiceType
= val
;
1889 r
= RegQueryValueExW( hKey
, szStart
, 0, &type
, (LPBYTE
)&val
, &sz
);
1890 if( ( r
== ERROR_SUCCESS
) || ( type
== REG_DWORD
) )
1891 lpServiceConfig
->dwStartType
= val
;
1894 r
= RegQueryValueExW( hKey
, szError
, 0, &type
, (LPBYTE
)&val
, &sz
);
1895 if( ( r
== ERROR_SUCCESS
) || ( type
== REG_DWORD
) )
1896 lpServiceConfig
->dwErrorControl
= val
;
1898 /* now do the strings */
1899 p
= (LPBYTE
) &lpServiceConfig
[1];
1900 n
= total
- sizeof (QUERY_SERVICE_CONFIGW
);
1902 sz
= sizeof(str_buffer
);
1903 r
= RegQueryValueExW( hKey
, szImagePath
, 0, &type
, (LPBYTE
) str_buffer
, &sz
);
1904 if( ( r
== ERROR_SUCCESS
) && ( type
== REG_SZ
|| type
== REG_EXPAND_SZ
) )
1906 sz
= ExpandEnvironmentStringsW(str_buffer
, (LPWSTR
) p
, n
);
1907 sz
*= sizeof(WCHAR
);
1908 if( 0 == sz
|| sz
> n
) return FALSE
;
1910 lpServiceConfig
->lpBinaryPathName
= (LPWSTR
) p
;
1916 /* FIXME: set last error */
1921 r
= RegQueryValueExW( hKey
, szGroup
, 0, &type
, p
, &sz
);
1922 if( ( r
== ERROR_SUCCESS
) || ( type
== REG_SZ
) )
1924 lpServiceConfig
->lpLoadOrderGroup
= (LPWSTR
) p
;
1930 r
= RegQueryValueExW( hKey
, szDependencies
, 0, &type
, p
, &sz
);
1931 lpServiceConfig
->lpDependencies
= (LPWSTR
) p
;
1932 if( ( r
== ERROR_SUCCESS
) || ( type
== REG_SZ
) )
1945 ERR("Buffer overflow!\n");
1947 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig
->lpBinaryPathName
) );
1948 TRACE("Group = %s\n", debugstr_w(lpServiceConfig
->lpLoadOrderGroup
) );
1953 /******************************************************************************
1954 * EnumServicesStatusA [ADVAPI32.@]
1957 EnumServicesStatusA( SC_HANDLE hSCManager
, DWORD dwServiceType
,
1958 DWORD dwServiceState
, LPENUM_SERVICE_STATUSA lpServices
,
1959 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
,
1960 LPDWORD lpServicesReturned
, LPDWORD lpResumeHandle
)
1962 FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager
,
1963 dwServiceType
, dwServiceState
, lpServices
, cbBufSize
,
1964 pcbBytesNeeded
, lpServicesReturned
, lpResumeHandle
);
1965 SetLastError (ERROR_ACCESS_DENIED
);
1969 /******************************************************************************
1970 * EnumServicesStatusW [ADVAPI32.@]
1973 EnumServicesStatusW( SC_HANDLE hSCManager
, DWORD dwServiceType
,
1974 DWORD dwServiceState
, LPENUM_SERVICE_STATUSW lpServices
,
1975 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
,
1976 LPDWORD lpServicesReturned
, LPDWORD lpResumeHandle
)
1978 FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager
,
1979 dwServiceType
, dwServiceState
, lpServices
, cbBufSize
,
1980 pcbBytesNeeded
, lpServicesReturned
, lpResumeHandle
);
1981 SetLastError (ERROR_ACCESS_DENIED
);
1985 /******************************************************************************
1986 * EnumServicesStatusExA [ADVAPI32.@]
1989 EnumServicesStatusExA(SC_HANDLE hSCManager
, SC_ENUM_TYPE InfoLevel
, DWORD dwServiceType
,
1990 DWORD dwServiceState
, LPBYTE lpServices
, DWORD cbBufSize
, LPDWORD pcbBytesNeeded
,
1991 LPDWORD lpServicesReturned
, LPDWORD lpResumeHandle
, LPCSTR pszGroupName
)
1993 FIXME("%p level=%d type=%x state=%x %p %x %p %p %p %s\n", hSCManager
, InfoLevel
,
1994 dwServiceType
, dwServiceState
, lpServices
, cbBufSize
,
1995 pcbBytesNeeded
, lpServicesReturned
, lpResumeHandle
, debugstr_a(pszGroupName
));
1996 SetLastError (ERROR_ACCESS_DENIED
);
2000 /******************************************************************************
2001 * EnumServicesStatusExW [ADVAPI32.@]
2004 EnumServicesStatusExW(SC_HANDLE hSCManager
, SC_ENUM_TYPE InfoLevel
, DWORD dwServiceType
,
2005 DWORD dwServiceState
, LPBYTE lpServices
, DWORD cbBufSize
, LPDWORD pcbBytesNeeded
,
2006 LPDWORD lpServicesReturned
, LPDWORD lpResumeHandle
, LPCWSTR pszGroupName
)
2008 FIXME("%p level=%d type=%x state=%x %p %x %p %p %p %s\n", hSCManager
, InfoLevel
,
2009 dwServiceType
, dwServiceState
, lpServices
, cbBufSize
,
2010 pcbBytesNeeded
, lpServicesReturned
, lpResumeHandle
, debugstr_w(pszGroupName
));
2011 SetLastError (ERROR_ACCESS_DENIED
);
2015 /******************************************************************************
2016 * GetServiceKeyNameA [ADVAPI32.@]
2018 BOOL WINAPI
GetServiceKeyNameA( SC_HANDLE hSCManager
, LPCSTR lpDisplayName
,
2019 LPSTR lpServiceName
, LPDWORD lpcchBuffer
)
2021 FIXME("%p %s %p %p\n", hSCManager
, debugstr_a(lpDisplayName
), lpServiceName
, lpcchBuffer
);
2025 /******************************************************************************
2026 * GetServiceKeyNameW [ADVAPI32.@]
2028 BOOL WINAPI
GetServiceKeyNameW( SC_HANDLE hSCManager
, LPCWSTR lpDisplayName
,
2029 LPWSTR lpServiceName
, LPDWORD lpcchBuffer
)
2031 FIXME("%p %s %p %p\n", hSCManager
, debugstr_w(lpDisplayName
), lpServiceName
, lpcchBuffer
);
2035 /******************************************************************************
2036 * QueryServiceLockStatusA [ADVAPI32.@]
2038 BOOL WINAPI
QueryServiceLockStatusA( SC_HANDLE hSCManager
,
2039 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
2040 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
)
2042 FIXME("%p %p %08x %p\n", hSCManager
, lpLockStatus
, cbBufSize
, pcbBytesNeeded
);
2047 /******************************************************************************
2048 * QueryServiceLockStatusW [ADVAPI32.@]
2050 BOOL WINAPI
QueryServiceLockStatusW( SC_HANDLE hSCManager
,
2051 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2052 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
)
2054 FIXME("%p %p %08x %p\n", hSCManager
, lpLockStatus
, cbBufSize
, pcbBytesNeeded
);
2059 /******************************************************************************
2060 * GetServiceDisplayNameA [ADVAPI32.@]
2062 BOOL WINAPI
GetServiceDisplayNameA( SC_HANDLE hSCManager
, LPCSTR lpServiceName
,
2063 LPSTR lpDisplayName
, LPDWORD lpcchBuffer
)
2065 struct sc_manager
*hscm
;
2069 TRACE("%p %s %p %p\n", hSCManager
,
2070 debugstr_a(lpServiceName
), lpDisplayName
, lpcchBuffer
);
2072 hscm
= sc_handle_get_handle_data(hSCManager
, SC_HTYPE_MANAGER
);
2075 SetLastError(ERROR_INVALID_HANDLE
);
2079 size
= *lpcchBuffer
;
2080 ret
= RegGetValueA(hscm
->hkey
, lpServiceName
, "DisplayName", RRF_RT_REG_SZ
, &type
, lpDisplayName
, &size
);
2083 if (lpDisplayName
&& *lpcchBuffer
) *lpDisplayName
= 0;
2085 if (ret
== ERROR_MORE_DATA
)
2087 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2088 *lpcchBuffer
= size
- 1;
2097 /******************************************************************************
2098 * GetServiceDisplayNameW [ADVAPI32.@]
2100 BOOL WINAPI
GetServiceDisplayNameW( SC_HANDLE hSCManager
, LPCWSTR lpServiceName
,
2101 LPWSTR lpDisplayName
, LPDWORD lpcchBuffer
)
2103 struct sc_manager
*hscm
;
2107 TRACE("%p %s %p %p\n", hSCManager
,
2108 debugstr_w(lpServiceName
), lpDisplayName
, lpcchBuffer
);
2110 hscm
= sc_handle_get_handle_data(hSCManager
, SC_HTYPE_MANAGER
);
2113 SetLastError(ERROR_INVALID_HANDLE
);
2117 size
= *lpcchBuffer
* sizeof(WCHAR
);
2118 ret
= RegGetValueW(hscm
->hkey
, lpServiceName
, szDisplayName
, RRF_RT_REG_SZ
, &type
, lpDisplayName
, &size
);
2121 if (lpDisplayName
&& *lpcchBuffer
) *lpDisplayName
= 0;
2123 if (ret
== ERROR_MORE_DATA
)
2125 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2126 *lpcchBuffer
= (size
/ sizeof(WCHAR
)) - 1;
2135 /******************************************************************************
2136 * ChangeServiceConfigW [ADVAPI32.@]
2138 BOOL WINAPI
ChangeServiceConfigW( SC_HANDLE hService
, DWORD dwServiceType
,
2139 DWORD dwStartType
, DWORD dwErrorControl
, LPCWSTR lpBinaryPathName
,
2140 LPCWSTR lpLoadOrderGroup
, LPDWORD lpdwTagId
, LPCWSTR lpDependencies
,
2141 LPCWSTR lpServiceStartName
, LPCWSTR lpPassword
, LPCWSTR lpDisplayName
)
2143 struct reg_value val
[10];
2144 struct sc_service
*hsvc
;
2145 DWORD r
= ERROR_SUCCESS
;
2149 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2150 hService
, dwServiceType
, dwStartType
, dwErrorControl
,
2151 debugstr_w(lpBinaryPathName
), debugstr_w(lpLoadOrderGroup
),
2152 lpdwTagId
, lpDependencies
, debugstr_w(lpServiceStartName
),
2153 debugstr_w(lpPassword
), debugstr_w(lpDisplayName
) );
2155 hsvc
= sc_handle_get_handle_data(hService
, SC_HTYPE_SERVICE
);
2158 SetLastError( ERROR_INVALID_HANDLE
);
2163 if( dwServiceType
!= SERVICE_NO_CHANGE
)
2164 service_set_dword( &val
[n
++], szType
, &dwServiceType
);
2166 if( dwStartType
!= SERVICE_NO_CHANGE
)
2167 service_set_dword( &val
[n
++], szStart
, &dwStartType
);
2169 if( dwErrorControl
!= SERVICE_NO_CHANGE
)
2170 service_set_dword( &val
[n
++], szError
, &dwErrorControl
);
2172 if( lpBinaryPathName
)
2173 service_set_string( &val
[n
++], szImagePath
, lpBinaryPathName
);
2175 if( lpLoadOrderGroup
)
2176 service_set_string( &val
[n
++], szGroup
, lpLoadOrderGroup
);
2178 if( lpDependencies
)
2179 service_set_multi_string( &val
[n
++], szDependencies
, lpDependencies
);
2182 FIXME("ignoring password\n");
2184 if( lpServiceStartName
)
2185 service_set_string( &val
[n
++], szDependOnService
, lpServiceStartName
);
2187 r
= service_write_values( hsvc
->hkey
, val
, n
);
2189 return (r
== ERROR_SUCCESS
) ? TRUE
: FALSE
;
2192 /******************************************************************************
2193 * ChangeServiceConfigA [ADVAPI32.@]
2195 BOOL WINAPI
ChangeServiceConfigA( SC_HANDLE hService
, DWORD dwServiceType
,
2196 DWORD dwStartType
, DWORD dwErrorControl
, LPCSTR lpBinaryPathName
,
2197 LPCSTR lpLoadOrderGroup
, LPDWORD lpdwTagId
, LPCSTR lpDependencies
,
2198 LPCSTR lpServiceStartName
, LPCSTR lpPassword
, LPCSTR lpDisplayName
)
2200 LPWSTR wBinaryPathName
, wLoadOrderGroup
, wDependencies
;
2201 LPWSTR wServiceStartName
, wPassword
, wDisplayName
;
2204 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2205 hService
, dwServiceType
, dwStartType
, dwErrorControl
,
2206 debugstr_a(lpBinaryPathName
), debugstr_a(lpLoadOrderGroup
),
2207 lpdwTagId
, lpDependencies
, debugstr_a(lpServiceStartName
),
2208 debugstr_a(lpPassword
), debugstr_a(lpDisplayName
) );
2210 wBinaryPathName
= SERV_dup( lpBinaryPathName
);
2211 wLoadOrderGroup
= SERV_dup( lpLoadOrderGroup
);
2212 wDependencies
= SERV_dupmulti( lpDependencies
);
2213 wServiceStartName
= SERV_dup( lpServiceStartName
);
2214 wPassword
= SERV_dup( lpPassword
);
2215 wDisplayName
= SERV_dup( lpDisplayName
);
2217 r
= ChangeServiceConfigW( hService
, dwServiceType
,
2218 dwStartType
, dwErrorControl
, wBinaryPathName
,
2219 wLoadOrderGroup
, lpdwTagId
, wDependencies
,
2220 wServiceStartName
, wPassword
, wDisplayName
);
2222 SERV_free( wBinaryPathName
);
2223 SERV_free( wLoadOrderGroup
);
2224 SERV_free( wDependencies
);
2225 SERV_free( wServiceStartName
);
2226 SERV_free( wPassword
);
2227 SERV_free( wDisplayName
);
2232 /******************************************************************************
2233 * ChangeServiceConfig2A [ADVAPI32.@]
2235 BOOL WINAPI
ChangeServiceConfig2A( SC_HANDLE hService
, DWORD dwInfoLevel
,
2240 TRACE("%p %d %p\n",hService
, dwInfoLevel
, lpInfo
);
2242 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
2244 LPSERVICE_DESCRIPTIONA sd
= (LPSERVICE_DESCRIPTIONA
) lpInfo
;
2245 SERVICE_DESCRIPTIONW sdw
;
2247 sdw
.lpDescription
= SERV_dup( sd
->lpDescription
);
2249 r
= ChangeServiceConfig2W( hService
, dwInfoLevel
, &sdw
);
2251 SERV_free( sdw
.lpDescription
);
2253 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
2255 LPSERVICE_FAILURE_ACTIONSA fa
= (LPSERVICE_FAILURE_ACTIONSA
) lpInfo
;
2256 SERVICE_FAILURE_ACTIONSW faw
;
2258 faw
.dwResetPeriod
= fa
->dwResetPeriod
;
2259 faw
.lpRebootMsg
= SERV_dup( fa
->lpRebootMsg
);
2260 faw
.lpCommand
= SERV_dup( fa
->lpCommand
);
2261 faw
.cActions
= fa
->cActions
;
2262 faw
.lpsaActions
= fa
->lpsaActions
;
2264 r
= ChangeServiceConfig2W( hService
, dwInfoLevel
, &faw
);
2266 SERV_free( faw
.lpRebootMsg
);
2267 SERV_free( faw
.lpCommand
);
2270 SetLastError( ERROR_INVALID_PARAMETER
);
2275 /******************************************************************************
2276 * ChangeServiceConfig2W [ADVAPI32.@]
2278 BOOL WINAPI
ChangeServiceConfig2W( SC_HANDLE hService
, DWORD dwInfoLevel
,
2282 struct sc_service
*hsvc
;
2284 hsvc
= sc_handle_get_handle_data(hService
, SC_HTYPE_SERVICE
);
2287 SetLastError( ERROR_INVALID_HANDLE
);
2292 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
2294 static const WCHAR szDescription
[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
2295 LPSERVICE_DESCRIPTIONW sd
= (LPSERVICE_DESCRIPTIONW
)lpInfo
;
2296 if (sd
->lpDescription
)
2298 TRACE("Setting Description to %s\n",debugstr_w(sd
->lpDescription
));
2299 if (sd
->lpDescription
[0] == 0)
2300 RegDeleteValueW(hKey
,szDescription
);
2302 RegSetValueExW(hKey
, szDescription
, 0, REG_SZ
,
2303 (LPVOID
)sd
->lpDescription
,
2304 sizeof(WCHAR
)*(strlenW(sd
->lpDescription
)+1));
2308 FIXME("STUB: %p %d %p\n",hService
, dwInfoLevel
, lpInfo
);
2312 /******************************************************************************
2313 * QueryServiceObjectSecurity [ADVAPI32.@]
2315 BOOL WINAPI
QueryServiceObjectSecurity(SC_HANDLE hService
,
2316 SECURITY_INFORMATION dwSecurityInformation
,
2317 PSECURITY_DESCRIPTOR lpSecurityDescriptor
,
2318 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
)
2322 FIXME("%p %d %p %u %p\n", hService
, dwSecurityInformation
,
2323 lpSecurityDescriptor
, cbBufSize
, pcbBytesNeeded
);
2325 InitializeSecurityDescriptor(lpSecurityDescriptor
, SECURITY_DESCRIPTOR_REVISION
);
2327 pACL
= HeapAlloc( GetProcessHeap(), 0, sizeof(ACL
) );
2328 InitializeAcl(pACL
, sizeof(ACL
), ACL_REVISION
);
2329 SetSecurityDescriptorDacl(lpSecurityDescriptor
, TRUE
, pACL
, TRUE
);
2333 /******************************************************************************
2334 * SetServiceObjectSecurity [ADVAPI32.@]
2336 BOOL WINAPI
SetServiceObjectSecurity(SC_HANDLE hService
,
2337 SECURITY_INFORMATION dwSecurityInformation
,
2338 PSECURITY_DESCRIPTOR lpSecurityDescriptor
)
2340 FIXME("%p %d %p\n", hService
, dwSecurityInformation
, lpSecurityDescriptor
);
2344 /******************************************************************************
2345 * SetServiceBits [ADVAPI32.@]
2347 BOOL WINAPI
SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus
,
2348 DWORD dwServiceBits
,
2350 BOOL bUpdateImmediately
)
2352 FIXME("%p %08x %x %x\n", hServiceStatus
, dwServiceBits
,
2353 bSetBitsOn
, bUpdateImmediately
);
2357 SERVICE_STATUS_HANDLE WINAPI
RegisterServiceCtrlHandlerExA( LPCSTR lpServiceName
,
2358 LPHANDLER_FUNCTION_EX lpHandlerProc
, LPVOID lpContext
)
2360 FIXME("%s %p %p\n", debugstr_a(lpServiceName
), lpHandlerProc
, lpContext
);
2364 SERVICE_STATUS_HANDLE WINAPI
RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceName
,
2365 LPHANDLER_FUNCTION_EX lpHandlerProc
, LPVOID lpContext
)
2367 service_data
*service
;
2369 TRACE("%s %p %p\n", debugstr_w(lpServiceName
), lpHandlerProc
, lpContext
);
2371 EnterCriticalSection( &service_cs
);
2372 for(service
= service_list
; service
; service
= service
->next
)
2373 if(!strcmpW(lpServiceName
, service
->name
))
2377 service
->handler
.handler_ex
= lpHandlerProc
;
2378 service
->context
= lpContext
;
2379 service
->extended
= TRUE
;
2381 LeaveCriticalSection( &service_cs
);
2383 return (SERVICE_STATUS_HANDLE
)service
;