Release 20030408.
[wine/gsoc-2012-control.git] / dlls / advapi32 / service.c
blob26b5a6265a7b616ab5f8302b59dd7297d1007756
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 <string.h>
22 #include <time.h>
24 #include "windef.h"
25 #include "winsvc.h"
26 #include "winerror.h"
27 #include "winreg.h"
28 #include "wine/unicode.h"
29 #include "heap.h"
30 #include "wine/debug.h"
31 #include "winternl.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
35 static DWORD start_dwNumServiceArgs;
36 static LPWSTR *start_lpServiceArgVectors;
38 /******************************************************************************
39 * EnumServicesStatusA [ADVAPI32.@]
41 BOOL WINAPI
42 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
43 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
44 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
45 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
46 { FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
47 dwServiceType, dwServiceState, lpServices, cbBufSize,
48 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
49 SetLastError (ERROR_ACCESS_DENIED);
50 return FALSE;
53 /******************************************************************************
54 * EnumServicesStatusW [ADVAPI32.@]
56 BOOL WINAPI
57 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
58 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
59 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
60 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
61 { FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
62 dwServiceType, dwServiceState, lpServices, cbBufSize,
63 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
64 SetLastError (ERROR_ACCESS_DENIED);
65 return FALSE;
68 /******************************************************************************
69 * StartServiceCtrlDispatcherA [ADVAPI32.@]
71 BOOL WINAPI
72 StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
74 LPSERVICE_MAIN_FUNCTIONA fpMain;
75 HANDLE wait;
76 DWORD dwNumServiceArgs ;
77 LPWSTR *lpArgVecW;
78 LPSTR *lpArgVecA;
79 int i;
81 TRACE("(%p)\n", servent);
82 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
83 if(wait == 0)
85 ERR("Couldn't find wait semaphore\n");
86 ERR("perhaps you need to start services using StartService\n");
87 return FALSE;
90 dwNumServiceArgs = start_dwNumServiceArgs;
91 lpArgVecW = start_lpServiceArgVectors;
93 ReleaseSemaphore(wait, 1, NULL);
95 /* Convert the Unicode arg vectors back to ASCII */
96 if(dwNumServiceArgs)
97 lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0,
98 dwNumServiceArgs*sizeof(LPSTR) );
99 else
100 lpArgVecA = NULL;
102 for(i=0; i<dwNumServiceArgs; i++)
103 lpArgVecA[i]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW[i]);
105 /* FIXME: should we blindly start all services? */
106 while (servent->lpServiceName) {
107 TRACE("%s at %p)\n", debugstr_a(servent->lpServiceName),servent);
108 fpMain = servent->lpServiceProc;
110 /* try to start the service */
111 fpMain( dwNumServiceArgs, lpArgVecA);
113 servent++;
116 if(dwNumServiceArgs)
118 /* free arg strings */
119 for(i=0; i<dwNumServiceArgs; i++)
120 HeapFree(GetProcessHeap(), 0, lpArgVecA[i]);
121 HeapFree(GetProcessHeap(), 0, lpArgVecA);
124 return TRUE;
127 /******************************************************************************
128 * StartServiceCtrlDispatcherW [ADVAPI32.@]
130 * PARAMS
131 * servent []
133 BOOL WINAPI
134 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
136 static const WCHAR _ServiceStartDataW[] = {'A','D','V','A','P','I','_','S',
137 'e','r','v','i','c','e','S','t',
138 'a','r','t','D','a','t','a',0};
139 LPSERVICE_MAIN_FUNCTIONW fpMain;
140 HANDLE wait;
141 DWORD dwNumServiceArgs ;
142 LPWSTR *lpServiceArgVectors ;
144 TRACE("(%p)\n", servent);
145 wait = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS, FALSE, _ServiceStartDataW);
146 if(wait == 0)
148 ERR("Couldn't find wait semaphore\n");
149 ERR("perhaps you need to start services using StartService\n");
150 return FALSE;
153 dwNumServiceArgs = start_dwNumServiceArgs;
154 lpServiceArgVectors = start_lpServiceArgVectors;
156 ReleaseSemaphore(wait, 1, NULL);
158 /* FIXME: should we blindly start all services? */
159 while (servent->lpServiceName) {
160 TRACE("%s at %p)\n", debugstr_w(servent->lpServiceName),servent);
161 fpMain = servent->lpServiceProc;
163 /* try to start the service */
164 fpMain( dwNumServiceArgs, lpServiceArgVectors);
166 servent++;
169 return TRUE;
172 /******************************************************************************
173 * LockServiceDatabase [ADVAPI32.@]
175 LPVOID WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
177 FIXME("%p\n",hSCManager);
178 return (SC_HANDLE)0xcacacafe;
181 /******************************************************************************
182 * UnlockServiceDatabase [ADVAPI32.@]
184 BOOL WINAPI UnlockServiceDatabase (LPVOID ScLock)
186 FIXME(": %p\n",ScLock);
187 return TRUE;
190 /******************************************************************************
191 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
193 SERVICE_STATUS_HANDLE WINAPI
194 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName,
195 LPHANDLER_FUNCTION lpfHandler )
196 { FIXME("%s %p\n", lpServiceName, lpfHandler);
197 return 0xcacacafe;
200 /******************************************************************************
201 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
203 * PARAMS
204 * lpServiceName []
205 * lpfHandler []
207 SERVICE_STATUS_HANDLE WINAPI
208 RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
209 LPHANDLER_FUNCTION lpfHandler )
210 { FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler);
211 return 0xcacacafe;
214 /******************************************************************************
215 * SetServiceStatus [ADVAPI32.@]
217 * PARAMS
218 * hService []
219 * lpStatus []
221 BOOL WINAPI
222 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
223 { FIXME("0x%lx %p\n",hService, lpStatus);
224 TRACE("\tType:%lx\n",lpStatus->dwServiceType);
225 TRACE("\tState:%lx\n",lpStatus->dwCurrentState);
226 TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted);
227 TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode);
228 TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode);
229 TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint);
230 TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint);
231 return TRUE;
234 /******************************************************************************
235 * OpenSCManagerA [ADVAPI32.@]
237 SC_HANDLE WINAPI
238 OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
239 DWORD dwDesiredAccess )
241 UNICODE_STRING lpMachineNameW;
242 UNICODE_STRING lpDatabaseNameW;
243 SC_HANDLE ret;
245 RtlCreateUnicodeStringFromAsciiz (&lpMachineNameW,lpMachineName);
246 RtlCreateUnicodeStringFromAsciiz (&lpDatabaseNameW,lpDatabaseName);
247 ret = OpenSCManagerW(lpMachineNameW.Buffer,lpDatabaseNameW.Buffer, dwDesiredAccess);
248 RtlFreeUnicodeString(&lpDatabaseNameW);
249 RtlFreeUnicodeString(&lpMachineNameW);
250 return ret;
253 /******************************************************************************
254 * OpenSCManagerW [ADVAPI32.@]
255 * Establishes a connection to the service control manager and opens database
257 * NOTES
258 * This should return a SC_HANDLE
260 * PARAMS
261 * lpMachineName [I] Pointer to machine name string
262 * lpDatabaseName [I] Pointer to database name string
263 * dwDesiredAccess [I] Type of access
265 * RETURNS
266 * Success: Handle to service control manager database
267 * Failure: NULL
269 SC_HANDLE WINAPI
270 OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
271 DWORD dwDesiredAccess )
273 HKEY hKey;
274 LONG r;
276 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
277 debugstr_w(lpDatabaseName), dwDesiredAccess);
280 * FIXME: what is lpDatabaseName?
281 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
282 * docs, but what if it isn't?
285 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hKey);
286 if (r!=ERROR_SUCCESS)
287 return 0;
289 TRACE("returning %p\n",hKey);
291 return hKey;
295 /******************************************************************************
296 * AllocateLocallyUniqueId [ADVAPI32.@]
298 * PARAMS
299 * lpluid []
301 BOOL WINAPI
302 AllocateLocallyUniqueId( PLUID lpluid )
304 lpluid->LowPart = time(NULL);
305 lpluid->HighPart = 0;
306 return TRUE;
310 /******************************************************************************
311 * ControlService [ADVAPI32.@]
312 * Sends a control code to a Win32-based service.
314 * PARAMS
315 * hService []
316 * dwControl []
317 * lpServiceStatus []
319 * RETURNS STD
321 BOOL WINAPI
322 ControlService( SC_HANDLE hService, DWORD dwControl,
323 LPSERVICE_STATUS lpServiceStatus )
325 FIXME("(%p,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
326 return TRUE;
330 /******************************************************************************
331 * CloseServiceHandle [ADVAPI32.@]
332 * Close handle to service or service control manager
334 * PARAMS
335 * hSCObject [I] Handle to service or service control manager database
337 * RETURNS STD
339 BOOL WINAPI
340 CloseServiceHandle( SC_HANDLE hSCObject )
342 TRACE("(%p)\n", hSCObject);
344 RegCloseKey(hSCObject);
346 return TRUE;
350 /******************************************************************************
351 * OpenServiceA [ADVAPI32.@]
353 SC_HANDLE WINAPI
354 OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
355 DWORD dwDesiredAccess )
357 UNICODE_STRING lpServiceNameW;
358 SC_HANDLE ret;
359 RtlCreateUnicodeStringFromAsciiz (&lpServiceNameW,lpServiceName);
360 if(lpServiceName)
361 TRACE("Request for service %s\n",lpServiceName);
362 else
363 return FALSE;
364 ret = OpenServiceW( hSCManager, lpServiceNameW.Buffer, dwDesiredAccess);
365 RtlFreeUnicodeString(&lpServiceNameW);
366 return ret;
370 /******************************************************************************
371 * OpenServiceW [ADVAPI32.@]
372 * Opens a handle to an existing service
374 * PARAMS
375 * hSCManager []
376 * lpServiceName []
377 * dwDesiredAccess []
379 * RETURNS
380 * Success: Handle to the service
381 * Failure: NULL
383 SC_HANDLE WINAPI
384 OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName,
385 DWORD dwDesiredAccess)
387 const char *str = "System\\CurrentControlSet\\Services\\";
388 WCHAR lpServiceKey[80]; /* FIXME: this should be dynamically allocated */
389 HKEY hKey;
390 long r;
392 TRACE("(%p,%p,%ld)\n",hSCManager, lpServiceName,
393 dwDesiredAccess);
395 MultiByteToWideChar( CP_ACP, 0, str, -1, lpServiceKey, sizeof(lpServiceKey)/sizeof(WCHAR) );
396 strcatW(lpServiceKey,lpServiceName);
398 TRACE("Opening reg key %s\n", debugstr_w(lpServiceKey));
400 /* FIXME: dwDesiredAccess may need some processing */
401 r = RegOpenKeyExW(hSCManager, lpServiceKey, 0, dwDesiredAccess, &hKey );
402 if (r!=ERROR_SUCCESS)
403 return 0;
405 TRACE("returning %p\n",hKey);
407 return hKey;
410 /******************************************************************************
411 * CreateServiceW [ADVAPI32.@]
413 SC_HANDLE WINAPI
414 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
415 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
416 DWORD dwServiceType, DWORD dwStartType,
417 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
418 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
419 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
420 LPCWSTR lpPassword )
422 FIXME("(%p,%s,%s,...)\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
423 return 0;
427 /******************************************************************************
428 * CreateServiceA [ADVAPI32.@]
430 SC_HANDLE WINAPI
431 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
432 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
433 DWORD dwServiceType, DWORD dwStartType,
434 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
435 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
436 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
437 LPCSTR lpPassword )
439 HKEY hKey;
440 LONG r;
441 DWORD dp;
443 TRACE("(%p,%s,%s,...)\n", hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
445 r = RegCreateKeyExA(hSCManager, lpServiceName, 0, NULL,
446 REG_OPTION_NON_VOLATILE, dwDesiredAccess, NULL, &hKey, &dp);
447 if (r!=ERROR_SUCCESS)
448 return 0;
449 if (dp != REG_CREATED_NEW_KEY)
450 return 0;
452 if(lpDisplayName)
454 r = RegSetValueExA(hKey, "DisplayName", 0, REG_SZ, lpDisplayName, strlen(lpDisplayName) );
455 if (r!=ERROR_SUCCESS)
456 return 0;
459 r = RegSetValueExA(hKey, "Type", 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
460 if (r!=ERROR_SUCCESS)
461 return 0;
463 r = RegSetValueExA(hKey, "Start", 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
464 if (r!=ERROR_SUCCESS)
465 return 0;
467 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
468 (LPVOID)&dwErrorControl, sizeof (DWORD) );
469 if (r!=ERROR_SUCCESS)
470 return 0;
472 if(lpBinaryPathName)
474 r = RegSetValueExA(hKey, "ImagePath", 0, REG_SZ,
475 lpBinaryPathName,strlen(lpBinaryPathName)+1 );
476 if (r!=ERROR_SUCCESS)
477 return 0;
480 if(lpLoadOrderGroup)
482 r = RegSetValueExA(hKey, "Group", 0, REG_SZ,
483 lpLoadOrderGroup, strlen(lpLoadOrderGroup)+1 );
484 if (r!=ERROR_SUCCESS)
485 return 0;
488 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
489 (LPVOID)&dwErrorControl, sizeof (DWORD) );
490 if (r!=ERROR_SUCCESS)
491 return 0;
493 if(lpDependencies)
495 DWORD len = 0;
497 /* determine the length of a double null terminated multi string */
498 do {
499 len += (strlen(&lpDependencies[len])+1);
500 } while (lpDependencies[len++]);
502 /* FIXME: this should be unicode */
503 r = RegSetValueExA(hKey, "Dependencies", 0, REG_MULTI_SZ,
504 lpDependencies, len );
505 if (r!=ERROR_SUCCESS)
506 return 0;
509 if(lpPassword)
511 FIXME("Don't know how to add a Password for a service.\n");
514 if(lpServiceStartName)
516 FIXME("Don't know how to add a ServiceStartName for a service.\n");
519 return hKey;
523 /******************************************************************************
524 * DeleteService [ADVAPI32.@]
526 * PARAMS
527 * hService [I] Handle to service
529 * RETURNS STD
532 BOOL WINAPI
533 DeleteService( SC_HANDLE hService )
535 FIXME("(%p): stub\n",hService);
536 return TRUE;
540 /******************************************************************************
541 * StartServiceA [ADVAPI32.@]
544 BOOL WINAPI
545 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
546 LPCSTR *lpServiceArgVectors )
548 LPWSTR *lpwstr=NULL;
549 UNICODE_STRING usBuffer;
550 int i;
552 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
554 if(dwNumServiceArgs)
555 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
556 dwNumServiceArgs*sizeof(LPWSTR) );
557 else
558 lpwstr = NULL;
560 for(i=0; i<dwNumServiceArgs; i++)
562 RtlCreateUnicodeStringFromAsciiz (&usBuffer,lpServiceArgVectors[i]);
563 lpwstr[i]=usBuffer.Buffer;
566 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
568 if(dwNumServiceArgs)
570 for(i=0; i<dwNumServiceArgs; i++)
571 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
572 HeapFree(GetProcessHeap(), 0, lpwstr);
575 return TRUE;
579 /******************************************************************************
580 * StartServiceW [ADVAPI32.@]
581 * Starts a service
583 * PARAMS
584 * hService [I] Handle of service
585 * dwNumServiceArgs [I] Number of arguments
586 * lpServiceArgVectors [I] Address of array of argument string pointers
588 * NOTES
590 * NT implements this function using an obscure RPC call...
592 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
593 * to get things like %SystemRoot%\\System32\\service.exe to load.
595 * Will only work for shared address space. How should the service
596 * args be transferred when address spaces are separated?
598 * Can only start one service at a time.
600 * Has no concept of privilege.
602 * RETURNS STD
605 BOOL WINAPI
606 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
607 LPCWSTR *lpServiceArgVectors )
609 static const WCHAR _ServiceStartDataW[] = {'A','D','V','A','P','I','_','S',
610 'e','r','v','i','c','e','S','t',
611 'a','r','t','D','a','t','a',0};
613 static const WCHAR _WaitServiceStartW[] = {'A','D','V','A','P','I','_','W',
614 'a','i','t','S','e','r','v','i',
615 'c','e','S','t','a','r','t',0};
616 static const WCHAR _ImagePathW[] = {'I','m','a','g','e','P','a','t','h',0};
618 WCHAR path[MAX_PATH],str[MAX_PATH];
619 DWORD type,size;
620 long r;
621 HANDLE data,wait;
622 PROCESS_INFORMATION procinfo;
623 STARTUPINFOW startupinfo;
624 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,
625 lpServiceArgVectors);
627 size = sizeof str;
628 r = RegQueryValueExW(hService, _ImagePathW, NULL, &type, (LPVOID)str, &size);
629 if (r!=ERROR_SUCCESS)
630 return FALSE;
631 ExpandEnvironmentStringsW(str,path,sizeof path);
633 TRACE("Starting service %s\n", debugstr_w(path) );
635 data = CreateSemaphoreW(NULL,1,1,_ServiceStartDataW);
636 if (!data)
638 data = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS, FALSE, _ServiceStartDataW);
639 if(data == 0)
641 ERR("Couldn't create data semaphore\n");
642 return FALSE;
645 wait = CreateSemaphoreW(NULL,0,1,_WaitServiceStartW);
647 wait = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS, FALSE, _ServiceStartDataW);
648 if(wait == 0)
650 ERR("Couldn't create wait semaphore\n");
651 return FALSE;
656 * FIXME: lpServiceArgsVectors need to be stored and returned to
657 * the service when it calls StartServiceCtrlDispatcher
659 * Chuck these in a global (yuk) so we can pass them to
660 * another process - address space separation will break this.
663 r = WaitForSingleObject(data,INFINITE);
665 if( r == WAIT_FAILED)
666 return FALSE;
668 FIXME("problematic because of address space separation.\n");
669 start_dwNumServiceArgs = dwNumServiceArgs;
670 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
672 ZeroMemory(&startupinfo,sizeof(STARTUPINFOW));
673 startupinfo.cb = sizeof(STARTUPINFOW);
675 r = CreateProcessW(path,
676 NULL,
677 NULL, /* process security attribs */
678 NULL, /* thread security attribs */
679 FALSE, /* inherit handles */
680 0, /* creation flags */
681 NULL, /* environment */
682 NULL, /* current directory */
683 &startupinfo, /* startup info */
684 &procinfo); /* process info */
686 if(r == FALSE)
688 ERR("Couldn't start process\n");
689 /* ReleaseSemaphore(data, 1, NULL);
690 return FALSE; */
693 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
694 r = WaitForSingleObject(wait,30000);
696 ReleaseSemaphore(data, 1, NULL);
698 if( r == WAIT_FAILED)
699 return FALSE;
701 return TRUE;
704 /******************************************************************************
705 * QueryServiceStatus [ADVAPI32.@]
707 * PARAMS
708 * hService []
709 * lpservicestatus []
712 BOOL WINAPI
713 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
715 LONG r;
716 DWORD type, val, size;
718 FIXME("(%p,%p) partial\n",hService,lpservicestatus);
720 /* read the service type from the registry */
721 size = sizeof val;
722 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
723 if(type!=REG_DWORD)
725 ERR("invalid Type\n");
726 return FALSE;
728 lpservicestatus->dwServiceType = val;
729 /* FIXME: how are these determined or read from the registry? */
730 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
731 lpservicestatus->dwCurrentState = 1;
732 lpservicestatus->dwControlsAccepted = 0;
733 lpservicestatus->dwWin32ExitCode = NO_ERROR;
734 lpservicestatus->dwServiceSpecificExitCode = 0;
735 lpservicestatus->dwCheckPoint = 0;
736 lpservicestatus->dwWaitHint = 0;
738 return TRUE;
741 /******************************************************************************
742 * QueryServiceStatusEx [ADVAPI32.@]
744 * PARAMS
745 * hService [handle to service]
746 * InfoLevel [information level]
747 * lpBuffer [buffer]
748 * cbBufSize [size of buffer]
749 * pcbBytesNeeded [bytes needed]
751 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
752 LPBYTE lpBuffer, DWORD cbBufSize,
753 LPDWORD pcbBytesNeeded)
755 FIXME("stub\n");
756 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
757 return FALSE;