2923a2ed2eea29e48b119064c3a88694a17a1d24
[openafs.git] / src / WINNT / afsd / afsd_service.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afs/param.h>
11 #include <afs/stds.h>
12
13 #include <windows.h>
14 #include <string.h>
15 #include <setjmp.h>
16 #include "afsd.h"
17 #include "afsd_init.h"
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <winsock2.h>
21 #include <winnt/osi_malloc.h>
22
23 #include <osi.h>
24 \r
25 #ifdef DEBUG\r
26 //#define NOTSERVICE\r
27 #endif\r
28
29 extern void afsi_log(char *pattern, ...);
30
31 extern char AFSConfigKeyName[];
32
33 HANDLE WaitToTerminate;
34
35 int GlobalStatus;
36
37 unsigned int MainThreadId;
38 jmp_buf notifier_jmp;
39
40 extern int traceOnPanic;
41
42 /*
43  * Notifier function for use by osi_panic
44  */
45 static void afsd_notifier(char *msgp, char *filep, long line)
46 {
47         char tbuffer[100];
48         char *ptbuf[1];
49         HANDLE h;
50
51         if (filep)
52                 sprintf(tbuffer, "Error at file %s, line %d: %s",
53                         filep, line, msgp);
54         else
55                 sprintf(tbuffer, "Error at unknown location: %s", msgp);
56
57         h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
58         ptbuf[0] = tbuffer;
59         ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, line, NULL, 1, 0, ptbuf, NULL);
60         DeregisterEventSource(h);
61
62         GlobalStatus = line;
63
64         osi_LogEnable(afsd_logp);
65
66         afsd_ForceTrace(TRUE);
67
68         if (traceOnPanic) {
69                 _asm int 3h;
70         }
71
72         SetEvent(WaitToTerminate);
73
74         if (GetCurrentThreadId() == MainThreadId)
75                 longjmp(notifier_jmp, 1);
76         else
77                 ExitThread(1);
78 }
79
80 /*
81  * For use miscellaneously in smb.c; need to do better
82  */
83 static int DummyMessageBox(HWND h, LPCTSTR l1, LPCTSTR l2, UINT ui)
84 {
85         return 0;
86 }
87
88 static SERVICE_STATUS           ServiceStatus;
89 static SERVICE_STATUS_HANDLE    StatusHandle;
90
91 void afsd_ServiceControlHandler(DWORD ctrlCode)
92 {
93         HKEY parmKey;
94         DWORD dummyLen, doTrace;
95         long code;
96
97         switch (ctrlCode) {
98                 case SERVICE_CONTROL_STOP:
99                         /* Shutdown RPC */
100                         RpcMgmtStopServerListening(NULL);
101
102                         /* Force trace if requested */
103                         code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
104                                             AFSConfigKeyName,
105                                             0, KEY_QUERY_VALUE, &parmKey);
106                         if (code != ERROR_SUCCESS)
107                                 goto doneTrace;
108
109                         dummyLen = sizeof(doTrace);
110                         code = RegQueryValueEx(parmKey, "TraceOnShutdown",
111                                                 NULL, NULL,
112                                                 (BYTE *) &doTrace, &dummyLen);
113                         RegCloseKey (parmKey);
114                         if (code != ERROR_SUCCESS)
115                                 doTrace = 0;
116                         if (doTrace)
117                                 afsd_ForceTrace(FALSE);
118
119 doneTrace:
120                         ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
121                         ServiceStatus.dwWin32ExitCode = NO_ERROR;
122                         ServiceStatus.dwCheckPoint = 1;
123                         ServiceStatus.dwWaitHint = 10000;
124                         ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
125                         SetServiceStatus(StatusHandle, &ServiceStatus);
126                         SetEvent(WaitToTerminate);
127                         break;
128                 case SERVICE_CONTROL_INTERROGATE:
129                         ServiceStatus.dwCurrentState = SERVICE_RUNNING;
130                         ServiceStatus.dwWin32ExitCode = NO_ERROR;
131                         ServiceStatus.dwCheckPoint = 0;
132                         ServiceStatus.dwWaitHint = 0;
133                         ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
134                         SetServiceStatus(StatusHandle, &ServiceStatus);
135                         break;
136                 /* XXX handle system shutdown */
137                 /* XXX handle pause & continue */
138         }
139 }
140
141 #if 0
142 /* This code was moved to Drivemap.cpp*/
143 /* Mount a drive into AFS if the user wants us to */
144 void CheckMountDrive()
145 {
146         char szAfsPath[_MAX_PATH];
147         char szDriveToMapTo[5];
148         DWORD dwResult;
149         char szKeyName[256];
150         HKEY hKey;
151         DWORD dwIndex = 0;
152         DWORD dwDriveSize;
153         DWORD dwSubMountSize;
154         char szSubMount[256];
155         DWORD dwType;
156
157         sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSConfigKeyName);
158
159         dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
160         if (dwResult != ERROR_SUCCESS)
161                 return;
162
163         while (1) {
164                 dwDriveSize = sizeof(szDriveToMapTo);
165                 dwSubMountSize = sizeof(szSubMount);
166                 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
167                 if (dwResult != ERROR_MORE_DATA) {
168                         if (dwResult != ERROR_SUCCESS) {
169                                 if (dwResult != ERROR_NO_MORE_ITEMS)
170                                         afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
171                                 break;
172                         }
173                 }
174                 
175                 sprintf(szAfsPath, "\\Device\\LanmanRedirector\\%s\\%s-AFS\\%s", szDriveToMapTo, cm_HostName, szSubMount);
176         
177                 dwResult = DefineDosDevice(DDD_RAW_TARGET_PATH, szDriveToMapTo, szAfsPath);
178                 afsi_log("GlobalAutoMap of %s to %s %s", szDriveToMapTo, szSubMount, dwResult ? "succeeded" : "failed");
179         }        
180
181         RegCloseKey(hKey);
182 }
183 #endif
184
185 void afsd_Main()
186 {
187         long code;
188         char *reason;
189         int jmpret;
190
191         osi_InitPanic(afsd_notifier);
192         osi_InitTraceOption();
193
194         GlobalStatus = 0;
195
196         WaitToTerminate = CreateEvent(NULL, TRUE, FALSE, NULL);
197
198 #ifndef NOTSERVICE\r
199         StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME,
200                         (LPHANDLER_FUNCTION) afsd_ServiceControlHandler);
201
202         ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
203         ServiceStatus.dwServiceSpecificExitCode = 0;
204         ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
205         ServiceStatus.dwWin32ExitCode = NO_ERROR;
206         ServiceStatus.dwCheckPoint = 1;
207         ServiceStatus.dwWaitHint = 15000;
208         ServiceStatus.dwControlsAccepted = 0;
209         SetServiceStatus(StatusHandle, &ServiceStatus);
210 #endif
211 {       
212         HANDLE h; char *ptbuf[1];
213         h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
214         ptbuf[0] = "AFS start pending";
215         ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
216         DeregisterEventSource(h);
217 }
218
219         afsi_start();
220
221         MainThreadId = GetCurrentThreadId();
222         jmpret = setjmp(notifier_jmp);
223
224         if (jmpret == 0) {
225                 code = afsd_InitCM(&reason);
226                 if (code != 0)
227                         osi_panic(reason, __FILE__, __LINE__);
228
229                 code = afsd_InitDaemons(&reason);
230                 if (code != 0)
231                         osi_panic(reason, __FILE__, __LINE__);
232
233                 code = afsd_InitSMB(&reason, DummyMessageBox);
234                 if (code != 0)
235                         osi_panic(reason, __FILE__, __LINE__);
236
237 #ifndef NOTSERVICE
238                 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
239                 ServiceStatus.dwWin32ExitCode = NO_ERROR;
240                 ServiceStatus.dwCheckPoint = 0;
241                 ServiceStatus.dwWaitHint = 0;
242                 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
243                 SetServiceStatus(StatusHandle, &ServiceStatus);
244 #endif
245         {
246                 HANDLE h; char *ptbuf[1];
247                 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
248                 ptbuf[0] = "AFS running";
249                 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
250                 DeregisterEventSource(h);
251         }
252         }
253
254         /* Check if we should mount a drive into AFS */
255 /*        CheckMountDrive();*/
256
257         WaitForSingleObject(WaitToTerminate, INFINITE);
258         
259 {   
260         HANDLE h; char *ptbuf[1];
261         h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
262         ptbuf[0] = "AFS quitting";
263         ReportEvent(h,
264                 GlobalStatus ? EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE,
265                 0, 0, NULL, 1, 0, ptbuf, NULL);
266         DeregisterEventSource(h);
267 }
268
269         ServiceStatus.dwCurrentState = SERVICE_STOPPED;
270         ServiceStatus.dwWin32ExitCode = NO_ERROR;
271         ServiceStatus.dwCheckPoint = 0;
272         ServiceStatus.dwWaitHint = 0;
273         ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
274         SetServiceStatus(StatusHandle, &ServiceStatus);
275 }
276
277 #ifdef NOTSERVICE
278 void main()
279 {
280         afsd_Main();
281         Sleep(1000);
282         return ;
283 }
284 #else
285 void main()
286 {
287         LONG status = ERROR_SUCCESS;
288         SERVICE_TABLE_ENTRY dispatchTable[] = {
289                 {AFS_DAEMON_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) afsd_Main},
290                 {NULL, NULL}
291         };
292
293         if (!StartServiceCtrlDispatcher(dispatchTable))
294                 status = GetLastError();
295 }
296 #endif