win-power-mgmt-flush-test-20041003
authorJeffrey Altman <jaltman@mit.edu>
Sun, 3 Oct 2004 14:34:27 +0000 (14:34 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Sun, 3 Oct 2004 14:34:27 +0000 (14:34 +0000)
The windows power management code responds to a request to suspend or
hibernate by performing a "fs flushvol" as the logged in user on each
of the SMB/CIFS mounted shares.  This can be very time consuming if
the cell servers cannot be reached.

This patch adds a test to ensure that there is at least one network
adapter in the machine which is not a loopback adapter.

While developing this patch other areas of concern have been raised.
The power management code waits a fixed period of time based upon
the hard dead timeout before allowing the suspend/hibernate to continue.
This allows the machine to shutdown even if there are active flush
operations being performed.  This defeats the benefit of performing
the flush at all.

A better mechanism could be developed if the functions called via
cm_IoctlFlushVolume returned and checked error codes.  Then it might
be possible to abandon the flush operation if a Server Not Reachable
state was obtained.

The power management flush operations will also not work on Terminal
Server.  This would be important in the case where a terminal server
is shutting down due to a switch over to a UPS.  The reason it does
not work on Terminal Server is that there is that it is not possible
for afsd_service.exe to enumerate the SMB/CIFS shares and impersonate
the individual logged in users.

It would be preferred for there to be a new cm_FlushAll() function
implemented which was not dependent on the use of the ioctl mechanism
for the purpose of identifying a volume ID or a user ID.

src/WINNT/afsd/afsd_flushvol.c
src/WINNT/afsd/afsd_service.c
src/WINNT/afsd/lanahelper.cpp
src/WINNT/afsd/lanahelper.h

index 32ab700..5d90c7f 100644 (file)
@@ -27,6 +27,9 @@
 
 #include "afsd_flushvol.h"
 #include "afsd_eventlog.h"
+#include "lanahelper.h"
+
+extern void afsi_log(char *pattern, ...);
 
 static FLUSHVOLTHREADINFO      gThreadInfo   = {0};
 static HANDLE                  gThreadHandle = NULL;
@@ -45,145 +48,150 @@ static HANDLE                     gThreadHandle = NULL;
 afs_int32
 afsd_ServicePerformFlushVolumeCmd(char *data)
 {
-       register afs_int32 code;
-       struct ViceIoctl blob;
+    register afs_int32 code;
+    struct ViceIoctl blob;
 
-       memset(&blob, '\0', sizeof(blob));
-       code = pioctl(data, VIOC_FLUSHVOLUME, &blob, 0);
+    afsi_log("Flushing Volume \"%s\"",data);
+    memset(&blob, '\0', sizeof(blob));
+    code = pioctl(data, VIOC_FLUSHVOLUME, &blob, 0);
     
-       return code;
+    return code;
 }
 
 BOOL
 afsd_ServicePerformFlushVolumes()
-{
-       CONST CHAR      COLON = ':';
-       CONST CHAR      SLASH = '\\';
-       CONST DWORD     NETRESBUFSIZE = 16384;
-       CHAR            bufMessage[1024];
-       UINT            i;
-       DWORD           dwServerSize;
-       DWORD           dwRet;
-       DWORD           dwCount;
-       DWORD           dwNetResBufSize;
-       DWORD           dwTotalVols = 0;
-       DWORD           dwVolBegin, dwVolEnd;
-       DWORD           dwFlushBegin, dwFlushEnd;
-       HANDLE          hEnum;
-       LPNETRESOURCE   lpNetResBuf, lpnr;
-       PCHAR           pszShareName, pc;
-       afs_int32       afsRet = 0;
-       
-       // Determine the root share name (\\AFS\ALL or \\<machine>-AFS\ALL),
-       // and the length of the server name prefix.
-       pszShareName = smb_GetSharename();
-       if (pszShareName == NULL)
-       {
-               LogEvent(EVENTLOG_ERROR_TYPE, MSG_FLUSH_NO_SHARE_NAME, NULL);
-               return FALSE;
-       }
-       pc = strrchr(pszShareName, SLASH);
-       if ((pc == NULL) || ((dwServerSize = pc - pszShareName) < 3))
-       {
-               LogEvent(EVENTLOG_ERROR_TYPE, MSG_FLUSH_BAD_SHARE_NAME,
-                        pszShareName, NULL);
-               free(pszShareName);
-               return FALSE;
-       }
-
-       // Allocate a buffer to hold network resources returned by
-       // WNetEnumResource().
-       lpNetResBuf = malloc(NETRESBUFSIZE);
-       if (lpNetResBuf == NULL)
-       {
-               // Out of memory, give up now.
-               LogEvent(EVENTLOG_ERROR_TYPE, MSG_FLUSH_NO_MEMORY, NULL);
-               free(pszShareName);
-               return FALSE;
-       }
-
-       // Initialize the flush timer.  Note that GetTickCount() returns
-       // the number of milliseconds since the system started, in a DWORD,
-       // so that the value wraps around every 49.7 days.  We do not bother
-       // to handle the case where the flush elapsed time is greater than
-       // that.
-       dwFlushBegin = GetTickCount();
+{       
+    CONST CHAR COLON = ':';
+    CONST CHAR SLASH = '\\';
+    CONST DWORD        NETRESBUFSIZE = 16384;
+    CHAR               bufMessage[1024];
+    UINT               i;
+    DWORD              dwServerSize;
+    DWORD              dwRet;
+    DWORD              dwCount;
+    DWORD              dwNetResBufSize;
+    DWORD              dwTotalVols = 0;
+    DWORD              dwVolBegin, dwVolEnd;
+    DWORD              dwFlushBegin, dwFlushEnd;
+    HANDLE             hEnum;
+    LPNETRESOURCE      lpNetResBuf, lpnr;
+    PCHAR              pszShareName, pc;
+    afs_int32  afsRet = 0;
+
+    if ( lana_OnlyLoopback() ) {
+        // Nothing to do if we only have a loopback interface
+        return TRUE;
+    }
+
+    // Determine the root share name (\\AFS\ALL or \\<machine>-AFS\ALL),
+    // and the length of the server name prefix.
+    pszShareName = smb_GetSharename();
+    if (pszShareName == NULL)
+    {
+        LogEvent(EVENTLOG_ERROR_TYPE, MSG_FLUSH_NO_SHARE_NAME, NULL);
+        return FALSE;
+    }
+    pc = strrchr(pszShareName, SLASH);
+    if ((pc == NULL) || ((dwServerSize = pc - pszShareName) < 3))
+    {
+        LogEvent(EVENTLOG_ERROR_TYPE, MSG_FLUSH_BAD_SHARE_NAME,
+                  pszShareName, NULL);
+        free(pszShareName);
+        return FALSE;
+    }
+
+    // Allocate a buffer to hold network resources returned by
+    // WNetEnumResource().
+    lpNetResBuf = malloc(NETRESBUFSIZE);
+    if (lpNetResBuf == NULL)
+    {
+        // Out of memory, give up now.
+        LogEvent(EVENTLOG_ERROR_TYPE, MSG_FLUSH_NO_MEMORY, NULL);
+        free(pszShareName);
+        return FALSE;
+    }
+
+    // Initialize the flush timer.  Note that GetTickCount() returns
+    // the number of milliseconds since the system started, in a DWORD,
+    // so that the value wraps around every 49.7 days.  We do not bother
+    // to handle the case where the flush elapsed time is greater than
+    // that.
+    dwFlushBegin = GetTickCount();
+
+    dwRet = WNetOpenEnum(RESOURCE_CONNECTED, RESOURCETYPE_ANY, 0, NULL,
+                          &hEnum);
+    if (dwRet != NO_ERROR)
+    {
+        LogEventMessage(EVENTLOG_ERROR_TYPE, MSG_FLUSH_OPEN_ENUM_ERROR,
+                         dwRet);
+        free(pszShareName);
+        return FALSE;
+    }
+
+    // Loop to enumerate network resources, and flush those associated
+    // with AFS volumes.
+    while (1)
+    {
+        dwCount = -1;
+        memset(lpNetResBuf, 0, NETRESBUFSIZE);
+        dwNetResBufSize = NETRESBUFSIZE;
+        dwRet = WNetEnumResource(hEnum, &dwCount,
+                                  lpNetResBuf, &dwNetResBufSize);
+        if (dwRet != NO_ERROR)
+            break;
+        // Iterate over the returned network resources.
+        for (i = 0, lpnr = lpNetResBuf; i < dwCount; i++, lpnr++)
+        {
+            // Ensure resource has a remote name, and is connected.
+            if ((lpnr->lpRemoteName == NULL) ||
+                 (lpnr->dwScope != RESOURCE_CONNECTED))
+                continue;
+            if ((_strnicmp(lpnr->lpRemoteName, pszShareName,
+                            dwServerSize) == 0) &&
+                 (lpnr->lpRemoteName[dwServerSize] == SLASH))
+            {
+                // got one!
+                // but we don't want to flush '\\[...]afs\all'
+                if (_stricmp(lpnr->lpRemoteName, pszShareName) == 0)
+                    continue;
+                ++dwTotalVols;
+
+                dwVolBegin = GetTickCount();
+                afsRet = afsd_ServicePerformFlushVolumeCmd(lpnr->lpRemoteName);
+                dwVolEnd = GetTickCount();
+                if (afsRet == 0)
+                {
+                    LogTimingEvent(MSG_TIME_FLUSH_PER_VOLUME,
+                                    lpnr->lpRemoteName,
+                                    dwVolEnd - dwVolBegin);
+                }
+                else
+                {
+                    LogEvent(EVENTLOG_WARNING_TYPE,
+                              MSG_FLUSH_FAILED,
+                              lpnr->lpRemoteName, NULL);
+                }
+            }
+        }
+    }
+    WNetCloseEnum(hEnum);
+    free(lpNetResBuf);
+    free(pszShareName);
+    if (dwRet != ERROR_NO_MORE_ITEMS)
+    {
+        LogEventMessage(EVENTLOG_ERROR_TYPE, MSG_FLUSH_ENUM_ERROR,
+                         dwRet);
+        return FALSE;
+    }
+
+    dwFlushEnd = GetTickCount();
        
-       dwRet = WNetOpenEnum(RESOURCE_CONNECTED, RESOURCETYPE_ANY, 0, NULL,
-                            &hEnum);
-       if (dwRet != NO_ERROR)
-       {
-               LogEventMessage(EVENTLOG_ERROR_TYPE, MSG_FLUSH_OPEN_ENUM_ERROR,
-                               dwRet);
-               free(pszShareName);
-               return FALSE;
-       }
-
-       // Loop to enumerate network resources, and flush those associated
-       // with AFS volumes.
-       while (1)
-       {
-               dwCount = -1;
-               memset(lpNetResBuf, 0, NETRESBUFSIZE);
-               dwNetResBufSize = NETRESBUFSIZE;
-               dwRet = WNetEnumResource(hEnum, &dwCount,
-                                        lpNetResBuf, &dwNetResBufSize);
-               if (dwRet != NO_ERROR)
-                       break;
-               // Iterate over the returned network resources.
-               for (i = 0, lpnr = lpNetResBuf; i < dwCount; i++, lpnr++)
-               {
-                       // Ensure resource has a remote name, and is connected.
-                       if ((lpnr->lpRemoteName == NULL) ||
-                           (lpnr->dwScope != RESOURCE_CONNECTED))
-                               continue;
-                       if ((_strnicmp(lpnr->lpRemoteName, pszShareName,
-                                      dwServerSize) == 0) &&
-                           (lpnr->lpRemoteName[dwServerSize] == SLASH))
-                       {
-                               // got one!
-                               // but we don't want to flush '\\[...]afs\all'
-                               if (_stricmp(lpnr->lpRemoteName,
-                                            pszShareName) == 0)
-                                       continue;
-                               ++dwTotalVols;
-
-                               dwVolBegin = GetTickCount();
-                               afsRet = afsd_ServicePerformFlushVolumeCmd(lpnr->lpRemoteName);
-                               dwVolEnd = GetTickCount();
-                               if (afsRet == 0)
-                               {
-                                       LogTimingEvent(MSG_TIME_FLUSH_PER_VOLUME,
-                                                      lpnr->lpRemoteName,
-                                                      dwVolEnd - dwVolBegin);
-                               }
-                               else
-                               {
-                                       LogEvent(EVENTLOG_WARNING_TYPE,
-                                                MSG_FLUSH_FAILED,
-                                                lpnr->lpRemoteName, NULL);
-                               }
-                       }
-               }
-       }
-       WNetCloseEnum(hEnum);
-       free(lpNetResBuf);
-       free(pszShareName);
-       if (dwRet != ERROR_NO_MORE_ITEMS)
-       {
-               LogEventMessage(EVENTLOG_ERROR_TYPE, MSG_FLUSH_ENUM_ERROR,
-                               dwRet);
-               return FALSE;
-       }
-
-       dwFlushEnd = GetTickCount();
-       
-       // display total volume count in Event Logger
-       sprintf(bufMessage, "%d", dwTotalVols);
-       LogTimingEvent(MSG_TIME_FLUSH_TOTAL, bufMessage,
-                      dwFlushEnd - dwFlushBegin);
+    // display total volume count in Event Logger
+    sprintf(bufMessage, "%d", dwTotalVols);
+    LogTimingEvent(MSG_TIME_FLUSH_TOTAL, bufMessage,
+                    dwFlushEnd - dwFlushBegin);
 
-       return TRUE;
+    return TRUE;
 }
 
 // Report a timing event to the system event log.
@@ -193,11 +201,11 @@ afsd_ServicePerformFlushVolumes()
 static VOID
 LogTimingEvent(DWORD dwEventID, LPTSTR lpString1, DWORD dwTime)
 {
-       CHAR    szTime[16];
+    CHAR       szTime[16];
        
-       sprintf(szTime, "%lu", dwTime);
-       LogEvent(EVENTLOG_INFORMATION_TYPE, dwEventID, lpString1, szTime,
-                NULL);
+    sprintf(szTime, "%lu", dwTime);
+    LogEvent(EVENTLOG_INFORMATION_TYPE, dwEventID, lpString1, szTime,
+              NULL);
 }
 
 
@@ -223,91 +231,91 @@ LogTimingEvent(DWORD dwEventID, LPTSTR lpString1, DWORD dwTime)
 //
 HANDLE GetUserToken(DWORD access)
 {
-       HANDLE hTok = NULL;
-       DWORD pid = 0, tid = 0;
-
-       // Try it the easy way first - look for a window owned by the shell on
-       // our current desktop.  If we find one, use that to get the process id.
-       HWND shell = FindWindowEx(NULL, NULL, "Progman", NULL);
-       if (shell != NULL)
-       {
-               tid = GetWindowThreadProcessId(shell, &pid);
-       }
-
-       // We are possibly running on a private window station and desktop: we must
-       // switch to the default (which we suppose is where we will find the
-       // running shell).
-       else
-       {
-               HWINSTA saveWinSta = GetProcessWindowStation(); 
-               HDESK saveDesk = GetThreadDesktop(GetCurrentThreadId()); 
-               HWINSTA winSta = NULL;
-               HDESK desk = NULL;
-               BOOL changeFlag = FALSE;
-               BOOL dummy = saveWinSta != NULL &&
-                                        saveDesk != NULL &&
-                                        (winSta = OpenWindowStation("WinSta0", FALSE,
-                                                                       MAXIMUM_ALLOWED)) != NULL &&
-                                        (changeFlag = SetProcessWindowStation(winSta)) != 0 &&
-                                        (desk = OpenDesktop("Default", 0, FALSE,
-                                                                       MAXIMUM_ALLOWED)) != NULL &&
-                                        SetThreadDesktop(desk) != 0;
-
-               // Now find the window and process on this desktop
-               shell = FindWindowEx(NULL, NULL, "Progman", NULL);
-               if (shell != NULL) 
-               {
-                       tid = GetWindowThreadProcessId(shell, &pid);
-               }
-
-               // Restore our own window station and desktop
-               if (changeFlag)
-               {
-                       SetProcessWindowStation(saveWinSta);
-                       SetThreadDesktop(saveDesk);
-               }
-
-               // Close temporary objects
-               if (winSta != NULL)
-                       CloseWindowStation(winSta);
-               if (desk != NULL) 
-                       CloseDesktop(desk);
-       }
-
-       //
-       // If we have a process id, use that to get the process handle and 
-       // from there the process' access token.
-       //
-       if (pid != 0)
-       {
-               HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
-               if (hProc != NULL)
-               {
-                       OpenProcessToken(hProc, access, &hTok) || (hTok = NULL);
-                       CloseHandle(hProc);
-               }
-       }
-
-       // Return token if we got one
-       return hTok;
-}
+    HANDLE hTok = NULL;
+    DWORD pid = 0, tid = 0;
+
+    // Try it the easy way first - look for a window owned by the shell on
+    // our current desktop.  If we find one, use that to get the process id.
+    HWND shell = FindWindowEx(NULL, NULL, "Progman", NULL);
+    if (shell != NULL)
+    {
+        tid = GetWindowThreadProcessId(shell, &pid);
+    }
+
+    // We are possibly running on a private window station and desktop: we must
+    // switch to the default (which we suppose is where we will find the
+    // running shell).
+    else
+    {
+        HWINSTA saveWinSta = GetProcessWindowStation(); 
+        HDESK saveDesk = GetThreadDesktop(GetCurrentThreadId()); 
+        HWINSTA winSta = NULL;
+        HDESK desk = NULL;
+        BOOL changeFlag = FALSE;
+        BOOL dummy = saveWinSta != NULL &&
+                     saveDesk != NULL &&
+                     (winSta = OpenWindowStation("WinSta0", FALSE,
+                                                 MAXIMUM_ALLOWED)) != NULL &&
+                     (changeFlag = SetProcessWindowStation(winSta)) != 0 &&
+                     (desk = OpenDesktop("Default", 0, FALSE,
+                                          MAXIMUM_ALLOWED)) != NULL &&
+                     SetThreadDesktop(desk) != 0;
+
+        // Now find the window and process on this desktop
+        shell = FindWindowEx(NULL, NULL, "Progman", NULL);
+        if (shell != NULL) 
+        {
+            tid = GetWindowThreadProcessId(shell, &pid);
+        }
+
+        // Restore our own window station and desktop
+        if (changeFlag)
+        {
+            SetProcessWindowStation(saveWinSta);
+            SetThreadDesktop(saveDesk);
+        }
+
+        // Close temporary objects
+        if (winSta != NULL)
+            CloseWindowStation(winSta);
+        if (desk != NULL) 
+            CloseDesktop(desk);
+    }
+
+    //
+    // If we have a process id, use that to get the process handle and 
+    // from there the process' access token.
+    //
+    if (pid != 0)
+    {
+        HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
+        if (hProc != NULL)
+        {
+            OpenProcessToken(hProc, access, &hTok) || (hTok = NULL);
+            CloseHandle(hProc);
+        }
+    }
+
+    // Return token if we got one
+    return hTok;
+}       
 
 // impersonate logged-on user as client
 BOOL
 ImpersonateClient()
 {
-       DWORD   dwDesiredAccess = TOKEN_ALL_ACCESS;
-       HANDLE  hUserToken = GetUserToken(dwDesiredAccess);
+    DWORD      dwDesiredAccess = TOKEN_ALL_ACCESS;
+    HANDLE     hUserToken = GetUserToken(dwDesiredAccess);
        
-       if (hUserToken == NULL)
-               return FALSE;
-       if (ImpersonateLoggedOnUser(hUserToken) == 0)
-       {
-               LogEvent(EVENTLOG_ERROR_TYPE, MSG_FLUSH_IMPERSONATE_ERROR,
-                        NULL);
-               return FALSE;
-       }
-       return TRUE;
+    if (hUserToken == NULL)
+        return FALSE;
+    if (ImpersonateLoggedOnUser(hUserToken) == 0)
+    {
+        LogEvent(EVENTLOG_ERROR_TYPE, MSG_FLUSH_IMPERSONATE_ERROR,
+                  NULL);
+        return FALSE;
+    }
+    return TRUE;
 }
        
 /////////////////////////////////////////////////////////////////////
@@ -317,67 +325,67 @@ ImpersonateClient()
 DWORD WINAPI 
 afsd_ServiceFlushVolumesThreadProc(LPVOID lpParam)
 {
-       FLUSHVOLTHREADINFO ThreadInfo;
-       PFLUSHVOLTHREADINFO pThreadInfo = (PFLUSHVOLTHREADINFO) lpParam; 
-       HANDLE  arHandles[2] = {0};
-       DWORD   dwWaitState = 0;
-
-       // thread running - get handles
-       ThreadInfo.hEventPowerEvent = pThreadInfo->hEventPowerEvent;
-       ThreadInfo.hEventResumeMain = pThreadInfo->hEventResumeMain;
-       ThreadInfo.hEventTerminate  = pThreadInfo->hEventTerminate;
-
-       // setup to wait
-       arHandles[0] = ThreadInfo.hEventTerminate;
-       arHandles[1] = ThreadInfo.hEventPowerEvent;
-
-       // do stuff ..
-       while (1)
-       {
-               // wait for an event to happen
-               dwWaitState = WaitForMultipleObjectsEx(2, arHandles, FALSE, INFINITE, FALSE);
-
-               switch (dwWaitState)
-               {
-               case WAIT_OBJECT_0:
-                       // termination signaled
-                       RevertToSelf();
+    FLUSHVOLTHREADINFO ThreadInfo;
+    PFLUSHVOLTHREADINFO pThreadInfo = (PFLUSHVOLTHREADINFO) lpParam; 
+    HANDLE     arHandles[2] = {0};
+    DWORD      dwWaitState = 0;
+
+    // thread running - get handles
+    ThreadInfo.hEventPowerEvent = pThreadInfo->hEventPowerEvent;
+    ThreadInfo.hEventResumeMain = pThreadInfo->hEventResumeMain;
+    ThreadInfo.hEventTerminate  = pThreadInfo->hEventTerminate;
+
+    // setup to wait
+    arHandles[0] = ThreadInfo.hEventTerminate;
+    arHandles[1] = ThreadInfo.hEventPowerEvent;
+
+    // do stuff ..
+    while (1)
+    {
+        // wait for an event to happen
+        dwWaitState = WaitForMultipleObjectsEx(2, arHandles, FALSE, INFINITE, FALSE);
+
+        switch (dwWaitState)
+        {
+        case WAIT_OBJECT_0:
+            // termination signaled
+            RevertToSelf();
             CheckAndCloseHandle(ThreadInfo.hEventPowerEvent);
             CheckAndCloseHandle(ThreadInfo.hEventResumeMain);
             CheckAndCloseHandle(ThreadInfo.hEventTerminate);
-                       ExitThread(0);
-                       break;
-
-               case WAIT_OBJECT_0+1:
-                       // Power event 
-                       // - flush 'em!
-                       if (ImpersonateClient())
-                       {
-                               afsd_ServicePerformFlushVolumes();
-                       }
-                       // acknowledge event
-                       ResetEvent(ThreadInfo.hEventPowerEvent);
-                       break;
-
-               case WAIT_ABANDONED_0:
-               case WAIT_ABANDONED_0+1:
-               case WAIT_IO_COMPLETION:
-               case WAIT_TIMEOUT:
-                       // sno*
-                       LogEvent(EVENTLOG_WARNING_TYPE,
-                                MSG_FLUSH_UNEXPECTED_EVENT, NULL);
-                       break;
-               
-               }       // end switch
-
-               // signal back to waiting mainline
-               SetEvent(ThreadInfo.hEventResumeMain);
-
-       }       // end while
-       
-       // I suppose we never get here
-       ExitThread(0);
-}
+            ExitThread(0);
+            break;
+
+        case WAIT_OBJECT_0+1:
+            // Power event 
+            // - flush 'em!
+            if (ImpersonateClient())
+            {
+                afsd_ServicePerformFlushVolumes();
+            }
+            // acknowledge event
+            ResetEvent(ThreadInfo.hEventPowerEvent);
+            break;
+
+        case WAIT_ABANDONED_0:
+        case WAIT_ABANDONED_0+1:
+        case WAIT_IO_COMPLETION:
+        case WAIT_TIMEOUT:
+            // sno*
+            LogEvent(EVENTLOG_WARNING_TYPE,
+                      MSG_FLUSH_UNEXPECTED_EVENT, NULL);
+            break;
+
+        }      // end switch
+
+        // signal back to waiting mainline
+        SetEvent(ThreadInfo.hEventResumeMain);
+
+    }  // end while
+
+    // I suppose we never get here
+    ExitThread(0);
+}       
 
 /////////////////////////////////////////////////////////////////////
 //
@@ -387,11 +395,11 @@ afsd_ServiceFlushVolumesThreadProc(LPVOID lpParam)
 VOID   
 CheckAndCloseHandle(HANDLE thisHandle)
 {
-       if (thisHandle != NULL)
-       {
-               CloseHandle(thisHandle);
-               thisHandle = NULL;
-       }
+    if (thisHandle != NULL)
+    {
+        CloseHandle(thisHandle);
+        thisHandle = NULL;
+    }
 }
 
 //
@@ -400,62 +408,62 @@ CheckAndCloseHandle(HANDLE thisHandle)
 BOOL
 PowerNotificationThreadCreate()
 {
-       BOOL    bSuccess = FALSE;
-       DWORD   dwThreadId = 0;
+    BOOL       bSuccess = FALSE;
+    DWORD      dwThreadId = 0;
     char    eventName[MAX_PATH];
        
-       do 
-       {
-               // create power event notification event
-               // bManualReset=TRUE, bInitialState=FALSE
-               gThreadInfo.hEventPowerEvent = CreateEvent(NULL, TRUE, FALSE, 
+    do 
+    {
+        // create power event notification event
+        // bManualReset=TRUE, bInitialState=FALSE
+        gThreadInfo.hEventPowerEvent = CreateEvent(NULL, TRUE, FALSE, 
                                                    TEXT("afsd_flushvol_EventPowerEvent"));
         if ( GetLastError() == ERROR_ALREADY_EXISTS )
             afsi_log("Event Object Already Exists: %s", eventName);
-               if (gThreadInfo.hEventPowerEvent == NULL)
-                       break;                  
+        if (gThreadInfo.hEventPowerEvent == NULL)
+            break;                     
 
-               // create mainline resume event
-               // bManualReset=FALSE, bInitialState=FALSE
-               gThreadInfo.hEventResumeMain = CreateEvent(NULL, FALSE, FALSE, 
+        // create mainline resume event
+        // bManualReset=FALSE, bInitialState=FALSE
+        gThreadInfo.hEventResumeMain = CreateEvent(NULL, FALSE, FALSE, 
                                                    TEXT("afsd_flushvol_EventResumeMain"));
         if ( GetLastError() == ERROR_ALREADY_EXISTS )
             afsi_log("Event Object Already Exists: %s", eventName);
-               if (gThreadInfo.hEventResumeMain == NULL)
-                       break;                  
+        if (gThreadInfo.hEventResumeMain == NULL)
+            break;                     
 
-               // create thread terminate event
-               // bManualReset=FALSE, bInitialState=FALSE
-               gThreadInfo.hEventTerminate = CreateEvent(NULL, FALSE, FALSE, 
+        // create thread terminate event
+        // bManualReset=FALSE, bInitialState=FALSE
+        gThreadInfo.hEventTerminate = CreateEvent(NULL, FALSE, FALSE, 
                                                   TEXT("afsd_flushvol_EventTerminate"));
         if ( GetLastError() == ERROR_ALREADY_EXISTS )
             afsi_log("Event Object Already Exists: %s", eventName);
-               if (gThreadInfo.hEventTerminate == NULL)
-                       break;                  
-
-               // good so far - create thread
-               gThreadHandle = CreateThread(NULL, 0,
-                                                       afsd_ServiceFlushVolumesThreadProc,
-                                                       (LPVOID) &gThreadInfo,
-                                                       0, &dwThreadId);
+        if (gThreadInfo.hEventTerminate == NULL)
+            break;                     
+
+        // good so far - create thread
+        gThreadHandle = CreateThread(NULL, 0,
+                                     afsd_ServiceFlushVolumesThreadProc,
+                                     (LPVOID) &gThreadInfo,
+                                     0, &dwThreadId);
                
-               if (!gThreadHandle)
-                       break;
+        if (!gThreadHandle)
+            break;
 
-               bSuccess = TRUE;
+        bSuccess = TRUE;
 
-       } while (0);
+    } while (0);
 
 
-       if (!bSuccess)
-       {
-               CheckAndCloseHandle(gThreadInfo.hEventPowerEvent);
-               CheckAndCloseHandle(gThreadInfo.hEventResumeMain);
-               CheckAndCloseHandle(gThreadInfo.hEventTerminate);
-               CheckAndCloseHandle(gThreadHandle);
-       }
+    if (!bSuccess)
+    {
+        CheckAndCloseHandle(gThreadInfo.hEventPowerEvent);
+        CheckAndCloseHandle(gThreadInfo.hEventResumeMain);
+        CheckAndCloseHandle(gThreadInfo.hEventTerminate);
+        CheckAndCloseHandle(gThreadHandle);
+    }
                
-       return bSuccess;
+    return bSuccess;
 }
 
 //
@@ -464,21 +472,21 @@ PowerNotificationThreadCreate()
 BOOL
 PowerNotificationThreadNotify()
 {
-       DWORD           dwRet = 0;
-       BOOL            bRet  = FALSE;
+    DWORD              dwRet = 0;
+    BOOL               bRet  = FALSE;
 
-       // Notify thread of power event, and wait for the HardDead timeout period
-       dwRet = SignalObjectAndWait(
-                               gThreadInfo.hEventPowerEvent,   // object to signal
-                               gThreadInfo.hEventResumeMain,   // object to watch
-                               HardDeadtimeout*1000,                   // timeout (ms)
-                               FALSE                                                   // alertable
-                               );
+    // Notify thread of power event, and wait for the HardDead timeout period
+    dwRet = SignalObjectAndWait(
+                gThreadInfo.hEventPowerEvent,  // object to signal
+                gThreadInfo.hEventResumeMain,  // object to watch
+               HardDeadtimeout*1000,           // timeout (ms)
+               FALSE                           // alertable
+               );
 
-       if (dwRet == WAIT_OBJECT_0)
-               bRet = TRUE;
+    if (dwRet == WAIT_OBJECT_0)
+        bRet = TRUE;
 
-       return bRet;
+    return bRet;
 }
 
 //
@@ -487,12 +495,12 @@ PowerNotificationThreadNotify()
 VOID
 PowerNotificationThreadExit()
 {
-       // ExitThread
-       if (gThreadHandle)
-       {
-               SetEvent(gThreadInfo.hEventTerminate);
+    // ExitThread
+    if (gThreadHandle)
+    {
+        SetEvent(gThreadInfo.hEventTerminate);
         WaitForSingleObject(gThreadHandle, INFINITE);
-               CloseHandle(gThreadHandle);
-       }
+        CloseHandle(gThreadHandle);
+    }
 }
 
index 0517ede..c69da65 100644 (file)
@@ -32,7 +32,8 @@
 // The following is defined if you want to receive Power notifications,
 // including Hibernation, and also subsequent flushing of AFS volumes
 //
-#define REGISTER_POWER_NOTIFICATIONS
+#define REGISTER_POWER_NOTIFICATIONS 1
+#define FLUSH_VOLUME                 1
 //
 // Check
 */
@@ -59,26 +60,26 @@ extern HANDLE afsi_file;
  */
 static void afsd_notifier(char *msgp, char *filep, long line)
 {
-       char tbuffer[512];
-       char *ptbuf[1];
-       HANDLE h;
+    char tbuffer[512];
+    char *ptbuf[1];
+    HANDLE h;
 
-       if (filep)
-               sprintf(tbuffer, "Error at file %s, line %d: %s",
-                       filep, line, msgp);
-       else
-               sprintf(tbuffer, "Error at unknown location: %s", msgp);
+    if (filep)
+        sprintf(tbuffer, "Error at file %s, line %d: %s",
+                 filep, line, msgp);
+    else
+        sprintf(tbuffer, "Error at unknown location: %s", msgp);
 
-       h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
-       ptbuf[0] = tbuffer;
-       ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, line, NULL, 1, 0, ptbuf, NULL);
-       DeregisterEventSource(h);
+    h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
+    ptbuf[0] = tbuffer;
+    ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, line, NULL, 1, 0, ptbuf, NULL);
+    DeregisterEventSource(h);
 
-       GlobalStatus = line;
+    GlobalStatus = line;
 
-       osi_LogEnable(afsd_logp);
+    osi_LogEnable(afsd_logp);
 
-       afsd_ForceTrace(TRUE);
+    afsd_ForceTrace(TRUE);
 
     afsi_log("--- begin dump ---");
     cm_DumpSCache(afsi_file, "a");
@@ -91,14 +92,14 @@ static void afsd_notifier(char *msgp, char *filep, long line)
     
     DebugBreak();      
 
-       SetEvent(WaitToTerminate);
+    SetEvent(WaitToTerminate);
 
 #ifdef JUMP
-       if (GetCurrentThreadId() == MainThreadId)
-               longjmp(notifier_jmp, 1);
-       else
+    if (GetCurrentThreadId() == MainThreadId)
+        longjmp(notifier_jmp, 1);
+    else
 #endif /* JUMP */
-               ExitThread(1);
+        ExitThread(1);
 }
 
 /*
@@ -106,7 +107,7 @@ static void afsd_notifier(char *msgp, char *filep, long line)
  */
 static int _stdcall DummyMessageBox(HWND h, LPCTSTR l1, LPCTSTR l2, UINT ui)
 {
-       return 0;
+    return 0;
 }
 
 static SERVICE_STATUS          ServiceStatus;
@@ -130,7 +131,6 @@ afsd_ServiceFlushVolume(DWORD dwlpEventData)
     {
         dwRet = NO_ERROR;
     }
-
     else
     {
         /* flush was unsuccessful, or timeout - deny shutdown */
@@ -151,53 +151,53 @@ afsd_ServiceFlushVolume(DWORD dwlpEventData)
 VOID WINAPI 
 afsd_ServiceControlHandler(DWORD ctrlCode)
 {
-       HKEY parmKey;
-       DWORD dummyLen, doTrace;
-       long code;
-
-       switch (ctrlCode) {
-               case SERVICE_CONTROL_STOP:
-                       /* Shutdown RPC */
-                       RpcMgmtStopServerListening(NULL);
-
-                       /* Force trace if requested */
-                       code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                                           AFSConfigKeyName,
-                                           0, KEY_QUERY_VALUE, &parmKey);
-                       if (code != ERROR_SUCCESS)
-                               goto doneTrace;
-
-                       dummyLen = sizeof(doTrace);
-                       code = RegQueryValueEx(parmKey, "TraceOnShutdown",
-                                               NULL, NULL,
-                                               (BYTE *) &doTrace, &dummyLen);
-                       RegCloseKey (parmKey);
-                       if (code != ERROR_SUCCESS)
-                               doTrace = 0;
-                       if (doTrace)
-                               afsd_ForceTrace(FALSE);
-
-doneTrace:
-                       ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
-                       ServiceStatus.dwWin32ExitCode = NO_ERROR;
-                       ServiceStatus.dwCheckPoint = 1;
-                       ServiceStatus.dwWaitHint = 10000;
-                       ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
-                       SetServiceStatus(StatusHandle, &ServiceStatus);
-                       SetEvent(WaitToTerminate);
-                       break;
-               case SERVICE_CONTROL_INTERROGATE:
-                       ServiceStatus.dwCurrentState = SERVICE_RUNNING;
-                       ServiceStatus.dwWin32ExitCode = NO_ERROR;
-                       ServiceStatus.dwCheckPoint = 0;
-                       ServiceStatus.dwWaitHint = 0;
-                       ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
-                       SetServiceStatus(StatusHandle, &ServiceStatus);
-                       break;
-               /* XXX handle system shutdown */
-               /* XXX handle pause & continue */
-       }
-}
+    HKEY parmKey;
+    DWORD dummyLen, doTrace;
+    long code;
+
+    switch (ctrlCode) {
+    case SERVICE_CONTROL_STOP:
+        /* Shutdown RPC */
+        RpcMgmtStopServerListening(NULL);
+
+        /* Force trace if requested */
+        code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                             AFSConfigKeyName,
+                             0, KEY_QUERY_VALUE, &parmKey);
+        if (code != ERROR_SUCCESS)
+            goto doneTrace;
+
+        dummyLen = sizeof(doTrace);
+        code = RegQueryValueEx(parmKey, "TraceOnShutdown",
+                                NULL, NULL,
+                                (BYTE *) &doTrace, &dummyLen);
+        RegCloseKey (parmKey);
+        if (code != ERROR_SUCCESS)
+            doTrace = 0;
+        if (doTrace)
+            afsd_ForceTrace(FALSE);
+
+      doneTrace:
+        ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
+        ServiceStatus.dwWin32ExitCode = NO_ERROR;
+        ServiceStatus.dwCheckPoint = 1;
+        ServiceStatus.dwWaitHint = 10000;
+        ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
+        SetServiceStatus(StatusHandle, &ServiceStatus);
+        SetEvent(WaitToTerminate);
+        break;
+    case SERVICE_CONTROL_INTERROGATE:
+        ServiceStatus.dwCurrentState = SERVICE_RUNNING;
+        ServiceStatus.dwWin32ExitCode = NO_ERROR;
+        ServiceStatus.dwCheckPoint = 0;
+        ServiceStatus.dwWaitHint = 0;
+        ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
+        SetServiceStatus(StatusHandle, &ServiceStatus);
+        break;
+        /* XXX handle system shutdown */
+        /* XXX handle pause & continue */
+    }
+}       
 
 
 /*
@@ -212,12 +212,12 @@ afsd_ServiceControlHandlerEx(
               LPVOID lpContext
               )
 {
-       HKEY parmKey;
-       DWORD dummyLen, doTrace;
-       long code;
+    HKEY parmKey;
+    DWORD dummyLen, doTrace;
+    long code;
     DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
 
-       switch (ctrlCode) 
+    switch (ctrlCode) 
     {
     case SERVICE_CONTROL_STOP:
         /* Shutdown RPC */
@@ -261,45 +261,45 @@ afsd_ServiceControlHandlerEx(
         dwRet = NO_ERROR;
         break;
 
-               /* XXX handle system shutdown */
-               /* XXX handle pause & continue */
-               case SERVICE_CONTROL_POWEREVENT:                                              
-               {                                                                                     
-                       /*                                                                                
+        /* XXX handle system shutdown */
+        /* XXX handle pause & continue */
+    case 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                                     
-                       */                                                                                
-                       switch((int) dwEventType)                                                         
+            ** 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                                     
+            */                                                                                
+            switch((int) dwEventType)                                                         
             {                                                                               
-                       case PBT_APMQUERYSUSPEND:                                                         
-                       case PBT_APMQUERYSTANDBY:                                                         
-                                                                                            
-#ifdef REGISTER_POWER_NOTIFICATIONS                                                                  
-                               /* handle event */                                                            
-                               dwRet = afsd_ServiceFlushVolume((DWORD) lpEventData);                         
+            case PBT_APMQUERYSUSPEND:                                                         
+            case PBT_APMQUERYSTANDBY:                                                         
+
+#ifdef FLUSH_VOLUME
+                /* handle event */                                                            
+                dwRet = afsd_ServiceFlushVolume((DWORD) lpEventData);                         
 #else                                                                                       
-                               dwRet = NO_ERROR;                                                             
+                dwRet = NO_ERROR;                                                             
 #endif                                                                                      
-                               break;                                                                        
+                break;                                                                        
                                                                                                                          
-            /* allow remaining case PBT_WhatEver */                                           
-                       case PBT_APMSUSPEND:                                                              
-                       case PBT_APMSTANDBY:                                                              
-                       case PBT_APMRESUMECRITICAL:                                                       
-                       case PBT_APMRESUMESUSPEND:                                                        
-                       case PBT_APMRESUMESTANDBY:                                                        
-                       case PBT_APMBATTERYLOW:                                                           
-                       case PBT_APMPOWERSTATUSCHANGE:                                                    
-                       case PBT_APMOEMEVENT:                                                             
-                       case PBT_APMRESUMEAUTOMATIC:                                                      
-                       default:                                                                          
-                               dwRet = NO_ERROR;                                                             
-            }
+                /* allow remaining case PBT_WhatEver */                                           
+            case PBT_APMSUSPEND:                                                              
+            case PBT_APMSTANDBY:                                                              
+            case PBT_APMRESUMECRITICAL:                                                       
+            case PBT_APMRESUMESUSPEND:                                                        
+            case PBT_APMRESUMESTANDBY:                                                        
+            case PBT_APMBATTERYLOW:                                                           
+            case PBT_APMPOWERSTATUSCHANGE:                                                    
+            case PBT_APMOEMEVENT:                                                             
+            case PBT_APMRESUMEAUTOMATIC:                                                      
+            default:                                                                          
+                dwRet = NO_ERROR;                                                             
+            }   
         }
     }          /* end switch(ctrlCode) */                                                        
-       return dwRet;   
+    return dwRet;   
 }
 
 /* There is similar code in client_config\drivemap.cpp GlobalMountDrive()
@@ -323,8 +323,8 @@ static void MountGlobalDrives()
 
     sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSConfigKeyName);
 
-       dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
-       if (dwResult != ERROR_SUCCESS)
+    dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
+    if (dwResult != ERROR_SUCCESS)
         return;
 
     while (dwRetry < MAX_RETRIES) {
@@ -385,8 +385,8 @@ static void DismountGlobalDrives()
 
     sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSConfigKeyName);
 
-       dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
-       if (dwResult != ERROR_SUCCESS)
+    dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
+    if (dwResult != ERROR_SUCCESS)
         return;
 
     while (1) {
@@ -428,10 +428,10 @@ RegisterServiceCtrlHandlerFunc   pRegisterServiceCtrlHandler   = NULL;
 
 void afsd_Main(DWORD argc, LPTSTR *argv)
 {
-       long code;
-       char *reason;
+    long code;
+    char *reason;
 #ifdef JUMP
-       int jmpret;
+    int jmpret;
 #endif /* JUMP */
     HANDLE hInitHookDll;
     HANDLE hAdvApi32;
@@ -443,13 +443,13 @@ void afsd_Main(DWORD argc, LPTSTR *argv)
 #endif 
 
     osi_InitPanic(afsd_notifier);
-       osi_InitTraceOption();
+    osi_InitTraceOption();
 
-       GlobalStatus = 0;
+    GlobalStatus = 0;
 
-       afsi_start();
+    afsi_start();
 
-       WaitToTerminate = CreateEvent(NULL, TRUE, FALSE, TEXT("afsd_service_WaitToTerminate"));
+    WaitToTerminate = CreateEvent(NULL, TRUE, FALSE, TEXT("afsd_service_WaitToTerminate"));
     if ( GetLastError() == ERROR_ALREADY_EXISTS )
         afsi_log("Event Object Already Exists: %s", TEXT("afsd_service_WaitToTerminate"));
 
@@ -472,15 +472,15 @@ void afsd_Main(DWORD argc, LPTSTR *argv)
         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 = 30000;
+    ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+    ServiceStatus.dwServiceSpecificExitCode = 0;
+    ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
+    ServiceStatus.dwWin32ExitCode = NO_ERROR;
+    ServiceStatus.dwCheckPoint = 1;
+    ServiceStatus.dwWaitHint = 30000;
     /* accept Power Events */
-       ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_POWEREVENT;
-       SetServiceStatus(StatusHandle, &ServiceStatus);
+    ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_POWEREVENT;
+    SetServiceStatus(StatusHandle, &ServiceStatus);
 #endif
 
     {       
@@ -538,15 +538,15 @@ void afsd_Main(DWORD argc, LPTSTR *argv)
 
 #ifdef JUMP
     MainThreadId = GetCurrentThreadId();
-       jmpret = setjmp(notifier_jmp);
+    jmpret = setjmp(notifier_jmp);
 
-       if (jmpret == 0) 
+    if (jmpret == 0) 
 #endif /* JUMP */
     {
-               code = afsd_InitCM(&reason);
-               if (code != 0) {
+        code = afsd_InitCM(&reason);
+        if (code != 0) {
             afsi_log("afsd_InitCM failed: %s (code = %d)", reason, code);
-                       osi_panic(reason, __FILE__, __LINE__);
+            osi_panic(reason, __FILE__, __LINE__);
         }
 
 #ifndef NOTSERVICE
@@ -554,8 +554,8 @@ void afsd_Main(DWORD argc, LPTSTR *argv)
         ServiceStatus.dwWaitHint -= 5000;
         SetServiceStatus(StatusHandle, &ServiceStatus);
 #endif
-               code = afsd_InitDaemons(&reason);
-               if (code != 0) {
+        code = afsd_InitDaemons(&reason);
+        if (code != 0) {
             afsi_log("afsd_InitDaemons failed: %s (code = %d)", reason, code);
                        osi_panic(reason, __FILE__, __LINE__);
         }
@@ -565,42 +565,42 @@ void afsd_Main(DWORD argc, LPTSTR *argv)
         ServiceStatus.dwWaitHint -= 5000;
         SetServiceStatus(StatusHandle, &ServiceStatus);
 #endif
-               code = afsd_InitSMB(&reason, MessageBox);
-               if (code != 0) {
+        code = afsd_InitSMB(&reason, MessageBox);
+        if (code != 0) {
             afsi_log("afsd_InitSMB failed: %s (code = %d)", reason, code);
-                       osi_panic(reason, __FILE__, __LINE__);
+            osi_panic(reason, __FILE__, __LINE__);
         }
 
         MountGlobalDrives();
 
 #ifndef NOTSERVICE
-               ServiceStatus.dwCurrentState = SERVICE_RUNNING;
-               ServiceStatus.dwWin32ExitCode = NO_ERROR;
-               ServiceStatus.dwCheckPoint = 0;
-               ServiceStatus.dwWaitHint = 0;
+        ServiceStatus.dwCurrentState = SERVICE_RUNNING;
+        ServiceStatus.dwWin32ExitCode = NO_ERROR;
+        ServiceStatus.dwCheckPoint = 0;
+        ServiceStatus.dwWaitHint = 0;
 
         /* accept Power events */
-               ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_POWEREVENT;
-               SetServiceStatus(StatusHandle, &ServiceStatus);
-#endif
+        ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_POWEREVENT;
+        SetServiceStatus(StatusHandle, &ServiceStatus);
+#endif  
         {
            HANDLE h; char *ptbuf[1];
-               h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
-               ptbuf[0] = "AFS running";
-               ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
-               DeregisterEventSource(h);
+            h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
+            ptbuf[0] = "AFS running";
+            ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
+            DeregisterEventSource(h);
         }
-       }
+    }
 
-       WaitForSingleObject(WaitToTerminate, INFINITE);
+    WaitForSingleObject(WaitToTerminate, INFINITE);
 
     {   
-    HANDLE h; char *ptbuf[1];
+        HANDLE h; char *ptbuf[1];
        h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
        ptbuf[0] = "AFS quitting";
        ReportEvent(h, GlobalStatus ? EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE,
                 0, 0, NULL, 1, 0, ptbuf, NULL);
-    DeregisterEventSource(h);
+        DeregisterEventSource(h);
     }
 
     DismountGlobalDrives();
@@ -608,20 +608,20 @@ void afsd_Main(DWORD argc, LPTSTR *argv)
     rx_Finalize();
 
 #ifdef REGISTER_POWER_NOTIFICATIONS
-       /* terminate thread used to flush cache */
-       PowerNotificationThreadExit();
+    /* terminate thread used to flush cache */
+    PowerNotificationThreadExit();
 #endif
 
     /* Remove the ExceptionFilter */
     SetUnhandledExceptionFilter(NULL);
 
     ServiceStatus.dwCurrentState = SERVICE_STOPPED;
-       ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
-       ServiceStatus.dwCheckPoint = 0;
-       ServiceStatus.dwWaitHint = 0;
-       ServiceStatus.dwControlsAccepted = 0;
-       SetServiceStatus(StatusHandle, &ServiceStatus);
-}
+    ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
+    ServiceStatus.dwCheckPoint = 0;
+    ServiceStatus.dwWaitHint = 0;
+    ServiceStatus.dwControlsAccepted = 0;
+    SetServiceStatus(StatusHandle, &ServiceStatus);
+}       
 
 DWORD __stdcall afsdMain_thread(void* notUsed)
 {
@@ -633,15 +633,15 @@ DWORD __stdcall afsdMain_thread(void* notUsed)
 int
 main(void)
 {
-       static SERVICE_TABLE_ENTRY dispatchTable[] = {
-               {AFS_DAEMON_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) afsd_Main},
-               {NULL, NULL}
-       };
+    static SERVICE_TABLE_ENTRY dispatchTable[] = {
+        {AFS_DAEMON_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) afsd_Main},
+        {NULL, NULL}
+    };
 
-       if (!StartServiceCtrlDispatcher(dispatchTable))
+    if (!StartServiceCtrlDispatcher(dispatchTable))
     {
         LONG status = GetLastError();
-           if (status == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
+        if (status == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
         {
             DWORD tid;
             hAFSDMainThread = CreateThread(NULL, 0, afsdMain_thread, 0, 0, &tid);
index d704ada..5cdc27b 100644 (file)
@@ -394,6 +394,35 @@ extern "C" lana_number_t lana_FindLoopback(void)
     return LANA_INVALID;
 }
 
+/* Returns TRUE if all adapters are loopback adapters */
+extern "C" BOOL lana_OnlyLoopback(void)
+{
+    NCB ncb;
+    LANA_ENUM lana_list;
+    int status;
+    int i;
+
+    memset(&ncb, 0, sizeof(ncb));
+    ncb.ncb_command = NCBENUM;
+    ncb.ncb_buffer = (UCHAR *) &lana_list;
+    ncb.ncb_length = sizeof(lana_list);
+    status = Netbios(&ncb);
+    if (status != 0) {
+#ifndef NOLOGGING
+        afsi_log("Netbios NCBENUM failed: status %ld", status);
+#endif
+        return FALSE;
+    }
+    for (i = 0; i < lana_list.length; i++) {
+       if (!lana_IsLoopback(lana_list.lana[i])) {
+           // Found one non-Loopback adapter
+           return FALSE;
+       }
+    }
+    // All adapters are loopback
+    return TRUE;
+}
+
 // Is the given lana a Windows Loopback Adapter?
 // TODO: implement a better check for loopback
 // TODO: also check for proper bindings (IPv4)
index d6ba0ed..22e88e3 100644 (file)
@@ -59,6 +59,8 @@ extern "C" {
 
   lana_number_t lana_FindLoopback(void);
 
+  BOOL lana_OnlyLoopback(void);
+
   BOOL lana_IsLoopback(lana_number_t lana);
 
   long lana_GetUncServerNameEx(char *buffer, lana_number_t * pLana, int * pIsGateway, int flags);