Allocate the correct nr of bytes for lpszCookies in HTTP_HttpOpenRequestA.
[wine.git] / dlls / advapi32 / service.c
blob70f7b5297a6ff6104618cfbca62d82005b533d1a
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 SC_HANDLE WINAPI
245 OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
246 DWORD dwDesiredAccess )
248 UNICODE_STRING lpMachineNameW;
249 UNICODE_STRING lpDatabaseNameW;
250 SC_HANDLE ret;
252 RtlCreateUnicodeStringFromAsciiz (&lpMachineNameW,lpMachineName);
253 RtlCreateUnicodeStringFromAsciiz (&lpDatabaseNameW,lpDatabaseName);
254 ret = OpenSCManagerW(lpMachineNameW.Buffer,lpDatabaseNameW.Buffer, dwDesiredAccess);
255 RtlFreeUnicodeString(&lpDatabaseNameW);
256 RtlFreeUnicodeString(&lpMachineNameW);
257 return ret;
260 /******************************************************************************
261 * OpenSCManagerW [ADVAPI32.@]
262 * Establishes a connection to the service control manager and opens database
264 * NOTES
265 * This should return a SC_HANDLE
267 * PARAMS
268 * lpMachineName [I] Pointer to machine name string
269 * lpDatabaseName [I] Pointer to database name string
270 * dwDesiredAccess [I] Type of access
272 * RETURNS
273 * Success: Handle to service control manager database
274 * Failure: NULL
276 SC_HANDLE WINAPI
277 OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
278 DWORD dwDesiredAccess )
280 HKEY hReg, hKey = NULL;
281 LONG r;
283 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
284 debugstr_w(lpDatabaseName), dwDesiredAccess);
287 * FIXME: what is lpDatabaseName?
288 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
289 * docs, but what if it isn't?
292 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg);
293 if (r==ERROR_SUCCESS)
295 r = RegOpenKeyExW(hReg, szServiceManagerKey,0, dwDesiredAccess, &hKey );
296 RegCloseKey( hReg );
299 TRACE("returning %p\n", hKey);
301 return hKey;
305 /******************************************************************************
306 * AllocateLocallyUniqueId [ADVAPI32.@]
308 * PARAMS
309 * lpluid []
311 BOOL WINAPI
312 AllocateLocallyUniqueId( PLUID lpluid )
314 lpluid->LowPart = time(NULL);
315 lpluid->HighPart = 0;
316 return TRUE;
320 /******************************************************************************
321 * ControlService [ADVAPI32.@]
322 * Sends a control code to a Win32-based service.
324 * PARAMS
325 * hService []
326 * dwControl []
327 * lpServiceStatus []
329 * RETURNS STD
331 BOOL WINAPI
332 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.@]
342 * Close handle to service or service control manager
344 * PARAMS
345 * hSCObject [I] Handle to service or service control manager database
347 * RETURNS STD
349 BOOL WINAPI
350 CloseServiceHandle( SC_HANDLE hSCObject )
352 TRACE("(%p)\n", hSCObject);
354 RegCloseKey(hSCObject);
356 return TRUE;
360 /******************************************************************************
361 * OpenServiceA [ADVAPI32.@]
363 SC_HANDLE WINAPI
364 OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
365 DWORD dwDesiredAccess )
367 UNICODE_STRING lpServiceNameW;
368 SC_HANDLE ret;
369 RtlCreateUnicodeStringFromAsciiz (&lpServiceNameW,lpServiceName);
370 if(lpServiceName)
371 TRACE("Request for service %s\n",lpServiceName);
372 else
373 return FALSE;
374 ret = OpenServiceW( hSCManager, lpServiceNameW.Buffer, dwDesiredAccess);
375 RtlFreeUnicodeString(&lpServiceNameW);
376 return ret;
380 /******************************************************************************
381 * OpenServiceW [ADVAPI32.@]
382 * Opens a handle to an existing service
384 * PARAMS
385 * hSCManager []
386 * lpServiceName []
387 * dwDesiredAccess []
389 * RETURNS
390 * Success: Handle to the service
391 * Failure: NULL
393 SC_HANDLE WINAPI
394 OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName,
395 DWORD dwDesiredAccess)
397 HKEY hKey;
398 long r;
400 TRACE("(%p,%p,%ld)\n",hSCManager, lpServiceName,
401 dwDesiredAccess);
403 /* FIXME: dwDesiredAccess may need some processing */
404 r = RegOpenKeyExW(hSCManager, lpServiceName, 0, dwDesiredAccess, &hKey );
405 if (r!=ERROR_SUCCESS)
406 return 0;
408 TRACE("returning %p\n",hKey);
410 return hKey;
413 /******************************************************************************
414 * CreateServiceW [ADVAPI32.@]
416 SC_HANDLE WINAPI
417 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
418 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
419 DWORD dwServiceType, DWORD dwStartType,
420 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
421 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
422 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
423 LPCWSTR lpPassword )
425 HKEY hKey;
426 LONG r;
427 DWORD dp;
428 const WCHAR szDisplayName[] = { 'D','i','s','p','l','a','y','N','a','m','e', 0 };
429 const WCHAR szType[] = {'T','y','p','e',0};
430 const WCHAR szStart[] = {'S','t','a','r','t',0};
431 const WCHAR szError[] = {'E','r','r','o','r','C','o','n','t','r','o','l', 0};
432 const WCHAR szImagePath[] = {'I','m','a','g','e','P','a','t','h',0};
433 const WCHAR szGroup[] = {'G','r','o','u','p',0};
434 const WCHAR szDependencies[] = { 'D','e','p','e','n','d','e','n','c','i','e','s',0};
436 FIXME("%p %s %s\n", hSCManager,
437 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
439 r = RegCreateKeyExW(hSCManager, lpServiceName, 0, NULL,
440 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dp);
441 if (r!=ERROR_SUCCESS)
442 return 0;
444 if (dp != REG_CREATED_NEW_KEY)
445 return 0;
447 if(lpDisplayName)
449 r = RegSetValueExW(hKey, szDisplayName, 0, REG_SZ, (LPBYTE)lpDisplayName,
450 (strlenW(lpDisplayName)+1)*sizeof(WCHAR) );
451 if (r!=ERROR_SUCCESS)
452 return 0;
455 r = RegSetValueExW(hKey, szType, 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
456 if (r!=ERROR_SUCCESS)
457 return 0;
459 r = RegSetValueExW(hKey, szStart, 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
460 if (r!=ERROR_SUCCESS)
461 return 0;
463 r = RegSetValueExW(hKey, szError, 0, REG_DWORD,
464 (LPVOID)&dwErrorControl, sizeof (DWORD) );
465 if (r!=ERROR_SUCCESS)
466 return 0;
468 if(lpBinaryPathName)
470 r = RegSetValueExW(hKey, szImagePath, 0, REG_SZ, (LPBYTE)lpBinaryPathName,
471 (strlenW(lpBinaryPathName)+1)*sizeof(WCHAR) );
472 if (r!=ERROR_SUCCESS)
473 return 0;
476 if(lpLoadOrderGroup)
478 r = RegSetValueExW(hKey, szGroup, 0, REG_SZ, (LPBYTE)lpLoadOrderGroup,
479 (strlenW(lpLoadOrderGroup)+1)*sizeof(WCHAR) );
480 if (r!=ERROR_SUCCESS)
481 return 0;
484 if(lpDependencies)
486 DWORD len = 0;
488 /* determine the length of a double null terminated multi string */
489 do {
490 len += (strlenW(&lpDependencies[len])+1);
491 } while (lpDependencies[len++]);
493 r = RegSetValueExW(hKey, szDependencies, 0, REG_MULTI_SZ,
494 (LPBYTE)lpDependencies, len );
495 if (r!=ERROR_SUCCESS)
496 return 0;
499 if(lpPassword)
501 FIXME("Don't know how to add a Password for a service.\n");
504 if(lpServiceStartName)
506 FIXME("Don't know how to add a ServiceStartName for a service.\n");
509 return hKey;
513 static inline LPWSTR SERV_dup( LPCSTR str )
515 UINT len;
516 LPWSTR wstr;
518 if( !str )
519 return NULL;
520 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
521 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
522 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
523 return wstr;
526 static inline LPWSTR SERV_dupmulti( LPCSTR str )
528 UINT len = 0, n = 0;
529 LPWSTR wstr;
531 if( !str )
532 return NULL;
533 do {
534 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
535 n += (strlen( &str[n] ) + 1);
536 } while (str[n]);
537 len++;
538 n++;
540 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
541 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
542 return wstr;
545 static inline VOID SERV_free( LPWSTR wstr )
547 HeapFree( GetProcessHeap(), 0, wstr );
550 /******************************************************************************
551 * CreateServiceA [ADVAPI32.@]
553 SC_HANDLE WINAPI
554 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
555 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
556 DWORD dwServiceType, DWORD dwStartType,
557 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
558 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
559 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
560 LPCSTR lpPassword )
562 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
563 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
564 SC_HANDLE r;
566 TRACE("%p %s %s\n", hSCManager,
567 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
569 lpServiceNameW = SERV_dup( lpServiceName );
570 lpDisplayNameW = SERV_dup( lpDisplayName );
571 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
572 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
573 lpDependenciesW = SERV_dupmulti( lpDependencies );
574 lpServiceStartNameW = SERV_dup( lpServiceStartName );
575 lpPasswordW = SERV_dup( lpPassword );
577 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
578 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
579 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
580 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
582 SERV_free( lpServiceNameW );
583 SERV_free( lpDisplayNameW );
584 SERV_free( lpBinaryPathNameW );
585 SERV_free( lpLoadOrderGroupW );
586 SERV_free( lpDependenciesW );
587 SERV_free( lpServiceStartNameW );
588 SERV_free( lpPasswordW );
590 return r;
594 /******************************************************************************
595 * DeleteService [ADVAPI32.@]
597 * PARAMS
598 * hService [I] Handle to service
600 * RETURNS STD
603 BOOL WINAPI
604 DeleteService( SC_HANDLE hService )
606 WCHAR valname[MAX_PATH+1];
607 INT index = 0;
608 LONG rc;
609 DWORD value = 0x1;
610 DWORD size;
611 HKEY hKey;
613 static const WCHAR szDeleted[] = {'D','e','l','e','t','e','d',0};
615 FIXME("(%p): stub\n",hService);
617 size = MAX_PATH+1;
618 /* Clean out the values */
619 rc = RegEnumValueW(hService, index, valname,&size,0,0,0,0);
620 while (rc == ERROR_SUCCESS)
622 RegDeleteValueW(hService,valname);
623 index++;
624 size = MAX_PATH+1;
625 rc = RegEnumValueW(hService, index, valname, &size,0,0,0,0);
628 /* tag for deletion */
629 RegSetValueExW(hService, szDeleted, 0, REG_DWORD, (LPVOID)&value,
630 sizeof (DWORD) );
632 RegCloseKey(hService);
634 /* find and delete the key */
635 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szServiceManagerKey,0,
636 KEY_ALL_ACCESS, &hKey );
637 index = 0;
638 size = MAX_PATH+1;
639 rc = RegEnumKeyExW(hKey,0, valname, &size, 0, 0, 0, 0);
640 while (rc == ERROR_SUCCESS)
642 HKEY checking;
643 rc = RegOpenKeyExW(hKey,valname,0,KEY_ALL_ACCESS,&checking);
644 if (rc == ERROR_SUCCESS)
646 DWORD deleted = 0;
647 DWORD size = sizeof(DWORD);
648 rc = RegQueryValueExW(checking, szDeleted , NULL, NULL,
649 (LPVOID)&deleted, &size);
650 if (deleted)
652 RegDeleteValueW(checking,szDeleted);
653 RegDeleteKeyW(hKey,valname);
655 else
656 index ++;
657 RegCloseKey(checking);
659 size = MAX_PATH+1;
660 rc = RegEnumKeyExW(hKey, index, valname, &size, 0, 0, 0, 0);
662 RegCloseKey(hKey);
664 return TRUE;
668 /******************************************************************************
669 * StartServiceA [ADVAPI32.@]
672 BOOL WINAPI
673 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
674 LPCSTR *lpServiceArgVectors )
676 LPWSTR *lpwstr=NULL;
677 UNICODE_STRING usBuffer;
678 int i;
680 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
682 if(dwNumServiceArgs)
683 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
684 dwNumServiceArgs*sizeof(LPWSTR) );
685 else
686 lpwstr = NULL;
688 for(i=0; i<dwNumServiceArgs; i++)
690 RtlCreateUnicodeStringFromAsciiz (&usBuffer,lpServiceArgVectors[i]);
691 lpwstr[i]=usBuffer.Buffer;
694 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
696 if(dwNumServiceArgs)
698 for(i=0; i<dwNumServiceArgs; i++)
699 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
700 HeapFree(GetProcessHeap(), 0, lpwstr);
703 return TRUE;
707 /******************************************************************************
708 * StartServiceW [ADVAPI32.@]
709 * Starts a service
711 * PARAMS
712 * hService [I] Handle of service
713 * dwNumServiceArgs [I] Number of arguments
714 * lpServiceArgVectors [I] Address of array of argument string pointers
716 * NOTES
718 * NT implements this function using an obscure RPC call...
720 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
721 * to get things like %SystemRoot%\\System32\\service.exe to load.
723 * Will only work for shared address space. How should the service
724 * args be transferred when address spaces are separated?
726 * Can only start one service at a time.
728 * Has no concept of privilege.
730 * RETURNS STD
733 BOOL WINAPI
734 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
735 LPCWSTR *lpServiceArgVectors )
737 static const WCHAR _WaitServiceStartW[] = {'A','D','V','A','P','I','_','W',
738 'a','i','t','S','e','r','v','i',
739 'c','e','S','t','a','r','t',0};
740 static const WCHAR _ImagePathW[] = {'I','m','a','g','e','P','a','t','h',0};
742 WCHAR path[MAX_PATH],str[MAX_PATH];
743 DWORD type,size;
744 long r;
745 HANDLE data,wait;
746 PROCESS_INFORMATION procinfo;
747 STARTUPINFOW startupinfo;
748 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,
749 lpServiceArgVectors);
751 size = sizeof(str);
752 r = RegQueryValueExW(hService, _ImagePathW, NULL, &type, (LPVOID)str, &size);
753 if (r!=ERROR_SUCCESS)
754 return FALSE;
755 ExpandEnvironmentStringsW(str,path,sizeof(path));
757 TRACE("Starting service %s\n", debugstr_w(path) );
759 data = CreateSemaphoreW(NULL,1,1,_ServiceStartDataW);
760 if (!data)
762 ERR("Couldn't create data semaphore\n");
763 return FALSE;
765 wait = CreateSemaphoreW(NULL,0,1,_WaitServiceStartW);
766 if (!wait)
768 ERR("Couldn't create wait semaphore\n");
769 return FALSE;
773 * FIXME: lpServiceArgsVectors need to be stored and returned to
774 * the service when it calls StartServiceCtrlDispatcher
776 * Chuck these in a global (yuk) so we can pass them to
777 * another process - address space separation will break this.
780 r = WaitForSingleObject(data,INFINITE);
782 if( r == WAIT_FAILED)
783 return FALSE;
785 FIXME("problematic because of address space separation.\n");
786 start_dwNumServiceArgs = dwNumServiceArgs;
787 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
789 ZeroMemory(&startupinfo,sizeof(STARTUPINFOW));
790 startupinfo.cb = sizeof(STARTUPINFOW);
792 r = CreateProcessW(path,
793 NULL,
794 NULL, /* process security attribs */
795 NULL, /* thread security attribs */
796 FALSE, /* inherit handles */
797 0, /* creation flags */
798 NULL, /* environment */
799 NULL, /* current directory */
800 &startupinfo, /* startup info */
801 &procinfo); /* process info */
803 if(r == FALSE)
805 ERR("Couldn't start process\n");
806 /* ReleaseSemaphore(data, 1, NULL);
807 return FALSE; */
810 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
811 r = WaitForSingleObject(wait,30000);
813 ReleaseSemaphore(data, 1, NULL);
815 if( r == WAIT_FAILED)
816 return FALSE;
818 return TRUE;
821 /******************************************************************************
822 * QueryServiceStatus [ADVAPI32.@]
824 * PARAMS
825 * hService []
826 * lpservicestatus []
829 BOOL WINAPI
830 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
832 LONG r;
833 DWORD type, val, size;
835 FIXME("(%p,%p) partial\n",hService,lpservicestatus);
837 /* read the service type from the registry */
838 size = sizeof(val);
839 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
840 if(type!=REG_DWORD)
842 ERR("invalid Type\n");
843 return FALSE;
845 lpservicestatus->dwServiceType = val;
846 /* FIXME: how are these determined or read from the registry? */
847 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
848 lpservicestatus->dwCurrentState = 1;
849 lpservicestatus->dwControlsAccepted = 0;
850 lpservicestatus->dwWin32ExitCode = NO_ERROR;
851 lpservicestatus->dwServiceSpecificExitCode = 0;
852 lpservicestatus->dwCheckPoint = 0;
853 lpservicestatus->dwWaitHint = 0;
855 return TRUE;
858 /******************************************************************************
859 * QueryServiceStatusEx [ADVAPI32.@]
861 * PARAMS
862 * hService [handle to service]
863 * InfoLevel [information level]
864 * lpBuffer [buffer]
865 * cbBufSize [size of buffer]
866 * pcbBytesNeeded [bytes needed]
868 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
869 LPBYTE lpBuffer, DWORD cbBufSize,
870 LPDWORD pcbBytesNeeded)
872 FIXME("stub\n");
873 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
874 return FALSE;
877 /******************************************************************************
878 * QueryServiceConfigA [ADVAPI32.@]
880 BOOL WINAPI
881 QueryServiceConfigA( SC_HANDLE hService,
882 LPQUERY_SERVICE_CONFIGA lpServiceConfig,
883 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
885 FIXME("%p %p %ld %p\n", hService, lpServiceConfig,
886 cbBufSize, pcbBytesNeeded);
887 return FALSE;
890 /******************************************************************************
891 * QueryServiceConfigW [ADVAPI32.@]
893 BOOL WINAPI
894 QueryServiceConfigW( SC_HANDLE hService,
895 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
896 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
898 const WCHAR szDisplayName[] = {
899 'D','i','s','p','l','a','y','N','a','m','e', 0 };
900 const WCHAR szType[] = {'T','y','p','e',0};
901 const WCHAR szStart[] = {'S','t','a','r','t',0};
902 const WCHAR szError[] = {
903 'E','r','r','o','r','C','o','n','t','r','o','l', 0};
904 const WCHAR szImagePath[] = {'I','m','a','g','e','P','a','t','h',0};
905 const WCHAR szGroup[] = {'G','r','o','u','p',0};
906 const WCHAR szDependencies[] = {
907 'D','e','p','e','n','d','e','n','c','i','e','s',0};
908 LONG r;
909 DWORD type, val, sz, total, n;
910 LPBYTE p;
912 TRACE("%p %p %ld %p\n", hService, lpServiceConfig,
913 cbBufSize, pcbBytesNeeded);
915 /* calculate the size required first */
916 total = sizeof (QUERY_SERVICE_CONFIGW);
918 sz = 0;
919 r = RegQueryValueExW( hService, szImagePath, 0, &type, NULL, &sz );
920 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
921 total += sz;
923 sz = 0;
924 r = RegQueryValueExW( hService, szGroup, 0, &type, NULL, &sz );
925 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
926 total += sz;
928 sz = 0;
929 r = RegQueryValueExW( hService, szDependencies, 0, &type, NULL, &sz );
930 if( ( r == ERROR_SUCCESS ) && ( type == REG_MULTI_SZ ) )
931 total += sz;
933 sz = 0;
934 r = RegQueryValueExW( hService, szStart, 0, &type, NULL, &sz );
935 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
936 total += sz;
938 sz = 0;
939 r = RegQueryValueExW( hService, szDisplayName, 0, &type, NULL, &sz );
940 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
941 total += sz;
943 /* if there's not enough memory, return an error */
944 if( total > *pcbBytesNeeded )
946 *pcbBytesNeeded = total;
947 SetLastError( ERROR_INSUFFICIENT_BUFFER );
948 return FALSE;
951 *pcbBytesNeeded = total;
952 ZeroMemory( lpServiceConfig, total );
954 sz = sizeof val;
955 r = RegQueryValueExW( hService, szType, 0, &type, (LPBYTE)&val, &sz );
956 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
957 lpServiceConfig->dwServiceType = val;
959 sz = sizeof val;
960 r = RegQueryValueExW( hService, szStart, 0, &type, (LPBYTE)&val, &sz );
961 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
962 lpServiceConfig->dwStartType = val;
964 sz = sizeof val;
965 r = RegQueryValueExW( hService, szError, 0, &type, (LPBYTE)&val, &sz );
966 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
967 lpServiceConfig->dwErrorControl = val;
969 /* now do the strings */
970 p = (LPBYTE) &lpServiceConfig[1];
971 n = total - sizeof (QUERY_SERVICE_CONFIGW);
973 sz = n;
974 r = RegQueryValueExW( hService, szImagePath, 0, &type, p, &sz );
975 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
977 lpServiceConfig->lpBinaryPathName = (LPWSTR) p;
978 p += sz;
979 n -= sz;
982 sz = n;
983 r = RegQueryValueExW( hService, szGroup, 0, &type, p, &sz );
984 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
986 lpServiceConfig->lpLoadOrderGroup = (LPWSTR) p;
987 p += sz;
988 n -= sz;
991 sz = n;
992 r = RegQueryValueExW( hService, szDependencies, 0, &type, p, &sz );
993 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
995 lpServiceConfig->lpDependencies = (LPWSTR) p;
996 p += sz;
997 n -= sz;
1000 if( n < 0 )
1001 ERR("Buffer overflow!\n");
1003 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1004 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1006 return TRUE;
1009 /******************************************************************************
1010 * ChangeServiceConfigW [ADVAPI32.@]
1012 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
1013 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1014 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
1015 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
1017 FIXME("%p %ld %ld %ld %s %s %p %p %s %s %s\n",
1018 hService, dwServiceType, dwStartType, dwErrorControl,
1019 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
1020 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
1021 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
1022 return TRUE;
1025 /******************************************************************************
1026 * ChangeServiceConfigA [ADVAPI32.@]
1028 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
1029 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1030 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
1031 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
1033 FIXME("%p %ld %ld %ld %s %s %p %p %s %s %s\n",
1034 hService, dwServiceType, dwStartType, dwErrorControl,
1035 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
1036 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
1037 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
1038 return TRUE;
1041 /******************************************************************************
1042 * ChangeServiceConfig2A [ADVAPI32.@]
1044 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
1045 LPVOID lpInfo)
1047 FIXME("STUB: %p %ld %p\n",hService, dwInfoLevel, lpInfo);
1048 return TRUE;
1051 /******************************************************************************
1052 * ChangeServiceConfig2W [ADVAPI32.@]
1054 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
1055 LPVOID lpInfo)
1057 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
1059 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
1060 LPSERVICE_DESCRIPTIONW sd = (LPSERVICE_DESCRIPTIONW)lpInfo;
1061 if (sd->lpDescription)
1063 TRACE("Setting Description to %s\n",debugstr_w(sd->lpDescription));
1064 if (sd->lpDescription[0] == 0)
1065 RegDeleteValueW(hService,szDescription);
1066 else
1067 RegSetValueExW(hService, szDescription, 0, REG_SZ,
1068 (LPVOID)sd->lpDescription,
1069 sizeof(WCHAR)*(strlenW(sd->lpDescription)+1));
1072 else
1073 FIXME("STUB: %p %ld %p\n",hService, dwInfoLevel, lpInfo);
1074 return TRUE;