/* * Win32 advapi functions * * Copyright 1995 Sven Verdoolaege */ #include #include "windef.h" #include "winsvc.h" #include "winerror.h" #include "winreg.h" #include "wine/unicode.h" #include "heap.h" #include "debugtools.h" DEFAULT_DEBUG_CHANNEL(advapi); static DWORD start_dwNumServiceArgs; static LPWSTR *start_lpServiceArgVectors; /****************************************************************************** * EnumServicesStatusA [ADVAPI32.@] */ BOOL WINAPI EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType, DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned, LPDWORD lpResumeHandle ) { FIXME("%x type=%lx state=%lx %p %lx %p %p %p\n", hSCManager, dwServiceType, dwServiceState, lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle); SetLastError (ERROR_ACCESS_DENIED); return 0; } /****************************************************************************** * EnumServicesStatusW [ADVAPI32.@] */ BOOL WINAPI EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType, DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned, LPDWORD lpResumeHandle ) { FIXME("%x type=%lx state=%lx %p %lx %p %p %p\n", hSCManager, dwServiceType, dwServiceState, lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle); SetLastError (ERROR_ACCESS_DENIED); return 0; } /****************************************************************************** * StartServiceCtrlDispatcherA [ADVAPI32.196] */ BOOL WINAPI StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent ) { LPSERVICE_MAIN_FUNCTIONA fpMain; HANDLE wait; DWORD dwNumServiceArgs ; LPWSTR *lpArgVecW; LPSTR *lpArgVecA; int i; TRACE("(%p)\n", servent); wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData"); if(wait == 0) { ERR("Couldn't find wait semaphore\n"); ERR("perhaps you need to start services using StartService\n"); return FALSE; } dwNumServiceArgs = start_dwNumServiceArgs; lpArgVecW = start_lpServiceArgVectors; ReleaseSemaphore(wait, 1, NULL); /* Convert the Unicode arg vectors back to ASCII */ if(dwNumServiceArgs) lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0, dwNumServiceArgs*sizeof(LPSTR) ); else lpArgVecA = NULL; for(i=0; ilpServiceName) { TRACE("%s at %p)\n", debugstr_a(servent->lpServiceName),servent); fpMain = servent->lpServiceProc; /* try to start the service */ fpMain( dwNumServiceArgs, lpArgVecA); servent++; } if(dwNumServiceArgs) { /* free arg strings */ for(i=0; ilpServiceName) { TRACE("%s at %p)\n", debugstr_w(servent->lpServiceName),servent); fpMain = servent->lpServiceProc; /* try to start the service */ fpMain( dwNumServiceArgs, lpServiceArgVectors); servent++; } return TRUE; } /****************************************************************************** * RegisterServiceCtrlHandlerA [ADVAPI32.176] */ SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerA( LPCSTR lpServiceName, LPHANDLER_FUNCTION lpfHandler ) { FIXME("%s %p\n", lpServiceName, lpfHandler); return 0xcacacafe; } /****************************************************************************** * RegisterServiceCtrlHandlerW [ADVAPI32.177] * * PARAMS * lpServiceName [] * lpfHandler [] */ SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName, LPHANDLER_FUNCTION lpfHandler ) { FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler); return 0xcacacafe; } /****************************************************************************** * SetServiceStatus [ADVAPI32.192] * * PARAMS * hService [] * lpStatus [] */ BOOL WINAPI SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus ) { FIXME("%x %p\n",hService, lpStatus); TRACE("\tType:%lx\n",lpStatus->dwServiceType); TRACE("\tState:%lx\n",lpStatus->dwCurrentState); TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted); TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode); TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode); TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint); TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint); return TRUE; } /****************************************************************************** * OpenSCManagerA [ADVAPI32.110] */ SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName, DWORD dwDesiredAccess ) { LPWSTR lpMachineNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpMachineName); LPWSTR lpDatabaseNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpDatabaseName); DWORD ret = OpenSCManagerW(lpMachineNameW,lpDatabaseNameW, dwDesiredAccess); HeapFree(GetProcessHeap(),0,lpDatabaseNameW); HeapFree(GetProcessHeap(),0,lpMachineNameW); return ret; } /****************************************************************************** * OpenSCManagerW [ADVAPI32.111] * Establishes a connection to the service control manager and opens database * * NOTES * This should return a SC_HANDLE * * PARAMS * lpMachineName [I] Pointer to machine name string * lpDatabaseName [I] Pointer to database name string * dwDesiredAccess [I] Type of access * * RETURNS * Success: Handle to service control manager database * Failure: NULL */ SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName, DWORD dwDesiredAccess ) { HKEY hKey; LONG r; TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName), debugstr_w(lpDatabaseName), dwDesiredAccess); /* * FIXME: what is lpDatabaseName? * It should be set to "SERVICES_ACTIVE_DATABASE" according to * docs, but what if it isn't? */ r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hKey); if (r!=ERROR_SUCCESS) return 0; TRACE("returning %x\n",hKey); return hKey; } /****************************************************************************** * AllocateLocallyUniqueId [ADVAPI32.12] * * PARAMS * lpluid [] */ BOOL WINAPI AllocateLocallyUniqueId( PLUID lpluid ) { lpluid->s.LowPart = time(NULL); lpluid->s.HighPart = 0; return TRUE; } /****************************************************************************** * ControlService [ADVAPI32.23] * Sends a control code to a Win32-based service. * * PARAMS * hService [] * dwControl [] * lpServiceStatus [] * * RETURNS STD */ BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus ) { FIXME("(%d,%ld,%p): stub\n",hService,dwControl,lpServiceStatus); return TRUE; } /****************************************************************************** * CloseServiceHandle [ADVAPI32.22] * Close handle to service or service control manager * * PARAMS * hSCObject [I] Handle to service or service control manager database * * RETURNS STD */ BOOL WINAPI CloseServiceHandle( SC_HANDLE hSCObject ) { TRACE("(%x)\n", hSCObject); RegCloseKey(hSCObject); return TRUE; } /****************************************************************************** * OpenServiceA [ADVAPI32.112] */ SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName, DWORD dwDesiredAccess ) { LPWSTR lpServiceNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpServiceName); DWORD ret; if(lpServiceName) TRACE("Request for service %s\n",lpServiceName); else return FALSE; ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess); HeapFree(GetProcessHeap(),0,lpServiceNameW); return ret; } /****************************************************************************** * OpenServiceW [ADVAPI32.113] * Opens a handle to an existing service * * PARAMS * hSCManager [] * lpServiceName [] * dwDesiredAccess [] * * RETURNS * Success: Handle to the service * Failure: NULL */ SC_HANDLE WINAPI OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName, DWORD dwDesiredAccess) { const char *str = "System\\CurrentControlSet\\Services\\"; WCHAR lpServiceKey[80]; /* FIXME: this should be dynamically allocated */ HKEY hKey; long r; TRACE("(%d,%p,%ld)\n",hSCManager, lpServiceName, dwDesiredAccess); MultiByteToWideChar( CP_ACP, 0, str, -1, lpServiceKey, sizeof(lpServiceKey)/sizeof(WCHAR) ); strcatW(lpServiceKey,lpServiceName); TRACE("Opening reg key %s\n", debugstr_w(lpServiceKey)); /* FIXME: dwDesiredAccess may need some processing */ r = RegOpenKeyExW(hSCManager, lpServiceKey, 0, dwDesiredAccess, &hKey ); if (r!=ERROR_SUCCESS) return 0; TRACE("returning %x\n",hKey); return hKey; } /****************************************************************************** * CreateServiceW [ADVAPI32.29] */ SC_HANDLE WINAPI CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName, LPCWSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName, LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies, LPCWSTR lpServiceStartName, LPCWSTR lpPassword ) { FIXME("(%u,%s,%s,...)\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName)); return FALSE; } /****************************************************************************** * CreateServiceA [ADVAPI32.28] */ SC_HANDLE WINAPI CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName, LPCSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName, LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies, LPCSTR lpServiceStartName, LPCSTR lpPassword ) { HKEY hKey; LONG r; DWORD dp; TRACE("(%u,%s,%s,...)\n", hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName)); r = RegCreateKeyExA(hSCManager, lpServiceName, 0, NULL, REG_OPTION_NON_VOLATILE, dwDesiredAccess, NULL, &hKey, &dp); if (r!=ERROR_SUCCESS) return 0; if (dp != REG_CREATED_NEW_KEY) return 0; if(lpDisplayName) { r = RegSetValueExA(hKey, "DisplayName", 0, REG_SZ, lpDisplayName, strlen(lpDisplayName) ); if (r!=ERROR_SUCCESS) return 0; } r = RegSetValueExA(hKey, "Type", 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) ); if (r!=ERROR_SUCCESS) return 0; r = RegSetValueExA(hKey, "Start", 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) ); if (r!=ERROR_SUCCESS) return 0; r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD, (LPVOID)&dwErrorControl, sizeof (DWORD) ); if (r!=ERROR_SUCCESS) return 0; if(lpBinaryPathName) { r = RegSetValueExA(hKey, "ImagePath", 0, REG_SZ, lpBinaryPathName,strlen(lpBinaryPathName)+1 ); if (r!=ERROR_SUCCESS) return 0; } if(lpLoadOrderGroup) { r = RegSetValueExA(hKey, "Group", 0, REG_SZ, lpLoadOrderGroup, strlen(lpLoadOrderGroup)+1 ); if (r!=ERROR_SUCCESS) return 0; } r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD, (LPVOID)&dwErrorControl, sizeof (DWORD) ); if (r!=ERROR_SUCCESS) return 0; if(lpDependencies) { DWORD len = 0; /* determine the length of a double null terminated multi string */ do { len += (strlen(&lpDependencies[len])+1); } while (lpDependencies[len++]); /* fixme: this should be unicode */ r = RegSetValueExA(hKey, "Dependencies", 0, REG_MULTI_SZ, lpDependencies, len ); if (r!=ERROR_SUCCESS) return 0; } if(lpPassword) { FIXME("Don't know how to add a Password for a service.\n"); } if(lpServiceStartName) { FIXME("Don't know how to add a ServiceStartName for a service.\n"); } return hKey; } /****************************************************************************** * DeleteService [ADVAPI32.31] * * PARAMS * hService [I] Handle to service * * RETURNS STD * */ BOOL WINAPI DeleteService( SC_HANDLE hService ) { FIXME("(%d): stub\n",hService); return TRUE; } /****************************************************************************** * StartServiceA [ADVAPI32.195] * */ BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs, LPCSTR *lpServiceArgVectors ) { LPWSTR *lpwstr=NULL; int i; TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors); if(dwNumServiceArgs) lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0, dwNumServiceArgs*sizeof(LPWSTR) ); else lpwstr = NULL; for(i=0; idwServiceType = val; /* FIXME: how are these determined or read from the registry? */ /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */; lpservicestatus->dwCurrentState = 1; lpservicestatus->dwControlsAccepted = 0; lpservicestatus->dwWin32ExitCode = NO_ERROR; lpservicestatus->dwServiceSpecificExitCode = 0; lpservicestatus->dwCheckPoint = 0; lpservicestatus->dwWaitHint = 0; return TRUE; }