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