Windows: update GetFileVersionInformation fail msg
[openafs.git] / src / WINNT / afsd / afsd_service.c
index e0d3576..ea47deb 100644 (file)
@@ -1,3 +1,15 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+#include <afsconfig.h>
+#include <afs/param.h>
+#include <roken.h>
 
 #include <afs/stds.h>
 
@@ -14,6 +26,9 @@
 #include <stdlib.h>
 #include <winsock2.h>
 #include <WINNT\afsreg.h>
+#include "cm_btree.h"
+#include "cm_rpc.h"
+#include "smb.h"
 
 #include <osi.h>
 
@@ -23,7 +38,6 @@
 #ifdef _DEBUG
 #include <crtdbg.h>
 #endif
-#include "afsdifs.h"
 
 //#define REGISTER_POWER_NOTIFICATIONS 1
 #include "afsd_flushvol.h"
@@ -32,11 +46,9 @@ extern void afsi_log(char *pattern, ...);
 
 static SERVICE_STATUS          ServiceStatus;
 static SERVICE_STATUS_HANDLE   StatusHandle;
+static BOOL bRunningAsService = TRUE;
 
 HANDLE hAFSDMainThread = NULL;
-#ifdef AFSIFS
-HANDLE hAFSDWorkerThread[WORKER_THREADS];
-#endif
 
 HANDLE WaitToTerminate;
 
@@ -52,20 +64,22 @@ extern HANDLE afsi_file;
 
 static int powerEventsRegistered = 0;
 extern int powerStateSuspended = 0;
+extern int RDR_Initialized = 0;
+
+static VOID (WINAPI* pRtlCaptureContext)(PCONTEXT ContextRecord) = NULL;
 
 /*
  * Notifier function for use by osi_panic
  */
 static void afsd_notifier(char *msgp, char *filep, long line)
 {
-#ifdef AFSIFS
-    int i;
-#endif
+    CONTEXT context;
+
     if (!msgp)
         msgp = "unspecified assert";
 
     if (filep)
-       LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP_WITH_MSG_AND_LOCATION, 
+       LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP_WITH_MSG_AND_LOCATION,
                  filep, line, msgp);
     else
        LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_ERROR_STOP_WITH_MSG, msgp);
@@ -77,43 +91,46 @@ static void afsd_notifier(char *msgp, char *filep, long line)
     afsd_ForceTrace(TRUE);
     buf_ForceTrace(TRUE);
 
+    if (pRtlCaptureContext) {
+        pRtlCaptureContext(&context);
+        afsd_printStack(GetCurrentThread(), &context);
+    }
+
+#ifdef DEBUG
+    if (IsDebuggerPresent())
+        DebugBreak();
+#endif
+
     afsi_log("--- begin dump ---");
     cm_MemDumpDirStats(afsi_file, "a", 0);
     cm_MemDumpBPlusStats(afsi_file, "a", 0);
     cm_DumpCells(afsi_file, "a", 0);
     cm_DumpVolumes(afsi_file, "a", 0);
     cm_DumpSCache(afsi_file, "a", 0);
-#ifdef keisa
-    cm_dnlcDump(afsi_file, "a");
-#endif
     cm_DumpBufHashTable(afsi_file, "a", 0);
-    smb_DumpVCP(afsi_file, "a", 0);                    
+    cm_DumpServers(afsi_file, "a", 0);
+    smb_DumpVCP(afsi_file, "a", 0);
+    rx_DumpPackets(afsi_file, "a");
+    rx_DumpCalls(afsi_file, "a");
     afsi_log("--- end   dump ---");
-    
-#ifdef DEBUG
-    if (IsDebuggerPresent())
-        DebugBreak();  
-#endif
+
+    GenerateMiniDump(NULL);
 
     SetEvent(WaitToTerminate);
-#ifdef AFSIFS
-    WaitForMultipleObjects(WORKER_THREADS, hAFSDWorkerThread, TRUE, INFINITE);
-    for (i = 0; i < WORKER_THREADS; i++)
-        CloseHandle(hAFSDWorkerThread[i]);
-#endif
 
 #ifdef JUMP
     if (GetCurrentThreadId() == MainThreadId)
         longjmp(notifier_jmp, 1);
 #endif /* JUMP */
 
-    ServiceStatus.dwCurrentState = SERVICE_STOPPED;
-    ServiceStatus.dwWin32ExitCode = NO_ERROR;
-    ServiceStatus.dwCheckPoint = 0;
-    ServiceStatus.dwWaitHint = 0;
-    ServiceStatus.dwControlsAccepted = 0;
-    SetServiceStatus(StatusHandle, &ServiceStatus);
-
+    if (bRunningAsService) {
+        ServiceStatus.dwCurrentState = SERVICE_STOPPED;
+        ServiceStatus.dwWin32ExitCode = ERROR_EXCEPTION_IN_SERVICE;
+        ServiceStatus.dwCheckPoint = 0;
+        ServiceStatus.dwWaitHint = 0;
+        ServiceStatus.dwControlsAccepted = 0;
+        SetServiceStatus(StatusHandle, &ServiceStatus);
+    }
     exit(1);
 }
 
@@ -160,7 +177,7 @@ afsd_ServiceFlushVolume(DWORD dwlpEventData)
 
 
 /* service control handler used in nt4 only for backward compat. */
-VOID WINAPI 
+VOID WINAPI
 afsd_ServiceControlHandler(DWORD ctrlCode)
 {
     HKEY parmKey;
@@ -220,7 +237,7 @@ afsd_ServiceControlHandler(DWORD ctrlCode)
         /* XXX handle system shutdown */
         /* XXX handle pause & continue */
     }
-}       
+}
 
 
 /*
@@ -240,13 +257,14 @@ afsd_ServiceControlHandlerEx(
     long code;
     DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
     OSVERSIONINFO osVersion;
+    DWORD dwCurrentState = ServiceStatus.dwCurrentState;
 
     /* Get the version of Windows */
     memset(&osVersion, 0x00, sizeof(osVersion));
     osVersion.dwOSVersionInfoSize = sizeof(osVersion);
     GetVersionEx(&osVersion);
 
-    switch (ctrlCode) 
+    switch (ctrlCode)
     {
     case SERVICE_CONTROL_SHUTDOWN:
     case SERVICE_CONTROL_STOP:
@@ -263,7 +281,8 @@ afsd_ServiceControlHandlerEx(
         SetServiceStatus(StatusHandle, &ServiceStatus);
 
         /* Write all dirty buffers back to server */
-       if ( !lana_OnlyLoopback() )
+       if (dwCurrentState == SERVICE_RUNNING &&
+            !lana_OnlyLoopback() )
            buf_CleanAndReset();
 
         /* Force trace if requested */
@@ -298,126 +317,175 @@ afsd_ServiceControlHandlerEx(
         ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
         SetServiceStatus(StatusHandle, &ServiceStatus);
         afsi_log("SERVICE_CONTROL_INTERROGATE");
+        osi_Log0(afsd_logp, "SERVICE_CONTROL_INTERROGATE");
         dwRet = NO_ERROR;
         break;
 
         /* XXX handle system shutdown */
         /* XXX handle pause & continue */
-    case SERVICE_CONTROL_POWEREVENT:                                              
-        { 
+    case SERVICE_CONTROL_POWEREVENT:
+        {
 #ifdef DEBUG
            afsi_log("SERVICE_CONTROL_POWEREVENT");
 #endif
-            /*                                                                                
-            ** dwEventType of this notification == WPARAM of WM_POWERBROADCAST               
-            ** Return NO_ERROR == return TRUE for that message, i.e. accept request          
-            ** Return any error code to deny request,                                        
-            ** i.e. as if returning BROADCAST_QUERY_DENY                                     
-            */                                                                                
+           osi_Log0(afsd_logp, "SERVICE_CONTROL_POWEREVENT");
+            /*
+            ** dwEventType of this notification == WPARAM of WM_POWERBROADCAST
+            ** Return NO_ERROR == return TRUE for that message, i.e. accept request
+            ** Return any error code to deny request,
+            ** i.e. as if returning BROADCAST_QUERY_DENY
+            */
             if (powerEventsRegistered) {
-                switch((int) dwEventType)                                                         
-                {                                                                               
-                case PBT_APMQUERYSUSPEND:       
-                    afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND"); 
+                switch((int) dwEventType)
+                {
+                case PBT_APMQUERYSUSPEND:
+                    afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND");
+                    osi_Log0(afsd_logp,"SERVICE_CONTROL_APMQUERYSUSPEND");
                     /* Write all dirty buffers back to server */
-                   if ( !lana_OnlyLoopback() ) {
+                   if ( !lana_OnlyLoopback() )
                        buf_CleanAndReset();
-                        cm_SuspendSCache();
-                    }
-                    afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND buf_CleanAndReset complete"); 
-                    dwRet = NO_ERROR;                       
-                    break;                                  
-                case PBT_APMQUERYSTANDBY:                                                         
-                    afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY"); 
+                    afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND buf_CleanAndReset complete");
+                    osi_Log0(afsd_logp,"SERVICE_CONTROL_APMQUERYSUSPEND buf_CleanAndReset complete");
+                    dwRet = NO_ERROR;
+                    break;
+                case PBT_APMQUERYSTANDBY:
+                    afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY");
+                    osi_Log0(afsd_logp,"SERVICE_CONTROL_APMQUERYSTANDBY");
                     /* Write all dirty buffers back to server */
-                   if ( !lana_OnlyLoopback() ) {
+                   if ( !lana_OnlyLoopback() )
                        buf_CleanAndReset();
-                        cm_SuspendSCache();
-                    }
-                    afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY buf_CleanAndReset complete"); 
-                    dwRet = NO_ERROR;                                                             
-                    break;                                                                        
-                                                                                                                         
-                    /* allow remaining case PBT_WhatEver */                                           
-                case PBT_APMSUSPEND:                         
+                    afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY buf_CleanAndReset complete");
+                    osi_Log0(afsd_logp,"SERVICE_CONTROL_APMQUERYSTANDBY buf_CleanAndReset complete");
+                    dwRet = NO_ERROR;
+                    break;
+
+                    /* allow remaining case PBT_WhatEver */
+                case PBT_APMSUSPEND:
                     afsi_log("SERVICE_CONTROL_APMSUSPEND");
+                    osi_Log0(afsd_logp,"SERVICE_CONTROL_APMSUSPEND");
                    powerStateSuspended = 1;
-                   if (osVersion.dwMajorVersion >= 6) {
-                        cm_SuspendSCache();
+                   if (osVersion.dwMajorVersion >= 6)
                        smb_StopListeners(0);
-                    }
-                    dwRet = NO_ERROR;                       
-                    break;                                  
-                case PBT_APMSTANDBY:                  
-                    afsi_log("SERVICE_CONTROL_APMSTANDBY"); 
+
+                    if (RDR_Initialized)
+                        RDR_Suspend();
+                    cm_SuspendSCache();
+
+                    dwRet = NO_ERROR;
+                    afsi_log("SERVICE_CONTROL_APMSUSPEND complete");
+                    osi_Log0(afsd_logp,"SERVICE_CONTROL_APMSUSPEND complete");
+                    break;
+                case PBT_APMSTANDBY:
+                    afsi_log("SERVICE_CONTROL_APMSTANDBY");
+                    osi_Log0(afsd_logp,"SERVICE_CONTROL_APMSTANDBY");
                    powerStateSuspended = 1;
-                   if (osVersion.dwMajorVersion >= 6) {
-                        cm_SuspendSCache();
+                   if (osVersion.dwMajorVersion >= 6)
                        smb_StopListeners(0);
-                    }
-                    dwRet = NO_ERROR;                       
-                    break;                                  
-                case PBT_APMRESUMECRITICAL:             
-                    afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL"); 
+                    if (RDR_Initialized)
+                        RDR_Suspend();
+                    cm_SuspendSCache();
+                    dwRet = NO_ERROR;
+                    afsi_log("SERVICE_CONTROL_APMSTANDBY complete");
+                    osi_Log0(afsd_logp,"SERVICE_CONTROL_APMSTANDBY complete");
+                    break;
+                case PBT_APMRESUMECRITICAL:
+                    afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL");
+                    osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMECRITICAL");
                    if (osVersion.dwMajorVersion >= 6)
                        smb_RestartListeners(0);
-                    dwRet = NO_ERROR;                       
-                    break;                                  
-                case PBT_APMRESUMESUSPEND:                                                        
+                    cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL);
+                    if (RDR_Initialized)
+                        RDR_Resume();
+                    dwRet = NO_ERROR;
+                    afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL complete");
+                    osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMECRITICAL complete");
+                    break;
+                case PBT_APMRESUMESUSPEND:
                    /* User logged in after suspend */
-                    afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND"); 
-                    dwRet = NO_ERROR;                       
-                    break;                                  
-                case PBT_APMRESUMESTANDBY:            
+                    afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND");
+                    osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMESUSPEND");
+                   powerStateSuspended = 0;
+                    cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL);
+                   if (osVersion.dwMajorVersion >= 6)
+                       smb_RestartListeners(0);
+                   if (smb_Enabled && osVersion.dwMajorVersion >= 6) {
+                       smb_SetLanAdapterChangeDetected();
+                    }
+                    if (RDR_Initialized)
+                        RDR_Resume();
+                    dwRet = NO_ERROR;
+                    afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND complete");
+                    osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMESUSPEND complete");
+                    break;
+                case PBT_APMRESUMESTANDBY:
                    /* User logged in after standby */
-                    afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY"); 
-                    dwRet = NO_ERROR;                       
-                    break;                                  
-                case PBT_APMBATTERYLOW:                                                           
-                    afsi_log("SERVICE_CONTROL_APMBATTERYLOW"); 
-                    dwRet = NO_ERROR;                       
-                    break;                                  
-                case PBT_APMPOWERSTATUSCHANGE:                                                    
+                    afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY");
+                    osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMESTANDBY");
+                   powerStateSuspended = 0;
+                    cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL);
+                   if (osVersion.dwMajorVersion >= 6)
+                       smb_RestartListeners(0);
+                   if (smb_Enabled && osVersion.dwMajorVersion >= 6) {
+                       smb_SetLanAdapterChangeDetected();
+                    }
+                    if (RDR_Initialized)
+                        RDR_Resume();
+                    dwRet = NO_ERROR;
+                    afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY complete");
+                    osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMESTANDBY complete");
+                    break;
+                case PBT_APMBATTERYLOW:
+                    afsi_log("SERVICE_CONTROL_APMBATTERYLOW");
+                    osi_Log0(afsd_logp,"SERVICE_CONTROL_APMBATTERYLOW");
+                    dwRet = NO_ERROR;
+                    break;
+                case PBT_APMPOWERSTATUSCHANGE:
 #ifdef DEBUG
                    afsi_log("SERVICE_CONTROL_APMPOWERSTATUSCHANGE");
 #endif
-                    dwRet = NO_ERROR;                       
-                    break;                                  
-                case PBT_APMOEMEVENT:                                                             
+                   osi_Log0(afsd_logp,"SERVICE_CONTROL_APMPOWERSTATUSCHANGE");
+                    dwRet = NO_ERROR;
+                    break;
+                case PBT_APMOEMEVENT:
 #ifdef DEBUG
-                    afsi_log("SERVICE_CONTROL_APMOEMEVENT"); 
+                    afsi_log("SERVICE_CONTROL_APMOEMEVENT");
 #endif
-                    dwRet = NO_ERROR;                       
-                    break;                                  
-                case PBT_APMRESUMEAUTOMATIC:          
+                    osi_Log0(afsd_logp,"SERVICE_CONTROL_APMOEMEVENT");
+                    dwRet = NO_ERROR;
+                    break;
+                case PBT_APMRESUMEAUTOMATIC:
                    /* This is the message delivered once all devices are up */
-                    afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC"); 
-                   powerStateSuspended = 0;
-                   if (osVersion.dwMajorVersion >= 6) {
+                    afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC");
+                    osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMEAUTOMATIC");
+                   if (smb_Enabled && osVersion.dwMajorVersion >= 6) {
                        smb_SetLanAdapterChangeDetected();
                     }
-                    dwRet = NO_ERROR;                       
-                    break;                                  
-                default:                                                                          
-                    afsi_log("SERVICE_CONTROL_unknown"); 
-                    dwRet = NO_ERROR;                       
-                }   
+                    cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL);
+                    dwRet = NO_ERROR;
+                    afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC complete");
+                    osi_Log0(afsd_logp,"SERVICE_CONTROL_APMRESUMEAUTOMATIC complete");
+                    break;
+                default:
+                    afsi_log("SERVICE_CONTROL_unknown");
+                    osi_Log1(afsd_logp, "SERVICE_CONTROL_unknown: 0x%x", dwEventType);
+                    dwRet = NO_ERROR;
+                }
             }
         }
         break;
-    case SERVICE_CONTROL_CUSTOM_DUMP: 
+    case SERVICE_CONTROL_CUSTOM_DUMP:
         {
-            afsi_log("SERVICE_CONTROL_CUSTOM_DUMP"); 
+            afsi_log("SERVICE_CONTROL_CUSTOM_DUMP");
             GenerateMiniDump(NULL);
            dwRet = NO_ERROR;
         }
         break;
-    }          /* end switch(ctrlCode) */                                                        
-    return dwRet;   
+    }          /* end switch(ctrlCode) */
+    return dwRet;
 }
 
 /* There is similar code in client_config\drivemap.cpp GlobalMountDrive()
- * 
+ *
  * Mount a drive into AFS if there global mapping
  */
 /* DEE Could check first if we are run as SYSTEM */
@@ -425,9 +493,7 @@ afsd_ServiceControlHandlerEx(
 #define MAX_DRIVES  23
 static DWORD __stdcall MountGlobalDrivesThread(void * notUsed)
 {
-#ifndef AFSIFS
     char szAfsPath[_MAX_PATH];
-#endif
     char szDriveToMapTo[5];
     DWORD dwResult;
     char szKeyName[256];
@@ -456,7 +522,6 @@ static DWORD __stdcall MountGlobalDrivesThread(void * notUsed)
             }
         }
 
-#ifndef AFSIFS
         for (dwRetry = 0 ; dwRetry < MAX_RETRIES; dwRetry++)
         {
             NETRESOURCE nr;
@@ -466,28 +531,24 @@ static DWORD __stdcall MountGlobalDrivesThread(void * notUsed)
 
             nr.dwScope = RESOURCE_GLOBALNET;              /* ignored parameter */
             nr.dwType=RESOURCETYPE_DISK;
-            nr.lpLocalName=szDriveToMapTo;
+            nr.lpLocalName=strlen(szDriveToMapTo) > 0 ? szDriveToMapTo : NULL;
             nr.lpRemoteName=szAfsPath;
             nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
             nr.dwUsage = RESOURCEUSAGE_CONNECTABLE;       /* ignored parameter */
 
             dwResult = WNetAddConnection2(&nr,NULL,NULL,0);
-            afsi_log("GlobalAutoMap of %s to %s %s (%d)", szDriveToMapTo, szSubMount, 
+            afsi_log("GlobalAutoMap of %s to %s %s (%d)", szDriveToMapTo, szSubMount,
                      (dwResult == NO_ERROR) ? "succeeded" : "failed", dwResult);
             if (dwResult == NO_ERROR) {
                 break;
             }
             /* wait for smb server to come up */
-            Sleep((DWORD)1000 /* miliseconds */);              
+            Sleep((DWORD)1000 /* miliseconds */);
 
             /* Disconnect any previous mappings */
             dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
         }
-#else
-       /* FIXFIX: implement */
-       afsi_log("GlobalAutoMap of %s to %s not implemented", szDriveToMapTo, szSubMount);
-#endif
-    }        
+    }
 
     RegCloseKey(hKey);
     return 0;
@@ -515,14 +576,12 @@ static void MountGlobalDrives()
 
 static void DismountGlobalDrives()
 {
-#ifndef AFSIFS
     char szAfsPath[_MAX_PATH];
     char szDriveToMapTo[5];
     DWORD dwDriveSize;
     DWORD dwSubMountSize;
     char szSubMount[256];
     DWORD dwType;
-#endif
     DWORD dwResult;
     char szKeyName[256];
     HKEY hKey;
@@ -547,9 +606,6 @@ static void DismountGlobalDrives()
     if (dwResult != ERROR_SUCCESS)
         return;
 
-#ifdef AFSIFS    
-    /* FIXFIX: implement */
-#else
     while (dwIndex < MAX_DRIVES) {
         dwDriveSize = sizeof(szDriveToMapTo);
         dwSubMountSize = sizeof(szSubMount);
@@ -563,13 +619,12 @@ static void DismountGlobalDrives()
         }
 
         sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
-                   
+
         dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
         dwResult = WNetCancelConnection(szAfsPath, TRUE);
-        
+
         afsi_log("Disconnect from GlobalAutoMap of %s to %s %s", szDriveToMapTo, szSubMount, dwResult ? "succeeded" : "failed");
-    }        
-#endif
+    }
 
     RegCloseKey(hKey);
 }
@@ -587,7 +642,7 @@ GetVersionInfo( CHAR * filename, CHAR * szOutput, DWORD dwOutput )
     DWORD size = GetFileVersionInfoSize(filename, &dwVersionHandle);
 
     if (!size) {
-        afsi_log("GetFileVersionInfoSize failed");
+       afsi_log("GetFileVersionInfoSize(%s) failed", filename);
         return GetLastError();
     }
 
@@ -674,7 +729,7 @@ void LoadCrypt32(void)
     (FARPROC) pCryptMsgClose = GetProcAddress( hCrypt32, "CryptMsgClose" );
     (FARPROC) pCertCompareCertificate = GetProcAddress( hCrypt32, "CertCompareCertificate" );
     (FARPROC) pCertFreeCertificateContext = GetProcAddress( hCrypt32, "CertFreeCertificateContext" );
-    
+
     if ( !pCertGetNameString ||
          !pCryptQueryObject ||
          !pCryptMsgGetParam ||
@@ -755,7 +810,7 @@ PCCERT_CONTEXT GetCertCtx(CHAR * filename)
                                0,
                                (PVOID)pSignerInfo,
                                &dwSignerInfo);
-    
+
     if (!fResult) {
         afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
                 filename,
@@ -809,7 +864,7 @@ BOOL VerifyTrust(CHAR * filename)
     LONG (WINAPI *pWinVerifyTrust)(HWND hWnd, GUID* pgActionID, WINTRUST_DATA* pWinTrustData) = NULL;
     HINSTANCE hWinTrust;
 
-    if (filename == NULL ) 
+    if (filename == NULL )
         return FALSE;
 
     hWinTrust = LoadLibrary("wintrust");
@@ -847,7 +902,7 @@ BOOL VerifyTrust(CHAR * filename)
         switch (gle) {
         case TRUST_E_PROVIDER_UNKNOWN:
             afsi_log("VerifyTrust failed: \"Generic Verify V2\" Provider Unknown");
-            break;  
+            break;
         case TRUST_E_NOSIGNATURE:
             afsi_log("VerifyTrust failed: Unsigned executable");
             break;
@@ -987,7 +1042,7 @@ BOOL AFSModulesVerify(void)
     }
 
 
-    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
+    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                         AFSREG_CLT_SVC_PARAM_SUBKEY,
                         0, KEY_QUERY_VALUE, &parmKey);
     if (code == ERROR_SUCCESS) {
@@ -1006,7 +1061,7 @@ BOOL AFSModulesVerify(void)
         RegCloseKey (parmKey);
     }
 
-    if (verifyServiceSig 
+    if (verifyServiceSig
 #ifndef _WIN64
          && cacheSize < 716800
 #endif
@@ -1063,7 +1118,7 @@ BOOL AFSModulesVerify(void)
                         if ( !VerifyTrust(szModName) ) {
                             afsi_log("Signature Verification failed: %s", szModName);
                             success = FALSE;
-                        } 
+                        }
                         else if (pCtxService) {
                             PCCERT_CONTEXT pCtx = GetCertCtx(szModName);
 
@@ -1073,10 +1128,10 @@ BOOL AFSModulesVerify(void)
                                 afsi_log("Certificate mismatch: %s", szModName);
                                 if (pCtx)
                                     LogCertCtx(pCtx);
-                                
+
                                 success = FALSE;
                             }
-                            
+
                             if (pCtx)
                                 pCertFreeCertificateContext(pCtx);
                         }
@@ -1105,7 +1160,7 @@ typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerExFunc )(  LPCTSTR ,
 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerFunc   )(  LPCTSTR ,  LPHANDLER_FUNCTION );
 
 RegisterServiceCtrlHandlerExFunc pRegisterServiceCtrlHandlerEx = NULL;
-RegisterServiceCtrlHandlerFunc   pRegisterServiceCtrlHandler   = NULL; 
+RegisterServiceCtrlHandlerFunc   pRegisterServiceCtrlHandler   = NULL;
 
 VOID WINAPI
 afsd_Main(DWORD argc, LPTSTR *argv)
@@ -1117,21 +1172,29 @@ afsd_Main(DWORD argc, LPTSTR *argv)
 #endif /* JUMP */
     HMODULE hHookDll;
     HMODULE hAdvApi32;
-#ifdef AFSIFS
-    int cnt;
-#endif
+    HMODULE hKernel32;
 
 #ifdef _DEBUG
+    void afsd_DbgBreakAllocInit();
+
     afsd_DbgBreakAllocInit();
-    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/ | 
+    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/ |
                    _CRTDBG_CHECK_CRT_DF /* | _CRTDBG_DELAY_FREE_MEM_DF */ );
-#endif 
+#endif
 
     afsd_SetUnhandledExceptionFilter();
-       
+
     osi_InitPanic(afsd_notifier);
     osi_InitTraceOption();
 
+    hKernel32 = LoadLibrary("kernel32.dll");
+    if (hKernel32 == NULL)
+    {
+        afsi_log("Fatal: cannot load kernel32.dll");
+        return;
+    }
+    pRtlCaptureContext = GetProcAddress(hKernel32, "RtlCaptureContext");
+
     GlobalStatus = 0;
 
     afsi_start();
@@ -1148,26 +1211,28 @@ afsd_Main(DWORD argc, LPTSTR *argv)
         return;
     }
 
-    pRegisterServiceCtrlHandlerEx = (RegisterServiceCtrlHandlerExFunc)GetProcAddress(hAdvApi32, "RegisterServiceCtrlHandlerExA");
-    if (pRegisterServiceCtrlHandlerEx)
-    {
-        afsi_log("running on 2000+ - using RegisterServiceCtrlHandlerEx");
-        StatusHandle = RegisterServiceCtrlHandlerEx(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandlerEx, NULL );
-    }
-    else
-    {
-        StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandler);
-    }
+    if (bRunningAsService) {
+        pRegisterServiceCtrlHandlerEx = (RegisterServiceCtrlHandlerExFunc)GetProcAddress(hAdvApi32, "RegisterServiceCtrlHandlerExA");
+        if (pRegisterServiceCtrlHandlerEx)
+        {
+            afsi_log("running on 2000+ - using RegisterServiceCtrlHandlerEx");
+            StatusHandle = RegisterServiceCtrlHandlerEx(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandlerEx, NULL );
+        }
+        else
+        {
+            StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandler);
+        }
 
-    ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
-    ServiceStatus.dwServiceSpecificExitCode = 0;
-    ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
-    ServiceStatus.dwWin32ExitCode = NO_ERROR;
-    ServiceStatus.dwCheckPoint = 1;
-    ServiceStatus.dwWaitHint = 120000;
-    /* accept Power Events */
-    ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
-    SetServiceStatus(StatusHandle, &ServiceStatus);
+        ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+        ServiceStatus.dwServiceSpecificExitCode = 0;
+        ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
+        ServiceStatus.dwWin32ExitCode = NO_ERROR;
+        ServiceStatus.dwCheckPoint = 1;
+        ServiceStatus.dwWaitHint = 120000;
+        /* accept Power Events */
+        ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
+        SetServiceStatus(StatusHandle, &ServiceStatus);
+    }
 #endif
 
     LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_START_PENDING);
@@ -1180,12 +1245,12 @@ afsd_Main(DWORD argc, LPTSTR *argv)
         int bpower = TRUE;
 
         /* see if we should handle power notifications */
-        code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 
+        code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
                             0, KEY_QUERY_VALUE, &hkParm);
         if (code == ERROR_SUCCESS) {
             dummyLen = sizeof(bpower);
             code = RegQueryValueEx(hkParm, "FlushOnHibernate", NULL, NULL,
-                (BYTE *) &bpower, &dummyLen);      
+                (BYTE *) &bpower, &dummyLen);
 
             if(code != ERROR_SUCCESS)
                 bpower = TRUE;
@@ -1202,13 +1267,14 @@ afsd_Main(DWORD argc, LPTSTR *argv)
 
     /* Verify the versions of the DLLs which were loaded */
     if (!AFSModulesVerify()) {
-        ServiceStatus.dwCurrentState = SERVICE_STOPPED;
-        ServiceStatus.dwWin32ExitCode = NO_ERROR;
-        ServiceStatus.dwCheckPoint = 0;
-        ServiceStatus.dwWaitHint = 0;
-        ServiceStatus.dwControlsAccepted = 0;
-        SetServiceStatus(StatusHandle, &ServiceStatus);
-
+        if (bRunningAsService) {
+            ServiceStatus.dwCurrentState = SERVICE_STOPPED;
+            ServiceStatus.dwWin32ExitCode = NO_ERROR;
+            ServiceStatus.dwCheckPoint = 0;
+            ServiceStatus.dwWaitHint = 0;
+            ServiceStatus.dwControlsAccepted = 0;
+            SetServiceStatus(StatusHandle, &ServiceStatus);
+        }
        LogEvent(EVENTLOG_ERROR_TYPE, MSG_SERVICE_INCORRECT_VERSIONS);
 
         /* exit if initialization failed */
@@ -1216,7 +1282,7 @@ afsd_Main(DWORD argc, LPTSTR *argv)
     }
 
     /* allow an exit to be called prior to any initialization */
-    hHookDll = LoadLibrary(AFSD_HOOK_DLL);
+    hHookDll = cm_LoadAfsdHookLib();
     if (hHookDll)
     {
         BOOL hookRc = TRUE;
@@ -1230,28 +1296,31 @@ afsd_Main(DWORD argc, LPTSTR *argv)
 
         if (hookRc == FALSE)
         {
-            ServiceStatus.dwCurrentState = SERVICE_STOPPED;
-            ServiceStatus.dwWin32ExitCode = NO_ERROR;
-            ServiceStatus.dwCheckPoint = 0;
-            ServiceStatus.dwWaitHint = 0;
-            ServiceStatus.dwControlsAccepted = 0;
-            SetServiceStatus(StatusHandle, &ServiceStatus);
-                       
+            if (bRunningAsService) {
+                ServiceStatus.dwCurrentState = SERVICE_STOPPED;
+                ServiceStatus.dwWin32ExitCode = NO_ERROR;
+                ServiceStatus.dwCheckPoint = 0;
+                ServiceStatus.dwWaitHint = 0;
+                ServiceStatus.dwControlsAccepted = 0;
+                SetServiceStatus(StatusHandle, &ServiceStatus);
+            }
             /* exit if initialization failed */
             return;
         }
         else
         {
             /* allow another 120 seconds to start */
-            ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
-            ServiceStatus.dwServiceSpecificExitCode = 0;
-            ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
-            ServiceStatus.dwWin32ExitCode = NO_ERROR;
-            ServiceStatus.dwCheckPoint = 2;
-            ServiceStatus.dwWaitHint = 120000;
-            /* accept Power Events */
-            ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
-            SetServiceStatus(StatusHandle, &ServiceStatus);
+            if (bRunningAsService) {
+                ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+                ServiceStatus.dwServiceSpecificExitCode = 0;
+                ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
+                ServiceStatus.dwWin32ExitCode = NO_ERROR;
+                ServiceStatus.dwCheckPoint = 2;
+                ServiceStatus.dwWaitHint = 120000;
+                /* accept Power Events */
+                ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
+                SetServiceStatus(StatusHandle, &ServiceStatus);
+            }
         }
     }
 
@@ -1262,7 +1331,7 @@ afsd_Main(DWORD argc, LPTSTR *argv)
     MainThreadId = GetCurrentThreadId();
     jmpret = setjmp(notifier_jmp);
 
-    if (jmpret == 0) 
+    if (jmpret == 0)
 #endif /* JUMP */
     {
         code = afsd_InitCM(&reason);
@@ -1272,18 +1341,14 @@ afsd_Main(DWORD argc, LPTSTR *argv)
         }
 
 #ifndef NOTSERVICE
-        ServiceStatus.dwCheckPoint = 3;
-        ServiceStatus.dwWaitHint = 30000;
-        SetServiceStatus(StatusHandle, &ServiceStatus);
-#endif
-        code = afsd_InitDaemons(&reason);
-        if (code != 0) {
-            afsi_log("afsd_InitDaemons failed: %s (code = %d)", reason, code);
-                       osi_panic(reason, __FILE__, __LINE__);
+        if (bRunningAsService) {
+            ServiceStatus.dwCheckPoint = 3;
+            ServiceStatus.dwWaitHint = 30000;
+            SetServiceStatus(StatusHandle, &ServiceStatus);
         }
-
+#endif
         /* allow an exit to be called post rx initialization */
-        hHookDll = LoadLibrary(AFSD_HOOK_DLL);
+        hHookDll = cm_LoadAfsdHookLib();
         if (hHookDll)
         {
             BOOL hookRc = TRUE;
@@ -1297,48 +1362,69 @@ afsd_Main(DWORD argc, LPTSTR *argv)
 
             if (hookRc == FALSE)
             {
-                ServiceStatus.dwCurrentState = SERVICE_STOPPED;
-                ServiceStatus.dwWin32ExitCode = NO_ERROR;
-                ServiceStatus.dwCheckPoint = 0;
-                ServiceStatus.dwWaitHint = 0;
-                ServiceStatus.dwControlsAccepted = 0;
-                SetServiceStatus(StatusHandle, &ServiceStatus);
-                       
+                if (bRunningAsService) {
+                    ServiceStatus.dwCurrentState = SERVICE_STOPPED;
+                    ServiceStatus.dwWin32ExitCode = NO_ERROR;
+                    ServiceStatus.dwCheckPoint = 0;
+                    ServiceStatus.dwWaitHint = 0;
+                    ServiceStatus.dwControlsAccepted = 0;
+                    SetServiceStatus(StatusHandle, &ServiceStatus);
+                }
                 /* exit if initialization failed */
                 return;
             }
         }
 
 #ifndef NOTSERVICE
-        ServiceStatus.dwCheckPoint = 4;
-        ServiceStatus.dwWaitHint = 15000;
-        SetServiceStatus(StatusHandle, &ServiceStatus);
+        if (bRunningAsService) {
+            ServiceStatus.dwCheckPoint = 4;
+            ServiceStatus.dwWaitHint = 15000;
+            SetServiceStatus(StatusHandle, &ServiceStatus);
+        }
 #endif
 
         /* Notify any volume status handlers that the cache manager has started */
         cm_VolStatus_Service_Started();
 
-/* the following ifdef chooses the mode of operation for the service.  to enable
- * a runtime flag (instead of compile-time), pioctl() would need to dynamically
- * determine the mode, in order to use the correct ioctl special-file path. */
-#ifndef AFSIFS
+        code = RDR_Initialize();
+        if ( code == ERROR_SERVICE_DISABLED) {
+            afsi_log("RDR_Initialize failed: 1058 (Unable to load AFSRedirLib.sys)");
+            osi_panic(reason, __FILE__, __LINE__);
+        } else {
+            RDR_Initialized = !code;
+            afsi_log("RDR_Initialize returned: (code = %d)", code);
+        }
+
+        if (RDR_Initialized) {
+            if (cm_sysNameCount)
+                RDR_SysName( AFS_SYSNAME_ARCH_32BIT, cm_sysNameCount, cm_sysNameList );
+#ifdef _WIN64
+            if (cm_sysName64Count)
+                RDR_SysName( AFS_SYSNAME_ARCH_64BIT, cm_sysName64Count, cm_sysName64List );
+            else if (cm_sysNameCount)
+                RDR_SysName( AFS_SYSNAME_ARCH_64BIT, cm_sysNameCount, cm_sysNameList );
+#endif
+        }
+
+        /*
+         * Set the default for the SMB interface based upon the state of the
+         * Redirector interface.
+         */
+        smb_Enabled = !RDR_Initialized;
+
         code = afsd_InitSMB(&reason, MessageBox);
-        if (code != 0) {
+        if (smb_Enabled && code != 0) {
             afsi_log("afsd_InitSMB failed: %s (code = %d)", reason, code);
             osi_panic(reason, __FILE__, __LINE__);
         }
-#else
-        code = ifs_Init(&reason);
-        if (code != 0) {
-            afsi_log("ifs_Init failed: %s (code = %d)", reason, code);
+
+        if (!smb_Enabled && !RDR_Initialized) {
+            afsi_log("Neither RDR nor SMB interfaces available");
             osi_panic(reason, __FILE__, __LINE__);
-        }     
-        for (cnt = 0; cnt < WORKER_THREADS; cnt++)
-            hAFSDWorkerThread[cnt] = CreateThread(NULL, 0, ifs_MainLoop, 0, 0, NULL);
-#endif  
+        }
 
         /* allow an exit to be called post smb initialization */
-        hHookDll = LoadLibrary(AFSD_HOOK_DLL);
+        hHookDll = cm_LoadAfsdHookLib();
         if (hHookDll)
         {
             BOOL hookRc = TRUE;
@@ -1352,13 +1438,14 @@ afsd_Main(DWORD argc, LPTSTR *argv)
 
             if (hookRc == FALSE)
             {
-                ServiceStatus.dwCurrentState = SERVICE_STOPPED;
-                ServiceStatus.dwWin32ExitCode = NO_ERROR;
-                ServiceStatus.dwCheckPoint = 0;
-                ServiceStatus.dwWaitHint = 0;
-                ServiceStatus.dwControlsAccepted = 0;
-                SetServiceStatus(StatusHandle, &ServiceStatus);
-                       
+                if (bRunningAsService) {
+                    ServiceStatus.dwCurrentState = SERVICE_STOPPED;
+                    ServiceStatus.dwWin32ExitCode = NO_ERROR;
+                    ServiceStatus.dwCheckPoint = 0;
+                    ServiceStatus.dwWaitHint = 0;
+                    ServiceStatus.dwControlsAccepted = 0;
+                    SetServiceStatus(StatusHandle, &ServiceStatus);
+                }
                 /* exit if initialization failed */
                 return;
             }
@@ -1366,22 +1453,30 @@ afsd_Main(DWORD argc, LPTSTR *argv)
 
         MountGlobalDrives();
 
+        code = afsd_InitDaemons(&reason);
+        if (code != 0) {
+            afsi_log("afsd_InitDaemons failed: %s (code = %d)", reason, code);
+                       osi_panic(reason, __FILE__, __LINE__);
+        }
+
 #ifndef NOTSERVICE
-        ServiceStatus.dwCurrentState = SERVICE_RUNNING;
-        ServiceStatus.dwWin32ExitCode = NO_ERROR;
-        ServiceStatus.dwCheckPoint = 5;
-        ServiceStatus.dwWaitHint = 0;
+        if (bRunningAsService) {
+            ServiceStatus.dwCurrentState = SERVICE_RUNNING;
+            ServiceStatus.dwWin32ExitCode = NO_ERROR;
+            ServiceStatus.dwCheckPoint = 5;
+            ServiceStatus.dwWaitHint = 0;
 
-        /* accept Power events */
-        ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
-        SetServiceStatus(StatusHandle, &ServiceStatus);
-#endif  
+            /* accept Power events */
+            ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
+            SetServiceStatus(StatusHandle, &ServiceStatus);
+        }
+#endif
 
        LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_RUNNING);
     }
 
     /* allow an exit to be called when started */
-    hHookDll = LoadLibrary(AFSD_HOOK_DLL);
+    hHookDll = cm_LoadAfsdHookLib();
     if (hHookDll)
     {
         BOOL hookRc = TRUE;
@@ -1395,33 +1490,29 @@ afsd_Main(DWORD argc, LPTSTR *argv)
 
         if (hookRc == FALSE)
         {
-            ServiceStatus.dwCurrentState = SERVICE_STOPPED;
-            ServiceStatus.dwWin32ExitCode = NO_ERROR;
-            ServiceStatus.dwCheckPoint = 0;
-            ServiceStatus.dwWaitHint = 0;
-            ServiceStatus.dwControlsAccepted = 0;
-            SetServiceStatus(StatusHandle, &ServiceStatus);
-                       
+            if (bRunningAsService) {
+                ServiceStatus.dwCurrentState = SERVICE_STOPPED;
+                ServiceStatus.dwWin32ExitCode = NO_ERROR;
+                ServiceStatus.dwCheckPoint = 0;
+                ServiceStatus.dwWaitHint = 0;
+                ServiceStatus.dwControlsAccepted = 0;
+                SetServiceStatus(StatusHandle, &ServiceStatus);
+            }
             /* exit if initialization failed */
             return;
         }
     }
 
-#ifndef AFSIFS
     WaitForSingleObject(WaitToTerminate, INFINITE);
-#else
-    WaitForMultipleObjects(WORKER_THREADS, hAFSDWorkerThread, TRUE, INFINITE);
-    for (cnt = 0; cnt < WORKER_THREADS; cnt++)
-        CloseHandle(hAFSDWorkerThread[cnt]);
-#endif
-
-    ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
-    ServiceStatus.dwWin32ExitCode = NO_ERROR;
-    ServiceStatus.dwCheckPoint = 6;
-    ServiceStatus.dwWaitHint = 120000;
-    ServiceStatus.dwControlsAccepted = 0;
-    SetServiceStatus(StatusHandle, &ServiceStatus);
 
+    if (bRunningAsService) {
+        ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
+        ServiceStatus.dwWin32ExitCode = NO_ERROR;
+        ServiceStatus.dwCheckPoint = 6;
+        ServiceStatus.dwWaitHint = 120000;
+        ServiceStatus.dwControlsAccepted = 0;
+        SetServiceStatus(StatusHandle, &ServiceStatus);
+    }
     afsi_log("Received Termination Signal, Stopping Service");
 
     if ( GlobalStatus )
@@ -1430,7 +1521,7 @@ afsd_Main(DWORD argc, LPTSTR *argv)
        LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_STOPPING);
 
     /* allow an exit to be called prior to stopping the service */
-    hHookDll = LoadLibrary(AFSD_HOOK_DLL);
+    hHookDll = cm_LoadAfsdHookLib();
     if (hHookDll)
     {
         BOOL hookRc = TRUE;
@@ -1451,32 +1542,38 @@ afsd_Main(DWORD argc, LPTSTR *argv)
 
     DismountGlobalDrives();
     afsi_log("Global Drives dismounted");
-                                         
-    cm_DaemonShutdown();                 
+
+    if (RDR_Initialized) {
+        RDR_ShutdownNotify();
+        cm_VolStatus_SetRDRNotifications(FALSE);
+        afsi_log("RDR notified of shutdown");
+    }
+
+    smb_Shutdown();
+    afsi_log("smb shutdown complete");
+
+    cm_ReleaseAllLocks();
+
+    cm_DaemonShutdown();
     afsi_log("Daemon shutdown complete");
-    
-    afsd_ShutdownCM();
 
-    buf_Shutdown();                      
+    buf_Shutdown();
     afsi_log("Buffer shutdown complete");
-                                         
-    rx_Finalize();                       
-    afsi_log("rx finalization complete");
-                                         
-#ifndef AFSIFS
-    smb_Shutdown();                      
-    afsi_log("smb shutdown complete");   
-#endif
-                                         
-    RpcShutdown();                       
 
-    cm_ReleaseAllLocks();
+    afsd_ShutdownCM();
+
+    RpcShutdown();
+
+    cm_ShutdownMappedMemory();
+
+    if (RDR_Initialized) {
+        RDR_ShutdownFinal();
+        afsi_log("RDR shutdown complete");
+    }
 
     rx_Finalize();
     afsi_log("rx finalization complete");
 
-    cm_ShutdownMappedMemory();           
-
 #ifdef REGISTER_POWER_NOTIFICATIONS
     /* terminate thread used to flush cache */
     if (powerEventsRegistered)
@@ -1495,7 +1592,7 @@ afsd_Main(DWORD argc, LPTSTR *argv)
     cm_VolStatus_Finalize();
 
     /* allow an exit to be called after stopping the service */
-    hHookDll = LoadLibrary(AFSD_HOOK_DLL);
+    hHookDll = cm_LoadAfsdHookLib();
     if (hHookDll)
     {
         BOOL hookRc = TRUE;
@@ -1511,13 +1608,17 @@ afsd_Main(DWORD argc, LPTSTR *argv)
     /* Remove the ExceptionFilter */
     SetUnhandledExceptionFilter(NULL);
 
-    ServiceStatus.dwCurrentState = SERVICE_STOPPED;
-    ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
-    ServiceStatus.dwCheckPoint = 7;
-    ServiceStatus.dwWaitHint = 0;
-    ServiceStatus.dwControlsAccepted = 0;
-    SetServiceStatus(StatusHandle, &ServiceStatus);
-}       
+    LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_STOPPED);
+
+    if (bRunningAsService) {
+        ServiceStatus.dwCurrentState = SERVICE_STOPPED;
+        ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
+        ServiceStatus.dwCheckPoint = 7;
+        ServiceStatus.dwWaitHint = 0;
+        ServiceStatus.dwControlsAccepted = 0;
+        SetServiceStatus(StatusHandle, &ServiceStatus);
+    }
+}
 
 DWORD __stdcall afsdMain_thread(void* notUsed)
 {
@@ -1560,14 +1661,14 @@ main(int argc, char * argv[])
         if (status == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
         {
             DWORD tid;
+
+            bRunningAsService = FALSE;
+
             hAFSDMainThread = CreateThread(NULL, 0, afsdMain_thread, 0, 0, &tid);
-               
+
             printf("Hit <Enter> to terminate OpenAFS Client Service\n");
-            getchar();  
+            getchar();
             SetEvent(WaitToTerminate);
-#ifdef AFSIFS
-           dc_release_hooks();
-#endif
         }
     }