winnt-enable-global-drive-mappings-20030701
[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
25 #ifdef DEBUG
26 //#define NOTSERVICE
27 #endif
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 1
142 /* This code was moved to Drivemap.cpp*/
143 /* Mount a drive into AFS if the user wants us to */
144 /* DEE Could check first if we are run as SYSTEM */
145 void CheckMountDrive()
146 {
147         char szAfsPath[_MAX_PATH];
148         char szDriveToMapTo[5];
149         DWORD dwResult;
150         char szKeyName[256];
151         HKEY hKey;
152         DWORD dwIndex = 0;
153         DWORD dwDriveSize;
154         DWORD dwSubMountSize;
155         char szSubMount[256];
156         DWORD dwType;
157
158         sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSConfigKeyName);
159
160         dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
161         if (dwResult != ERROR_SUCCESS)
162                 return;
163
164         while (1) {
165                 dwDriveSize = sizeof(szDriveToMapTo);
166                 dwSubMountSize = sizeof(szSubMount);
167                 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
168                 if (dwResult != ERROR_MORE_DATA) {
169                         if (dwResult != ERROR_SUCCESS) {
170                                 if (dwResult != ERROR_NO_MORE_ITEMS)
171                                         afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
172                                 break;
173                         }
174                 }
175                 
176 #if 0
177                 sprintf(szAfsPath, "\\Device\\LanmanRedirector\\%s\\%s-AFS\\%s", szDriveToMapTo, cm_HostName, szSubMount);
178         
179                 dwResult = DefineDosDevice(DDD_RAW_TARGET_PATH, szDriveToMapTo, szAfsPath);
180 #else
181                 {
182                     NETRESOURCE nr;
183                     memset (&nr, 0x00, sizeof(NETRESOURCE));
184  
185                     sprintf(szAfsPath,"\\\\%s-AFS\\%s",cm_HostName,szSubMount);
186                     
187                     nr.dwScope = RESOURCE_GLOBALNET;
188                     nr.dwType=RESOURCETYPE_DISK;
189                     nr.lpLocalName=szDriveToMapTo;
190                     nr.lpRemoteName=szAfsPath;
191                     nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
192                     nr.dwUsage = RESOURCEUSAGE_CONNECTABLE;
193
194                     dwResult = WNetAddConnection2(&nr,NULL,NULL,FALSE);
195                 }
196 #endif
197                 afsi_log("GlobalAutoMap of %s to %s %s", szDriveToMapTo, szSubMount, dwResult ? "succeeded" : "failed");
198         }        
199
200         RegCloseKey(hKey);
201 }
202 #endif
203
204 void afsd_Main()
205 {
206         long code;
207         char *reason;
208         int jmpret;
209
210         osi_InitPanic(afsd_notifier);
211         osi_InitTraceOption();
212
213         GlobalStatus = 0;
214
215         WaitToTerminate = CreateEvent(NULL, TRUE, FALSE, NULL);
216
217 #ifndef NOTSERVICE
218         StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME,
219                         (LPHANDLER_FUNCTION) afsd_ServiceControlHandler);
220
221         ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
222         ServiceStatus.dwServiceSpecificExitCode = 0;
223         ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
224         ServiceStatus.dwWin32ExitCode = NO_ERROR;
225         ServiceStatus.dwCheckPoint = 1;
226         ServiceStatus.dwWaitHint = 15000;
227         ServiceStatus.dwControlsAccepted = 0;
228         SetServiceStatus(StatusHandle, &ServiceStatus);
229 #endif
230 {       
231         HANDLE h; char *ptbuf[1];
232         h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
233         ptbuf[0] = "AFS start pending";
234         ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
235         DeregisterEventSource(h);
236 }
237
238         afsi_start();
239
240         MainThreadId = GetCurrentThreadId();
241         jmpret = setjmp(notifier_jmp);
242
243         if (jmpret == 0) {
244                 code = afsd_InitCM(&reason);
245                 if (code != 0)
246                         osi_panic(reason, __FILE__, __LINE__);
247
248                 code = afsd_InitDaemons(&reason);
249                 if (code != 0)
250                         osi_panic(reason, __FILE__, __LINE__);
251
252                 code = afsd_InitSMB(&reason, DummyMessageBox);
253                 if (code != 0)
254                         osi_panic(reason, __FILE__, __LINE__);
255
256 #ifndef NOTSERVICE
257                 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
258                 ServiceStatus.dwWin32ExitCode = NO_ERROR;
259                 ServiceStatus.dwCheckPoint = 0;
260                 ServiceStatus.dwWaitHint = 0;
261                 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
262                 SetServiceStatus(StatusHandle, &ServiceStatus);
263 #endif
264         {
265                 HANDLE h; char *ptbuf[1];
266                 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
267                 ptbuf[0] = "AFS running";
268                 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
269                 DeregisterEventSource(h);
270         }
271         }
272
273         /* Check if we should mount a drive into AFS */
274         CheckMountDrive();
275
276         WaitForSingleObject(WaitToTerminate, INFINITE);
277         
278 {   
279         HANDLE h; char *ptbuf[1];
280         h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
281         ptbuf[0] = "AFS quitting";
282         ReportEvent(h,
283                 GlobalStatus ? EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE,
284                 0, 0, NULL, 1, 0, ptbuf, NULL);
285         DeregisterEventSource(h);
286 }
287
288         ServiceStatus.dwCurrentState = SERVICE_STOPPED;
289         ServiceStatus.dwWin32ExitCode = NO_ERROR;
290         ServiceStatus.dwCheckPoint = 0;
291         ServiceStatus.dwWaitHint = 0;
292         ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
293         SetServiceStatus(StatusHandle, &ServiceStatus);
294 }
295
296 #ifdef NOTSERVICE
297 void main()
298 {
299         afsd_Main();
300         Sleep(1000);
301         return ;
302 }
303 #else
304 void main()
305 {
306         LONG status = ERROR_SUCCESS;
307         SERVICE_TABLE_ENTRY dispatchTable[] = {
308                 {AFS_DAEMON_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) afsd_Main},
309                 {NULL, NULL}
310         };
311
312         if (!StartServiceCtrlDispatcher(dispatchTable))
313                 status = GetLastError();
314 }
315 #endif