Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Win32 advapi functions |
| 3 | * |
| 4 | * Copyright 1995 Sven Verdoolaege |
| 5 | */ |
| 6 | |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 7 | #include <time.h> |
Patrik Stridvall | 4a73973 | 1999-07-04 11:01:21 +0000 | [diff] [blame] | 8 | |
Jim Aston | 2e1cafa | 1999-03-14 16:35:05 +0000 | [diff] [blame] | 9 | #include "windef.h" |
Patrik Stridvall | 4a73973 | 1999-07-04 11:01:21 +0000 | [diff] [blame] | 10 | #include "winsvc.h" |
Marcus Meissner | 317af32 | 1999-02-17 13:51:06 +0000 | [diff] [blame] | 11 | #include "winerror.h" |
Michael McCormack | 75a8413 | 1999-11-21 00:58:14 +0000 | [diff] [blame] | 12 | #include "winreg.h" |
Marcus Meissner | 317af32 | 1999-02-17 13:51:06 +0000 | [diff] [blame] | 13 | #include "heap.h" |
Alexandre Julliard | 9fe7a25 | 1999-05-14 08:17:14 +0000 | [diff] [blame] | 14 | #include "debugtools.h" |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 15 | |
Patrik Stridvall | b4b9fae | 1999-04-19 14:56:29 +0000 | [diff] [blame] | 16 | DEFAULT_DEBUG_CHANNEL(advapi) |
| 17 | |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 18 | static DWORD start_dwNumServiceArgs; |
| 19 | static LPWSTR *start_lpServiceArgVectors; |
| 20 | |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 21 | /****************************************************************************** |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 22 | * EnumServicesStatusA [ADVAPI32.38] |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 23 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 24 | BOOL WINAPI |
Patrik Stridvall | 4a73973 | 1999-07-04 11:01:21 +0000 | [diff] [blame] | 25 | EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType, |
| 26 | DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices, |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 27 | DWORD cbBufSize, LPDWORD pcbBytesNeeded, |
| 28 | LPDWORD lpServicesReturned, LPDWORD lpResumeHandle ) |
Alexandre Julliard | 9fe7a25 | 1999-05-14 08:17:14 +0000 | [diff] [blame] | 29 | { FIXME("%x type=%lx state=%lx %p %lx %p %p %p\n", hSCManager, |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 30 | dwServiceType, dwServiceState, lpServices, cbBufSize, |
| 31 | pcbBytesNeeded, lpServicesReturned, lpResumeHandle); |
| 32 | SetLastError (ERROR_ACCESS_DENIED); |
| 33 | return 0; |
| 34 | } |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 35 | |
| 36 | /****************************************************************************** |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 37 | * StartServiceCtrlDispatcherA [ADVAPI32.196] |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 38 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 39 | BOOL WINAPI |
| 40 | StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent ) |
Peter Schlaile | 096aba2 | 1999-11-21 01:01:04 +0000 | [diff] [blame] | 41 | { |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 42 | LPSERVICE_MAIN_FUNCTIONA fpMain; |
| 43 | HANDLE wait; |
| 44 | DWORD dwNumServiceArgs ; |
| 45 | LPWSTR *lpArgVecW; |
| 46 | LPSTR *lpArgVecA; |
| 47 | int i; |
| 48 | |
| 49 | TRACE("(%p)\n", servent); |
| 50 | wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData"); |
| 51 | if(wait == 0) |
| 52 | { |
| 53 | ERR("Couldn't find wait semaphore\n"); |
| 54 | ERR("perhaps you need to start services using StartService\n"); |
| 55 | return FALSE; |
| 56 | } |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 57 | |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 58 | dwNumServiceArgs = start_dwNumServiceArgs; |
| 59 | lpArgVecW = start_lpServiceArgVectors; |
| 60 | |
| 61 | ReleaseSemaphore(wait, 1, NULL); |
| 62 | |
| 63 | /* Convert the Unicode arg vectors back to ASCII */ |
| 64 | if(dwNumServiceArgs) |
| 65 | lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0, |
| 66 | dwNumServiceArgs*sizeof(LPSTR) ); |
| 67 | else |
| 68 | lpArgVecA = NULL; |
| 69 | |
| 70 | for(i=0; i<dwNumServiceArgs; i++) |
| 71 | lpArgVecA[i]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW[i]); |
| 72 | |
| 73 | /* FIXME: should we blindly start all services? */ |
| 74 | while (servent->lpServiceName) { |
| 75 | TRACE("%s at %p)\n", debugstr_a(servent->lpServiceName),servent); |
| 76 | fpMain = servent->lpServiceProc; |
| 77 | |
| 78 | /* try to start the service */ |
| 79 | fpMain( dwNumServiceArgs, lpArgVecA); |
| 80 | |
| 81 | servent++; |
| 82 | } |
| 83 | |
| 84 | if(dwNumServiceArgs) |
| 85 | { |
| 86 | /* free arg strings */ |
| 87 | for(i=0; i<dwNumServiceArgs; i++) |
| 88 | HeapFree(GetProcessHeap(), 0, lpArgVecA[i]); |
| 89 | HeapFree(GetProcessHeap(), 0, lpArgVecA); |
| 90 | } |
| 91 | |
| 92 | return TRUE; |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 93 | } |
| 94 | |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 95 | /****************************************************************************** |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 96 | * StartServiceCtrlDispatcherW [ADVAPI32.197] |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 97 | * |
| 98 | * PARAMS |
| 99 | * servent [] |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 100 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 101 | BOOL WINAPI |
| 102 | StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent ) |
Peter Schlaile | 096aba2 | 1999-11-21 01:01:04 +0000 | [diff] [blame] | 103 | { |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 104 | LPSERVICE_MAIN_FUNCTIONW fpMain; |
| 105 | HANDLE wait; |
| 106 | DWORD dwNumServiceArgs ; |
| 107 | LPWSTR *lpServiceArgVectors ; |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 108 | |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 109 | TRACE("(%p)\n", servent); |
| 110 | wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData"); |
| 111 | if(wait == 0) |
| 112 | { |
| 113 | ERR("Couldn't find wait semaphore\n"); |
| 114 | ERR("perhaps you need to start services using StartService\n"); |
| 115 | return FALSE; |
| 116 | } |
| 117 | |
| 118 | dwNumServiceArgs = start_dwNumServiceArgs; |
| 119 | lpServiceArgVectors = start_lpServiceArgVectors; |
| 120 | |
| 121 | ReleaseSemaphore(wait, 1, NULL); |
| 122 | |
| 123 | /* FIXME: should we blindly start all services? */ |
| 124 | while (servent->lpServiceName) { |
| 125 | TRACE("%s at %p)\n", debugstr_w(servent->lpServiceName),servent); |
| 126 | fpMain = servent->lpServiceProc; |
| 127 | |
| 128 | /* try to start the service */ |
| 129 | fpMain( dwNumServiceArgs, lpServiceArgVectors); |
| 130 | |
| 131 | servent++; |
| 132 | } |
| 133 | |
| 134 | return TRUE; |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 135 | } |
| 136 | |
Matthew Becker | 6d59445 | 1999-01-30 12:54:32 +0000 | [diff] [blame] | 137 | /****************************************************************************** |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 138 | * RegisterServiceCtrlHandlerA [ADVAPI32.176] |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 139 | */ |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 140 | SERVICE_STATUS_HANDLE WINAPI |
Patrik Stridvall | 4a73973 | 1999-07-04 11:01:21 +0000 | [diff] [blame] | 141 | RegisterServiceCtrlHandlerA( LPCSTR lpServiceName, |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 142 | LPHANDLER_FUNCTION lpfHandler ) |
Alexandre Julliard | 9fe7a25 | 1999-05-14 08:17:14 +0000 | [diff] [blame] | 143 | { FIXME("%s %p\n", lpServiceName, lpfHandler); |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 144 | return 0xcacacafe; |
| 145 | } |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 146 | |
| 147 | /****************************************************************************** |
| 148 | * RegisterServiceCtrlHandlerW [ADVAPI32.177] |
| 149 | * |
| 150 | * PARAMS |
| 151 | * lpServiceName [] |
| 152 | * lpfHandler [] |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 153 | */ |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 154 | SERVICE_STATUS_HANDLE WINAPI |
Patrik Stridvall | 4a73973 | 1999-07-04 11:01:21 +0000 | [diff] [blame] | 155 | RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName, |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 156 | LPHANDLER_FUNCTION lpfHandler ) |
Alexandre Julliard | 9fe7a25 | 1999-05-14 08:17:14 +0000 | [diff] [blame] | 157 | { FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler); |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 158 | return 0xcacacafe; |
| 159 | } |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 160 | |
| 161 | /****************************************************************************** |
| 162 | * SetServiceStatus [ADVAPI32.192] |
| 163 | * |
| 164 | * PARAMS |
| 165 | * hService [] |
| 166 | * lpStatus [] |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 167 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 168 | BOOL WINAPI |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 169 | SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus ) |
Alexandre Julliard | 9fe7a25 | 1999-05-14 08:17:14 +0000 | [diff] [blame] | 170 | { FIXME("%lx %p\n",hService, lpStatus); |
| 171 | TRACE("\tType:%lx\n",lpStatus->dwServiceType); |
| 172 | TRACE("\tState:%lx\n",lpStatus->dwCurrentState); |
| 173 | TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted); |
| 174 | TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode); |
| 175 | TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode); |
| 176 | TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint); |
| 177 | TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint); |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 178 | return TRUE; |
| 179 | } |
| 180 | |
| 181 | /****************************************************************************** |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 182 | * OpenSCManagerA [ADVAPI32.110] |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 183 | */ |
Patrik Stridvall | 4a73973 | 1999-07-04 11:01:21 +0000 | [diff] [blame] | 184 | SC_HANDLE WINAPI |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 185 | OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName, |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 186 | DWORD dwDesiredAccess ) |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 187 | { |
| 188 | LPWSTR lpMachineNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpMachineName); |
| 189 | LPWSTR lpDatabaseNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpDatabaseName); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 190 | DWORD ret = OpenSCManagerW(lpMachineNameW,lpDatabaseNameW, |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 191 | dwDesiredAccess); |
| 192 | HeapFree(GetProcessHeap(),0,lpDatabaseNameW); |
| 193 | HeapFree(GetProcessHeap(),0,lpMachineNameW); |
| 194 | return ret; |
| 195 | } |
| 196 | |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 197 | /****************************************************************************** |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 198 | * OpenSCManagerW [ADVAPI32.111] |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 199 | * Establishes a connection to the service control manager and opens database |
| 200 | * |
| 201 | * NOTES |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 202 | * This should return a SC_HANDLE |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 203 | * |
| 204 | * PARAMS |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 205 | * lpMachineName [I] Pointer to machine name string |
| 206 | * lpDatabaseName [I] Pointer to database name string |
| 207 | * dwDesiredAccess [I] Type of access |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 208 | * |
| 209 | * RETURNS |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 210 | * Success: Handle to service control manager database |
| 211 | * Failure: NULL |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 212 | */ |
Patrik Stridvall | 4a73973 | 1999-07-04 11:01:21 +0000 | [diff] [blame] | 213 | SC_HANDLE WINAPI |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 214 | OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName, |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 215 | DWORD dwDesiredAccess ) |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 216 | { |
Michael McCormack | 75a8413 | 1999-11-21 00:58:14 +0000 | [diff] [blame] | 217 | HKEY hKey; |
| 218 | LONG r; |
| 219 | |
| 220 | TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName), |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 221 | debugstr_w(lpDatabaseName), dwDesiredAccess); |
Michael McCormack | 75a8413 | 1999-11-21 00:58:14 +0000 | [diff] [blame] | 222 | |
| 223 | /* |
| 224 | * FIXME: what is lpDatabaseName? |
| 225 | * It should be set to "SERVICES_ACTIVE_DATABASE" according to |
| 226 | * docs, but what if it isn't? |
| 227 | */ |
| 228 | |
| 229 | r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hKey); |
| 230 | if (r!=ERROR_SUCCESS) |
| 231 | return 0; |
| 232 | |
| 233 | TRACE("returning %x\n",hKey); |
| 234 | |
| 235 | return hKey; |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 236 | } |
| 237 | |
| 238 | |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 239 | /****************************************************************************** |
| 240 | * AllocateLocallyUniqueId [ADVAPI32.12] |
| 241 | * |
| 242 | * PARAMS |
| 243 | * lpluid [] |
| 244 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 245 | BOOL WINAPI |
Juergen Schmied | 1ed51af | 1999-02-12 17:47:07 +0000 | [diff] [blame] | 246 | AllocateLocallyUniqueId( PLUID lpluid ) |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 247 | { |
Patrik Stridvall | 311e456 | 1999-09-19 14:20:33 +0000 | [diff] [blame] | 248 | lpluid->s.LowPart = time(NULL); |
| 249 | lpluid->s.HighPart = 0; |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 250 | return TRUE; |
| 251 | } |
| 252 | |
| 253 | |
| 254 | /****************************************************************************** |
| 255 | * ControlService [ADVAPI32.23] |
| 256 | * Sends a control code to a Win32-based service. |
| 257 | * |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 258 | * PARAMS |
| 259 | * hService [] |
| 260 | * dwControl [] |
| 261 | * lpServiceStatus [] |
| 262 | * |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 263 | * RETURNS STD |
| 264 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 265 | BOOL WINAPI |
Patrik Stridvall | 4a73973 | 1999-07-04 11:01:21 +0000 | [diff] [blame] | 266 | ControlService( SC_HANDLE hService, DWORD dwControl, |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 267 | LPSERVICE_STATUS lpServiceStatus ) |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 268 | { |
Alexandre Julliard | 9fe7a25 | 1999-05-14 08:17:14 +0000 | [diff] [blame] | 269 | FIXME("(%d,%ld,%p): stub\n",hService,dwControl,lpServiceStatus); |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 270 | return TRUE; |
| 271 | } |
| 272 | |
| 273 | |
| 274 | /****************************************************************************** |
| 275 | * CloseServiceHandle [ADVAPI32.22] |
| 276 | * Close handle to service or service control manager |
| 277 | * |
| 278 | * PARAMS |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 279 | * hSCObject [I] Handle to service or service control manager database |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 280 | * |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 281 | * RETURNS STD |
| 282 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 283 | BOOL WINAPI |
Patrik Stridvall | 4a73973 | 1999-07-04 11:01:21 +0000 | [diff] [blame] | 284 | CloseServiceHandle( SC_HANDLE hSCObject ) |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 285 | { |
Michael McCormack | 75a8413 | 1999-11-21 00:58:14 +0000 | [diff] [blame] | 286 | TRACE("(%x)\n", hSCObject); |
| 287 | |
| 288 | RegCloseKey(hSCObject); |
| 289 | |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 290 | return TRUE; |
| 291 | } |
| 292 | |
| 293 | |
| 294 | /****************************************************************************** |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 295 | * OpenServiceA [ADVAPI32.112] |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 296 | */ |
Patrik Stridvall | 4a73973 | 1999-07-04 11:01:21 +0000 | [diff] [blame] | 297 | SC_HANDLE WINAPI |
| 298 | OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName, |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 299 | DWORD dwDesiredAccess ) |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 300 | { |
| 301 | LPWSTR lpServiceNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpServiceName); |
Michael McCormack | 75a8413 | 1999-11-21 00:58:14 +0000 | [diff] [blame] | 302 | DWORD ret; |
| 303 | |
| 304 | if(lpServiceName) |
| 305 | TRACE("Request for service %s\n",lpServiceName); |
| 306 | else |
| 307 | return FALSE; |
| 308 | ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess); |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 309 | HeapFree(GetProcessHeap(),0,lpServiceNameW); |
| 310 | return ret; |
| 311 | } |
| 312 | |
| 313 | |
| 314 | /****************************************************************************** |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 315 | * OpenServiceW [ADVAPI32.113] |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 316 | * Opens a handle to an existing service |
| 317 | * |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 318 | * PARAMS |
| 319 | * hSCManager [] |
| 320 | * lpServiceName [] |
| 321 | * dwDesiredAccess [] |
| 322 | * |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 323 | * RETURNS |
| 324 | * Success: Handle to the service |
| 325 | * Failure: NULL |
| 326 | */ |
Patrik Stridvall | 4a73973 | 1999-07-04 11:01:21 +0000 | [diff] [blame] | 327 | SC_HANDLE WINAPI |
| 328 | OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName, |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 329 | DWORD dwDesiredAccess) |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 330 | { |
Michael McCormack | 75a8413 | 1999-11-21 00:58:14 +0000 | [diff] [blame] | 331 | const char *str = "System\\CurrentControlSet\\Services\\"; |
| 332 | WCHAR lpServiceKey[80]; /* FIXME: this should be dynamically allocated */ |
| 333 | HKEY hKey; |
| 334 | long r; |
| 335 | |
| 336 | TRACE("(%d,%p,%ld)\n",hSCManager, lpServiceName, |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 337 | dwDesiredAccess); |
Michael McCormack | 75a8413 | 1999-11-21 00:58:14 +0000 | [diff] [blame] | 338 | |
| 339 | lstrcpyAtoW(lpServiceKey,str); |
| 340 | lstrcatW(lpServiceKey,lpServiceName); |
| 341 | |
| 342 | TRACE("Opening reg key %s\n", debugstr_w(lpServiceKey)); |
| 343 | |
| 344 | /* FIXME: dwDesiredAccess may need some processing */ |
| 345 | r = RegOpenKeyExW(hSCManager, lpServiceKey, 0, dwDesiredAccess, &hKey ); |
| 346 | if (r!=ERROR_SUCCESS) |
| 347 | return 0; |
| 348 | |
| 349 | TRACE("returning %x\n",hKey); |
| 350 | |
| 351 | return hKey; |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 352 | } |
| 353 | |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 354 | /****************************************************************************** |
| 355 | * CreateServiceW [ADVAPI32.29] |
| 356 | */ |
| 357 | SC_HANDLE WINAPI |
| 358 | CreateServiceW( DWORD hSCManager, LPCWSTR lpServiceName, |
| 359 | LPCWSTR lpDisplayName, DWORD dwDesiredAccess, |
| 360 | DWORD dwServiceType, DWORD dwStartType, |
| 361 | DWORD dwErrorControl, LPCWSTR lpBinaryPathName, |
| 362 | LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, |
| 363 | LPCWSTR lpDependencies, LPCWSTR lpServiceStartName, |
| 364 | LPCWSTR lpPassword ) |
| 365 | { |
| 366 | FIXME("(%ld,%s,%s,...)\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName)); |
| 367 | return FALSE; |
| 368 | } |
| 369 | |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 370 | |
| 371 | /****************************************************************************** |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 372 | * CreateServiceA [ADVAPI32.28] |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 373 | */ |
Patrik Stridvall | 4a73973 | 1999-07-04 11:01:21 +0000 | [diff] [blame] | 374 | SC_HANDLE WINAPI |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 375 | CreateServiceA( DWORD hSCManager, LPCSTR lpServiceName, |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 376 | LPCSTR lpDisplayName, DWORD dwDesiredAccess, |
| 377 | DWORD dwServiceType, DWORD dwStartType, |
| 378 | DWORD dwErrorControl, LPCSTR lpBinaryPathName, |
| 379 | LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, |
| 380 | LPCSTR lpDependencies, LPCSTR lpServiceStartName, |
| 381 | LPCSTR lpPassword ) |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 382 | { |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 383 | HKEY hKey; |
| 384 | LONG r; |
| 385 | DWORD dp; |
| 386 | |
| 387 | TRACE("(%ld,%s,%s,...)\n", hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName)); |
| 388 | |
| 389 | r = RegCreateKeyExA(hSCManager, lpServiceName, 0, NULL, |
| 390 | REG_OPTION_NON_VOLATILE, dwDesiredAccess, NULL, &hKey, &dp); |
| 391 | if (r!=ERROR_SUCCESS) |
| 392 | return 0; |
| 393 | if (dp != REG_CREATED_NEW_KEY) |
| 394 | return 0; |
| 395 | |
| 396 | if(lpDisplayName) |
| 397 | { |
| 398 | r = RegSetValueExA(hKey, "DisplayName", 0, REG_SZ, lpDisplayName, lstrlenA(lpDisplayName) ); |
| 399 | if (r!=ERROR_SUCCESS) |
| 400 | return 0; |
| 401 | } |
| 402 | |
| 403 | r = RegSetValueExA(hKey, "Type", 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) ); |
| 404 | if (r!=ERROR_SUCCESS) |
| 405 | return 0; |
| 406 | |
| 407 | r = RegSetValueExA(hKey, "Start", 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) ); |
| 408 | if (r!=ERROR_SUCCESS) |
| 409 | return 0; |
| 410 | |
| 411 | r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD, |
| 412 | (LPVOID)&dwErrorControl, sizeof (DWORD) ); |
| 413 | if (r!=ERROR_SUCCESS) |
| 414 | return 0; |
| 415 | |
| 416 | if(lpBinaryPathName) |
| 417 | { |
| 418 | r = RegSetValueExA(hKey, "ImagePath", 0, REG_SZ, |
| 419 | lpBinaryPathName,lstrlenA(lpBinaryPathName)+1 ); |
| 420 | if (r!=ERROR_SUCCESS) |
| 421 | return 0; |
| 422 | } |
| 423 | |
| 424 | if(lpLoadOrderGroup) |
| 425 | { |
| 426 | r = RegSetValueExA(hKey, "Group", 0, REG_SZ, |
| 427 | lpLoadOrderGroup, lstrlenA(lpLoadOrderGroup)+1 ); |
| 428 | if (r!=ERROR_SUCCESS) |
| 429 | return 0; |
| 430 | } |
| 431 | |
| 432 | r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD, |
| 433 | (LPVOID)&dwErrorControl, sizeof (DWORD) ); |
| 434 | if (r!=ERROR_SUCCESS) |
| 435 | return 0; |
| 436 | |
| 437 | if(lpDependencies) |
| 438 | { |
| 439 | DWORD len = 0; |
| 440 | |
| 441 | /* determine the length of a double null terminated multi string */ |
| 442 | do { |
| 443 | len += (lstrlenA(&lpDependencies[len])+1); |
| 444 | } while (lpDependencies[len++]); |
| 445 | |
| 446 | /* fixme: this should be unicode */ |
| 447 | r = RegSetValueExA(hKey, "Dependencies", 0, REG_MULTI_SZ, |
| 448 | lpDependencies, len ); |
| 449 | if (r!=ERROR_SUCCESS) |
| 450 | return 0; |
| 451 | } |
| 452 | |
| 453 | if(lpPassword) |
| 454 | { |
| 455 | FIXME("Don't know how to add a Password for a service.\n"); |
| 456 | } |
| 457 | |
| 458 | if(lpServiceStartName) |
| 459 | { |
| 460 | FIXME("Don't know how to add a ServiceStartName for a service.\n"); |
| 461 | } |
| 462 | |
| 463 | return hKey; |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 464 | } |
| 465 | |
| 466 | |
| 467 | /****************************************************************************** |
| 468 | * DeleteService [ADVAPI32.31] |
| 469 | * |
| 470 | * PARAMS |
| 471 | * hService [I] Handle to service |
| 472 | * |
| 473 | * RETURNS STD |
| 474 | * |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 475 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 476 | BOOL WINAPI |
Patrik Stridvall | 4a73973 | 1999-07-04 11:01:21 +0000 | [diff] [blame] | 477 | DeleteService( SC_HANDLE hService ) |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 478 | { |
Alexandre Julliard | 9fe7a25 | 1999-05-14 08:17:14 +0000 | [diff] [blame] | 479 | FIXME("(%d): stub\n",hService); |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 480 | return TRUE; |
| 481 | } |
| 482 | |
| 483 | |
| 484 | /****************************************************************************** |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 485 | * StartServiceA [ADVAPI32.195] |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 486 | * |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 487 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 488 | BOOL WINAPI |
Patrik Stridvall | 4a73973 | 1999-07-04 11:01:21 +0000 | [diff] [blame] | 489 | StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs, |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 490 | LPCSTR *lpServiceArgVectors ) |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 491 | { |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 492 | LPWSTR *lpwstr=NULL; |
| 493 | int i; |
| 494 | |
| 495 | TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors); |
| 496 | |
| 497 | if(dwNumServiceArgs) |
| 498 | lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0, |
| 499 | dwNumServiceArgs*sizeof(LPWSTR) ); |
| 500 | else |
| 501 | lpwstr = NULL; |
| 502 | |
| 503 | for(i=0; i<dwNumServiceArgs; i++) |
| 504 | lpwstr[i]=HEAP_strdupAtoW(GetProcessHeap(), 0, lpServiceArgVectors[i]); |
| 505 | |
Andreas Mohr | 7fb732e | 1999-12-12 00:47:51 +0000 | [diff] [blame] | 506 | StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr); |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 507 | |
| 508 | if(dwNumServiceArgs) |
| 509 | { |
| 510 | for(i=0; i<dwNumServiceArgs; i++) |
| 511 | HeapFree(GetProcessHeap(), 0, lpwstr[i]); |
| 512 | HeapFree(GetProcessHeap(), 0, lpwstr); |
| 513 | } |
| 514 | |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 515 | return TRUE; |
| 516 | } |
| 517 | |
| 518 | |
| 519 | /****************************************************************************** |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 520 | * StartServiceW [ADVAPI32.198] |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 521 | * Starts a service |
| 522 | * |
| 523 | * PARAMS |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 524 | * hService [I] Handle of service |
| 525 | * dwNumServiceArgs [I] Number of arguments |
| 526 | * lpServiceArgVectors [I] Address of array of argument string pointers |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 527 | * |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 528 | * NOTES |
| 529 | * |
| 530 | * NT implements this function using an obscure RPC call... |
| 531 | * |
| 532 | * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc |
| 533 | * to get things like %SystemRoot%\\System32\\service.exe to load. |
| 534 | * |
| 535 | * Will only work for shared address space. How should the service |
| 536 | * args be transferred when address spaces are separated? |
| 537 | * |
| 538 | * Can only start one service at a time. |
| 539 | * |
| 540 | * Has no concept of priviledge. |
| 541 | * |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 542 | * RETURNS STD |
| 543 | * |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 544 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 545 | BOOL WINAPI |
Patrik Stridvall | 4a73973 | 1999-07-04 11:01:21 +0000 | [diff] [blame] | 546 | StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs, |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 547 | LPCWSTR *lpServiceArgVectors ) |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 548 | { |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 549 | CHAR path[MAX_PATH],str[MAX_PATH]; |
| 550 | DWORD type,size; |
| 551 | long r; |
| 552 | HANDLE data,wait; |
| 553 | PROCESS_INFORMATION procinfo; |
| 554 | STARTUPINFOA startupinfo; |
| 555 | |
| 556 | TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs, |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 557 | lpServiceArgVectors); |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 558 | |
| 559 | size = sizeof str; |
| 560 | r = RegQueryValueExA(hService, "ImagePath", NULL, &type, (LPVOID)str, &size); |
| 561 | if (r!=ERROR_SUCCESS) |
| 562 | return FALSE; |
| 563 | ExpandEnvironmentStringsA(str,path,sizeof path); |
| 564 | |
| 565 | TRACE("Starting service %s\n", debugstr_a(path) ); |
| 566 | |
| 567 | data = CreateSemaphoreA(NULL,1,1,"ADVAPI32_ServiceStartData"); |
| 568 | if(data == ERROR_INVALID_HANDLE) |
| 569 | { |
| 570 | data = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData"); |
| 571 | if(data == 0) |
| 572 | { |
| 573 | ERR("Couldn't create data semaphore\n"); |
| 574 | return FALSE; |
| 575 | } |
| 576 | } |
| 577 | wait = CreateSemaphoreA(NULL,0,1,"ADVAPI32_WaitServiceStart"); |
| 578 | { |
| 579 | wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData"); |
| 580 | if(wait == 0) |
| 581 | { |
| 582 | ERR("Couldn't create wait semaphore\n"); |
| 583 | return FALSE; |
| 584 | } |
| 585 | } |
| 586 | |
| 587 | /* |
| 588 | * FIXME: lpServiceArgsVectors need to be stored and returned to |
| 589 | * the service when it calls StartServiceCtrlDispatcher |
| 590 | * |
| 591 | * Chuck these in a global (yuk) so we can pass them to |
| 592 | * another process - address space separation will break this. |
| 593 | */ |
| 594 | |
| 595 | r = WaitForSingleObject(data,INFINITE); |
| 596 | |
| 597 | if( r == WAIT_FAILED) |
| 598 | return FALSE; |
| 599 | |
| 600 | start_dwNumServiceArgs = dwNumServiceArgs; |
Andreas Mohr | 7fb732e | 1999-12-12 00:47:51 +0000 | [diff] [blame] | 601 | start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors; |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 602 | |
| 603 | ZeroMemory(&startupinfo,sizeof(STARTUPINFOA)); |
| 604 | startupinfo.cb = sizeof(STARTUPINFOA); |
| 605 | |
| 606 | r = CreateProcessA(path, |
| 607 | NULL, |
| 608 | NULL, /* process security attribs */ |
| 609 | NULL, /* thread security attribs */ |
| 610 | FALSE, /* inherit handles */ |
| 611 | 0, /* creation flags */ |
| 612 | NULL, /* environment */ |
| 613 | NULL, /* current directory */ |
| 614 | &startupinfo, /* startup info */ |
| 615 | &procinfo); /* process info */ |
| 616 | |
| 617 | if(r == FALSE) |
| 618 | { |
| 619 | ERR("Couldn't start process\n"); |
| 620 | /* ReleaseSemaphore(data, 1, NULL); |
| 621 | return FALSE; */ |
| 622 | } |
| 623 | |
| 624 | /* docs for StartServiceCtrlDispatcher say this should be 30 sec */ |
| 625 | r = WaitForSingleObject(wait,30000); |
| 626 | |
| 627 | ReleaseSemaphore(data, 1, NULL); |
| 628 | |
| 629 | if( r == WAIT_FAILED) |
| 630 | return FALSE; |
| 631 | |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 632 | return TRUE; |
| 633 | } |
| 634 | |
| 635 | /****************************************************************************** |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 636 | * QueryServiceStatus [ADVAPI32.123] |
| 637 | * |
| 638 | * PARAMS |
| 639 | * hService [] |
| 640 | * lpservicestatus [] |
| 641 | * |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 642 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 643 | BOOL WINAPI |
Patrik Stridvall | 4a73973 | 1999-07-04 11:01:21 +0000 | [diff] [blame] | 644 | QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus ) |
Matthew Becker | e905f3c | 1999-01-28 13:46:25 +0000 | [diff] [blame] | 645 | { |
Michael McCormack | 75a8413 | 1999-11-21 00:58:14 +0000 | [diff] [blame] | 646 | LONG r; |
| 647 | DWORD type, val, size; |
| 648 | |
| 649 | FIXME("(%x,%p) partial\n",hService,lpservicestatus); |
| 650 | |
| 651 | /* read the service type from the registry */ |
| 652 | size = sizeof val; |
| 653 | r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size); |
| 654 | if(type!=REG_DWORD) |
| 655 | { |
| 656 | ERR("invalid Type\n"); |
| 657 | return FALSE; |
| 658 | } |
| 659 | lpservicestatus->dwServiceType = val; |
Michael McCormack | 75a8413 | 1999-11-21 00:58:14 +0000 | [diff] [blame] | 660 | /* FIXME: how are these determined or read from the registry? */ |
Michael McCormack | 0c0f7d3 | 1999-12-04 04:03:45 +0000 | [diff] [blame] | 661 | /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */; |
| 662 | lpservicestatus->dwCurrentState = 1; |
Michael McCormack | 75a8413 | 1999-11-21 00:58:14 +0000 | [diff] [blame] | 663 | lpservicestatus->dwControlsAccepted = 0; |
| 664 | lpservicestatus->dwWin32ExitCode = NO_ERROR; |
| 665 | lpservicestatus->dwServiceSpecificExitCode = 0; |
| 666 | lpservicestatus->dwCheckPoint = 0; |
| 667 | lpservicestatus->dwWaitHint = 0; |
| 668 | |
| 669 | return TRUE; |
Juergen Schmied | f7b0de3 | 1999-01-03 12:48:29 +0000 | [diff] [blame] | 670 | } |
| 671 | |