windows-nt/Source/XPSP1/NT/admin/services/sched/at/atconv.cxx
2020-09-26 16:20:57 +08:00

260 lines
7.9 KiB
C++

//+----------------------------------------------------------------------------
//
// Scheduling Agent Service
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996.
//
// File: atconv.cxx
//
// Classes: None.
//
// Functions: ConvertAtJobsToTasks
//
// History: 13-Jun-96 EricB Created.
//
//-----------------------------------------------------------------------------
#include "..\pch\headers.hxx"
#pragma hdrstop
#include <sch_cls.hxx>
#include <job_cls.hxx>
#include "..\inc\debug.hxx"
//
// The constants and types below taken from net\svcdlls\at\server\at.h
//
#define AT_REGISTRY_PATH L"System\\CurrentControlSet\\Services\\Schedule"
#define AT_SCHEDULE_NAME L"Schedule"
#define AT_COMMAND_NAME L"Command"
#define MAXIMUM_COMMAND_LENGTH (MAX_PATH - 1) // == 259, cmd.exe uses this
#define MAXIMUM_JOB_TIME (24 * 60 * 60 * 1000 - 1)
#define DAYS_OF_WEEK 0x7F // 7 bits for 7 days
#define DAYS_OF_MONTH 0x7FFFFFFF // 31 bits for 31 days
#define AT_KEY_BUF_LEN 20 // 9 would suffice, but this is safer
typedef struct _AT_SCHEDULE {
DWORD JobTime; // time of day to run, in seconds from midnight
DWORD DaysOfMonth; // bitmask for days of month to run
UCHAR DaysOfWeek; // bitmask for days of week to run
UCHAR Flags; // see lmat.h
WORD Reserved; // padding, since registry pads them as well
} AT_SCHEDULE;
//+----------------------------------------------------------------------------
//
// Function: ConvertAtJobsToTasks
//
// Synopsis: At setup time, read the AT service jobs out of the registry
// and convert them to Scheduling Agent Tasks.
//
//-----------------------------------------------------------------------------
STDAPI_(void)
ConvertAtJobsToTasks(void)
{
struct KEYNAME {
KEYNAME * pNext;
WCHAR wszName[AT_KEY_BUF_LEN];
};
CSchedule * pSch = new CSchedule;
if (pSch == NULL)
{
ERR_OUT("ConvertAtJobsToTasks, new pSch", E_OUTOFMEMORY);
return;
}
HRESULT hr = pSch->Init();
if (FAILED(hr))
{
pSch->Release();
ERR_OUT("ConvertAtJobsToTasks, pSch->Init", hr);
return;
}
HKEY hKeySvc, hKey;
DWORD index;
WCHAR wszNameBuffer[AT_KEY_BUF_LEN];
FILETIME lastWriteTime;
WCHAR wszCommand[MAXIMUM_COMMAND_LENGTH + 1];
AT_SCHEDULE Schedule;
DWORD Length;
DWORD type;
DWORD NameSize;
DWORD CommandSize;
KEYNAME * pDeleteList = NULL;
long lRet;
//
// Open the AT service registry tree.
//
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
AT_REGISTRY_PATH,
0,
KEY_READ,
&hKeySvc);
if (lRet != ERROR_SUCCESS)
{
ERR_OUT("ConvertAtJobsToTasks: open hKeySvc", lRet);
pSch->Release();
return;
}
for (index = 0; ; index++)
{
//
// Regedit can sometimes display other keys in addition to keys
// found here. Also, it often fails to display last character in
// the Command and after a refresh it may not display some of the
// spurious keys.
//
Length = sizeof(wszNameBuffer) / sizeof(wszNameBuffer[0]);
lRet = RegEnumKeyEx(hKeySvc,
index,
wszNameBuffer, // lpName
&Length, // lpcbName
0, // lpReserved
NULL, // lpClass
NULL, // lpcbClass
&lastWriteTime);
if (lRet != ERROR_SUCCESS)
{
if (lRet != ERROR_NO_MORE_ITEMS)
{
ERR_OUT("ConvertAtJobsToTasks: RegEnumKeyEx", lRet);
}
//
// The only exit point from this loop
//
break;
}
//
// Length returned is the number of characters in a UNICODE string
// representing the key name (not counting the terminating NULL
// character which is also supplied).
//
NameSize = (Length + 1) * sizeof(WCHAR);
lRet = RegOpenKeyEx(hKeySvc,
wszNameBuffer,
0,
KEY_READ,
&hKey);
if (lRet != ERROR_SUCCESS)
{
ERR_OUT("ConvertAtJobsToTasks: RegOpenKeyEx", lRet);
continue;
}
Length = sizeof(Schedule);
lRet = RegQueryValueEx(hKey,
AT_SCHEDULE_NAME,
NULL,
&type,
(LPBYTE)&Schedule,
&Length);
if (lRet != ERROR_SUCCESS)
{
ERR_OUT("ConvertAtJobsToTasks: RegQueryValueEx(AT_SCHEDULE_NAME)",
lRet);
RegCloseKey(hKey);
continue;
}
if (type != REG_BINARY ||
Length != sizeof(AT_SCHEDULE) ||
(Schedule.DaysOfWeek & ~DAYS_OF_WEEK) != 0 ||
(Schedule.DaysOfMonth & ~DAYS_OF_MONTH) != 0 ||
Schedule.JobTime >= MAXIMUM_JOB_TIME )
{
schDebugOut((DEB_ERROR,"ConvertAtJobsToTasks: RegQueryValueEx invalid data: "
"type=%lu, Length=%lu, DOW=%#x, DOM=%#lx, Time=%lu\n",
type, Length, Schedule.DaysOfWeek, Schedule.DaysOfMonth,
Schedule.JobTime));
RegCloseKey(hKey);
continue;
}
Length = sizeof(wszCommand);
lRet = RegQueryValueEx(hKey,
AT_COMMAND_NAME,
NULL,
&type,
(LPBYTE)wszCommand,
&Length);
RegCloseKey(hKey);
if (lRet != ERROR_SUCCESS)
{
ERR_OUT("ConvertAtJobsToTasks: RegQueryValueEx(AT_COMMAND_NAME)",
lRet);
continue;
}
if (type != REG_SZ)
{
ERR_OUT("ConvertAtJobsToTasks: Command is not of REG_SZ type", 0);
continue;
}
AT_INFO At;
At.Command = wszCommand;
At.JobTime = Schedule.JobTime;
At.DaysOfMonth = Schedule.DaysOfMonth;
At.DaysOfWeek = Schedule.DaysOfWeek;
At.Flags = Schedule.Flags;
hr = pSch->AddAtJob(At, NULL);
if (SUCCEEDED(hr))
{
//
// If the job was successfully converted, then add it to the
// list of jobs to delete from the registry. Don't delete it
// right away, because that would mess up the operation of
// RegEnumKeyEx.
//
KEYNAME * pKey = new KEYNAME;
if (pKey == NULL)
{
ERR_OUT("ConvertAtJobsToTasks: new KEYNAME", GetLastError());
RegDeleteKey(hKeySvc, wszNameBuffer);
break;
}
pKey->pNext = pDeleteList;
pDeleteList = pKey;
wcscpy(pKey->wszName, wszNameBuffer);
}
#if DBG == 1
else
{
ERR_OUT("ConvertAtJobsToTasks: AddAtJob", hr);
}
#endif
}
//
// Delete the reg keys for all jobs that were successfully converted
//
KEYNAME * pNext;
for ( ; pDeleteList != NULL; pDeleteList = pNext)
{
RegDeleteKey(hKeySvc, pDeleteList->wszName);
pNext = pDeleteList->pNext;
delete pDeleteList;
}
RegCloseKey(hKeySvc);
pSch->Release();
return;
}