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