windows-nt/Source/XPSP1/NT/mergedcomponents/wlnotify/schedlog.cxx
2020-09-26 16:20:57 +08:00

187 lines
4.5 KiB
C++

//+----------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: schedlog.c
//
// Contents: Task Scheduler StartShell notification
//
// Classes: None.
//
// Functions:
// SchedStartShell - queue the work to the WinLogon thread pool.
// DoSchedStartShell - notify Sched service that a user logged on.
//
// History: 07-Mar-01 JBenton Created
//
//-----------------------------------------------------------------------------
//
// Note: We don't build/publish a lib here as suggested in wlnotify.cxx.
// Rather we include the source file here because there is only a single
// simple function.
//
// Note: We are using the StartShell event because the Scheduler service
// expects the user's explorer session to be running.
//
#include <windows.h>
#include <winwlx.h>
#define SCHED_SERVICE_NAME TEXT("Schedule")
//
// The following LOGON and LOGOFF defines must be kept in sync with
// the definition in %sdxroot%\admin\services\sched\inc\common.hxx
//
#define SERVICE_CONTROL_USER_LOGON 128
#define SERVICE_CONTROL_USER_LOGOFF 133
DWORD WINAPI SchedStartShell(LPVOID lpvParam);
DWORD WINAPI DoSchedStartShell(LPVOID lpvParam);
DWORD WINAPI
SchedEventLogOff(LPVOID lpvParam)
//
//
// Routine Description:
//
// Send a logoff notification to the Task Scheduler service
// via a user defined Service Control.
//
// Arguments:
//
// lpvParam - Winlogon notification info (unused as of yet)
//
// Return Value:
//
// Extended error status from Service control functions.
//
{
DWORD status = ERROR_SUCCESS;
SC_HANDLE hSC = NULL;
SC_HANDLE hSvc = NULL;
BOOL bSucceeded = FALSE;
SERVICE_STATUS ServiceStatus;
hSC = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (hSC == NULL)
{
return GetLastError();
}
hSvc = OpenService(hSC, SCHED_SERVICE_NAME,
SERVICE_USER_DEFINED_CONTROL);
if (hSvc == NULL)
{
CloseServiceHandle(hSC);
return GetLastError();
}
bSucceeded = ControlService(hSvc,
SERVICE_CONTROL_USER_LOGOFF,
&ServiceStatus);
if( !bSucceeded )
{
status = GetLastError();
}
CloseServiceHandle(hSvc);
CloseServiceHandle(hSC);
return status;
}
DWORD WINAPI
SchedStartShell(LPVOID lpvParam)
{
DWORD dwSessionId = 0;
//
// Don't send logon notification to Terminal Server sessions.
//
if (ProcessIdToSessionId(GetCurrentProcessId(), &dwSessionId) &&
(dwSessionId == 0))
{
//
// Queue the work to the thread pool since we may
// be looping on the notification.
//
QueueUserWorkItem(DoSchedStartShell, lpvParam, WT_EXECUTELONGFUNCTION);
}
return GetLastError();
}
DWORD WINAPI
DoSchedStartShell(LPVOID lpvParam)
//
//
// Routine Description:
//
// Send a logon notification to the Task Scheduler service
// via a user defined Service Control.
//
// Arguments:
//
// lpvParam - Winlogon notification info (unused as of yet)
//
// Return Value:
//
// Extended error status from Service control functions.
//
{
DWORD status = ERROR_SUCCESS;
PWLX_NOTIFICATION_INFO pTempInfo = (PWLX_NOTIFICATION_INFO) lpvParam;
SC_HANDLE hSC = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (hSC == NULL)
{
return GetLastError();
}
SC_HANDLE hSvc = OpenService(hSC, SCHED_SERVICE_NAME,
SERVICE_USER_DEFINED_CONTROL);
if (hSvc == NULL)
{
CloseServiceHandle(hSC);
return GetLastError();
}
BOOL fSucceeded;
const int NOTIFY_RETRIES = 20;
const DWORD NOTIFY_SLEEP = 4000;
//
// Use a retry loop to notify the service. This is done
// because, if the user logs in quickly, the service may not
// be started when the shell runs this instance.
//
for (int i = 1; ; i++)
{
SERVICE_STATUS Status;
fSucceeded = ControlService(hSvc,
SERVICE_CONTROL_USER_LOGON,
&Status);
if (fSucceeded)
{
break;
}
if (i >= NOTIFY_RETRIES)
{
status = GetLastError();
break;
}
Sleep(NOTIFY_SLEEP);
}
CloseServiceHandle(hSvc);
CloseServiceHandle(hSC);
return status;
}