Set version to 9.
[wine/wine64.git] / dlls / advapi32 / service.c
blob9f5b8cfe341a69984b0ef9711f830c2be7b196ca
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 /******************************************************************************
41 * EnumServicesStatusA [ADVAPI32.@]
43 BOOL WINAPI
44 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
45 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
46 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
47 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
48 { FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
49 dwServiceType, dwServiceState, lpServices, cbBufSize,
50 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
51 SetLastError (ERROR_ACCESS_DENIED);
52 return FALSE;
55 /******************************************************************************
56 * EnumServicesStatusW [ADVAPI32.@]
58 BOOL WINAPI
59 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
60 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
61 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
62 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
63 { FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
64 dwServiceType, dwServiceState, lpServices, cbBufSize,
65 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
66 SetLastError (ERROR_ACCESS_DENIED);
67 return FALSE;
70 /******************************************************************************
71 * StartServiceCtrlDispatcherA [ADVAPI32.@]
73 BOOL WINAPI
74 StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
76 LPSERVICE_MAIN_FUNCTIONA fpMain;
77 HANDLE wait;
78 DWORD dwNumServiceArgs ;
79 LPWSTR *lpArgVecW;
80 LPSTR *lpArgVecA;
81 int i;
83 TRACE("(%p)\n", servent);
84 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
85 if(wait == 0)
87 ERR("Couldn't find wait semaphore\n");
88 ERR("perhaps you need to start services using StartService\n");
89 return FALSE;
92 dwNumServiceArgs = start_dwNumServiceArgs;
93 lpArgVecW = start_lpServiceArgVectors;
95 ReleaseSemaphore(wait, 1, NULL);
97 /* Convert the Unicode arg vectors back to ASCII */
98 if(dwNumServiceArgs)
99 lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0,
100 dwNumServiceArgs*sizeof(LPSTR) );
101 else
102 lpArgVecA = NULL;
104 for(i=0; i<dwNumServiceArgs; i++)
105 lpArgVecA[i]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW[i]);
107 /* FIXME: should we blindly start all services? */
108 while (servent->lpServiceName) {
109 TRACE("%s at %p)\n", debugstr_a(servent->lpServiceName),servent);
110 fpMain = servent->lpServiceProc;
112 /* try to start the service */
113 fpMain( dwNumServiceArgs, lpArgVecA);
115 servent++;
118 if(dwNumServiceArgs)
120 /* free arg strings */
121 for(i=0; i<dwNumServiceArgs; i++)
122 HeapFree(GetProcessHeap(), 0, lpArgVecA[i]);
123 HeapFree(GetProcessHeap(), 0, lpArgVecA);
126 return TRUE;
129 /******************************************************************************
130 * StartServiceCtrlDispatcherW [ADVAPI32.@]
132 * PARAMS
133 * servent []
135 BOOL WINAPI
136 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
138 static const WCHAR _ServiceStartDataW[] = {'A','D','V','A','P','I','_','S',
139 'e','r','v','i','c','e','S','t',
140 'a','r','t','D','a','t','a',0};
141 LPSERVICE_MAIN_FUNCTIONW fpMain;
142 HANDLE wait;
143 DWORD dwNumServiceArgs ;
144 LPWSTR *lpServiceArgVectors ;
146 TRACE("(%p)\n", servent);
147 wait = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS, FALSE, _ServiceStartDataW);
148 if(wait == 0)
150 ERR("Couldn't find wait semaphore\n");
151 ERR("perhaps you need to start services using StartService\n");
152 return FALSE;
155 dwNumServiceArgs = start_dwNumServiceArgs;
156 lpServiceArgVectors = start_lpServiceArgVectors;
158 ReleaseSemaphore(wait, 1, NULL);
160 /* FIXME: should we blindly start all services? */
161 while (servent->lpServiceName) {
162 TRACE("%s at %p)\n", debugstr_w(servent->lpServiceName),servent);
163 fpMain = servent->lpServiceProc;
165 /* try to start the service */
166 fpMain( dwNumServiceArgs, lpServiceArgVectors);
168 servent++;
171 return TRUE;
174 /******************************************************************************
175 * LockServiceDatabase [ADVAPI32.@]
177 LPVOID WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
179 FIXME("%p\n",hSCManager);
180 return (SC_HANDLE)0xcacacafe;
183 /******************************************************************************
184 * UnlockServiceDatabase [ADVAPI32.@]
186 BOOL WINAPI UnlockServiceDatabase (LPVOID ScLock)
188 FIXME(": %p\n",ScLock);
189 return TRUE;
192 /******************************************************************************
193 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
195 SERVICE_STATUS_HANDLE WINAPI
196 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName,
197 LPHANDLER_FUNCTION lpfHandler )
198 { FIXME("%s %p\n", lpServiceName, lpfHandler);
199 return 0xcacacafe;
202 /******************************************************************************
203 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
205 * PARAMS
206 * lpServiceName []
207 * lpfHandler []
209 SERVICE_STATUS_HANDLE WINAPI
210 RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
211 LPHANDLER_FUNCTION lpfHandler )
212 { FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler);
213 return 0xcacacafe;
216 /******************************************************************************
217 * SetServiceStatus [ADVAPI32.@]
219 * PARAMS
220 * hService []
221 * lpStatus []
223 BOOL WINAPI
224 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
225 { FIXME("0x%lx %p\n",hService, lpStatus);
226 TRACE("\tType:%lx\n",lpStatus->dwServiceType);
227 TRACE("\tState:%lx\n",lpStatus->dwCurrentState);
228 TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted);
229 TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode);
230 TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode);
231 TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint);
232 TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint);
233 return TRUE;
236 /******************************************************************************
237 * OpenSCManagerA [ADVAPI32.@]
239 SC_HANDLE WINAPI
240 OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
241 DWORD dwDesiredAccess )
243 UNICODE_STRING lpMachineNameW;
244 UNICODE_STRING lpDatabaseNameW;
245 SC_HANDLE ret;
247 RtlCreateUnicodeStringFromAsciiz (&lpMachineNameW,lpMachineName);
248 RtlCreateUnicodeStringFromAsciiz (&lpDatabaseNameW,lpDatabaseName);
249 ret = OpenSCManagerW(lpMachineNameW.Buffer,lpDatabaseNameW.Buffer, dwDesiredAccess);
250 RtlFreeUnicodeString(&lpDatabaseNameW);
251 RtlFreeUnicodeString(&lpMachineNameW);
252 return ret;
255 /******************************************************************************
256 * OpenSCManagerW [ADVAPI32.@]
257 * Establishes a connection to the service control manager and opens database
259 * NOTES
260 * This should return a SC_HANDLE
262 * PARAMS
263 * lpMachineName [I] Pointer to machine name string
264 * lpDatabaseName [I] Pointer to database name string
265 * dwDesiredAccess [I] Type of access
267 * RETURNS
268 * Success: Handle to service control manager database
269 * Failure: NULL
271 SC_HANDLE WINAPI
272 OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
273 DWORD dwDesiredAccess )
275 HKEY hKey;
276 LONG r;
278 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
279 debugstr_w(lpDatabaseName), dwDesiredAccess);
282 * FIXME: what is lpDatabaseName?
283 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
284 * docs, but what if it isn't?
287 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hKey);
288 if (r!=ERROR_SUCCESS)
289 return 0;
291 TRACE("returning %p\n",hKey);
293 return hKey;
297 /******************************************************************************
298 * AllocateLocallyUniqueId [ADVAPI32.@]
300 * PARAMS
301 * lpluid []
303 BOOL WINAPI
304 AllocateLocallyUniqueId( PLUID lpluid )
306 lpluid->LowPart = time(NULL);
307 lpluid->HighPart = 0;
308 return TRUE;
312 /******************************************************************************
313 * ControlService [ADVAPI32.@]
314 * Sends a control code to a Win32-based service.
316 * PARAMS
317 * hService []
318 * dwControl []
319 * lpServiceStatus []
321 * RETURNS STD
323 BOOL WINAPI
324 ControlService( SC_HANDLE hService, DWORD dwControl,
325 LPSERVICE_STATUS lpServiceStatus )
327 FIXME("(%p,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
328 return TRUE;
332 /******************************************************************************
333 * CloseServiceHandle [ADVAPI32.@]
334 * Close handle to service or service control manager
336 * PARAMS
337 * hSCObject [I] Handle to service or service control manager database
339 * RETURNS STD
341 BOOL WINAPI
342 CloseServiceHandle( SC_HANDLE hSCObject )
344 TRACE("(%p)\n", hSCObject);
346 RegCloseKey(hSCObject);
348 return TRUE;
352 /******************************************************************************
353 * OpenServiceA [ADVAPI32.@]
355 SC_HANDLE WINAPI
356 OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
357 DWORD dwDesiredAccess )
359 UNICODE_STRING lpServiceNameW;
360 SC_HANDLE ret;
361 RtlCreateUnicodeStringFromAsciiz (&lpServiceNameW,lpServiceName);
362 if(lpServiceName)
363 TRACE("Request for service %s\n",lpServiceName);
364 else
365 return FALSE;
366 ret = OpenServiceW( hSCManager, lpServiceNameW.Buffer, dwDesiredAccess);
367 RtlFreeUnicodeString(&lpServiceNameW);
368 return ret;
372 /******************************************************************************
373 * OpenServiceW [ADVAPI32.@]
374 * Opens a handle to an existing service
376 * PARAMS
377 * hSCManager []
378 * lpServiceName []
379 * dwDesiredAccess []
381 * RETURNS
382 * Success: Handle to the service
383 * Failure: NULL
385 SC_HANDLE WINAPI
386 OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName,
387 DWORD dwDesiredAccess)
389 const char *str = "System\\CurrentControlSet\\Services\\";
390 WCHAR lpServiceKey[80]; /* FIXME: this should be dynamically allocated */
391 HKEY hKey;
392 long r;
394 TRACE("(%p,%p,%ld)\n",hSCManager, lpServiceName,
395 dwDesiredAccess);
397 MultiByteToWideChar( CP_ACP, 0, str, -1, lpServiceKey, sizeof(lpServiceKey)/sizeof(WCHAR) );
398 strcatW(lpServiceKey,lpServiceName);
400 TRACE("Opening reg key %s\n", debugstr_w(lpServiceKey));
402 /* FIXME: dwDesiredAccess may need some processing */
403 r = RegOpenKeyExW(hSCManager, lpServiceKey, 0, dwDesiredAccess, &hKey );
404 if (r!=ERROR_SUCCESS)
405 return 0;
407 TRACE("returning %p\n",hKey);
409 return hKey;
412 /******************************************************************************
413 * CreateServiceW [ADVAPI32.@]
415 SC_HANDLE WINAPI
416 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
417 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
418 DWORD dwServiceType, DWORD dwStartType,
419 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
420 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
421 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
422 LPCWSTR lpPassword )
424 FIXME("(%p,%s,%s,...)\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
425 return 0;
429 /******************************************************************************
430 * CreateServiceA [ADVAPI32.@]
432 SC_HANDLE WINAPI
433 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
434 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
435 DWORD dwServiceType, DWORD dwStartType,
436 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
437 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
438 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
439 LPCSTR lpPassword )
441 HKEY hKey;
442 LONG r;
443 DWORD dp;
445 TRACE("(%p,%s,%s,...)\n", hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
447 r = RegCreateKeyExA(hSCManager, lpServiceName, 0, NULL,
448 REG_OPTION_NON_VOLATILE, dwDesiredAccess, NULL, &hKey, &dp);
449 if (r!=ERROR_SUCCESS)
450 return 0;
451 if (dp != REG_CREATED_NEW_KEY)
452 return 0;
454 if(lpDisplayName)
456 r = RegSetValueExA(hKey, "DisplayName", 0, REG_SZ, lpDisplayName, strlen(lpDisplayName) );
457 if (r!=ERROR_SUCCESS)
458 return 0;
461 r = RegSetValueExA(hKey, "Type", 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
462 if (r!=ERROR_SUCCESS)
463 return 0;
465 r = RegSetValueExA(hKey, "Start", 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
466 if (r!=ERROR_SUCCESS)
467 return 0;
469 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
470 (LPVOID)&dwErrorControl, sizeof (DWORD) );
471 if (r!=ERROR_SUCCESS)
472 return 0;
474 if(lpBinaryPathName)
476 r = RegSetValueExA(hKey, "ImagePath", 0, REG_SZ,
477 lpBinaryPathName,strlen(lpBinaryPathName)+1 );
478 if (r!=ERROR_SUCCESS)
479 return 0;
482 if(lpLoadOrderGroup)
484 r = RegSetValueExA(hKey, "Group", 0, REG_SZ,
485 lpLoadOrderGroup, strlen(lpLoadOrderGroup)+1 );
486 if (r!=ERROR_SUCCESS)
487 return 0;
490 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
491 (LPVOID)&dwErrorControl, sizeof (DWORD) );
492 if (r!=ERROR_SUCCESS)
493 return 0;
495 if(lpDependencies)
497 DWORD len = 0;
499 /* determine the length of a double null terminated multi string */
500 do {
501 len += (strlen(&lpDependencies[len])+1);
502 } while (lpDependencies[len++]);
504 /* FIXME: this should be unicode */
505 r = RegSetValueExA(hKey, "Dependencies", 0, REG_MULTI_SZ,
506 lpDependencies, len );
507 if (r!=ERROR_SUCCESS)
508 return 0;
511 if(lpPassword)
513 FIXME("Don't know how to add a Password for a service.\n");
516 if(lpServiceStartName)
518 FIXME("Don't know how to add a ServiceStartName for a service.\n");
521 return hKey;
525 /******************************************************************************
526 * DeleteService [ADVAPI32.@]
528 * PARAMS
529 * hService [I] Handle to service
531 * RETURNS STD
534 BOOL WINAPI
535 DeleteService( SC_HANDLE hService )
537 FIXME("(%p): stub\n",hService);
538 return TRUE;
542 /******************************************************************************
543 * StartServiceA [ADVAPI32.@]
546 BOOL WINAPI
547 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
548 LPCSTR *lpServiceArgVectors )
550 LPWSTR *lpwstr=NULL;
551 UNICODE_STRING usBuffer;
552 int i;
554 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
556 if(dwNumServiceArgs)
557 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
558 dwNumServiceArgs*sizeof(LPWSTR) );
559 else
560 lpwstr = NULL;
562 for(i=0; i<dwNumServiceArgs; i++)
564 RtlCreateUnicodeStringFromAsciiz (&usBuffer,lpServiceArgVectors[i]);
565 lpwstr[i]=usBuffer.Buffer;
568 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
570 if(dwNumServiceArgs)
572 for(i=0; i<dwNumServiceArgs; i++)
573 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
574 HeapFree(GetProcessHeap(), 0, lpwstr);
577 return TRUE;
581 /******************************************************************************
582 * StartServiceW [ADVAPI32.@]
583 * Starts a service
585 * PARAMS
586 * hService [I] Handle of service
587 * dwNumServiceArgs [I] Number of arguments
588 * lpServiceArgVectors [I] Address of array of argument string pointers
590 * NOTES
592 * NT implements this function using an obscure RPC call...
594 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
595 * to get things like %SystemRoot%\\System32\\service.exe to load.
597 * Will only work for shared address space. How should the service
598 * args be transferred when address spaces are separated?
600 * Can only start one service at a time.
602 * Has no concept of privilege.
604 * RETURNS STD
607 BOOL WINAPI
608 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
609 LPCWSTR *lpServiceArgVectors )
611 static const WCHAR _ServiceStartDataW[] = {'A','D','V','A','P','I','_','S',
612 'e','r','v','i','c','e','S','t',
613 'a','r','t','D','a','t','a',0};
615 static const WCHAR _WaitServiceStartW[] = {'A','D','V','A','P','I','_','W',
616 'a','i','t','S','e','r','v','i',
617 'c','e','S','t','a','r','t',0};
618 static const WCHAR _ImagePathW[] = {'I','m','a','g','e','P','a','t','h',0};
620 WCHAR path[MAX_PATH],str[MAX_PATH];
621 DWORD type,size;
622 long r;
623 HANDLE data,wait;
624 PROCESS_INFORMATION procinfo;
625 STARTUPINFOW startupinfo;
626 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,
627 lpServiceArgVectors);
629 size = sizeof(str);
630 r = RegQueryValueExW(hService, _ImagePathW, NULL, &type, (LPVOID)str, &size);
631 if (r!=ERROR_SUCCESS)
632 return FALSE;
633 ExpandEnvironmentStringsW(str,path,sizeof(path));
635 TRACE("Starting service %s\n", debugstr_w(path) );
637 data = CreateSemaphoreW(NULL,1,1,_ServiceStartDataW);
638 if (!data)
640 data = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS, FALSE, _ServiceStartDataW);
641 if(data == 0)
643 ERR("Couldn't create data semaphore\n");
644 return FALSE;
647 wait = CreateSemaphoreW(NULL,0,1,_WaitServiceStartW);
649 wait = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS, FALSE, _ServiceStartDataW);
650 if(wait == 0)
652 ERR("Couldn't create wait semaphore\n");
653 return FALSE;
658 * FIXME: lpServiceArgsVectors need to be stored and returned to
659 * the service when it calls StartServiceCtrlDispatcher
661 * Chuck these in a global (yuk) so we can pass them to
662 * another process - address space separation will break this.
665 r = WaitForSingleObject(data,INFINITE);
667 if( r == WAIT_FAILED)
668 return FALSE;
670 FIXME("problematic because of address space separation.\n");
671 start_dwNumServiceArgs = dwNumServiceArgs;
672 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
674 ZeroMemory(&startupinfo,sizeof(STARTUPINFOW));
675 startupinfo.cb = sizeof(STARTUPINFOW);
677 r = CreateProcessW(path,
678 NULL,
679 NULL, /* process security attribs */
680 NULL, /* thread security attribs */
681 FALSE, /* inherit handles */
682 0, /* creation flags */
683 NULL, /* environment */
684 NULL, /* current directory */
685 &startupinfo, /* startup info */
686 &procinfo); /* process info */
688 if(r == FALSE)
690 ERR("Couldn't start process\n");
691 /* ReleaseSemaphore(data, 1, NULL);
692 return FALSE; */
695 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
696 r = WaitForSingleObject(wait,30000);
698 ReleaseSemaphore(data, 1, NULL);
700 if( r == WAIT_FAILED)
701 return FALSE;
703 return TRUE;
706 /******************************************************************************
707 * QueryServiceStatus [ADVAPI32.@]
709 * PARAMS
710 * hService []
711 * lpservicestatus []
714 BOOL WINAPI
715 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
717 LONG r;
718 DWORD type, val, size;
720 FIXME("(%p,%p) partial\n",hService,lpservicestatus);
722 /* read the service type from the registry */
723 size = sizeof(val);
724 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
725 if(type!=REG_DWORD)
727 ERR("invalid Type\n");
728 return FALSE;
730 lpservicestatus->dwServiceType = val;
731 /* FIXME: how are these determined or read from the registry? */
732 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
733 lpservicestatus->dwCurrentState = 1;
734 lpservicestatus->dwControlsAccepted = 0;
735 lpservicestatus->dwWin32ExitCode = NO_ERROR;
736 lpservicestatus->dwServiceSpecificExitCode = 0;
737 lpservicestatus->dwCheckPoint = 0;
738 lpservicestatus->dwWaitHint = 0;
740 return TRUE;
743 /******************************************************************************
744 * QueryServiceStatusEx [ADVAPI32.@]
746 * PARAMS
747 * hService [handle to service]
748 * InfoLevel [information level]
749 * lpBuffer [buffer]
750 * cbBufSize [size of buffer]
751 * pcbBytesNeeded [bytes needed]
753 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
754 LPBYTE lpBuffer, DWORD cbBufSize,
755 LPDWORD pcbBytesNeeded)
757 FIXME("stub\n");
758 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
759 return FALSE;