windows-unix-mode-bit-enforcement-20070105
[openafs.git] / src / WINNT / afsd / afsd_init.c
index 38e5241..629915f 100644 (file)
@@ -19,6 +19,7 @@
 #include <locale.h>
 #include <mbctype.h>
 #include <winsock2.h>
+#include <ErrorRep.h>
 
 #include <osi.h>
 #include "afsd.h"
 #include "cm_rpc.h"
 #include "lanahelper.h"
 #include <strsafe.h>
-#include "afsicf.h"
 #include "cm_memmap.h"
 
 extern int RXAFSCB_ExecuteRequest(struct rx_call *z_call);
 extern int RXSTATS_ExecuteRequest(struct rx_call *z_call);
 
 extern afs_int32 cryptall;
+extern int cm_enableServerLocks;
+extern int cm_deleteReadOnly;
 
 osi_log_t *afsd_logp;
 
@@ -59,13 +61,14 @@ int LANadapter;
 
 int numBkgD;
 int numSvThreads;
-
+long rx_mtu = -1;
 int traceOnPanic = 0;
 
 int logReady = 0;
 
 char cm_HostName[200];
 long cm_HostAddr;
+unsigned short cm_callbackport = CM_DEFAULT_CALLBACKPORT;
 
 char cm_NetbiosName[MAX_NB_NAME_LENGTH] = "";
 
@@ -114,15 +117,15 @@ afsi_log(char *pattern, ...)
     if ( afsi_log_useTimestamp ) {
         GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, t, sizeof(t));
         GetDateFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, d, sizeof(d));
-        StringCbPrintfA(u, sizeof(u), "%s %s: %s\n", d, t, s);
+        StringCbPrintfA(u, sizeof(u), "%s %s: %s\r\n", d, t, s);
         if (afsi_file != INVALID_HANDLE_VALUE)
-            WriteFile(afsi_file, u, strlen(u), &zilch, NULL);
+            WriteFile(afsi_file, u, (DWORD)strlen(u), &zilch, NULL);
 #ifdef NOTSERVICE
         printf("%s", u);
 #endif 
     } else {
         if (afsi_file != INVALID_HANDLE_VALUE)
-            WriteFile(afsi_file, s, strlen(s), &zilch, NULL);
+            WriteFile(afsi_file, s, (DWORD)strlen(s), &zilch, NULL);
     }
 }
 
@@ -135,21 +138,18 @@ void afsd_initUpperCaseTable()
 void
 afsi_start()
 {
-    char wd[100];
+    char wd[256];
     char t[100], u[100], *p, *path;
     int zilch;
-    int code;
+    DWORD code;
     DWORD dwLow, dwHigh;
     HKEY parmKey;
     DWORD dummyLen;
     DWORD maxLogSize = 100 * 1024;
 
     afsi_file = INVALID_HANDLE_VALUE;
-    if (getenv("TEMP"))
-    {
-        StringCbCopyA(wd, sizeof(wd), getenv("TEMP"));
-    }
-    else
+    code = GetEnvironmentVariable("TEMP", wd, sizeof(wd));
+    if ( code == 0 || code > sizeof(wd) )
     {
         code = GetWindowsDirectory(wd, sizeof(wd));
         if (code == 0) 
@@ -182,13 +182,16 @@ afsi_start()
     GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, u, sizeof(u));
     StringCbCatA(t, sizeof(t), ": Create log file\n");
     StringCbCatA(u, sizeof(u), ": Created log file\n");
-    WriteFile(afsi_file, t, strlen(t), &zilch, NULL);
-    WriteFile(afsi_file, u, strlen(u), &zilch, NULL);
+    WriteFile(afsi_file, t, (DWORD)strlen(t), &zilch, NULL);
+    WriteFile(afsi_file, u, (DWORD)strlen(u), &zilch, NULL);
     p = "PATH=";
-    path = getenv("PATH");
-    WriteFile(afsi_file, p, strlen(p), &zilch, NULL);
-    WriteFile(afsi_file, path, strlen(path), &zilch, NULL);
-    WriteFile(afsi_file, "\n", 1, &zilch, NULL);
+    code = GetEnvironmentVariable("PATH", NULL, 0);
+    path = malloc(code);
+    code = GetEnvironmentVariable("PATH", path, code);
+    WriteFile(afsi_file, p, (DWORD)strlen(p), &zilch, NULL);
+    WriteFile(afsi_file, path, (DWORD)strlen(path), &zilch, NULL);
+    WriteFile(afsi_file, "\n", (DWORD)1, &zilch, NULL);
+    free(path);
 
     /* Initialize C RTL Code Page conversion functions */
     /* All of the path info obtained from the SMB client is in the OEM code page */
@@ -268,7 +271,7 @@ configureBackConnectionHostNames(void)
     HKEY hkMSV10;
     HKEY hkClient;
     DWORD dwType;
-    DWORD dwSize;
+    DWORD dwSize, dwAllocSize;
     DWORD dwValue;
     PBYTE pHostNames = NULL, pName = NULL;
     BOOL  bNameFound = FALSE;   
@@ -279,32 +282,38 @@ configureBackConnectionHostNames(void)
                        KEY_READ|KEY_WRITE,
                        &hkMSV10) == ERROR_SUCCESS )
     {
-        if (RegQueryValueEx( hkMSV10, "BackConnectionHostNames", 0, &dwType, NULL, &dwSize) == ERROR_SUCCESS) {
-            pHostNames = malloc(dwSize + strlen(cm_NetbiosName) + 1);
-            RegQueryValueEx( hkMSV10, "BackConnectionHostNames", 0, &dwType, pHostNames, &dwSize);
-
-            for (pName = pHostNames; *pName ; pName += strlen(pName) + 1)
-            {
-                if ( !stricmp(pName, cm_NetbiosName) ) {
-                    bNameFound = TRUE;
-                    break;
-                }   
-            }
+        if (RegQueryValueEx( hkMSV10, "BackConnectionHostNames", 0, 
+                            &dwType, NULL, &dwAllocSize) == ERROR_SUCCESS) {
+           dwAllocSize += 1 /* in case the source string is not nul terminated */
+               + strlen(cm_NetbiosName) + 2;
+           pHostNames = malloc(dwAllocSize);
+           dwSize = dwAllocSize;
+            if (RegQueryValueEx( hkMSV10, "BackConnectionHostNames", 0, &dwType, 
+                                pHostNames, &dwSize) == ERROR_SUCCESS) {
+               for (pName = pHostNames; 
+                    (pName - pHostNames < dwSize) && *pName ; 
+                    pName += strlen(pName) + 1)
+               {
+                   if ( !stricmp(pName, cm_NetbiosName) ) {
+                       bNameFound = TRUE;
+                       break;
+                   }   
+               }
+           }
         }
              
         if ( !bNameFound ) {
-            int size = strlen(cm_NetbiosName) + 2;
+            size_t size = strlen(cm_NetbiosName) + 2;
             if ( !pHostNames ) {
                 pHostNames = malloc(size);
-                dwSize = 1;
+               pName = pHostNames;
             }
-            pName = pHostNames;
             StringCbCopyA(pName, size, cm_NetbiosName);
             pName += size - 1;
             *pName = '\0';  /* add a second nul terminator */
 
             dwType = REG_MULTI_SZ;
-            dwSize += strlen(cm_NetbiosName) + 1;
+           dwSize = pName - pHostNames + 1;
             RegSetValueEx( hkMSV10, "BackConnectionHostNames", 0, dwType, pHostNames, dwSize);
 
             if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
@@ -370,9 +379,12 @@ configureBackConnectionHostNames(void)
         }
         RegCloseKey(hkMSV10);
     }
+
+    if (pHostNames)
+       free(pHostNames);
 }
 
-#if !defined(DJGPP)
+
 static void afsd_InitServerPreferences(void)
 {
     HKEY hkPrefs = 0;
@@ -522,7 +534,6 @@ static void afsd_InitServerPreferences(void)
         RegCloseKey(hkPrefs);
     }
 }
-#endif /* DJGPP */
 
 /*
  * AFSD Initialization
@@ -531,14 +542,17 @@ static void afsd_InitServerPreferences(void)
 int afsd_InitCM(char **reasonP)
 {
     osi_uid_t debugID;
-    DWORD cacheBlocks;
+    afs_uint64 cacheBlocks;
     DWORD cacheSize;
     long logChunkSize;
     DWORD stats;
+    DWORD dwValue;
+    DWORD rx_enable_peer_stats = 0;
+    DWORD rx_enable_process_stats = 0;
     long traceBufSize;
     long maxcpus;
     long ltt, ltto;
-    long rx_mtu, rx_nojumbo;
+    long rx_nojumbo;
     long virtualCache = 0;
     char rootCellName[256];
     struct rx_service *serverp;
@@ -564,15 +578,19 @@ int afsd_InitCM(char **reasonP)
     WSAStartup(0x0101, &WSAjunk);
 
     afsd_initUpperCaseTable();
+    init_et_to_sys_error();
 
     /* setup osidebug server at RPC slot 1000 */
     osi_LongToUID(1000, &debugID);
     code = osi_InitDebug(&debugID);
     afsi_log("osi_InitDebug code %d", code);
 
-    // osi_LockTypeSetDefault("stat"); /* comment this out for speed *
+    // osi_LockTypeSetDefault("stat"); /* comment this out for speed */
     if (code != 0) {
-        *reasonP = "unknown error";
+        if (code == RPC_S_NO_PROTSEQS)
+            *reasonP = "No RPC Protocol Sequences registered.  Check HKLM\\SOFTWARE\\Microsoft\\RPC\\ClientProtocols";
+        else
+            *reasonP = "unknown error";
         return -1;
     }
 
@@ -637,7 +655,7 @@ int afsd_InitCM(char **reasonP)
     dummyLen = sizeof(TraceOption);
     code = RegQueryValueEx(parmKey, "TraceOption", NULL, NULL,
                             (BYTE *) &TraceOption, &dummyLen);
-    afsi_log("Event Log Tracing = %lX", TraceOption);
+    afsi_log("Trace Options = %lX", TraceOption);
 
     dummyLen = sizeof(traceBufSize);
     code = RegQueryValueEx(parmKey, "TraceBufferSize", NULL, NULL,
@@ -651,8 +669,14 @@ int afsd_InitCM(char **reasonP)
 
     /* setup and enable debug log */
     afsd_logp = osi_LogCreate("afsd", traceBufSize);
-    afsi_log("osi_LogCreate log addr %x", (int)afsd_logp);
-    osi_LogEnable(afsd_logp);
+    afsi_log("osi_LogCreate log addr %x", PtrToUlong(afsd_logp));
+    if ((TraceOption & 0x8)
+#ifdef DEBUG
+        || 1
+#endif
+        ) {
+       osi_LogEnable(afsd_logp);
+    }
     logReady = 1;
 
     osi_Log0(afsd_logp, "Log init");
@@ -717,30 +741,22 @@ int afsd_InitCM(char **reasonP)
     dummyLen = sizeof(ltt);
     code = RegQueryValueEx(parmKey, "LogoffTokenTransfer", NULL, NULL,
                             (BYTE *) &ltt, &dummyLen);
-    if (code == ERROR_SUCCESS)
-        afsi_log("Logoff token transfer %s",  (ltt ? "on" : "off"));
-    else {
+    if (code != ERROR_SUCCESS)
         ltt = 1;
-        afsi_log("Logoff token transfer on by default");
-    }
     smb_LogoffTokenTransfer = ltt;
-    afsi_log("Logoff token transfer is currently ignored");
+    afsi_log("Logoff token transfer %s",  (ltt ? "on" : "off"));
 
     if (ltt) {
         dummyLen = sizeof(ltto);
         code = RegQueryValueEx(parmKey, "LogoffTokenTransferTimeout",
                                 NULL, NULL, (BYTE *) &ltto, &dummyLen);
-        if (code == ERROR_SUCCESS)
-            afsi_log("Logoff token tranfer timeout %d seconds", ltto);
-        else {
-            ltto = 10;
-            afsi_log("Default logoff token transfer timeout 10 seconds");
-        }
+        if (code != ERROR_SUCCESS)
+            ltto = 120;
     } else {
         ltto = 0;
     }   
     smb_LogoffTransferTimeout = ltto;
-    afsi_log("Default logoff token is currently ignored");
+    afsi_log("Logoff token transfer timeout %d seconds", ltto);
 
     dummyLen = sizeof(cm_rootVolumeName);
     code = RegQueryValueEx(parmKey, "RootVolume", NULL, NULL,
@@ -757,7 +773,7 @@ int afsd_InitCM(char **reasonP)
                             cm_mountRoot, &cm_mountRootLen);
     if (code == ERROR_SUCCESS) {
         afsi_log("Mount root %s", cm_mountRoot);
-        cm_mountRootLen = strlen(cm_mountRoot);
+        cm_mountRootLen = (DWORD)strlen(cm_mountRoot);
     } else {
         StringCbCopyA(cm_mountRoot, sizeof(cm_mountRoot), "/afs");
         cm_mountRootLen = 4;
@@ -815,13 +831,9 @@ int afsd_InitCM(char **reasonP)
     dummyLen = sizeof(traceOnPanic);
     code = RegQueryValueEx(parmKey, "TrapOnPanic", NULL, NULL,
                             (BYTE *) &traceOnPanic, &dummyLen);
-    if (code == ERROR_SUCCESS)
-        afsi_log("Set to %s on panic",
-                  traceOnPanic ? "trap" : "not trap");
-    else {  
-        traceOnPanic = 0;
-        /* Don't log */
-    }
+    if (code != ERROR_SUCCESS)
+        traceOnPanic = 1;              /* log */
+    afsi_log("Set to %s on panic", traceOnPanic ? "trap" : "not trap");
 
     dummyLen = sizeof(reportSessionStartups);
     code = RegQueryValueEx(parmKey, "ReportSessionStartups", NULL, NULL,
@@ -845,8 +857,8 @@ int afsd_InitCM(char **reasonP)
     if (code != ERROR_SUCCESS || !buf[0]) {
 #if defined(_IA64_)
         StringCbCopyA(buf, sizeof(buf), "ia64_win64");
-#elif defined(_AMD64)
-        StringCbCopyA(buf, sizeof(buf), "amd64_win64");
+#elif defined(_AMD64_)
+        StringCbCopyA(buf, sizeof(buf), "amd64_win64 x86_win32 i386_w2k");
 #else /* assume x86 32-bit */
         StringCbCopyA(buf, sizeof(buf), "x86_win32 i386_w2k i386_nt40");
 #endif
@@ -883,6 +895,11 @@ int afsd_InitCM(char **reasonP)
         afsi_log("Default SecurityLevel is clear");
     }
 
+    if (cryptall)
+       LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_ON);
+    else
+       LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_OFF);
+
 #ifdef AFS_AFSDB_ENV
     dummyLen = sizeof(cm_dnsEnabled);
     code = RegQueryValueEx(parmKey, "UseDNS", NULL, NULL,
@@ -908,29 +925,10 @@ int afsd_InitCM(char **reasonP)
                   cm_freelanceEnabled ? "is" : "is not");
     }       
     else {
-        cm_freelanceEnabled = 0;  /* default off */
+        cm_freelanceEnabled = 1;  /* default on */
     }
 #endif /* AFS_FREELANCE_CLIENT */
 
-#ifdef COMMENT
-    /* The netbios name is looked up in lana_GetUNCServerNameEx */
-    dummyLen = sizeof(buf);
-    code = RegQueryValueEx(parmKey, "NetbiosName", NULL, NULL,
-                           (BYTE *) &buf, &dummyLen);
-    if (code == ERROR_SUCCESS) {
-        DWORD len = ExpandEnvironmentStrings(buf, cm_NetbiosName, MAX_NB_NAME_LENGTH);
-        if ( len > 0 && len <= MAX_NB_NAME_LENGTH ) {
-            afsi_log("Explicit NetBios name is used %s", cm_NetbiosName);
-        } else {
-            afsi_log("Unable to Expand Explicit NetBios name: %s", buf);
-            cm_NetbiosName[0] = 0;  /* turn it off */
-        }
-    }
-    else {
-        cm_NetbiosName[0] = 0;   /* default off */
-    }
-#endif
-
     dummyLen = sizeof(smb_hideDotFiles);
     code = RegQueryValueEx(parmKey, "HideDotFiles", NULL, NULL,
                            (BYTE *) &smb_hideDotFiles, &dummyLen);
@@ -984,16 +982,101 @@ int afsd_InitCM(char **reasonP)
     if (rx_mtu != -1)
         afsi_log("RX maximum MTU is %d", rx_mtu);
 
-    dummyLen = sizeof(ConnDeadtimeout);
-    code = RegQueryValueEx(parmKey, "ConnDeadTimeout", NULL, NULL,
-                           (BYTE *) &ConnDeadtimeout, &dummyLen);
-    afsi_log("ConnDeadTimeout is %d", ConnDeadtimeout);
+    dummyLen = sizeof(rx_enable_peer_stats);
+    code = RegQueryValueEx(parmKey, "RxEnablePeerStats", NULL, NULL,
+                           (BYTE *) &rx_enable_peer_stats, &dummyLen);
+    if (code != ERROR_SUCCESS) {
+        rx_enable_peer_stats = 0;
+    }
+    if (rx_enable_peer_stats)
+        afsi_log("RX Peer Statistics gathering is enabled");
+
+    dummyLen = sizeof(rx_enable_process_stats);
+    code = RegQueryValueEx(parmKey, "RxEnableProcessStats", NULL, NULL,
+                           (BYTE *) &rx_enable_process_stats, &dummyLen);
+    if (code != ERROR_SUCCESS) {
+        rx_enable_process_stats = 0;
+    }
+    if (rx_enable_process_stats)
+        afsi_log("RX Process Statistics gathering is enabled");
+
+    dummyLen = sizeof(DWORD);
+    code = RegQueryValueEx(parmKey, "daemonCheckDownInterval", NULL, NULL,
+                           (BYTE *) &dwValue, &dummyLen);
+    if (code == ERROR_SUCCESS)
+       cm_daemonCheckDownInterval = dwValue;
+    afsi_log("daemonCheckDownInterval is %d", cm_daemonCheckDownInterval);
+
+    dummyLen = sizeof(DWORD);
+    code = RegQueryValueEx(parmKey, "daemonCheckUpInterval", NULL, NULL,
+                           (BYTE *) &dwValue, &dummyLen);
+    if (code == ERROR_SUCCESS)
+       cm_daemonCheckUpInterval = dwValue;
+    afsi_log("daemonCheckUpInterval is %d", cm_daemonCheckUpInterval);
+
+    dummyLen = sizeof(DWORD);
+    code = RegQueryValueEx(parmKey, "daemonCheckVolInterval", NULL, NULL,
+                           (BYTE *) &dwValue, &dummyLen);
+    if (code == ERROR_SUCCESS)
+       cm_daemonCheckVolInterval = dwValue;
+    afsi_log("daemonCheckVolInterval is %d", cm_daemonCheckVolInterval);
+
+    dummyLen = sizeof(DWORD);
+    code = RegQueryValueEx(parmKey, "daemonCheckCBInterval", NULL, NULL,
+                           (BYTE *) &dwValue, &dummyLen);
+    if (code == ERROR_SUCCESS)
+       cm_daemonCheckCBInterval = dwValue;
+    afsi_log("daemonCheckCBInterval is %d", cm_daemonCheckCBInterval);
+
+    dummyLen = sizeof(DWORD);
+    code = RegQueryValueEx(parmKey, "daemonCheckLockInterval", NULL, NULL,
+                           (BYTE *) &dwValue, &dummyLen);
+    if (code == ERROR_SUCCESS)
+       cm_daemonCheckLockInterval = dwValue;
+    afsi_log("daemonCheckLockInterval is %d", cm_daemonCheckLockInterval);
+
+    dummyLen = sizeof(DWORD);
+    code = RegQueryValueEx(parmKey, "daemonCheckTokenInterval", NULL, NULL,
+                           (BYTE *) &dwValue, &dummyLen);
+    if (code == ERROR_SUCCESS)
+       cm_daemonTokenCheckInterval = dwValue;
+    afsi_log("daemonCheckTokenInterval is %d", cm_daemonTokenCheckInterval);
 
-    dummyLen = sizeof(HardDeadtimeout);
-    code = RegQueryValueEx(parmKey, "HardDeadTimeout", NULL, NULL,
-                           (BYTE *) &HardDeadtimeout, &dummyLen);
-    afsi_log("HardDeadTimeout is %d", HardDeadtimeout);
+    dummyLen = sizeof(DWORD);
+    code = RegQueryValueEx(parmKey, "CallBackPort", NULL, NULL,
+                           (BYTE *) &dwValue, &dummyLen);
+    if (code == ERROR_SUCCESS) {
+        cm_callbackport = (unsigned short) dwValue;
+    }
+    afsi_log("CM CallBackPort is %u", cm_callbackport);
 
+    dummyLen = sizeof(DWORD);
+    code = RegQueryValueEx(parmKey, "EnableServerLocks", NULL, NULL,
+                           (BYTE *) &dwValue, &dummyLen);
+    if (code == ERROR_SUCCESS) {
+        cm_enableServerLocks = (unsigned short) dwValue;
+    } 
+    switch (cm_enableServerLocks) {
+    case 0:
+       afsi_log("EnableServerLocks: never");
+       break;
+    case 2:
+       afsi_log("EnableServerLocks: always");
+       break;
+    case 1:
+    default:
+       afsi_log("EnableServerLocks: server requested");
+       break;
+    }
+
+    dummyLen = sizeof(DWORD);
+    code = RegQueryValueEx(parmKey, "DeleteReadOnly", NULL, NULL,
+                           (BYTE *) &dwValue, &dummyLen);
+    if (code == ERROR_SUCCESS) {
+        cm_deleteReadOnly = (unsigned short) dwValue;
+    } 
+    afsi_log("CM DeleteReadOnly is %u", cm_deleteReadOnly);
+    
     RegCloseKey (parmKey);
 
     /* Call lanahelper to get Netbios name, lan adapter number and gateway flag */
@@ -1015,7 +1098,7 @@ int afsd_InitCM(char **reasonP)
         osi_panic(buf, __FILE__, __LINE__);
     }
 
-    cacheBlocks = (cacheSize * 1024) / CM_CONFIGDEFAULT_BLOCKSIZE;
+    cacheBlocks = ((afs_uint64)cacheSize * 1024) / CM_CONFIGDEFAULT_BLOCKSIZE;
         
     /* get network related info */
     cm_noIPAddr = CM_MAXINTERFACE_ADDR;
@@ -1034,7 +1117,7 @@ int afsd_InitCM(char **reasonP)
      */
     cm_initParams.nChunkFiles = 0;
     cm_initParams.nStatCaches = stats;
-    cm_initParams.nDataCaches = cacheBlocks;
+    cm_initParams.nDataCaches = (afs_uint32)(cacheBlocks > 0xFFFFFFFF ? 0xFFFFFFFF : cacheBlocks);
     cm_initParams.nVolumeCaches = stats/2;
     cm_initParams.firstChunkSize = cm_chunkSize;
     cm_initParams.otherChunkSize = cm_chunkSize;
@@ -1042,20 +1125,6 @@ int afsd_InitCM(char **reasonP)
     cm_initParams.setTime = 0;
     cm_initParams.memCache = 1;
 
-    /* Set RX parameters before initializing RX */
-    if ( rx_nojumbo ) {
-        rx_SetNoJumbo();
-        afsi_log("rx_SetNoJumbo successful");
-    }
-
-    if ( rx_mtu != -1 ) {
-        rx_SetMaxMTU(rx_mtu);
-        afsi_log("rx_SetMaxMTU %d successful", rx_mtu);
-    }
-
-    /* Open Microsoft Firewall to allow in port 7001 */
-    icf_CheckAndAddAFSPorts(AFS_PORTSET_CLIENT);
-
     /* Ensure the AFS Netbios Name is registered to allow loopback access */
     configureBackConnectionHostNames();
 
@@ -1087,13 +1156,28 @@ int afsd_InitCM(char **reasonP)
 #endif
 #endif
 
-    /* initialize RX, and tell it to listen to port 7001, which is used for
-     * callback RPC messages.
+    /* Set RX parameters before initializing RX */
+    if ( rx_nojumbo ) {
+        rx_SetNoJumbo();
+        afsi_log("rx_SetNoJumbo successful");
+    }
+
+    if ( rx_mtu != -1 ) {
+        rx_SetMaxMTU(rx_mtu);
+        afsi_log("rx_SetMaxMTU %d successful", rx_mtu);
+    }
+
+    /* initialize RX, and tell it to listen to the callbackport, 
+     * which is used for callback RPC messages.
      */
-    code = rx_Init(htons(7001));
+    code = rx_Init(htons(cm_callbackport));
+    if (code != 0) {
+       afsi_log("rx_Init code %x - retrying with a random port number", code);
+       code = rx_Init(0);
+    }
     afsi_log("rx_Init code %x", code);
     if (code != 0) {
-        *reasonP = "afsd: failed to init rx client on port 7001";
+        *reasonP = "afsd: failed to init rx client";
         return -1;
     }
 
@@ -1101,7 +1185,7 @@ int afsd_InitCM(char **reasonP)
     nullServerSecurityClassp = rxnull_NewServerSecurityObject();
     serverp = rx_NewService(0, 1, "AFS", &nullServerSecurityClassp, 1,
                              RXAFSCB_ExecuteRequest);
-    afsi_log("rx_NewService addr %x", (int)serverp);
+    afsi_log("rx_NewService addr %x", PtrToUlong(serverp));
     if (serverp == NULL) {
         *reasonP = "unknown error";
         return -1;
@@ -1110,7 +1194,7 @@ int afsd_InitCM(char **reasonP)
     nullServerSecurityClassp = rxnull_NewServerSecurityObject();
     serverp = rx_NewService(0, RX_STATS_SERVICE_ID, "rpcstats",
                              &nullServerSecurityClassp, 1, RXSTATS_ExecuteRequest);
-    afsi_log("rx_NewService addr %x", (int)serverp);
+    afsi_log("rx_NewService addr %x", PtrToUlong(serverp));
     if (serverp == NULL) {
         *reasonP = "unknown error";
         return -1;
@@ -1120,12 +1204,18 @@ int afsd_InitCM(char **reasonP)
     rx_StartServer(0);
     afsi_log("rx_StartServer");
 
+    if (rx_enable_peer_stats)
+       rx_enablePeerRPCStats();
+
+    if (rx_enable_process_stats)
+       rx_enableProcessRPCStats();
+
     code = cm_GetRootCellName(rootCellName);
     afsi_log("cm_GetRootCellName code %d, cm_freelanceEnabled= %d, rcn= %s", 
               code, cm_freelanceEnabled, (code ? "<none>" : rootCellName));
     if (code != 0 && !cm_freelanceEnabled) 
     {
-        *reasonP = "can't find root cell name in afsd.ini";
+        *reasonP = "can't find root cell name in CellServDB";
         return -1;
     }   
     else if (cm_freelanceEnabled)
@@ -1134,7 +1224,7 @@ int afsd_InitCM(char **reasonP)
     if (code == 0 && !cm_freelanceEnabled) 
     {
         cm_data.rootCellp = cm_GetCell(rootCellName, CM_FLAG_CREATE);
-        afsi_log("cm_GetCell addr %x", (int)cm_data.rootCellp);
+        afsi_log("cm_GetCell addr %x", PtrToUlong(cm_data.rootCellp));
         if (cm_data.rootCellp == NULL) 
         {
             *reasonP = "can't find root cell in afsdcell.ini";
@@ -1150,9 +1240,14 @@ int afsd_InitCM(char **reasonP)
     /* Initialize the RPC server for session keys */
     RpcInit();
 
-#if !defined(DJGPP)
     afsd_InitServerPreferences();
-#endif
+    return 0;
+}
+
+int afsd_ShutdownCM(void)
+{
+    cm_ReleaseSCache(cm_data.rootSCachep);
+
     return 0;
 }
 
@@ -1166,11 +1261,15 @@ int afsd_InitDaemons(char **reasonP)
     /* this should really be in an init daemon from here on down */
 
     if (!cm_freelanceEnabled) {
+       int attempts = 10;
+
         osi_Log0(afsd_logp, "Loading Root Volume from cell");
-        code = cm_GetVolumeByName(cm_data.rootCellp, cm_rootVolumeName, cm_rootUserp,
-                                  &req, CM_FLAG_CREATE, &cm_data.rootVolumep);
-        afsi_log("cm_GetVolumeByName code %x root vol %x", code,
-                 (code ? (cm_volume_t *)-1 : cm_data.rootVolumep));
+       do {
+           code = cm_GetVolumeByName(cm_data.rootCellp, cm_rootVolumeName, cm_rootUserp,
+                                      &req, CM_FLAG_CREATE, &cm_data.rootVolumep);
+           afsi_log("cm_GetVolumeByName code %x root vol %x", code,
+                     (code ? (cm_volume_t *)-1 : cm_data.rootVolumep));
+       } while (code && --attempts);
         if (code != 0) {
             *reasonP = "can't find root volume in root cell";
             return -1;
@@ -1244,9 +1343,14 @@ int afsd_InitSMB(char **reasonP, void *aMBfunc)
 
 void afsd_printStack(HANDLE hThread, CONTEXT *c)
 {
+#if defined(_X86_)
     HANDLE hProcess = GetCurrentProcess();
     int frameNum;
+#if defined(_AMD64_)
+    DWORD64 offset;
+#elif defined(_X86_)
     DWORD offset;
+#endif
     DWORD symOptions;
     char functionName[MAXNAMELEN];
   
@@ -1285,6 +1389,11 @@ void afsd_printStack(HANDLE hThread, CONTEXT *c)
 #if defined (_ALPHA_) || defined (_MIPS_) || defined (_PPC_)
 #error The STACKFRAME initialization in afsd_printStack() for this platform
 #error must be properly configured
+#elif defined(_AMD64_)
+    s.AddrPC.Offset = 0;
+    s.AddrPC.Mode = AddrModeFlat;
+    s.AddrFrame.Offset = 0;
+    s.AddrFrame.Mode = AddrModeFlat;
 #else
     s.AddrPC.Offset = c->Eip;
     s.AddrPC.Mode = AddrModeFlat;
@@ -1383,6 +1492,7 @@ void afsd_printStack(HANDLE hThread, CONTEXT *c)
   
     SymCleanup(hProcess);
     GlobalFree(pSym);
+#endif /* _X86_ */
 }
 
 #ifdef _DEBUG
@@ -1390,12 +1500,105 @@ static DWORD *afsd_crtDbgBreakCurrent = NULL;
 static DWORD afsd_crtDbgBreaks[256];
 #endif
 
+static EFaultRepRetVal (WINAPI *pReportFault)(LPEXCEPTION_POINTERS pep, DWORD dwMode) = NULL;
+static BOOL (WINAPI *pMiniDumpWriteDump)(HANDLE hProcess,DWORD ProcessId,HANDLE hFile,
+                                  MINIDUMP_TYPE DumpType,
+                                  PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
+                                  PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
+                                  PMINIDUMP_CALLBACK_INFORMATION CallbackParam) = NULL;
+
+
+static HANDLE
+OpenDumpFile(void)
+{
+    char wd[256];
+    DWORD code;
+
+    code = GetEnvironmentVariable("TEMP", wd, sizeof(wd));
+    if ( code == 0 || code > sizeof(wd) )
+    {
+        if (!GetWindowsDirectory(wd, sizeof(wd)))
+            return NULL;
+    }
+    StringCbCatA(wd, sizeof(wd), "\\afsd.dmp");
+    return CreateFile( wd, GENERIC_WRITE, FILE_SHARE_READ, NULL,
+                            CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
+}
+
+void 
+GenerateMiniDump(PEXCEPTION_POINTERS ep)
+{
+       if (IsDebuggerPresent())
+               return;
+
+    if (ep == NULL) 
+    {
+        // Generate exception to get proper context in dump
+        __try 
+        {
+            RaiseException(DBG_CONTINUE, 0, 0, NULL);
+        } 
+        __except(GenerateMiniDump(GetExceptionInformation()), EXCEPTION_CONTINUE_EXECUTION) 
+        {
+        }
+    } 
+    else
+    {
+        MINIDUMP_EXCEPTION_INFORMATION eInfo;
+        HANDLE hFile = NULL;
+        HMODULE hDbgHelp = NULL;
+
+        hDbgHelp = LoadLibrary("Dbghelp.dll");
+        if ( hDbgHelp == NULL )
+            return;
+
+        (FARPROC) pMiniDumpWriteDump = GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
+        if ( pMiniDumpWriteDump == NULL ) {
+            FreeLibrary(hDbgHelp);
+            return;
+        }
+
+        hFile = OpenDumpFile();
+
+        if ( hFile ) {
+            HKEY parmKey;
+            DWORD dummyLen;
+            DWORD dwValue;
+            DWORD code;
+            DWORD dwMiniDumpType = MiniDumpWithDataSegs;
+
+            code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
+                                 0, KEY_QUERY_VALUE, &parmKey);
+            if (code == ERROR_SUCCESS) {
+                dummyLen = sizeof(DWORD);
+                code = RegQueryValueEx(parmKey, "MiniDumpType", NULL, NULL,
+                                        (BYTE *) &dwValue, &dummyLen);
+                if (code == ERROR_SUCCESS)
+                    dwMiniDumpType = dwValue;
+                RegCloseKey (parmKey);
+            }
+
+            eInfo.ThreadId = GetCurrentThreadId();
+            eInfo.ExceptionPointers = ep;
+            eInfo.ClientPointers = FALSE;
+
+            pMiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(),
+                                hFile, dwMiniDumpType, ep ? &eInfo : NULL,
+                                NULL, NULL);
+
+            CloseHandle(hFile);
+        }
+        FreeLibrary(hDbgHelp);
+    }
+}
+
 LONG __stdcall afsd_ExceptionFilter(EXCEPTION_POINTERS *ep)
 {
     CONTEXT context;
 #ifdef _DEBUG  
     BOOL allocRequestBrk = FALSE;
 #endif 
+    HMODULE hLib = NULL;
   
     afsi_log("UnhandledException : code : 0x%x, address: 0x%x\n", 
              ep->ExceptionRecord->ExceptionCode, 
@@ -1414,7 +1617,17 @@ LONG __stdcall afsd_ExceptionFilter(EXCEPTION_POINTERS *ep)
     context = *ep->ContextRecord;
           
     afsd_printStack(GetCurrentThread(), &context);
-          
+
+    GenerateMiniDump(ep);
+
+    hLib = LoadLibrary("Faultrep.dll");
+    if ( hLib ) {
+        (FARPROC) pReportFault = GetProcAddress(hLib, "ReportFault");
+        if ( pReportFault )
+            pReportFault(ep, 0);
+        FreeLibrary(hLib);
+    }
+
     if (ep->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
     {
         afsi_log("\nEXCEPTION_BREAKPOINT - continue execution ...\n");
@@ -1426,8 +1639,9 @@ LONG __stdcall afsd_ExceptionFilter(EXCEPTION_POINTERS *ep)
             _CrtSetBreakAlloc(*afsd_crtDbgBreakCurrent);
         }
 #endif         
-    
+#if defined(_X86)    
         ep->ContextRecord->Eip++;
+#endif
         return EXCEPTION_CONTINUE_EXECUTION;
     }
     else