1dc22c6d42812223bc9e6df75fe45f37d51c5f27
[openafs.git] / src / WINNT / afsd / afsd_init.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 #include <afs/afs_args.h>
13
14 #include <windows.h>
15 #include <string.h>
16 #include <nb30.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <locale.h>
20 #include <mbctype.h>
21 #include <winsock2.h>
22 #include <ErrorRep.h>
23
24 #include <osi.h>
25 #include "afsd.h"
26 #include <rx\rx.h>
27 #include <rx\rx_null.h>
28 #include <WINNT/syscfg.h>
29 #include <WINNT/afsreg.h>
30
31 #include "smb.h"
32 #include "cm_rpc.h"
33 #include "lanahelper.h"
34 #include <strsafe.h>
35 #include "cm_memmap.h"
36
37 extern int RXAFSCB_ExecuteRequest(struct rx_call *z_call);
38 extern int RXSTATS_ExecuteRequest(struct rx_call *z_call);
39
40 extern afs_int32 cryptall;
41 extern int cm_enableServerLocks;
42
43 osi_log_t *afsd_logp;
44
45 cm_config_data_t        cm_data;
46
47 char cm_rootVolumeName[VL_MAXNAMELEN];
48 DWORD cm_rootVolumeNameLen;
49 char cm_mountRoot[1024];
50 DWORD cm_mountRootLen;
51 int cm_logChunkSize;
52 int cm_chunkSize;
53 #ifdef AFS_FREELANCE_CLIENT
54 char *cm_FakeRootDir;
55 #endif /* freelance */
56
57 int smb_UseV3 = 1;
58
59 int LANadapter;
60
61 int numBkgD;
62 int numSvThreads;
63 long rx_mtu = -1;
64 int traceOnPanic = 0;
65
66 int logReady = 0;
67
68 char cm_HostName[200];
69 long cm_HostAddr;
70 unsigned short cm_callbackport = CM_DEFAULT_CALLBACKPORT;
71
72 char cm_NetbiosName[MAX_NB_NAME_LENGTH] = "";
73
74 char cm_CachePath[MAX_PATH];
75 DWORD cm_CachePathLen;
76 DWORD cm_ValidateCache = 1;
77
78 BOOL isGateway = FALSE;
79
80 BOOL reportSessionStartups = FALSE;
81
82 cm_initparams_v1 cm_initParams;
83
84 char *cm_sysName = 0;
85 unsigned int   cm_sysNameCount = 0;
86 char *cm_sysNameList[MAXNUMSYSNAMES];
87
88 DWORD TraceOption = 0;
89
90 /*
91  * AFSD Initialization Log
92  *
93  * This is distinct from the regular debug logging facility.
94  * Log items go directly to a file, not to an array in memory, so that even
95  * if AFSD crashes, the log can be inspected.
96  */
97
98 HANDLE afsi_file;
99
100 #ifdef AFS_AFSDB_ENV
101 int cm_dnsEnabled = 1;
102 #endif
103
104
105 static int afsi_log_useTimestamp = 1;
106
107 void
108 afsi_log(char *pattern, ...)
109 {
110     char s[256], t[100], d[100], u[512];
111     DWORD zilch;
112     va_list ap;
113     va_start(ap, pattern);
114
115     StringCbVPrintfA(s, sizeof(s), pattern, ap);
116     if ( afsi_log_useTimestamp ) {
117         GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, t, sizeof(t));
118         GetDateFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, d, sizeof(d));
119         StringCbPrintfA(u, sizeof(u), "%s %s: %s\r\n", d, t, s);
120         if (afsi_file != INVALID_HANDLE_VALUE)
121             WriteFile(afsi_file, u, (DWORD)strlen(u), &zilch, NULL);
122 #ifdef NOTSERVICE
123         printf("%s", u);
124 #endif 
125     } else {
126         if (afsi_file != INVALID_HANDLE_VALUE)
127             WriteFile(afsi_file, s, (DWORD)strlen(s), &zilch, NULL);
128     }
129 }
130
131 extern initUpperCaseTable();
132 void afsd_initUpperCaseTable() 
133 {
134     initUpperCaseTable();
135 }
136
137 void
138 afsi_start()
139 {
140     char wd[256];
141     char t[100], u[100], *p, *path;
142     int zilch;
143     DWORD code;
144     DWORD dwLow, dwHigh;
145     HKEY parmKey;
146     DWORD dummyLen;
147     DWORD maxLogSize = 100 * 1024;
148
149     afsi_file = INVALID_HANDLE_VALUE;
150     code = GetEnvironmentVariable("TEMP", wd, sizeof(wd));
151     if ( code == 0 || code > sizeof(wd) )
152     {
153         code = GetWindowsDirectory(wd, sizeof(wd));
154         if (code == 0) 
155             return;
156     }
157     StringCbCatA(wd, sizeof(wd), "\\afsd_init.log");
158     GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, t, sizeof(t));
159     afsi_file = CreateFile(wd, GENERIC_WRITE, FILE_SHARE_READ, NULL,
160                            OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
161
162     code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
163                          0, KEY_QUERY_VALUE, &parmKey);
164     if (code == ERROR_SUCCESS) {
165         dummyLen = sizeof(maxLogSize);
166         code = RegQueryValueEx(parmKey, "MaxLogSize", NULL, NULL,
167                                 (BYTE *) &maxLogSize, &dummyLen);
168         RegCloseKey (parmKey);
169     }
170
171     if (maxLogSize) {
172         dwLow = GetFileSize( afsi_file, &dwHigh );
173         if ( dwHigh > 0 || dwLow >= maxLogSize ) {
174             CloseHandle(afsi_file);
175             afsi_file = CreateFile( wd, GENERIC_WRITE, FILE_SHARE_READ, NULL,
176                                     CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
177         }
178     }
179
180     SetFilePointer(afsi_file, 0, NULL, FILE_END);
181     GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, u, sizeof(u));
182     StringCbCatA(t, sizeof(t), ": Create log file\n");
183     StringCbCatA(u, sizeof(u), ": Created log file\n");
184     WriteFile(afsi_file, t, (DWORD)strlen(t), &zilch, NULL);
185     WriteFile(afsi_file, u, (DWORD)strlen(u), &zilch, NULL);
186     p = "PATH=";
187     code = GetEnvironmentVariable("PATH", NULL, 0);
188     path = malloc(code);
189     code = GetEnvironmentVariable("PATH", path, code);
190     WriteFile(afsi_file, p, (DWORD)strlen(p), &zilch, NULL);
191     WriteFile(afsi_file, path, (DWORD)strlen(path), &zilch, NULL);
192     WriteFile(afsi_file, "\n", (DWORD)1, &zilch, NULL);
193     free(path);
194
195     /* Initialize C RTL Code Page conversion functions */
196     /* All of the path info obtained from the SMB client is in the OEM code page */
197     afsi_log("OEM Code Page = %d", GetOEMCP());
198     afsi_log("locale =  %s", setlocale(LC_ALL,NULL));
199 #ifdef COMMENT
200     /* Two things to look into.  First, should mbstowcs() be performing 
201      * character set translations from OEM to Unicode in smb3.c; 
202      * Second, do we need to set this translation in each function 
203      * due to multi-threading. 
204      */
205     afsi_log("locale -> %s", setlocale(LC_ALL, ".OCP"));
206     afsi_log("_setmbcp = %d -> %d", _setmbcp(_MB_CP_OEM), _getmbcp());
207 #endif /* COMMENT */
208 }
209
210 /*
211  * Standard AFSD trace
212  */
213
214 void afsd_ForceTrace(BOOL flush)
215 {
216     HANDLE handle;
217     int len;
218     char buf[256];
219
220     if (!logReady) 
221         return;
222
223     len = GetTempPath(sizeof(buf)-10, buf);
224     StringCbCopyA(&buf[len], sizeof(buf)-len, "/afsd.log");
225     handle = CreateFile(buf, GENERIC_WRITE, FILE_SHARE_READ,
226                          NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
227     if (handle == INVALID_HANDLE_VALUE) {
228         logReady = 0;
229         osi_panic("Cannot create log file", __FILE__, __LINE__);
230     }
231     osi_LogPrint(afsd_logp, handle);
232     if (flush)
233         FlushFileBuffers(handle);
234     CloseHandle(handle);
235 }
236
237 static void
238 configureBackConnectionHostNames(void)
239 {
240     /* On Windows XP SP2, Windows 2003 SP1, and all future Windows operating systems
241      * there is a restriction on the use of SMB authentication on loopback connections.
242      * There are two work arounds available:
243      * 
244      *   (1) We can disable the check for matching host names.  This does not
245      *   require a reboot:
246      *   [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa]
247      *     "DisableLoopbackCheck"=dword:00000001
248      *
249      *   (2) We can add the AFS SMB/CIFS service name to an approved list.  This
250      *   does require a reboot:
251      *   [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0]
252      *     "BackConnectionHostNames"=multi-sz
253      *
254      * The algorithm will be:
255      *   (1) Check to see if cm_NetbiosName exists in the BackConnectionHostNames list
256      *   (2a) If not, add it to the list.  (This will not take effect until the next reboot.)
257      *   (2b1)    and check to see if DisableLoopbackCheck is set.
258      *   (2b2)    If not set, set the DisableLoopbackCheck value to 0x1 
259      *   (2b3)                and create HKLM\SOFTWARE\OpenAFS\Client  UnsetDisableLoopbackCheck
260      *   (2c) else If cm_NetbiosName exists in the BackConnectionHostNames list,
261      *             check for the UnsetDisableLoopbackCheck value.  
262      *             If set, set the DisableLoopbackCheck flag to 0x0 
263      *             and delete the UnsetDisableLoopbackCheck value
264      *
265      * Starting in Longhorn Beta 1, an entry in the BackConnectionHostNames value will
266      * force Windows to use the loopback authentication mechanism for the specified 
267      * services.
268      */
269     HKEY hkLsa;
270     HKEY hkMSV10;
271     HKEY hkClient;
272     DWORD dwType;
273     DWORD dwSize, dwAllocSize;
274     DWORD dwValue;
275     PBYTE pHostNames = NULL, pName = NULL;
276     BOOL  bNameFound = FALSE;   
277
278     if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
279                        "SYSTEM\\CurrentControlSet\\Control\\Lsa\\MSV1_0",
280                        0,
281                        KEY_READ|KEY_WRITE,
282                        &hkMSV10) == ERROR_SUCCESS )
283     {
284         if (RegQueryValueEx( hkMSV10, "BackConnectionHostNames", 0, 
285                              &dwType, NULL, &dwAllocSize) == ERROR_SUCCESS) {
286             dwAllocSize += 1 /* in case the source string is not nul terminated */
287                 + strlen(cm_NetbiosName) + 2;
288             pHostNames = malloc(dwAllocSize);
289             dwSize = dwAllocSize;
290             if (RegQueryValueEx( hkMSV10, "BackConnectionHostNames", 0, &dwType, 
291                                  pHostNames, &dwSize) == ERROR_SUCCESS) {
292                 for (pName = pHostNames; 
293                      (pName - pHostNames < dwSize) && *pName ; 
294                      pName += strlen(pName) + 1)
295                 {
296                     if ( !stricmp(pName, cm_NetbiosName) ) {
297                         bNameFound = TRUE;
298                         break;
299                     }   
300                 }
301             }
302         }
303              
304         if ( !bNameFound ) {
305             size_t size = strlen(cm_NetbiosName) + 2;
306             if ( !pHostNames ) {
307                 pHostNames = malloc(size);
308                 pName = pHostNames;
309             }
310             StringCbCopyA(pName, size, cm_NetbiosName);
311             pName += size - 1;
312             *pName = '\0';  /* add a second nul terminator */
313
314             dwType = REG_MULTI_SZ;
315             dwSize = pName - pHostNames + 1;
316             RegSetValueEx( hkMSV10, "BackConnectionHostNames", 0, dwType, pHostNames, dwSize);
317
318             if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
319                                "SYSTEM\\CurrentControlSet\\Control\\Lsa",
320                                0,
321                                KEY_READ|KEY_WRITE,
322                                &hkLsa) == ERROR_SUCCESS )
323             {
324                 dwSize = sizeof(DWORD);
325                 if ( RegQueryValueEx( hkLsa, "DisableLoopbackCheck", 0, &dwType, (LPBYTE)&dwValue, &dwSize) != ERROR_SUCCESS ||
326                      dwValue == 0 ) {
327                     dwType = REG_DWORD;
328                     dwSize = sizeof(DWORD);
329                     dwValue = 1;
330                     RegSetValueEx( hkLsa, "DisableLoopbackCheck", 0, dwType, (LPBYTE)&dwValue, dwSize);
331
332                     if (RegCreateKeyEx( HKEY_LOCAL_MACHINE, 
333                                         AFSREG_CLT_OPENAFS_SUBKEY,
334                                         0,
335                                         NULL,
336                                         REG_OPTION_NON_VOLATILE,
337                                         KEY_READ|KEY_WRITE,
338                                         NULL,
339                                         &hkClient,
340                                         NULL) == ERROR_SUCCESS) {
341
342                         dwType = REG_DWORD;
343                         dwSize = sizeof(DWORD);
344                         dwValue = 1;
345                         RegSetValueEx( hkClient, "RemoveDisableLoopbackCheck", 0, dwType, (LPBYTE)&dwValue, dwSize);
346                         RegCloseKey(hkClient);
347                     }
348                     RegCloseKey(hkLsa);
349                 }
350             }
351         } else {
352             if (RegCreateKeyEx( HKEY_LOCAL_MACHINE, 
353                                 AFSREG_CLT_OPENAFS_SUBKEY,
354                                 0,
355                                 NULL,
356                                 REG_OPTION_NON_VOLATILE,
357                                 KEY_READ|KEY_WRITE,
358                                 NULL,
359                                 &hkClient,
360                                 NULL) == ERROR_SUCCESS) {
361
362                 dwSize = sizeof(DWORD);
363                 if ( RegQueryValueEx( hkClient, "RemoveDisableLoopbackCheck", 0, &dwType, (LPBYTE)&dwValue, &dwSize) == ERROR_SUCCESS &&
364                      dwValue == 1 ) {
365                     if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
366                                        "SYSTEM\\CurrentControlSet\\Control\\Lsa",
367                                        0,
368                                        KEY_READ|KEY_WRITE,
369                                        &hkLsa) == ERROR_SUCCESS )
370                     {
371                         RegDeleteValue(hkLsa, "DisableLoopbackCheck");
372                         RegCloseKey(hkLsa);
373                     }
374                 }
375                 RegDeleteValue(hkClient, "RemoveDisableLoopbackCheck");
376                 RegCloseKey(hkClient);
377             }
378         }
379         RegCloseKey(hkMSV10);
380     }
381
382     if (pHostNames)
383         free(pHostNames);
384 }
385
386
387 static void afsd_InitServerPreferences(void)
388 {
389     HKEY hkPrefs = 0;
390     DWORD dwType, dwSize;
391     DWORD dwPrefs = 0;
392     DWORD dwIndex;
393     TCHAR szHost[256];
394     DWORD dwHostSize = 256;
395     DWORD dwRank;
396     struct sockaddr_in  saddr;
397     cm_server_t       *tsp;
398
399     if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
400                       AFSREG_CLT_OPENAFS_SUBKEY "\\Server Preferences\\VLDB",
401                       0,
402                       KEY_READ|KEY_QUERY_VALUE,
403                       &hkPrefs) == ERROR_SUCCESS) {
404
405         RegQueryInfoKey( hkPrefs,
406                          NULL,  /* lpClass */
407                          NULL,  /* lpcClass */
408                          NULL,  /* lpReserved */
409                          NULL,  /* lpcSubKeys */
410                          NULL,  /* lpcMaxSubKeyLen */
411                          NULL,  /* lpcMaxClassLen */
412                          &dwPrefs, /* lpcValues */
413                          NULL,  /* lpcMaxValueNameLen */
414                          NULL,  /* lpcMaxValueLen */
415                          NULL,  /* lpcbSecurityDescriptor */
416                          NULL   /* lpftLastWriteTime */
417                          );
418
419         for ( dwIndex = 0 ; dwIndex < dwPrefs; dwIndex++ ) {
420
421             dwSize = sizeof(DWORD);
422             dwHostSize = 256;
423
424             if (RegEnumValue( hkPrefs, dwIndex, szHost, &dwHostSize, NULL,
425                               &dwType, (LPBYTE)&dwRank, &dwSize))
426             {
427                 afsi_log("RegEnumValue(hkPrefs) failed");
428                 continue;
429             }
430
431             afsi_log("VLDB Server Preference: %s = %d",szHost, dwRank);
432
433             if (isdigit(szHost[0]))
434             {
435                 if ((saddr.sin_addr.S_un.S_addr = inet_addr (szHost)) == INADDR_NONE)
436                     continue;
437             } else {
438                 HOSTENT *pEntry;
439                 if ((pEntry = gethostbyname (szHost)) == NULL)
440                     continue;
441
442                 saddr.sin_addr.S_un.S_addr = *(unsigned long *)pEntry->h_addr;
443             }
444             saddr.sin_family = AF_INET;
445             dwRank += (rand() & 0x000f);
446
447             tsp = cm_FindServer(&saddr, CM_SERVER_VLDB);
448             if ( tsp )          /* an existing server - ref count increased */
449             {
450                 tsp->ipRank = (USHORT)dwRank; /* no need to protect by mutex*/
451
452                 /* set preferences for an existing vlserver */
453                 cm_ChangeRankCellVLServer(tsp);
454                 cm_PutServer(tsp);  /* decrease refcount */
455             }
456             else        /* add a new server without a cell */
457             {
458                 tsp = cm_NewServer(&saddr, CM_SERVER_VLDB, NULL); /* refcount = 1 */
459                 tsp->ipRank = (USHORT)dwRank;
460             }
461         }
462
463         RegCloseKey(hkPrefs);
464     }
465
466     if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
467                       AFSREG_CLT_OPENAFS_SUBKEY "\\Server Preferences\\File",
468                       0,
469                       KEY_READ|KEY_QUERY_VALUE,
470                       &hkPrefs) == ERROR_SUCCESS) {
471
472         RegQueryInfoKey( hkPrefs,
473                          NULL,  /* lpClass */
474                          NULL,  /* lpcClass */
475                          NULL,  /* lpReserved */
476                          NULL,  /* lpcSubKeys */
477                          NULL,  /* lpcMaxSubKeyLen */
478                          NULL,  /* lpcMaxClassLen */
479                          &dwPrefs, /* lpcValues */
480                          NULL,  /* lpcMaxValueNameLen */
481                          NULL,  /* lpcMaxValueLen */
482                          NULL,  /* lpcbSecurityDescriptor */
483                          NULL   /* lpftLastWriteTime */
484                          );
485
486         for ( dwIndex = 0 ; dwIndex < dwPrefs; dwIndex++ ) {
487
488             dwSize = sizeof(DWORD);
489             dwHostSize = 256;
490
491             if (RegEnumValue( hkPrefs, dwIndex, szHost, &dwHostSize, NULL,
492                               &dwType, (LPBYTE)&dwRank, &dwSize))
493             {
494                 afsi_log("RegEnumValue(hkPrefs) failed");
495                 continue;
496             }
497
498             afsi_log("File Server Preference: %s = %d",szHost, dwRank);
499
500             if (isdigit(szHost[0]))
501             {
502                 if ((saddr.sin_addr.S_un.S_addr = inet_addr (szHost)) == INADDR_NONE)
503                     continue;
504             } else {
505                 HOSTENT *pEntry;
506                 if ((pEntry = gethostbyname (szHost)) == NULL)
507                     continue;
508
509                 saddr.sin_addr.S_un.S_addr = *(unsigned long *)pEntry->h_addr;
510             }
511             saddr.sin_family = AF_INET;
512             dwRank += (rand() & 0x000f);
513
514             tsp = cm_FindServer(&saddr, CM_SERVER_FILE);
515             if ( tsp )          /* an existing server - ref count increased */
516             {
517                 tsp->ipRank = (USHORT)dwRank; /* no need to protect by mutex*/
518
519                 /* find volumes which might have RO copy 
520                 /* on server and change the ordering of 
521                  * their RO list 
522                  */
523                 cm_ChangeRankVolume(tsp);
524                 cm_PutServer(tsp);  /* decrease refcount */
525             }
526             else        /* add a new server without a cell */
527             {
528                 tsp = cm_NewServer(&saddr, CM_SERVER_FILE, NULL); /* refcount = 1 */
529                 tsp->ipRank = (USHORT)dwRank;
530             }
531         }
532
533         RegCloseKey(hkPrefs);
534     }
535 }
536
537 /*
538  * AFSD Initialization
539  */
540
541 int afsd_InitCM(char **reasonP)
542 {
543     osi_uid_t debugID;
544     afs_uint64 cacheBlocks;
545     DWORD cacheSize;
546     long logChunkSize;
547     DWORD stats;
548     DWORD dwValue;
549     DWORD rx_enable_peer_stats = 0;
550     DWORD rx_enable_process_stats = 0;
551     long traceBufSize;
552     long maxcpus;
553     long ltt, ltto;
554     long rx_nojumbo;
555     long virtualCache = 0;
556     char rootCellName[256];
557     struct rx_service *serverp;
558     static struct rx_securityClass *nullServerSecurityClassp;
559     struct hostent *thp;
560     char *msgBuf;
561     char buf[1024];
562     HKEY parmKey;
563     DWORD dummyLen;
564     DWORD regType;
565     long code;
566     /*int freelanceEnabled;*/
567     WSADATA WSAjunk;
568     lana_number_t lanaNum;
569     int i;
570     char *p, *q; 
571     int cm_noIPAddr;         /* number of client network interfaces */
572     int cm_IPAddr[CM_MAXINTERFACE_ADDR];    /* client's IP address in host order */
573     int cm_SubnetMask[CM_MAXINTERFACE_ADDR];/* client's subnet mask in host order*/
574     int cm_NetMtu[CM_MAXINTERFACE_ADDR];    /* client's MTU sizes */
575     int cm_NetFlags[CM_MAXINTERFACE_ADDR];  /* network flags */
576
577     WSAStartup(0x0101, &WSAjunk);
578
579     afsd_initUpperCaseTable();
580     init_et_to_sys_error();
581
582     /* setup osidebug server at RPC slot 1000 */
583     osi_LongToUID(1000, &debugID);
584     code = osi_InitDebug(&debugID);
585     afsi_log("osi_InitDebug code %d", code);
586
587     //  osi_LockTypeSetDefault("stat"); /* comment this out for speed */
588     if (code != 0) {
589         if (code == RPC_S_NO_PROTSEQS)
590             *reasonP = "No RPC Protocol Sequences registered.  Check HKLM\\SOFTWARE\\Microsoft\\RPC\\ClientProtocols";
591         else
592             *reasonP = "unknown error";
593         return -1;
594     }
595
596     /* who are we ? */
597     gethostname(cm_HostName, sizeof(cm_HostName));
598     afsi_log("gethostname %s", cm_HostName);
599     thp = gethostbyname(cm_HostName);
600     memcpy(&cm_HostAddr, thp->h_addr_list[0], 4);
601
602     /* seed random number generator */
603     srand(ntohl(cm_HostAddr));
604
605     /* Look up configuration parameters in Registry */
606     code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
607                          0, KEY_QUERY_VALUE, &parmKey);
608     if (code != ERROR_SUCCESS) {
609         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
610                        | FORMAT_MESSAGE_ALLOCATE_BUFFER,
611                        NULL, code, 0, (LPTSTR)&msgBuf, 0, NULL);
612         StringCbPrintfA(buf, sizeof(buf),
613                          "Failure in configuration while opening Registry: %s",
614                          msgBuf);
615         osi_panic(buf, __FILE__, __LINE__);
616     }
617
618     dummyLen = sizeof(maxcpus);
619     code = RegQueryValueEx(parmKey, "MaxCPUs", NULL, NULL,
620                             (BYTE *) &maxcpus, &dummyLen);
621     if (code == ERROR_SUCCESS) {
622         HANDLE hProcess;
623         DWORD_PTR processAffinityMask, systemAffinityMask;
624
625         hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION,
626                                FALSE, GetCurrentProcessId());
627         if ( hProcess != NULL &&
628              GetProcessAffinityMask(hProcess, &processAffinityMask, &systemAffinityMask) )
629         {
630             int i, n, bits;
631             DWORD_PTR mask, newAffinityMask;
632
633 #if defined(_WIN64)
634             bits = 64;
635 #else
636             bits = 32;
637 #endif
638             for ( i=0, n=0, mask=1, newAffinityMask=0; i<bits && n<maxcpus; i++ ) {
639                 if ( processAffinityMask & mask ) {
640                     newAffinityMask |= mask;
641                     n++;
642                 }
643                 mask *= 2;
644             }
645
646             SetProcessAffinityMask(hProcess, newAffinityMask);
647             CloseHandle(hProcess);
648             afsi_log("CPU Restrictions set to %d cpu(s); %d cpu(s) available", maxcpus, n);
649         } else {
650             afsi_log("CPU Restrictions set to %d cpu(s); unable to access process information", maxcpus);
651         }
652     }
653
654     dummyLen = sizeof(TraceOption);
655     code = RegQueryValueEx(parmKey, "TraceOption", NULL, NULL,
656                             (BYTE *) &TraceOption, &dummyLen);
657     afsi_log("Trace Options = %lX", TraceOption);
658
659     dummyLen = sizeof(traceBufSize);
660     code = RegQueryValueEx(parmKey, "TraceBufferSize", NULL, NULL,
661                             (BYTE *) &traceBufSize, &dummyLen);
662     if (code == ERROR_SUCCESS)
663         afsi_log("Trace Buffer size %d", traceBufSize);
664     else {
665         traceBufSize = CM_CONFIGDEFAULT_TRACEBUFSIZE;
666         afsi_log("Default trace buffer size %d", traceBufSize);
667     }
668
669     /* setup and enable debug log */
670     afsd_logp = osi_LogCreate("afsd", traceBufSize);
671     afsi_log("osi_LogCreate log addr %x", PtrToUlong(afsd_logp));
672     if ((TraceOption & 0x8)
673 #ifdef DEBUG
674          || 1
675 #endif
676          ) {
677         osi_LogEnable(afsd_logp);
678     }
679     logReady = 1;
680
681     osi_Log0(afsd_logp, "Log init");
682
683     dummyLen = sizeof(cacheSize);
684     code = RegQueryValueEx(parmKey, "CacheSize", NULL, NULL,
685                             (BYTE *) &cacheSize, &dummyLen);
686     if (code == ERROR_SUCCESS)
687         afsi_log("Cache size %d", cacheSize);
688     else {
689         cacheSize = CM_CONFIGDEFAULT_CACHESIZE;
690         afsi_log("Default cache size %d", cacheSize);
691     }
692
693     dummyLen = sizeof(logChunkSize);
694     code = RegQueryValueEx(parmKey, "ChunkSize", NULL, NULL,
695                             (BYTE *) &logChunkSize, &dummyLen);
696     if (code == ERROR_SUCCESS) {
697         if (logChunkSize < 12 || logChunkSize > 30) {
698             afsi_log("Invalid chunk size %d, using default",
699                       logChunkSize);
700             logChunkSize = CM_CONFIGDEFAULT_CHUNKSIZE;
701         }
702         afsi_log("Chunk size %d", logChunkSize);
703     } else {
704         logChunkSize = CM_CONFIGDEFAULT_CHUNKSIZE;
705         afsi_log("Default chunk size %d", logChunkSize);
706     }
707     cm_logChunkSize = logChunkSize;
708     cm_chunkSize = 1 << logChunkSize;
709
710     dummyLen = sizeof(numBkgD);
711     code = RegQueryValueEx(parmKey, "Daemons", NULL, NULL,
712                             (BYTE *) &numBkgD, &dummyLen);
713     if (code == ERROR_SUCCESS)
714         afsi_log("%d background daemons", numBkgD);
715     else {
716         numBkgD = CM_CONFIGDEFAULT_DAEMONS;
717         afsi_log("Defaulting to %d background daemons", numBkgD);
718     }
719
720     dummyLen = sizeof(numSvThreads);
721     code = RegQueryValueEx(parmKey, "ServerThreads", NULL, NULL,
722                             (BYTE *) &numSvThreads, &dummyLen);
723     if (code == ERROR_SUCCESS)
724         afsi_log("%d server threads", numSvThreads);
725     else {
726         numSvThreads = CM_CONFIGDEFAULT_SVTHREADS;
727         afsi_log("Defaulting to %d server threads", numSvThreads);
728     }
729
730     dummyLen = sizeof(stats);
731     code = RegQueryValueEx(parmKey, "Stats", NULL, NULL,
732                             (BYTE *) &stats, &dummyLen);
733     if (code == ERROR_SUCCESS)
734         afsi_log("Status cache size %d", stats);
735     else {
736         stats = CM_CONFIGDEFAULT_STATS;
737         afsi_log("Default status cache size %d", stats);
738     }
739
740     dummyLen = sizeof(ltt);
741     code = RegQueryValueEx(parmKey, "LogoffTokenTransfer", NULL, NULL,
742                             (BYTE *) &ltt, &dummyLen);
743     if (code != ERROR_SUCCESS)
744         ltt = 1;
745     smb_LogoffTokenTransfer = ltt;
746     afsi_log("Logoff token transfer %s",  (ltt ? "on" : "off"));
747
748     if (ltt) {
749         dummyLen = sizeof(ltto);
750         code = RegQueryValueEx(parmKey, "LogoffTokenTransferTimeout",
751                                 NULL, NULL, (BYTE *) &ltto, &dummyLen);
752         if (code != ERROR_SUCCESS)
753             ltto = 120;
754     } else {
755         ltto = 0;
756     }   
757     smb_LogoffTransferTimeout = ltto;
758     afsi_log("Logoff token transfer timeout %d seconds", ltto);
759
760     dummyLen = sizeof(cm_rootVolumeName);
761     code = RegQueryValueEx(parmKey, "RootVolume", NULL, NULL,
762                             cm_rootVolumeName, &dummyLen);
763     if (code == ERROR_SUCCESS)
764         afsi_log("Root volume %s", cm_rootVolumeName);
765     else {
766         StringCbCopyA(cm_rootVolumeName, sizeof(cm_rootVolumeName), "root.afs");
767         afsi_log("Default root volume name root.afs");
768     }
769
770     cm_mountRootLen = sizeof(cm_mountRoot);
771     code = RegQueryValueEx(parmKey, "MountRoot", NULL, NULL,
772                             cm_mountRoot, &cm_mountRootLen);
773     if (code == ERROR_SUCCESS) {
774         afsi_log("Mount root %s", cm_mountRoot);
775         cm_mountRootLen = (DWORD)strlen(cm_mountRoot);
776     } else {
777         StringCbCopyA(cm_mountRoot, sizeof(cm_mountRoot), "/afs");
778         cm_mountRootLen = 4;
779         /* Don't log */
780     }
781
782     dummyLen = sizeof(buf);
783     code = RegQueryValueEx(parmKey, "CachePath", NULL, &regType,
784                             buf, &dummyLen);
785     if (code == ERROR_SUCCESS && buf[0]) {
786         if (regType == REG_EXPAND_SZ) {
787             dummyLen = ExpandEnvironmentStrings(buf, cm_CachePath, sizeof(cm_CachePath));
788             if (dummyLen > sizeof(cm_CachePath)) {
789                 afsi_log("Cache path [%s] longer than %d after expanding env strings", buf, sizeof(cm_CachePath));
790                 osi_panic("CachePath too long", __FILE__, __LINE__);
791             }
792         } else {
793             StringCbCopyA(cm_CachePath, sizeof(cm_CachePath), buf);
794         }
795         afsi_log("Cache path %s", cm_CachePath);
796     } else {
797         dummyLen = ExpandEnvironmentStrings("%TEMP%\\AFSCache", cm_CachePath, sizeof(cm_CachePath));
798         if (dummyLen > sizeof(cm_CachePath)) {
799             afsi_log("Cache path [%%TEMP%%\\AFSCache] longer than %d after expanding env strings", 
800                      sizeof(cm_CachePath));
801             osi_panic("CachePath too long", __FILE__, __LINE__);
802         }
803         afsi_log("Default cache path %s", cm_CachePath);
804     }
805
806     dummyLen = sizeof(virtualCache);
807     code = RegQueryValueEx(parmKey, "NonPersistentCaching", NULL, NULL,
808                             (LPBYTE)&virtualCache, &dummyLen);
809     afsi_log("Cache type is %s", (virtualCache?"VIRTUAL":"FILE"));
810
811     if (!virtualCache) {
812         dummyLen = sizeof(cm_ValidateCache);
813         code = RegQueryValueEx(parmKey, "ValidateCache", NULL, NULL,
814                                (LPBYTE)&cm_ValidateCache, &dummyLen);
815         if ( cm_ValidateCache < 0 || cm_ValidateCache > 2 )
816             cm_ValidateCache = 1;
817         switch (cm_ValidateCache) {
818         case 0:
819             afsi_log("Cache Validation disabled");
820             break;
821         case 1:
822             afsi_log("Cache Validation on Startup");
823             break;
824         case 2:
825             afsi_log("Cache Validation on Startup and Shutdown");
826             break;
827         }
828     }
829
830     dummyLen = sizeof(traceOnPanic);
831     code = RegQueryValueEx(parmKey, "TrapOnPanic", NULL, NULL,
832                             (BYTE *) &traceOnPanic, &dummyLen);
833     if (code != ERROR_SUCCESS)
834         traceOnPanic = 1;              /* log */
835     afsi_log("Set to %s on panic", traceOnPanic ? "trap" : "not trap");
836
837     dummyLen = sizeof(reportSessionStartups);
838     code = RegQueryValueEx(parmKey, "ReportSessionStartups", NULL, NULL,
839                             (BYTE *) &reportSessionStartups, &dummyLen);
840     if (code == ERROR_SUCCESS)
841         afsi_log("Session startups %s be recorded in the Event Log",
842                   reportSessionStartups ? "will" : "will not");
843     else {
844         reportSessionStartups = 0;
845         /* Don't log */
846     }
847
848     for ( i=0; i < MAXNUMSYSNAMES; i++ ) {
849         cm_sysNameList[i] = osi_Alloc(MAXSYSNAME);
850         cm_sysNameList[i][0] = '\0';
851     }
852     cm_sysName = cm_sysNameList[0];
853
854     dummyLen = sizeof(buf);
855     code = RegQueryValueEx(parmKey, "SysName", NULL, NULL, buf, &dummyLen);
856     if (code != ERROR_SUCCESS || !buf[0]) {
857 #if defined(_IA64_)
858         StringCbCopyA(buf, sizeof(buf), "ia64_win64");
859 #elif defined(_AMD64_)
860         StringCbCopyA(buf, sizeof(buf), "amd64_win64 x86_win32 i386_w2k");
861 #else /* assume x86 32-bit */
862         StringCbCopyA(buf, sizeof(buf), "x86_win32 i386_w2k i386_nt40");
863 #endif
864     }
865     afsi_log("Sys name %s", buf); 
866
867     /* breakup buf into individual search string entries */
868     for (p = q = buf; p < buf + dummyLen; p++)
869     {
870         if (*p == '\0' || isspace(*p)) {
871             memcpy(cm_sysNameList[cm_sysNameCount],q,p-q);
872             cm_sysNameList[cm_sysNameCount][p-q] = '\0';
873             cm_sysNameCount++;
874
875             do {
876                 if (*p == '\0')
877                     goto done_sysname;
878                 p++;
879             } while (*p == '\0' || isspace(*p));
880             q = p;
881             p--;
882         }
883     }
884   done_sysname:
885     StringCbCopyA(cm_sysName, MAXSYSNAME, cm_sysNameList[0]);
886
887     dummyLen = sizeof(cryptall);
888     code = RegQueryValueEx(parmKey, "SecurityLevel", NULL, NULL,
889                             (BYTE *) &cryptall, &dummyLen);
890     if (code == ERROR_SUCCESS) {
891         afsi_log("SecurityLevel is %s", cryptall?"crypt":"clear");
892     } else {
893         cryptall = 0;
894         afsi_log("Default SecurityLevel is clear");
895     }
896
897     if (cryptall)
898         LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_ON);
899     else
900         LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_OFF);
901
902 #ifdef AFS_AFSDB_ENV
903     dummyLen = sizeof(cm_dnsEnabled);
904     code = RegQueryValueEx(parmKey, "UseDNS", NULL, NULL,
905                             (BYTE *) &cm_dnsEnabled, &dummyLen);
906     if (code == ERROR_SUCCESS) {
907         afsi_log("DNS %s be used to find AFS cell servers",
908                   cm_dnsEnabled ? "will" : "will not");
909     }       
910     else {
911         cm_dnsEnabled = 1;   /* default on */
912         afsi_log("Default to use DNS to find AFS cell servers");
913     }
914 #else /* AFS_AFSDB_ENV */
915     afsi_log("AFS not built with DNS support to find AFS cell servers");
916 #endif /* AFS_AFSDB_ENV */
917
918 #ifdef AFS_FREELANCE_CLIENT
919     dummyLen = sizeof(cm_freelanceEnabled);
920     code = RegQueryValueEx(parmKey, "FreelanceClient", NULL, NULL,
921                             (BYTE *) &cm_freelanceEnabled, &dummyLen);
922     if (code == ERROR_SUCCESS) {
923         afsi_log("Freelance client feature %s activated",
924                   cm_freelanceEnabled ? "is" : "is not");
925     }       
926     else {
927         cm_freelanceEnabled = 1;  /* default on */
928     }
929 #endif /* AFS_FREELANCE_CLIENT */
930
931     dummyLen = sizeof(smb_hideDotFiles);
932     code = RegQueryValueEx(parmKey, "HideDotFiles", NULL, NULL,
933                            (BYTE *) &smb_hideDotFiles, &dummyLen);
934     if (code != ERROR_SUCCESS) {
935         smb_hideDotFiles = 1; /* default on */
936     }
937     afsi_log("Dot files/dirs will %sbe marked hidden",
938               smb_hideDotFiles ? "" : "not ");
939
940     dummyLen = sizeof(smb_maxMpxRequests);
941     code = RegQueryValueEx(parmKey, "MaxMpxRequests", NULL, NULL,
942                            (BYTE *) &smb_maxMpxRequests, &dummyLen);
943     if (code != ERROR_SUCCESS) {
944         smb_maxMpxRequests = 50;
945     }
946     afsi_log("Maximum number of multiplexed sessions is %d", smb_maxMpxRequests);
947
948     dummyLen = sizeof(smb_maxVCPerServer);
949     code = RegQueryValueEx(parmKey, "MaxVCPerServer", NULL, NULL,
950                            (BYTE *) &smb_maxVCPerServer, &dummyLen);
951     if (code != ERROR_SUCCESS) {
952         smb_maxVCPerServer = 100;
953     }
954     afsi_log("Maximum number of VCs per server is %d", smb_maxVCPerServer);
955
956     dummyLen = sizeof(smb_authType);
957     code = RegQueryValueEx(parmKey, "SMBAuthType", NULL, NULL,
958                             (BYTE *) &smb_authType, &dummyLen);
959
960     if (code != ERROR_SUCCESS || 
961          (smb_authType != SMB_AUTH_EXTENDED && smb_authType != SMB_AUTH_NTLM && smb_authType != SMB_AUTH_NONE)) {
962         smb_authType = SMB_AUTH_EXTENDED; /* default is to use extended authentication */
963     }
964     afsi_log("SMB authentication type is %s", ((smb_authType == SMB_AUTH_NONE)?"NONE":((smb_authType == SMB_AUTH_EXTENDED)?"EXTENDED":"NTLM")));
965
966     dummyLen = sizeof(rx_nojumbo);
967     code = RegQueryValueEx(parmKey, "RxNoJumbo", NULL, NULL,
968                            (BYTE *) &rx_nojumbo, &dummyLen);
969     if (code != ERROR_SUCCESS) {
970         rx_nojumbo = 0;
971     }
972     if (rx_nojumbo)
973         afsi_log("RX Jumbograms are disabled");
974
975     dummyLen = sizeof(rx_mtu);
976     code = RegQueryValueEx(parmKey, "RxMaxMTU", NULL, NULL,
977                            (BYTE *) &rx_mtu, &dummyLen);
978     if (code != ERROR_SUCCESS || !rx_mtu) {
979         rx_mtu = -1;
980     }
981     if (rx_mtu != -1)
982         afsi_log("RX maximum MTU is %d", rx_mtu);
983
984     dummyLen = sizeof(rx_enable_peer_stats);
985     code = RegQueryValueEx(parmKey, "RxEnablePeerStats", NULL, NULL,
986                            (BYTE *) &rx_enable_peer_stats, &dummyLen);
987     if (code != ERROR_SUCCESS) {
988         rx_enable_peer_stats = 0;
989     }
990     if (rx_enable_peer_stats)
991         afsi_log("RX Peer Statistics gathering is enabled");
992
993     dummyLen = sizeof(rx_enable_process_stats);
994     code = RegQueryValueEx(parmKey, "RxEnableProcessStats", NULL, NULL,
995                            (BYTE *) &rx_enable_process_stats, &dummyLen);
996     if (code != ERROR_SUCCESS) {
997         rx_enable_process_stats = 0;
998     }
999     if (rx_enable_process_stats)
1000         afsi_log("RX Process Statistics gathering is enabled");
1001
1002     dummyLen = sizeof(DWORD);
1003     code = RegQueryValueEx(parmKey, "daemonCheckDownInterval", NULL, NULL,
1004                             (BYTE *) &dwValue, &dummyLen);
1005     if (code == ERROR_SUCCESS)
1006         cm_daemonCheckDownInterval = dwValue;
1007     afsi_log("daemonCheckDownInterval is %d", cm_daemonCheckDownInterval);
1008
1009     dummyLen = sizeof(DWORD);
1010     code = RegQueryValueEx(parmKey, "daemonCheckUpInterval", NULL, NULL,
1011                             (BYTE *) &dwValue, &dummyLen);
1012     if (code == ERROR_SUCCESS)
1013         cm_daemonCheckUpInterval = dwValue;
1014     afsi_log("daemonCheckUpInterval is %d", cm_daemonCheckUpInterval);
1015
1016     dummyLen = sizeof(DWORD);
1017     code = RegQueryValueEx(parmKey, "daemonCheckVolInterval", NULL, NULL,
1018                             (BYTE *) &dwValue, &dummyLen);
1019     if (code == ERROR_SUCCESS)
1020         cm_daemonCheckVolInterval = dwValue;
1021     afsi_log("daemonCheckVolInterval is %d", cm_daemonCheckVolInterval);
1022
1023     dummyLen = sizeof(DWORD);
1024     code = RegQueryValueEx(parmKey, "daemonCheckCBInterval", NULL, NULL,
1025                             (BYTE *) &dwValue, &dummyLen);
1026     if (code == ERROR_SUCCESS)
1027         cm_daemonCheckCBInterval = dwValue;
1028     afsi_log("daemonCheckCBInterval is %d", cm_daemonCheckCBInterval);
1029
1030     dummyLen = sizeof(DWORD);
1031     code = RegQueryValueEx(parmKey, "daemonCheckLockInterval", NULL, NULL,
1032                             (BYTE *) &dwValue, &dummyLen);
1033     if (code == ERROR_SUCCESS)
1034         cm_daemonCheckLockInterval = dwValue;
1035     afsi_log("daemonCheckLockInterval is %d", cm_daemonCheckLockInterval);
1036
1037     dummyLen = sizeof(DWORD);
1038     code = RegQueryValueEx(parmKey, "daemonCheckTokenInterval", NULL, NULL,
1039                             (BYTE *) &dwValue, &dummyLen);
1040     if (code == ERROR_SUCCESS)
1041         cm_daemonTokenCheckInterval = dwValue;
1042     afsi_log("daemonCheckTokenInterval is %d", cm_daemonTokenCheckInterval);
1043
1044     dummyLen = sizeof(DWORD);
1045     code = RegQueryValueEx(parmKey, "CallBackPort", NULL, NULL,
1046                            (BYTE *) &dwValue, &dummyLen);
1047     if (code == ERROR_SUCCESS) {
1048         cm_callbackport = (unsigned short) dwValue;
1049     }
1050     afsi_log("CM CallBackPort is %u", cm_callbackport);
1051
1052     dummyLen = sizeof(DWORD);
1053     code = RegQueryValueEx(parmKey, "EnableServerLocks", NULL, NULL,
1054                            (BYTE *) &dwValue, &dummyLen);
1055     if (code == ERROR_SUCCESS) {
1056         cm_enableServerLocks = (unsigned short) dwValue;
1057     } 
1058     switch (cm_enableServerLocks) {
1059     case 0:
1060         afsi_log("EnableServerLocks: never");
1061         break;
1062     case 2:
1063         afsi_log("EnableServerLocks: always");
1064         break;
1065     case 1:
1066     default:
1067         afsi_log("EnableServerLocks: server requested");
1068         break;
1069     }
1070     RegCloseKey (parmKey);
1071
1072     /* Call lanahelper to get Netbios name, lan adapter number and gateway flag */
1073     if (SUCCEEDED(code = lana_GetUncServerNameEx(cm_NetbiosName, &lanaNum, &isGateway, LANA_NETBIOS_NAME_FULL))) {
1074         LANadapter = (lanaNum == LANA_INVALID)? -1: lanaNum;
1075
1076         if (LANadapter != -1)
1077             afsi_log("LAN adapter number %d", LANadapter);
1078         else
1079             afsi_log("LAN adapter number not determined");
1080
1081         if (isGateway)
1082             afsi_log("Set for gateway service");
1083
1084         afsi_log("Using >%s< as SMB server name", cm_NetbiosName);
1085     } else {
1086         /* something went horribly wrong.  We can't proceed without a netbios name */
1087         StringCbPrintfA(buf,sizeof(buf),"Netbios name could not be determined: %li", code);
1088         osi_panic(buf, __FILE__, __LINE__);
1089     }
1090
1091     cacheBlocks = ((afs_uint64)cacheSize * 1024) / CM_CONFIGDEFAULT_BLOCKSIZE;
1092         
1093     /* get network related info */
1094     cm_noIPAddr = CM_MAXINTERFACE_ADDR;
1095     code = syscfg_GetIFInfo(&cm_noIPAddr,
1096                              cm_IPAddr, cm_SubnetMask,
1097                              cm_NetMtu, cm_NetFlags);
1098
1099     if ( (cm_noIPAddr <= 0) || (code <= 0 ) )
1100         afsi_log("syscfg_GetIFInfo error code %d", code);
1101     else
1102         afsi_log("First Network address %x SubnetMask %x",
1103                   cm_IPAddr[0], cm_SubnetMask[0]);
1104
1105     /*
1106      * Save client configuration for GetCacheConfig requests
1107      */
1108     cm_initParams.nChunkFiles = 0;
1109     cm_initParams.nStatCaches = stats;
1110     cm_initParams.nDataCaches = (afs_uint32)(cacheBlocks > 0xFFFFFFFF ? 0xFFFFFFFF : cacheBlocks);
1111     cm_initParams.nVolumeCaches = stats/2;
1112     cm_initParams.firstChunkSize = cm_chunkSize;
1113     cm_initParams.otherChunkSize = cm_chunkSize;
1114     cm_initParams.cacheSize = cacheSize;
1115     cm_initParams.setTime = 0;
1116     cm_initParams.memCache = 1;
1117
1118     /* Ensure the AFS Netbios Name is registered to allow loopback access */
1119     configureBackConnectionHostNames();
1120
1121     /* init user daemon, and other packages */
1122     cm_InitUser();
1123
1124     cm_InitConn();
1125
1126     cm_InitServer();
1127         
1128     cm_InitIoctl();
1129         
1130     smb_InitIoctl();
1131         
1132     cm_InitCallback();
1133         
1134     code = cm_InitMappedMemory(virtualCache, cm_CachePath, stats, cm_chunkSize, cacheBlocks);
1135     afsi_log("cm_InitMappedMemory code %x", code);
1136     if (code != 0) {
1137         *reasonP = "error initializing cache file";
1138         return -1;
1139     }
1140
1141 #ifdef AFS_AFSDB_ENV
1142 #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
1143     if (cm_InitDNS(cm_dnsEnabled) == -1)
1144         cm_dnsEnabled = 0;  /* init failed, so deactivate */
1145     afsi_log("cm_InitDNS %d", cm_dnsEnabled);
1146 #endif
1147 #endif
1148
1149     /* Set RX parameters before initializing RX */
1150     if ( rx_nojumbo ) {
1151         rx_SetNoJumbo();
1152         afsi_log("rx_SetNoJumbo successful");
1153     }
1154
1155     if ( rx_mtu != -1 ) {
1156         rx_SetMaxMTU(rx_mtu);
1157         afsi_log("rx_SetMaxMTU %d successful", rx_mtu);
1158     }
1159
1160     /* initialize RX, and tell it to listen to the callbackport, 
1161      * which is used for callback RPC messages.
1162      */
1163     code = rx_Init(htons(cm_callbackport));
1164     if (code != 0) {
1165         afsi_log("rx_Init code %x - retrying with a random port number", code);
1166         code = rx_Init(0);
1167     }
1168     afsi_log("rx_Init code %x", code);
1169     if (code != 0) {
1170         *reasonP = "afsd: failed to init rx client";
1171         return -1;
1172     }
1173
1174     /* create an unauthenticated service #1 for callbacks */
1175     nullServerSecurityClassp = rxnull_NewServerSecurityObject();
1176     serverp = rx_NewService(0, 1, "AFS", &nullServerSecurityClassp, 1,
1177                              RXAFSCB_ExecuteRequest);
1178     afsi_log("rx_NewService addr %x", PtrToUlong(serverp));
1179     if (serverp == NULL) {
1180         *reasonP = "unknown error";
1181         return -1;
1182     }
1183
1184     nullServerSecurityClassp = rxnull_NewServerSecurityObject();
1185     serverp = rx_NewService(0, RX_STATS_SERVICE_ID, "rpcstats",
1186                              &nullServerSecurityClassp, 1, RXSTATS_ExecuteRequest);
1187     afsi_log("rx_NewService addr %x", PtrToUlong(serverp));
1188     if (serverp == NULL) {
1189         *reasonP = "unknown error";
1190         return -1;
1191     }
1192         
1193     /* start server threads, *not* donating this one to the pool */
1194     rx_StartServer(0);
1195     afsi_log("rx_StartServer");
1196
1197     if (rx_enable_peer_stats)
1198         rx_enablePeerRPCStats();
1199
1200     if (rx_enable_process_stats)
1201         rx_enableProcessRPCStats();
1202
1203     code = cm_GetRootCellName(rootCellName);
1204     afsi_log("cm_GetRootCellName code %d, cm_freelanceEnabled= %d, rcn= %s", 
1205               code, cm_freelanceEnabled, (code ? "<none>" : rootCellName));
1206     if (code != 0 && !cm_freelanceEnabled) 
1207     {
1208         *reasonP = "can't find root cell name in CellServDB";
1209         return -1;
1210     }   
1211     else if (cm_freelanceEnabled)
1212         cm_data.rootCellp = NULL;
1213
1214     if (code == 0 && !cm_freelanceEnabled) 
1215     {
1216         cm_data.rootCellp = cm_GetCell(rootCellName, CM_FLAG_CREATE);
1217         afsi_log("cm_GetCell addr %x", PtrToUlong(cm_data.rootCellp));
1218         if (cm_data.rootCellp == NULL) 
1219         {
1220             *reasonP = "can't find root cell in afsdcell.ini";
1221             return -1;
1222         }
1223     }
1224
1225 #ifdef AFS_FREELANCE_CLIENT
1226     if (cm_freelanceEnabled)
1227         cm_InitFreelance();
1228 #endif
1229
1230     /* Initialize the RPC server for session keys */
1231     RpcInit();
1232
1233     afsd_InitServerPreferences();
1234     return 0;
1235 }
1236
1237 int afsd_ShutdownCM(void)
1238 {
1239     cm_ReleaseSCache(cm_data.rootSCachep);
1240
1241     return 0;
1242 }
1243
1244 int afsd_InitDaemons(char **reasonP)
1245 {
1246     long code;
1247     cm_req_t req;
1248
1249     cm_InitReq(&req);
1250
1251     /* this should really be in an init daemon from here on down */
1252
1253     if (!cm_freelanceEnabled) {
1254         int attempts = 10;
1255
1256         osi_Log0(afsd_logp, "Loading Root Volume from cell");
1257         do {
1258             code = cm_GetVolumeByName(cm_data.rootCellp, cm_rootVolumeName, cm_rootUserp,
1259                                        &req, CM_FLAG_CREATE, &cm_data.rootVolumep);
1260             afsi_log("cm_GetVolumeByName code %x root vol %x", code,
1261                       (code ? (cm_volume_t *)-1 : cm_data.rootVolumep));
1262         } while (code && --attempts);
1263         if (code != 0) {
1264             *reasonP = "can't find root volume in root cell";
1265             return -1;
1266         }
1267     }
1268
1269     /* compute the root fid */
1270     if (!cm_freelanceEnabled) {
1271         cm_data.rootFid.cell = cm_data.rootCellp->cellID;
1272         cm_data.rootFid.volume = cm_GetROVolumeID(cm_data.rootVolumep);
1273         cm_data.rootFid.vnode = 1;
1274         cm_data.rootFid.unique = 1;
1275     }
1276     else
1277         cm_FakeRootFid(&cm_data.rootFid);
1278         
1279     code = cm_GetSCache(&cm_data.rootFid, &cm_data.rootSCachep, cm_rootUserp, &req);
1280     afsi_log("cm_GetSCache code %x scache %x", code,
1281              (code ? (cm_scache_t *)-1 : cm_data.rootSCachep));
1282     if (code != 0) {
1283         *reasonP = "unknown error";
1284         return -1;
1285     }
1286
1287     cm_InitDaemon(numBkgD);
1288     afsi_log("cm_InitDaemon complete");
1289
1290     return 0;
1291 }
1292
1293 int afsd_InitSMB(char **reasonP, void *aMBfunc)
1294 {
1295     HKEY parmKey;
1296     DWORD dummyLen;
1297     DWORD dwValue;
1298     DWORD code;
1299
1300     code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
1301                          0, KEY_QUERY_VALUE, &parmKey);
1302     if (code == ERROR_SUCCESS) {
1303         dummyLen = sizeof(DWORD);
1304         code = RegQueryValueEx(parmKey, "StoreAnsiFilenames", NULL, NULL,
1305                                 (BYTE *) &dwValue, &dummyLen);
1306         if (code == ERROR_SUCCESS)
1307             smb_StoreAnsiFilenames = dwValue ? 1 : 0;
1308         RegCloseKey (parmKey);
1309     }
1310
1311     /* Do this last so that we don't handle requests before init is done.
1312      * Here we initialize the SMB listener.
1313      */
1314     smb_Init(afsd_logp, cm_NetbiosName, smb_UseV3, LANadapter, numSvThreads, aMBfunc);
1315     afsi_log("smb_Init complete");
1316
1317     return 0;
1318 }
1319
1320 #ifdef ReadOnly
1321 #undef ReadOnly
1322 #endif
1323
1324 #ifdef File
1325 #undef File
1326 #endif
1327
1328 #pragma pack( push, before_imagehlp, 8 )
1329 #include <imagehlp.h>
1330 #pragma pack( pop, before_imagehlp )
1331
1332 #define MAXNAMELEN 1024
1333
1334 void afsd_printStack(HANDLE hThread, CONTEXT *c)
1335 {
1336 #if defined(_X86_)
1337     HANDLE hProcess = GetCurrentProcess();
1338     int frameNum;
1339 #if defined(_AMD64_)
1340     DWORD64 offset;
1341 #elif defined(_X86_)
1342     DWORD offset;
1343 #endif
1344     DWORD symOptions;
1345     char functionName[MAXNAMELEN];
1346   
1347     IMAGEHLP_MODULE Module;
1348     IMAGEHLP_LINE Line;
1349   
1350     STACKFRAME s;
1351     IMAGEHLP_SYMBOL *pSym;
1352   
1353     afsi_log_useTimestamp = 0;
1354   
1355     pSym = (IMAGEHLP_SYMBOL *) GlobalAlloc(0, sizeof (IMAGEHLP_SYMBOL) + MAXNAMELEN);
1356   
1357     memset( &s, '\0', sizeof s );
1358     if (!SymInitialize(hProcess, NULL, 1) )
1359     {
1360         afsi_log("SymInitialize(): GetLastError() = %lu\n", GetLastError() );
1361       
1362         SymCleanup( hProcess );
1363         GlobalFree(pSym);
1364       
1365         return;
1366     }
1367   
1368     symOptions = SymGetOptions();
1369     symOptions |= SYMOPT_LOAD_LINES;
1370     symOptions &= ~SYMOPT_UNDNAME;
1371     SymSetOptions( symOptions );
1372   
1373     /*
1374      * init STACKFRAME for first call
1375      * Notes: AddrModeFlat is just an assumption. I hate VDM debugging.
1376      * Notes: will have to be #ifdef-ed for Alphas; MIPSes are dead anyway,
1377      * and good riddance.
1378      */
1379 #if defined (_ALPHA_) || defined (_MIPS_) || defined (_PPC_)
1380 #error The STACKFRAME initialization in afsd_printStack() for this platform
1381 #error must be properly configured
1382 #elif defined(_AMD64_)
1383     s.AddrPC.Offset = 0;
1384     s.AddrPC.Mode = AddrModeFlat;
1385     s.AddrFrame.Offset = 0;
1386     s.AddrFrame.Mode = AddrModeFlat;
1387 #else
1388     s.AddrPC.Offset = c->Eip;
1389     s.AddrPC.Mode = AddrModeFlat;
1390     s.AddrFrame.Offset = c->Ebp;
1391     s.AddrFrame.Mode = AddrModeFlat;
1392 #endif
1393
1394     memset( pSym, '\0', sizeof (IMAGEHLP_SYMBOL) + MAXNAMELEN );
1395     pSym->SizeOfStruct = sizeof (IMAGEHLP_SYMBOL);
1396     pSym->MaxNameLength = MAXNAMELEN;
1397   
1398     memset( &Line, '\0', sizeof Line );
1399     Line.SizeOfStruct = sizeof Line;
1400   
1401     memset( &Module, '\0', sizeof Module );
1402     Module.SizeOfStruct = sizeof Module;
1403   
1404     offset = 0;
1405   
1406     afsi_log("\n--# FV EIP----- RetAddr- FramePtr StackPtr Symbol" );
1407   
1408     for ( frameNum = 0; ; ++ frameNum )
1409     {
1410         /*
1411          * get next stack frame (StackWalk(), SymFunctionTableAccess(), 
1412          * SymGetModuleBase()). if this returns ERROR_INVALID_ADDRESS (487) or
1413          * ERROR_NOACCESS (998), you can assume that either you are done, or
1414          * that the stack is so hosed that the next deeper frame could not be
1415          * found.
1416          */
1417         if ( ! StackWalk( IMAGE_FILE_MACHINE_I386, hProcess, hThread, &s, c, 
1418                           NULL, SymFunctionTableAccess, SymGetModuleBase, 
1419                           NULL ) )
1420             break;
1421       
1422         /* display its contents */
1423         afsi_log("\n%3d %c%c %08lx %08lx %08lx %08lx ",
1424                  frameNum, s.Far? 'F': '.', s.Virtual? 'V': '.',
1425                  s.AddrPC.Offset, s.AddrReturn.Offset,
1426                  s.AddrFrame.Offset, s.AddrStack.Offset );
1427       
1428         if ( s.AddrPC.Offset == 0 )
1429         {
1430             afsi_log("(-nosymbols- PC == 0)" );
1431         }
1432         else
1433         { 
1434             /* show procedure info from a valid PC */
1435             if (!SymGetSymFromAddr(hProcess, s.AddrPC.Offset, &offset, pSym))
1436             {
1437                 if ( GetLastError() != ERROR_INVALID_ADDRESS )
1438                 {
1439                     afsi_log("SymGetSymFromAddr(): errno = %lu", 
1440                              GetLastError());
1441                 }
1442             }
1443             else
1444             {
1445                 UnDecorateSymbolName(pSym->Name, functionName, MAXNAMELEN, 
1446                                      UNDNAME_NAME_ONLY);
1447                 afsi_log("%s", functionName );
1448
1449                 if ( offset != 0 )
1450                 {
1451                     afsi_log(" %+ld bytes", (long) offset);
1452                 }
1453             }
1454
1455             if (!SymGetLineFromAddr(hProcess, s.AddrPC.Offset, &offset, &Line))
1456             {
1457                 if (GetLastError() != ERROR_INVALID_ADDRESS)
1458                 {
1459                     afsi_log("Error: SymGetLineFromAddr(): errno = %lu", 
1460                              GetLastError());
1461                 }
1462             }
1463             else
1464             {
1465                 afsi_log("    Line: %s(%lu) %+ld bytes", Line.FileName, 
1466                          Line.LineNumber, offset);
1467             }
1468         }
1469       
1470         /* no return address means no deeper stackframe */
1471         if (s.AddrReturn.Offset == 0)
1472         {
1473             SetLastError(0);
1474             break;
1475         }
1476     }
1477   
1478     if (GetLastError() != 0)
1479     {
1480         afsi_log("\nStackWalk(): errno = %lu\n", GetLastError());
1481     }
1482   
1483     SymCleanup(hProcess);
1484     GlobalFree(pSym);
1485 #endif /* _X86_ */
1486 }
1487
1488 #ifdef _DEBUG
1489 static DWORD *afsd_crtDbgBreakCurrent = NULL;
1490 static DWORD afsd_crtDbgBreaks[256];
1491 #endif
1492
1493 static EFaultRepRetVal (WINAPI *pReportFault)(LPEXCEPTION_POINTERS pep, DWORD dwMode) = NULL;
1494 static BOOL (WINAPI *pMiniDumpWriteDump)(HANDLE hProcess,DWORD ProcessId,HANDLE hFile,
1495                                   MINIDUMP_TYPE DumpType,
1496                                   PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
1497                                   PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
1498                                   PMINIDUMP_CALLBACK_INFORMATION CallbackParam) = NULL;
1499
1500
1501 static HANDLE
1502 OpenDumpFile(void)
1503 {
1504     char wd[256];
1505     DWORD code;
1506
1507     code = GetEnvironmentVariable("TEMP", wd, sizeof(wd));
1508     if ( code == 0 || code > sizeof(wd) )
1509     {
1510         if (!GetWindowsDirectory(wd, sizeof(wd)))
1511             return NULL;
1512     }
1513     StringCbCatA(wd, sizeof(wd), "\\afsd.dmp");
1514     return CreateFile( wd, GENERIC_WRITE, FILE_SHARE_READ, NULL,
1515                             CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
1516 }
1517
1518 void 
1519 GenerateMiniDump(PEXCEPTION_POINTERS ep)
1520 {
1521         if (IsDebuggerPresent())
1522                 return;
1523
1524     if (ep == NULL) 
1525     {
1526         // Generate exception to get proper context in dump
1527         __try 
1528         {
1529             RaiseException(DBG_CONTINUE, 0, 0, NULL);
1530         } 
1531         __except(GenerateMiniDump(GetExceptionInformation()), EXCEPTION_CONTINUE_EXECUTION) 
1532         {
1533         }
1534     } 
1535     else
1536     {
1537         MINIDUMP_EXCEPTION_INFORMATION eInfo;
1538         HANDLE hFile = NULL;
1539         HMODULE hDbgHelp = NULL;
1540
1541         hDbgHelp = LoadLibrary("Dbghelp.dll");
1542         if ( hDbgHelp == NULL )
1543             return;
1544
1545         (FARPROC) pMiniDumpWriteDump = GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
1546         if ( pMiniDumpWriteDump == NULL ) {
1547             FreeLibrary(hDbgHelp);
1548             return;
1549         }
1550
1551         hFile = OpenDumpFile();
1552
1553         if ( hFile ) {
1554             HKEY parmKey;
1555             DWORD dummyLen;
1556             DWORD dwValue;
1557             DWORD code;
1558             DWORD dwMiniDumpType = MiniDumpWithDataSegs;
1559
1560             code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
1561                                  0, KEY_QUERY_VALUE, &parmKey);
1562             if (code == ERROR_SUCCESS) {
1563                 dummyLen = sizeof(DWORD);
1564                 code = RegQueryValueEx(parmKey, "MiniDumpType", NULL, NULL,
1565                                         (BYTE *) &dwValue, &dummyLen);
1566                 if (code == ERROR_SUCCESS)
1567                     dwMiniDumpType = dwValue;
1568                 RegCloseKey (parmKey);
1569             }
1570
1571             eInfo.ThreadId = GetCurrentThreadId();
1572             eInfo.ExceptionPointers = ep;
1573             eInfo.ClientPointers = FALSE;
1574
1575             pMiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(),
1576                                 hFile, dwMiniDumpType, ep ? &eInfo : NULL,
1577                                 NULL, NULL);
1578
1579             CloseHandle(hFile);
1580         }
1581         FreeLibrary(hDbgHelp);
1582     }
1583 }
1584
1585 LONG __stdcall afsd_ExceptionFilter(EXCEPTION_POINTERS *ep)
1586 {
1587     CONTEXT context;
1588 #ifdef _DEBUG  
1589     BOOL allocRequestBrk = FALSE;
1590 #endif 
1591     HMODULE hLib = NULL;
1592   
1593     afsi_log("UnhandledException : code : 0x%x, address: 0x%x\n", 
1594              ep->ExceptionRecord->ExceptionCode, 
1595              ep->ExceptionRecord->ExceptionAddress);
1596            
1597 #ifdef _DEBUG
1598     if (afsd_crtDbgBreakCurrent && 
1599         *afsd_crtDbgBreakCurrent == _CrtSetBreakAlloc(*afsd_crtDbgBreakCurrent))
1600     { 
1601         allocRequestBrk = TRUE;
1602         afsi_log("Breaking on alloc request # %d\n", *afsd_crtDbgBreakCurrent);
1603     }
1604 #endif
1605            
1606     /* save context if we want to print the stack information */
1607     context = *ep->ContextRecord;
1608            
1609     afsd_printStack(GetCurrentThread(), &context);
1610
1611     GenerateMiniDump(ep);
1612
1613     hLib = LoadLibrary("Faultrep.dll");
1614     if ( hLib ) {
1615         (FARPROC) pReportFault = GetProcAddress(hLib, "ReportFault");
1616         if ( pReportFault )
1617             pReportFault(ep, 0);
1618         FreeLibrary(hLib);
1619     }
1620
1621     if (ep->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
1622     {
1623         afsi_log("\nEXCEPTION_BREAKPOINT - continue execution ...\n");
1624     
1625 #ifdef _DEBUG
1626         if (allocRequestBrk)
1627         {
1628             afsd_crtDbgBreakCurrent++;
1629             _CrtSetBreakAlloc(*afsd_crtDbgBreakCurrent);
1630         }
1631 #endif         
1632 #if defined(_X86)    
1633         ep->ContextRecord->Eip++;
1634 #endif
1635         return EXCEPTION_CONTINUE_EXECUTION;
1636     }
1637     else
1638     {
1639         return EXCEPTION_CONTINUE_SEARCH;
1640     }
1641 }
1642   
1643 void afsd_SetUnhandledExceptionFilter()
1644 {
1645     SetUnhandledExceptionFilter(afsd_ExceptionFilter);
1646 }
1647   
1648 #ifdef _DEBUG
1649 void afsd_DbgBreakAllocInit()
1650 {
1651     memset(afsd_crtDbgBreaks, -1, sizeof(afsd_crtDbgBreaks));
1652     afsd_crtDbgBreakCurrent = afsd_crtDbgBreaks;
1653 }
1654   
1655 void afsd_DbgBreakAdd(DWORD requestNumber)
1656 {
1657     int i;
1658     for (i = 0; i < sizeof(afsd_crtDbgBreaks) - 1; i++)
1659         {
1660         if (afsd_crtDbgBreaks[i] == -1)
1661             {
1662             break;
1663             }
1664         }
1665     afsd_crtDbgBreaks[i] = requestNumber;
1666
1667     _CrtSetBreakAlloc(afsd_crtDbgBreaks[0]);
1668 }
1669 #endif