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