mirror of
https://git.openafs.org/openafs.git
synced 2025-01-20 16:00:12 +00:00
win-power-mgmt-flush-test-20041003
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.
This commit is contained in:
parent
3f2e943d43
commit
2469663d0d
@ -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;
|
||||
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;
|
||||
}
|
||||
if ( lana_OnlyLoopback() ) {
|
||||
// Nothing to do if we only have a loopback interface
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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();
|
||||
// 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
// 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();
|
||||
|
||||
// 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;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
// 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;
|
||||
|
||||
dwFlushEnd = GetTickCount();
|
||||
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;
|
||||
}
|
||||
|
||||
// display total volume count in Event Logger
|
||||
sprintf(bufMessage, "%d", dwTotalVols);
|
||||
LogTimingEvent(MSG_TIME_FLUSH_TOTAL, bufMessage,
|
||||
dwFlushEnd - dwFlushBegin);
|
||||
dwFlushEnd = GetTickCount();
|
||||
|
||||
return TRUE;
|
||||
// display total volume count in Event Logger
|
||||
sprintf(bufMessage, "%d", dwTotalVols);
|
||||
LogTimingEvent(MSG_TIME_FLUSH_TOTAL, bufMessage,
|
||||
dwFlushEnd - dwFlushBegin);
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
// 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;
|
||||
// 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);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
//
|
||||
// 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;
|
||||
// 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,66 +325,66 @@ ImpersonateClient()
|
||||
DWORD WINAPI
|
||||
afsd_ServiceFlushVolumesThreadProc(LPVOID lpParam)
|
||||
{
|
||||
FLUSHVOLTHREADINFO ThreadInfo;
|
||||
PFLUSHVOLTHREADINFO pThreadInfo = (PFLUSHVOLTHREADINFO) lpParam;
|
||||
HANDLE arHandles[2] = {0};
|
||||
DWORD dwWaitState = 0;
|
||||
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;
|
||||
// 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;
|
||||
// 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);
|
||||
// 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();
|
||||
switch (dwWaitState)
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
// termination signaled
|
||||
RevertToSelf();
|
||||
CheckAndCloseHandle(ThreadInfo.hEventPowerEvent);
|
||||
CheckAndCloseHandle(ThreadInfo.hEventResumeMain);
|
||||
CheckAndCloseHandle(ThreadInfo.hEventTerminate);
|
||||
ExitThread(0);
|
||||
break;
|
||||
ExitThread(0);
|
||||
break;
|
||||
|
||||
case WAIT_OBJECT_0+1:
|
||||
// Power event
|
||||
// - flush 'em!
|
||||
if (ImpersonateClient())
|
||||
{
|
||||
afsd_ServicePerformFlushVolumes();
|
||||
}
|
||||
// acknowledge event
|
||||
ResetEvent(ThreadInfo.hEventPowerEvent);
|
||||
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;
|
||||
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
|
||||
} // end switch
|
||||
|
||||
// signal back to waiting mainline
|
||||
SetEvent(ThreadInfo.hEventResumeMain);
|
||||
// signal back to waiting mainline
|
||||
SetEvent(ThreadInfo.hEventResumeMain);
|
||||
|
||||
} // end while
|
||||
} // end while
|
||||
|
||||
// I suppose we never get here
|
||||
ExitThread(0);
|
||||
// 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;
|
||||
if (gThreadInfo.hEventTerminate == NULL)
|
||||
break;
|
||||
|
||||
// good so far - create thread
|
||||
gThreadHandle = CreateThread(NULL, 0,
|
||||
afsd_ServiceFlushVolumesThreadProc,
|
||||
(LPVOID) &gThreadInfo,
|
||||
0, &dwThreadId);
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,52 +151,52 @@ afsd_ServiceFlushVolume(DWORD dwlpEventData)
|
||||
VOID WINAPI
|
||||
afsd_ServiceControlHandler(DWORD ctrlCode)
|
||||
{
|
||||
HKEY parmKey;
|
||||
DWORD dummyLen, doTrace;
|
||||
long code;
|
||||
HKEY parmKey;
|
||||
DWORD dummyLen, doTrace;
|
||||
long code;
|
||||
|
||||
switch (ctrlCode) {
|
||||
case SERVICE_CONTROL_STOP:
|
||||
/* Shutdown RPC */
|
||||
RpcMgmtStopServerListening(NULL);
|
||||
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;
|
||||
/* 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);
|
||||
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 */
|
||||
}
|
||||
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:
|
||||
case PBT_APMQUERYSUSPEND:
|
||||
case PBT_APMQUERYSTANDBY:
|
||||
|
||||
#ifdef REGISTER_POWER_NOTIFICATIONS
|
||||
/* handle event */
|
||||
dwRet = afsd_ServiceFlushVolume((DWORD) lpEventData);
|
||||
#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);
|
||||
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,19 +608,19 @@ 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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user