Fix a crash when launching Unix executables.
[wine/multimedia.git] / dlls / advapi32 / service.c
blob82701e4579009cb4c7be546a990bb4075ac7592b
1 /*
2 * Win32 advapi functions
4 * Copyright 1995 Sven Verdoolaege
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <stdarg.h>
22 #include <string.h>
23 #include <time.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winsvc.h"
28 #include "winerror.h"
29 #include "winreg.h"
30 #include "wine/unicode.h"
31 #include "heap.h"
32 #include "wine/debug.h"
33 #include "winternl.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
37 static DWORD start_dwNumServiceArgs;
38 static LPWSTR *start_lpServiceArgVectors;
40 static const WCHAR _ServiceStartDataW[] = {'A','D','V','A','P','I','_','S',
41 'e','r','v','i','c','e','S','t',
42 'a','r','t','D','a','t','a',0};
43 static const WCHAR szServiceManagerKey[] = { 'S','y','s','t','e','m','\\',
44 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
45 'S','e','r','v','i','c','e','s','\\',0 };
48 /******************************************************************************
49 * EnumServicesStatusA [ADVAPI32.@]
51 BOOL WINAPI
52 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
53 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
54 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
55 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
56 { FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
57 dwServiceType, dwServiceState, lpServices, cbBufSize,
58 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
59 SetLastError (ERROR_ACCESS_DENIED);
60 return FALSE;
63 /******************************************************************************
64 * EnumServicesStatusW [ADVAPI32.@]
66 BOOL WINAPI
67 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
68 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
69 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
70 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
71 { FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
72 dwServiceType, dwServiceState, lpServices, cbBufSize,
73 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
74 SetLastError (ERROR_ACCESS_DENIED);
75 return FALSE;
78 /******************************************************************************
79 * StartServiceCtrlDispatcherA [ADVAPI32.@]
81 BOOL WINAPI
82 StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
84 LPSERVICE_MAIN_FUNCTIONA fpMain;
85 HANDLE wait;
86 DWORD dwNumServiceArgs ;
87 LPWSTR *lpArgVecW;
88 LPSTR *lpArgVecA;
89 int i;
91 TRACE("(%p)\n", servent);
92 wait = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS, FALSE, _ServiceStartDataW);
93 if(wait == 0)
95 ERR("Couldn't find wait semaphore\n");
96 ERR("perhaps you need to start services using StartService\n");
97 return FALSE;
100 dwNumServiceArgs = start_dwNumServiceArgs;
101 lpArgVecW = start_lpServiceArgVectors;
103 ReleaseSemaphore(wait, 1, NULL);
105 /* Convert the Unicode arg vectors back to ASCII */
106 if(dwNumServiceArgs)
107 lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0,
108 dwNumServiceArgs*sizeof(LPSTR) );
109 else
110 lpArgVecA = NULL;
112 for(i=0; i<dwNumServiceArgs; i++)
113 lpArgVecA[i]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW[i]);
115 /* FIXME: should we blindly start all services? */
116 while (servent->lpServiceName) {
117 TRACE("%s at %p)\n", debugstr_a(servent->lpServiceName),servent);
118 fpMain = servent->lpServiceProc;
120 /* try to start the service */
121 fpMain( dwNumServiceArgs, lpArgVecA);
123 servent++;
126 if(dwNumServiceArgs)
128 /* free arg strings */
129 for(i=0; i<dwNumServiceArgs; i++)
130 HeapFree(GetProcessHeap(), 0, lpArgVecA[i]);
131 HeapFree(GetProcessHeap(), 0, lpArgVecA);
134 return TRUE;
137 /******************************************************************************
138 * StartServiceCtrlDispatcherW [ADVAPI32.@]
140 * PARAMS
141 * servent []
143 BOOL WINAPI
144 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
146 LPSERVICE_MAIN_FUNCTIONW fpMain;
147 HANDLE wait;
148 DWORD dwNumServiceArgs ;
149 LPWSTR *lpServiceArgVectors ;
151 TRACE("(%p)\n", servent);
152 wait = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS, FALSE, _ServiceStartDataW);
153 if(wait == 0)
155 ERR("Couldn't find wait semaphore\n");
156 ERR("perhaps you need to start services using StartService\n");
157 return FALSE;
160 dwNumServiceArgs = start_dwNumServiceArgs;
161 lpServiceArgVectors = start_lpServiceArgVectors;
163 ReleaseSemaphore(wait, 1, NULL);
165 /* FIXME: should we blindly start all services? */
166 while (servent->lpServiceName) {
167 TRACE("%s at %p)\n", debugstr_w(servent->lpServiceName),servent);
168 fpMain = servent->lpServiceProc;
170 /* try to start the service */
171 fpMain( dwNumServiceArgs, lpServiceArgVectors);
173 servent++;
176 return TRUE;
179 /******************************************************************************
180 * LockServiceDatabase [ADVAPI32.@]
182 LPVOID WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
184 FIXME("%p\n",hSCManager);
185 return (SC_HANDLE)0xcacacafe;
188 /******************************************************************************
189 * UnlockServiceDatabase [ADVAPI32.@]
191 BOOL WINAPI UnlockServiceDatabase (LPVOID ScLock)
193 FIXME(": %p\n",ScLock);
194 return TRUE;
197 /******************************************************************************
198 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
200 SERVICE_STATUS_HANDLE WINAPI
201 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName,
202 LPHANDLER_FUNCTION lpfHandler )
203 { FIXME("%s %p\n", lpServiceName, lpfHandler);
204 return 0xcacacafe;
207 /******************************************************************************
208 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
210 * PARAMS
211 * lpServiceName []
212 * lpfHandler []
214 SERVICE_STATUS_HANDLE WINAPI
215 RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
216 LPHANDLER_FUNCTION lpfHandler )
217 { FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler);
218 return 0xcacacafe;
221 /******************************************************************************
222 * SetServiceStatus [ADVAPI32.@]
224 * PARAMS
225 * hService []
226 * lpStatus []
228 BOOL WINAPI
229 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
230 { FIXME("0x%lx %p\n",hService, lpStatus);
231 TRACE("\tType:%lx\n",lpStatus->dwServiceType);
232 TRACE("\tState:%lx\n",lpStatus->dwCurrentState);
233 TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted);
234 TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode);
235 TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode);
236 TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint);
237 TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint);
238 return TRUE;
241 /******************************************************************************
242 * OpenSCManagerA [ADVAPI32.@]
244 * Establish a connection to the service control manager and open its database.
246 * PARAMS
247 * lpMachineName [I] Pointer to machine name string
248 * lpDatabaseName [I] Pointer to database name string
249 * dwDesiredAccess [I] Type of access
251 * RETURNS
252 * Success: A Handle to the service control manager database
253 * Failure: NULL
255 SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
256 DWORD dwDesiredAccess )
258 UNICODE_STRING lpMachineNameW;
259 UNICODE_STRING lpDatabaseNameW;
260 SC_HANDLE ret;
262 RtlCreateUnicodeStringFromAsciiz (&lpMachineNameW,lpMachineName);
263 RtlCreateUnicodeStringFromAsciiz (&lpDatabaseNameW,lpDatabaseName);
264 ret = OpenSCManagerW(lpMachineNameW.Buffer,lpDatabaseNameW.Buffer, dwDesiredAccess);
265 RtlFreeUnicodeString(&lpDatabaseNameW);
266 RtlFreeUnicodeString(&lpMachineNameW);
267 return ret;
270 /******************************************************************************
271 * OpenSCManagerW [ADVAPI32.@]
273 * See OpenSCManagerA.
275 SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
276 DWORD dwDesiredAccess )
278 HKEY hReg, hKey = NULL;
279 LONG r;
281 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
282 debugstr_w(lpDatabaseName), dwDesiredAccess);
285 * FIXME: what is lpDatabaseName?
286 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
287 * docs, but what if it isn't?
290 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg);
291 if (r==ERROR_SUCCESS)
293 r = RegOpenKeyExW(hReg, szServiceManagerKey,0, dwDesiredAccess, &hKey );
294 RegCloseKey( hReg );
297 TRACE("returning %p\n", hKey);
299 return hKey;
303 /******************************************************************************
304 * AllocateLocallyUniqueId [ADVAPI32.@]
306 * PARAMS
307 * lpluid []
309 BOOL WINAPI
310 AllocateLocallyUniqueId( PLUID lpluid )
312 lpluid->LowPart = time(NULL);
313 lpluid->HighPart = 0;
314 return TRUE;
318 /******************************************************************************
319 * ControlService [ADVAPI32.@]
321 * Send a control code to a service.
323 * PARAMS
324 * hService [I] Handle of the service control manager database
325 * dwControl [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
326 * lpServiceStatus [O] Destination for the status of the service, if available
328 * RETURNS
329 * Success: TRUE.
330 * Failure: FALSE.
332 BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl,
333 LPSERVICE_STATUS lpServiceStatus )
335 FIXME("(%p,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
336 return TRUE;
340 /******************************************************************************
341 * CloseServiceHandle [ADVAPI32.@]
343 * Close a handle to a service or the service control manager database.
345 * PARAMS
346 * hSCObject [I] Handle to service or service control manager database
348 * RETURNS
349 * Success: TRUE
350 * Failure: FALSE
352 BOOL WINAPI
353 CloseServiceHandle( SC_HANDLE hSCObject )
355 TRACE("(%p)\n", hSCObject);
357 RegCloseKey(hSCObject);
359 return TRUE;
363 /******************************************************************************
364 * OpenServiceA [ADVAPI32.@]
366 * Open a handle to a service.
368 * PARAMS
369 * hSCManager [I] Handle of the service control manager database
370 * lpServiceName [I] Name of the service to open
371 * dwDesiredAccess [I] Access required to the service
373 * RETURNS
374 * Success: Handle to the service
375 * Failure: NULL
377 SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
378 DWORD dwDesiredAccess )
380 UNICODE_STRING lpServiceNameW;
381 SC_HANDLE ret;
382 RtlCreateUnicodeStringFromAsciiz (&lpServiceNameW,lpServiceName);
383 if(lpServiceName)
384 TRACE("Request for service %s\n",lpServiceName);
385 else
386 return FALSE;
387 ret = OpenServiceW( hSCManager, lpServiceNameW.Buffer, dwDesiredAccess);
388 RtlFreeUnicodeString(&lpServiceNameW);
389 return ret;
393 /******************************************************************************
394 * OpenServiceW [ADVAPI32.@]
396 * See OpenServiceA.
398 SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
399 DWORD dwDesiredAccess)
401 HKEY hKey;
402 long r;
404 TRACE("(%p,%p,%ld)\n",hSCManager, lpServiceName,
405 dwDesiredAccess);
407 r = RegOpenKeyExW(hSCManager, lpServiceName, 0, KEY_ALL_ACCESS, &hKey );
408 if (r!=ERROR_SUCCESS)
409 return 0;
411 TRACE("returning %p\n",hKey);
413 return hKey;
416 /******************************************************************************
417 * CreateServiceW [ADVAPI32.@]
419 SC_HANDLE WINAPI
420 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
421 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
422 DWORD dwServiceType, DWORD dwStartType,
423 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
424 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
425 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
426 LPCWSTR lpPassword )
428 HKEY hKey;
429 LONG r;
430 DWORD dp;
431 static const WCHAR szDisplayName[] = { 'D','i','s','p','l','a','y','N','a','m','e', 0 };
432 static const WCHAR szType[] = {'T','y','p','e',0};
433 static const WCHAR szStart[] = {'S','t','a','r','t',0};
434 static const WCHAR szError[] = {'E','r','r','o','r','C','o','n','t','r','o','l', 0};
435 static const WCHAR szImagePath[] = {'I','m','a','g','e','P','a','t','h',0};
436 static const WCHAR szGroup[] = {'G','r','o','u','p',0};
437 static const WCHAR szDependencies[] = { 'D','e','p','e','n','d','e','n','c','i','e','s',0};
439 FIXME("%p %s %s\n", hSCManager,
440 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
442 r = RegCreateKeyExW(hSCManager, lpServiceName, 0, NULL,
443 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dp);
444 if (r!=ERROR_SUCCESS)
445 return 0;
447 if (dp != REG_CREATED_NEW_KEY)
448 return 0;
450 if(lpDisplayName)
452 r = RegSetValueExW(hKey, szDisplayName, 0, REG_SZ, (LPBYTE)lpDisplayName,
453 (strlenW(lpDisplayName)+1)*sizeof(WCHAR) );
454 if (r!=ERROR_SUCCESS)
455 return 0;
458 r = RegSetValueExW(hKey, szType, 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
459 if (r!=ERROR_SUCCESS)
460 return 0;
462 r = RegSetValueExW(hKey, szStart, 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
463 if (r!=ERROR_SUCCESS)
464 return 0;
466 r = RegSetValueExW(hKey, szError, 0, REG_DWORD,
467 (LPVOID)&dwErrorControl, sizeof (DWORD) );
468 if (r!=ERROR_SUCCESS)
469 return 0;
471 if(lpBinaryPathName)
473 r = RegSetValueExW(hKey, szImagePath, 0, REG_SZ, (LPBYTE)lpBinaryPathName,
474 (strlenW(lpBinaryPathName)+1)*sizeof(WCHAR) );
475 if (r!=ERROR_SUCCESS)
476 return 0;
479 if(lpLoadOrderGroup)
481 r = RegSetValueExW(hKey, szGroup, 0, REG_SZ, (LPBYTE)lpLoadOrderGroup,
482 (strlenW(lpLoadOrderGroup)+1)*sizeof(WCHAR) );
483 if (r!=ERROR_SUCCESS)
484 return 0;
487 if(lpDependencies)
489 DWORD len = 0;
491 /* determine the length of a double null terminated multi string */
492 do {
493 len += (strlenW(&lpDependencies[len])+1);
494 } while (lpDependencies[len++]);
496 r = RegSetValueExW(hKey, szDependencies, 0, REG_MULTI_SZ,
497 (LPBYTE)lpDependencies, len );
498 if (r!=ERROR_SUCCESS)
499 return 0;
502 if(lpPassword)
504 FIXME("Don't know how to add a Password for a service.\n");
507 if(lpServiceStartName)
509 FIXME("Don't know how to add a ServiceStartName for a service.\n");
512 return hKey;
516 static inline LPWSTR SERV_dup( LPCSTR str )
518 UINT len;
519 LPWSTR wstr;
521 if( !str )
522 return NULL;
523 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
524 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
525 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
526 return wstr;
529 static inline LPWSTR SERV_dupmulti( LPCSTR str )
531 UINT len = 0, n = 0;
532 LPWSTR wstr;
534 if( !str )
535 return NULL;
536 do {
537 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
538 n += (strlen( &str[n] ) + 1);
539 } while (str[n]);
540 len++;
541 n++;
543 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
544 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
545 return wstr;
548 static inline VOID SERV_free( LPWSTR wstr )
550 HeapFree( GetProcessHeap(), 0, wstr );
553 /******************************************************************************
554 * CreateServiceA [ADVAPI32.@]
556 SC_HANDLE WINAPI
557 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
558 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
559 DWORD dwServiceType, DWORD dwStartType,
560 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
561 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
562 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
563 LPCSTR lpPassword )
565 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
566 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
567 SC_HANDLE r;
569 TRACE("%p %s %s\n", hSCManager,
570 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
572 lpServiceNameW = SERV_dup( lpServiceName );
573 lpDisplayNameW = SERV_dup( lpDisplayName );
574 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
575 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
576 lpDependenciesW = SERV_dupmulti( lpDependencies );
577 lpServiceStartNameW = SERV_dup( lpServiceStartName );
578 lpPasswordW = SERV_dup( lpPassword );
580 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
581 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
582 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
583 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
585 SERV_free( lpServiceNameW );
586 SERV_free( lpDisplayNameW );
587 SERV_free( lpBinaryPathNameW );
588 SERV_free( lpLoadOrderGroupW );
589 SERV_free( lpDependenciesW );
590 SERV_free( lpServiceStartNameW );
591 SERV_free( lpPasswordW );
593 return r;
597 /******************************************************************************
598 * DeleteService [ADVAPI32.@]
600 * Delete a service from the service control manager database.
602 * PARAMS
603 * hService [I] Handle of the service to delete
605 * RETURNS
606 * Success: TRUE
607 * Failure: FALSE
609 BOOL WINAPI DeleteService( SC_HANDLE hService )
611 WCHAR valname[MAX_PATH+1];
612 INT index = 0;
613 LONG rc;
614 DWORD value = 0x1;
615 DWORD size;
616 HKEY hKey;
618 static const WCHAR szDeleted[] = {'D','e','l','e','t','e','d',0};
620 FIXME("(%p): stub\n",hService);
622 size = MAX_PATH+1;
623 /* Clean out the values */
624 rc = RegEnumValueW(hService, index, valname,&size,0,0,0,0);
625 while (rc == ERROR_SUCCESS)
627 RegDeleteValueW(hService,valname);
628 index++;
629 size = MAX_PATH+1;
630 rc = RegEnumValueW(hService, index, valname, &size,0,0,0,0);
633 /* tag for deletion */
634 RegSetValueExW(hService, szDeleted, 0, REG_DWORD, (LPVOID)&value,
635 sizeof (DWORD) );
637 RegCloseKey(hService);
639 /* find and delete the key */
640 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szServiceManagerKey,0,
641 KEY_ALL_ACCESS, &hKey );
642 index = 0;
643 size = MAX_PATH+1;
644 rc = RegEnumKeyExW(hKey,0, valname, &size, 0, 0, 0, 0);
645 while (rc == ERROR_SUCCESS)
647 HKEY checking;
648 rc = RegOpenKeyExW(hKey,valname,0,KEY_ALL_ACCESS,&checking);
649 if (rc == ERROR_SUCCESS)
651 DWORD deleted = 0;
652 DWORD size = sizeof(DWORD);
653 rc = RegQueryValueExW(checking, szDeleted , NULL, NULL,
654 (LPVOID)&deleted, &size);
655 if (deleted)
657 RegDeleteValueW(checking,szDeleted);
658 RegDeleteKeyW(hKey,valname);
660 else
661 index ++;
662 RegCloseKey(checking);
664 size = MAX_PATH+1;
665 rc = RegEnumKeyExW(hKey, index, valname, &size, 0, 0, 0, 0);
667 RegCloseKey(hKey);
669 return TRUE;
673 /******************************************************************************
674 * StartServiceA [ADVAPI32.@]
676 * Start a service
678 * PARAMS
679 * hService [I] Handle of service
680 * dwNumServiceArgs [I] Number of arguments
681 * lpServiceArgVectors [I] Address of array of argument strings
683 * NOTES
684 * - NT implements this function using an obscure RPC call.
685 * - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
686 * to get things like "%SystemRoot%\\System32\\service.exe" to load.
687 * - This will only work for shared address space. How should the service
688 * args be transferred when address spaces are separated?
689 * - Can only start one service at a time.
690 * - Has no concept of privilege.
692 * RETURNS
693 * Success: TRUE.
694 * Failure: FALSE
696 BOOL WINAPI
697 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
698 LPCSTR *lpServiceArgVectors )
700 LPWSTR *lpwstr=NULL;
701 UNICODE_STRING usBuffer;
702 int i;
704 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
706 if(dwNumServiceArgs)
707 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
708 dwNumServiceArgs*sizeof(LPWSTR) );
709 else
710 lpwstr = NULL;
712 for(i=0; i<dwNumServiceArgs; i++)
714 RtlCreateUnicodeStringFromAsciiz (&usBuffer,lpServiceArgVectors[i]);
715 lpwstr[i]=usBuffer.Buffer;
718 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
720 if(dwNumServiceArgs)
722 for(i=0; i<dwNumServiceArgs; i++)
723 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
724 HeapFree(GetProcessHeap(), 0, lpwstr);
727 return TRUE;
731 /******************************************************************************
732 * StartServiceW [ADVAPI32.@]
734 * See StartServiceA.
736 BOOL WINAPI
737 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
738 LPCWSTR *lpServiceArgVectors )
740 static const WCHAR _WaitServiceStartW[] = {'A','D','V','A','P','I','_','W',
741 'a','i','t','S','e','r','v','i',
742 'c','e','S','t','a','r','t',0};
743 static const WCHAR _ImagePathW[] = {'I','m','a','g','e','P','a','t','h',0};
745 WCHAR path[MAX_PATH],str[MAX_PATH];
746 DWORD type,size;
747 long r;
748 HANDLE data,wait;
749 PROCESS_INFORMATION procinfo;
750 STARTUPINFOW startupinfo;
751 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,
752 lpServiceArgVectors);
754 size = sizeof(str);
755 r = RegQueryValueExW(hService, _ImagePathW, NULL, &type, (LPVOID)str, &size);
756 if (r!=ERROR_SUCCESS)
757 return FALSE;
758 ExpandEnvironmentStringsW(str,path,sizeof(path));
760 TRACE("Starting service %s\n", debugstr_w(path) );
762 data = CreateSemaphoreW(NULL,1,1,_ServiceStartDataW);
763 if (!data)
765 ERR("Couldn't create data semaphore\n");
766 return FALSE;
768 wait = CreateSemaphoreW(NULL,0,1,_WaitServiceStartW);
769 if (!wait)
771 ERR("Couldn't create wait semaphore\n");
772 return FALSE;
776 * FIXME: lpServiceArgsVectors need to be stored and returned to
777 * the service when it calls StartServiceCtrlDispatcher
779 * Chuck these in a global (yuk) so we can pass them to
780 * another process - address space separation will break this.
783 r = WaitForSingleObject(data,INFINITE);
785 if( r == WAIT_FAILED)
786 return FALSE;
788 FIXME("problematic because of address space separation.\n");
789 start_dwNumServiceArgs = dwNumServiceArgs;
790 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
792 ZeroMemory(&startupinfo,sizeof(STARTUPINFOW));
793 startupinfo.cb = sizeof(STARTUPINFOW);
795 r = CreateProcessW(path,
796 NULL,
797 NULL, /* process security attribs */
798 NULL, /* thread security attribs */
799 FALSE, /* inherit handles */
800 0, /* creation flags */
801 NULL, /* environment */
802 NULL, /* current directory */
803 &startupinfo, /* startup info */
804 &procinfo); /* process info */
806 if(r == FALSE)
808 ERR("Couldn't start process\n");
809 /* ReleaseSemaphore(data, 1, NULL);
810 return FALSE; */
813 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
814 r = WaitForSingleObject(wait,30000);
816 ReleaseSemaphore(data, 1, NULL);
818 if( r == WAIT_FAILED)
819 return FALSE;
821 return TRUE;
824 /******************************************************************************
825 * QueryServiceStatus [ADVAPI32.@]
827 * PARAMS
828 * hService []
829 * lpservicestatus []
832 BOOL WINAPI
833 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
835 LONG r;
836 DWORD type, val, size;
838 FIXME("(%p,%p) partial\n",hService,lpservicestatus);
840 /* read the service type from the registry */
841 size = sizeof(val);
842 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
843 if(type!=REG_DWORD)
845 ERR("invalid Type\n");
846 return FALSE;
848 lpservicestatus->dwServiceType = val;
849 /* FIXME: how are these determined or read from the registry? */
850 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
851 lpservicestatus->dwCurrentState = 1;
852 lpservicestatus->dwControlsAccepted = 0;
853 lpservicestatus->dwWin32ExitCode = NO_ERROR;
854 lpservicestatus->dwServiceSpecificExitCode = 0;
855 lpservicestatus->dwCheckPoint = 0;
856 lpservicestatus->dwWaitHint = 0;
858 return TRUE;
861 /******************************************************************************
862 * QueryServiceStatusEx [ADVAPI32.@]
864 * Get information about a service.
866 * PARAMS
867 * hService [I] Handle to service to get information about
868 * InfoLevel [I] Level of information to get
869 * lpBuffer [O] Destination for requested information
870 * cbBufSize [I] Size of lpBuffer in bytes
871 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
873 * RETURNS
874 * Success: TRUE
875 * FAILURE: FALSE
877 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
878 LPBYTE lpBuffer, DWORD cbBufSize,
879 LPDWORD pcbBytesNeeded)
881 FIXME("stub\n");
882 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
883 return FALSE;
886 /******************************************************************************
887 * QueryServiceConfigA [ADVAPI32.@]
889 BOOL WINAPI
890 QueryServiceConfigA( SC_HANDLE hService,
891 LPQUERY_SERVICE_CONFIGA lpServiceConfig,
892 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
894 FIXME("%p %p %ld %p\n", hService, lpServiceConfig,
895 cbBufSize, pcbBytesNeeded);
896 return FALSE;
899 /******************************************************************************
900 * QueryServiceConfigW [ADVAPI32.@]
902 BOOL WINAPI
903 QueryServiceConfigW( SC_HANDLE hService,
904 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
905 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
907 static const WCHAR szDisplayName[] = {
908 'D','i','s','p','l','a','y','N','a','m','e', 0 };
909 static const WCHAR szType[] = {'T','y','p','e',0};
910 static const WCHAR szStart[] = {'S','t','a','r','t',0};
911 static const WCHAR szError[] = {
912 'E','r','r','o','r','C','o','n','t','r','o','l', 0};
913 static const WCHAR szImagePath[] = {'I','m','a','g','e','P','a','t','h',0};
914 static const WCHAR szGroup[] = {'G','r','o','u','p',0};
915 static const WCHAR szDependencies[] = {
916 'D','e','p','e','n','d','e','n','c','i','e','s',0};
917 LONG r;
918 DWORD type, val, sz, total, n;
919 LPBYTE p;
921 TRACE("%p %p %ld %p\n", hService, lpServiceConfig,
922 cbBufSize, pcbBytesNeeded);
924 /* calculate the size required first */
925 total = sizeof (QUERY_SERVICE_CONFIGW);
927 sz = 0;
928 r = RegQueryValueExW( hService, szImagePath, 0, &type, NULL, &sz );
929 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
930 total += sz;
932 sz = 0;
933 r = RegQueryValueExW( hService, szGroup, 0, &type, NULL, &sz );
934 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
935 total += sz;
937 sz = 0;
938 r = RegQueryValueExW( hService, szDependencies, 0, &type, NULL, &sz );
939 if( ( r == ERROR_SUCCESS ) && ( type == REG_MULTI_SZ ) )
940 total += sz;
942 sz = 0;
943 r = RegQueryValueExW( hService, szStart, 0, &type, NULL, &sz );
944 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
945 total += sz;
947 sz = 0;
948 r = RegQueryValueExW( hService, szDisplayName, 0, &type, NULL, &sz );
949 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
950 total += sz;
952 /* if there's not enough memory, return an error */
953 if( total > *pcbBytesNeeded )
955 *pcbBytesNeeded = total;
956 SetLastError( ERROR_INSUFFICIENT_BUFFER );
957 return FALSE;
960 *pcbBytesNeeded = total;
961 ZeroMemory( lpServiceConfig, total );
963 sz = sizeof val;
964 r = RegQueryValueExW( hService, szType, 0, &type, (LPBYTE)&val, &sz );
965 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
966 lpServiceConfig->dwServiceType = val;
968 sz = sizeof val;
969 r = RegQueryValueExW( hService, szStart, 0, &type, (LPBYTE)&val, &sz );
970 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
971 lpServiceConfig->dwStartType = val;
973 sz = sizeof val;
974 r = RegQueryValueExW( hService, szError, 0, &type, (LPBYTE)&val, &sz );
975 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
976 lpServiceConfig->dwErrorControl = val;
978 /* now do the strings */
979 p = (LPBYTE) &lpServiceConfig[1];
980 n = total - sizeof (QUERY_SERVICE_CONFIGW);
982 sz = n;
983 r = RegQueryValueExW( hService, szImagePath, 0, &type, p, &sz );
984 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
986 lpServiceConfig->lpBinaryPathName = (LPWSTR) p;
987 p += sz;
988 n -= sz;
991 sz = n;
992 r = RegQueryValueExW( hService, szGroup, 0, &type, p, &sz );
993 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
995 lpServiceConfig->lpLoadOrderGroup = (LPWSTR) p;
996 p += sz;
997 n -= sz;
1000 sz = n;
1001 r = RegQueryValueExW( hService, szDependencies, 0, &type, p, &sz );
1002 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
1004 lpServiceConfig->lpDependencies = (LPWSTR) p;
1005 p += sz;
1006 n -= sz;
1009 if( n < 0 )
1010 ERR("Buffer overflow!\n");
1012 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1013 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1015 return TRUE;
1018 /******************************************************************************
1019 * ChangeServiceConfigW [ADVAPI32.@]
1021 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
1022 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1023 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
1024 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
1026 FIXME("%p %ld %ld %ld %s %s %p %p %s %s %s\n",
1027 hService, dwServiceType, dwStartType, dwErrorControl,
1028 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
1029 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
1030 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
1031 return TRUE;
1034 /******************************************************************************
1035 * ChangeServiceConfigA [ADVAPI32.@]
1037 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
1038 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1039 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
1040 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
1042 FIXME("%p %ld %ld %ld %s %s %p %p %s %s %s\n",
1043 hService, dwServiceType, dwStartType, dwErrorControl,
1044 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
1045 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
1046 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
1047 return TRUE;
1050 /******************************************************************************
1051 * ChangeServiceConfig2A [ADVAPI32.@]
1053 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
1054 LPVOID lpInfo)
1056 FIXME("STUB: %p %ld %p\n",hService, dwInfoLevel, lpInfo);
1057 return TRUE;
1060 /******************************************************************************
1061 * ChangeServiceConfig2W [ADVAPI32.@]
1063 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
1064 LPVOID lpInfo)
1066 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
1068 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
1069 LPSERVICE_DESCRIPTIONW sd = (LPSERVICE_DESCRIPTIONW)lpInfo;
1070 if (sd->lpDescription)
1072 TRACE("Setting Description to %s\n",debugstr_w(sd->lpDescription));
1073 if (sd->lpDescription[0] == 0)
1074 RegDeleteValueW(hService,szDescription);
1075 else
1076 RegSetValueExW(hService, szDescription, 0, REG_SZ,
1077 (LPVOID)sd->lpDescription,
1078 sizeof(WCHAR)*(strlenW(sd->lpDescription)+1));
1081 else
1082 FIXME("STUB: %p %ld %p\n",hService, dwInfoLevel, lpInfo);
1083 return TRUE;