Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

897 lines
21 KiB

/*++
Copyright (C) 1999 Microsoft Corporation
--*/
#include <windows.h>
#include <comdef.h>
#include <stdio.h>
#include <genlex.h>
#include <qllex.h>
#include <ql.h>
#include "dnf.h"
#include "datep.h"
/******************************************************************/
COrderedUniqueSet64::COrderedUniqueSet64(void)
{
m_BitField = SETEMPTY;
}
COrderedUniqueSet64 COrderedUniqueSet64::Set(ULONGLONG n)
{
m_BitField = n;
return *this;
}
COrderedUniqueSet64 COrderedUniqueSet64::Add(ULONGLONG n)
{
ULONGLONG iBit = SETMIN;
if((n <= 63))
m_BitField |= iBit << n;
return *this;
}
COrderedUniqueSet64 COrderedUniqueSet64::Remove(ULONGLONG n)
{
ULONGLONG iBit = SETMIN;
if((n >= 1) && (n <= 64))
m_BitField &= ~(iBit << n);
return *this;
}
COrderedUniqueSet64 COrderedUniqueSet64::Union(COrderedUniqueSet64 n)
{
m_BitField |= n.m_BitField;
return *this;
}
COrderedUniqueSet64 COrderedUniqueSet64::Intersection(COrderedUniqueSet64 n)
{
m_BitField &= n.m_BitField;
return *this;
}
COrderedUniqueSet64 COrderedUniqueSet64::UpperBound(ULONGLONG n)
{
if((n <= 63))
{
n = 63 - n;
m_BitField = (m_BitField << n) >> n;
}
return *this;
}
COrderedUniqueSet64 COrderedUniqueSet64::LowerBound(ULONGLONG n)
{
if((n <= 63))
m_BitField = (m_BitField >> n) << n;
return *this;
}
COrderedUniqueSet64 COrderedUniqueSet64::Rotate(int n)
{
while(n > 64) n -= 64;
while(n < 0) n += 64;
m_BitField = (m_BitField << n) | (m_BitField >> (64 - n));
return *this;
}
BOOL COrderedUniqueSet64::Member(ULONGLONG n)
{
return ((n <= 63) ? m_BitField & (SETMIN << n) : 0);
}
unsigned COrderedUniqueSet64::Next(ULONGLONG n)
{
ULONGLONG nStart = n;
ULONGLONG
SetValue = SETMIN << n;
if(0x0 == m_BitField)
return -1;
while(! (SetValue & m_BitField))
{
SetValue <<= 1;
n++;
if(SETEMPTY == SetValue)
{
SetValue = SETMIN;
n = 0;
}
}
return (unsigned)n;
}
unsigned COrderedUniqueSet64::Prev(ULONGLONG n)
{
ULONGLONG nStart = n;
ULONGLONG SetValue = SETMIN << n;
if(0x0 == m_BitField)
return -1;
while(! (SetValue & m_BitField))
{
SetValue >>= 1;
n--;
if(SETEMPTY == SetValue)
{
SetValue = SETMAX;
n = 63;
}
}
return (unsigned)n;
}
/******************************************************************/
unsigned CPattern::GetNextValue(unsigned NextValue)
{
unsigned i;
// **** perform quick sanity check
if((m_FieldsUsed & LOWERBOUND) &&
(m_FieldsUsed & UPPERBOUND) &&
(m_UpperBound < m_LowerBound))
return -1;
if(m_FieldsUsed & EQUALTO)
{
if(NextValue > m_EqualTo)
return -1;
else
NextValue = m_EqualTo;
// **** perform sanity checks for equality
if((m_FieldsUsed & LOWERBOUND) &&
(m_EqualTo < m_LowerBound))
return -1;
if((m_FieldsUsed & UPPERBOUND) &&
(m_EqualTo > m_UpperBound))
return -1;
if(m_FieldsUsed & NOTEQUALTO)
{
for(i = 0; i < m_CountNotEqualTo; i++)
if(NextValue == m_NotEqualTo[i])
return -1;
}
}
else
{
if(m_FieldsUsed & LOWERBOUND)
{
if(NextValue < m_LowerBound)
NextValue = m_LowerBound;
}
if(m_FieldsUsed & NOTEQUALTO)
{
int
YearGotBumpedUp = 1;
while(YearGotBumpedUp)
{
YearGotBumpedUp = 0;
for(i = 0; i < m_CountNotEqualTo; i++)
if(NextValue == m_NotEqualTo[i])
{
NextValue += 1;
YearGotBumpedUp = 1;
}
}
}
if(m_FieldsUsed & UPPERBOUND)
{
if(NextValue > m_UpperBound)
return -1;
}
}
return NextValue;
}
/******************************************************************/
// this belongs to CDatePattern but is stuck outside
// of scope because of compiler bug (re: C2334)
wchar_t* m_FieldName[] =
{
L"Year",
L"Month",
L"Day",
L"DayOfWeek",
L"WeekInMonth",
L"Quarter",
L"Hour",
L"Minute",
L"Second"
};
int CDatePattern::FieldIndx(const wchar_t *suName)
{
int
iField;
if(NULL == suName) return -1;
for(iField = INDX_Year;
(iField < INDX_MAX) && wbem_wcsicmp(m_FieldName[iField], suName);
iField++);
if(INDX_MAX == iField) iField = -1;
return iField;
}
HRESULT CDatePattern::AugmentPattern(QL_LEVEL_1_TOKEN *pExp)
{
int
i = pExp->PropertyName.GetNumElements(),
iField = FieldIndx(pExp->PropertyName.GetStringAt(i - 1));
unsigned
j,
testVal;
VARIANT
iValue;
VariantInit(&iValue);
if(-1 == iField)
{
if(wbem_wcsicmp(L"TargetInstance", pExp->PropertyName.GetStringAt(i - 1)))
return WBEM_E_INVALID_PROPERTY;
else
return WBEM_S_NO_ERROR;
}
if(FAILED(VariantChangeType(&iValue, &(pExp->vConstValue), 0x0, VT_I4)))
return WBEM_E_INVALID_QUERY;
switch(pExp->nOperator)
{
case QL_LEVEL_1_TOKEN::OP_EQUAL :
// **** first make sure that value can be in pattern
testVal = m_Pattern[iField].GetNextValue(iValue.lVal);
if(testVal == iValue.lVal)
{
m_Pattern[iField].m_FieldsUsed |= CPattern::EQUALTO;
m_Pattern[iField].m_EqualTo = iValue.lVal;
}
break;
case QL_LEVEL_1_TOKEN::OP_NOT_EQUAL :
m_Pattern[iField].m_FieldsUsed |= CPattern::NOTEQUALTO;
j = m_Pattern[iField].m_CountNotEqualTo;
if(j < 64)
{
m_Pattern[iField].m_NotEqualTo[j] = iValue.lVal;
m_Pattern[iField].m_CountNotEqualTo++;
}
else
{
return WBEM_E_FAILED;
}
break;
case QL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN :
if(! (m_Pattern[iField].m_FieldsUsed & CPattern::LOWERBOUND))
{
m_Pattern[iField].m_LowerBound = 0;
m_Pattern[iField].m_FieldsUsed |= CPattern::LOWERBOUND;
}
if(m_Pattern[iField].m_LowerBound < iValue.lVal)
m_Pattern[iField].m_LowerBound = iValue.lVal;
break;
case QL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN :
if(! (m_Pattern[iField].m_FieldsUsed & CPattern::UPPERBOUND))
{
m_Pattern[iField].m_UpperBound = -1;
m_Pattern[iField].m_FieldsUsed |= CPattern::UPPERBOUND;
}
m_Pattern[iField].m_FieldsUsed |= CPattern::UPPERBOUND;
if(m_Pattern[iField].m_UpperBound > iValue.lVal)
m_Pattern[iField].m_UpperBound = iValue.lVal;
break;
case QL_LEVEL_1_TOKEN::OP_LESSTHAN :
if(! (m_Pattern[iField].m_FieldsUsed & CPattern::UPPERBOUND))
{
m_Pattern[iField].m_UpperBound = -1;
m_Pattern[iField].m_FieldsUsed |= CPattern::UPPERBOUND;
}
m_Pattern[iField].m_FieldsUsed |= CPattern::UPPERBOUND;
if(m_Pattern[iField].m_UpperBound >= iValue.lVal)
m_Pattern[iField].m_UpperBound = iValue.lVal - 1;
break;
case QL_LEVEL_1_TOKEN::OP_GREATERTHAN :
if(! (m_Pattern[iField].m_FieldsUsed & CPattern::LOWERBOUND))
{
m_Pattern[iField].m_LowerBound = 0;
m_Pattern[iField].m_FieldsUsed |= CPattern::LOWERBOUND;
}
m_Pattern[iField].m_FieldsUsed |= CPattern::LOWERBOUND;
if(m_Pattern[iField].m_LowerBound <= iValue.lVal)
m_Pattern[iField].m_LowerBound = iValue.lVal + 1;
break;
case QL_LEVEL_1_TOKEN::OP_LIKE :
default : ;
return WBEM_E_INVALID_QUERY;
}
return WBEM_S_NO_ERROR;
}
HRESULT CDatePattern::BuildSetsFromPatterns(void)
{
// Second
m_Set[INDX_Second].Set(SETFULL);
MapPatternToSet(&m_Pattern[INDX_Second], &m_Set[INDX_Second]);
m_Set[INDX_Second].UpperBound(59);
// Minute
m_Set[INDX_Minute].Set(SETFULL);
MapPatternToSet(&m_Pattern[INDX_Minute], &m_Set[INDX_Minute]);
m_Set[INDX_Minute].UpperBound(59);
// Hour
m_Set[INDX_Hour].Set(SETFULL);
MapPatternToSet(&m_Pattern[INDX_Hour], &m_Set[INDX_Hour]);
m_Set[INDX_Hour].UpperBound(23);
// Quarter
m_Set[INDX_Quarter].Set(SETFULL);
MapPatternToSet(&m_Pattern[INDX_Quarter], &m_Set[INDX_Quarter]);
m_Set[INDX_Quarter].LowerBound(1);
m_Set[INDX_Quarter].UpperBound(4);
// WeekInMonth
m_Set[INDX_WeekInMonth].Set(SETFULL);
MapPatternToSet(&m_Pattern[INDX_WeekInMonth], &m_Set[INDX_WeekInMonth]);
m_Set[INDX_WeekInMonth].LowerBound(1);
m_Set[INDX_WeekInMonth].UpperBound(7);
// DayOfWeek
m_Set[INDX_DayOfWeek].Set(SETFULL);
MapPatternToSet(&m_Pattern[INDX_DayOfWeek], &m_Set[INDX_DayOfWeek]);
m_Set[INDX_DayOfWeek].LowerBound(1);
m_Set[INDX_DayOfWeek].UpperBound(7);
// Day
m_Set[INDX_Day].Set(SETEMPTY);
// Month
m_Set[INDX_Month].Set(SETFULL);
MapPatternToSet(&m_Pattern[INDX_Month], &m_Set[INDX_Month]);
m_Set[INDX_Month].LowerBound(1);
m_Set[INDX_Month].UpperBound(12);
// Year
m_Set[INDX_Year].Set(SETEMPTY);
return WBEM_S_NO_ERROR;
}
HRESULT CDatePattern::MapPatternToSet(CPattern *pPattern, COrderedUniqueSet64 *pSet)
{
unsigned i;
if(pPattern->m_FieldsUsed & CPattern::EQUALTO)
{
pSet->Set(SETEMPTY);
pSet->Add(pPattern->m_EqualTo);
}
else
{
if(pPattern->m_FieldsUsed & CPattern::NOTEQUALTO)
{
for(i = 0; i < pPattern->m_CountNotEqualTo; i++)
pSet->Remove(pPattern->m_NotEqualTo[i]);
}
if(pPattern->m_FieldsUsed & CPattern::UPPERBOUND)
{
pSet->UpperBound(pPattern->m_UpperBound);
}
if(pPattern->m_FieldsUsed & CPattern::LOWERBOUND)
{
pSet->LowerBound(pPattern->m_LowerBound);
}
}
return WBEM_S_NO_ERROR;
}
HRESULT CDatePattern::GetDaysInMonth(WORD iYear, WORD iMonth)
{
ULONGLONG
Time1,
Time2;
int
i, j, k,
DayOfWeek,
DaysInMonth;
SYSTEMTIME
SystemTime;
FILETIME
FileTime1,
FileTime2;
SystemTime.wYear = iYear;
SystemTime.wMonth = iMonth;
SystemTime.wDay = 1;
SystemTime.wHour = 0;
SystemTime.wMinute = 0;
SystemTime.wSecond = 0;
SystemTime.wMilliseconds = 0;
if(m_Set[INDX_Month].Member(iMonth) &&
m_Set[INDX_Quarter].Member(1 + (iMonth - 1) / 3))
{
// **** get DayOfWeek
SystemTimeToFileTime(&SystemTime, &FileTime1);
if(12 == SystemTime.wMonth)
{
SystemTime.wMonth = 1;
SystemTime.wYear++;
}
else
SystemTime.wMonth++;
SystemTimeToFileTime(&SystemTime, &FileTime2);
FileTimeToSystemTime(&FileTime1, &SystemTime);
DayOfWeek = SystemTime.wDayOfWeek; // 0..6
// **** get DaysInMonth
Time1 = FileTime1.dwHighDateTime;
Time1 = (Time1 << 32) + FileTime1.dwLowDateTime;
Time2 = FileTime2.dwHighDateTime;
Time2 = (Time2 << 32) + FileTime2.dwLowDateTime;
DaysInMonth = (int) ((Time2 - Time1) / 864000000000);
// **** get set for DaysInMonth
m_Set[INDX_Day].Set(SETFULL);
m_Set[INDX_Day].LowerBound(1);
m_Set[INDX_Day].UpperBound(DaysInMonth);
MapPatternToSet(&m_Pattern[INDX_Day], &m_Set[INDX_Day]);
// build bitfield from DayOfWeek and WeekInMonth sets
m_Set[INDX_MAX].Set(SETEMPTY);
for(i = 0; i < DaysInMonth; i++)
{
j = (DayOfWeek + i) % 7 + 1; // Day of week
k = (DayOfWeek + i) / 7 + 1; // Week in Month
if(m_Set[INDX_DayOfWeek].Member(j) &&
m_Set[INDX_WeekInMonth].Member(k))
m_Set[INDX_MAX].Add(i + 1);
}
m_Set[INDX_Day].Intersection(m_Set[INDX_MAX]);
}
else
m_Set[INDX_Day].Set(SETEMPTY);
return WBEM_S_NO_ERROR;
}
ULONGLONG CDatePattern::GetNextTime(SYSTEMTIME *pSystemTime)
{
WORD
wCurrValue,
wCurrValue2,
ThresholdYear = 12;
FILETIME
FileTime;
ULONGLONG
NewTime;
/*
Assumptions:
1. ASSUME EACH SET HAS AT LEAST ONE MEMBER EXCEPT 'Day'
2. set values start at 1 but hours, mins and secs start at 0
*/
// **** second
wCurrValue = m_CurrentTime.wSecond + 1;
m_CurrentTime.wSecond = (USHORT) m_Set[INDX_Second].Next(wCurrValue);
if(m_CurrentTime.wSecond < wCurrValue)
{
// **** minute
wCurrValue = m_CurrentTime.wMinute + 1;
m_CurrentTime.wMinute = (USHORT) m_Set[INDX_Minute].Next(wCurrValue);
if(m_CurrentTime.wMinute < wCurrValue)
{
// **** hour
wCurrValue = m_CurrentTime.wHour + 1;
m_CurrentTime.wHour = (USHORT) m_Set[INDX_Hour].Next(wCurrValue);
if(m_CurrentTime.wHour < wCurrValue)
{
// **** day
wCurrValue = m_CurrentTime.wDay + 1;
m_CurrentTime.wDay = (USHORT) m_Set[INDX_Day].Next(wCurrValue);
while((SETEMPTY == m_Set[INDX_Day].m_BitField) ||
(m_CurrentTime.wDay < wCurrValue))
{
// **** Month
wCurrValue2 = m_CurrentTime.wMonth + 1;
m_CurrentTime.wMonth = (USHORT) m_Set[INDX_Month].Next(wCurrValue2);
if(m_CurrentTime.wMonth < wCurrValue2)
{
if(!ThresholdYear--)
return -1;
// **** year
m_CurrentTime.wYear = (USHORT)
m_Pattern[INDX_Year].GetNextValue(m_CurrentTime.wYear + 1);
if((WORD)-1 == m_CurrentTime.wYear)
return -1;
}
GetDaysInMonth(m_CurrentTime.wYear, m_CurrentTime.wMonth);
wCurrValue = 1;
m_CurrentTime.wDay = (USHORT) m_Set[INDX_Day].Next(wCurrValue);
}
}
}
}
SystemTimeToFileTime(&m_CurrentTime, &FileTime);
NewTime = FileTime.dwHighDateTime;
NewTime = (NewTime << 32) + FileTime.dwLowDateTime;
if(NULL != pSystemTime)
*pSystemTime = m_CurrentTime;
return NewTime;
}
ULONGLONG CDatePattern::SetStartTime(SYSTEMTIME StartTime)
{
WORD
wCurrValue,
ThresholdYear = 12;
FILETIME
FileTime;
ULONGLONG
NewTime;
m_CurrentTime = StartTime;
// **** check that there are at least one each of
// **** year, month, hour, min and sec
if((SETEMPTY == m_Set[INDX_Second].m_BitField) ||
(SETEMPTY == m_Set[INDX_Minute].m_BitField) ||
(SETEMPTY == m_Set[INDX_Hour].m_BitField) ||
(SETEMPTY == m_Set[INDX_Quarter].m_BitField) ||
(SETEMPTY == m_Set[INDX_WeekInMonth].m_BitField) ||
(SETEMPTY == m_Set[INDX_DayOfWeek].m_BitField) ||
(SETEMPTY == m_Set[INDX_Month].m_BitField))
return -1;
// **** find first Month/year combo following current time
m_CurrentTime.wYear =
(USHORT) m_Pattern[INDX_Year].GetNextValue(m_CurrentTime.wYear);
if(m_CurrentTime.wYear == (USHORT)-1)
return -1;
if(m_CurrentTime.wYear != StartTime.wYear)
m_CurrentTime.wMonth = (USHORT) m_Set[INDX_Month].Next(1);
// **** now find first month/year that has at least
// **** one day in it
GetDaysInMonth(m_CurrentTime.wYear, m_CurrentTime.wMonth);
while(SETEMPTY == m_Set[INDX_Day].m_BitField)
{
wCurrValue = m_CurrentTime.wMonth + 1;
m_CurrentTime.wMonth = (USHORT) m_Set[INDX_Month].Next(wCurrValue);
if(m_CurrentTime.wMonth < wCurrValue)
m_CurrentTime.wYear
= (USHORT) m_Pattern[INDX_Year].GetNextValue(m_CurrentTime.wYear + 1);
if(m_CurrentTime.wYear == (USHORT)-1)
return -1;
GetDaysInMonth(m_CurrentTime.wYear, m_CurrentTime.wMonth);
}
// **** NOTE: it is still possible, at this point, to have a
// **** day in month for the current year/month that is before
// **** the current day. But, this is taken care of below.
// **** align hour:min:sec to first valid date
if((m_CurrentTime.wYear != StartTime.wYear) ||
(m_CurrentTime.wMonth != StartTime.wMonth))
{
m_CurrentTime.wSecond = (USHORT) m_Set[INDX_Second].Next(0);
m_CurrentTime.wMinute = (USHORT) m_Set[INDX_Minute].Next(0);
m_CurrentTime.wHour = (USHORT) m_Set[INDX_Hour].Next(0);
m_CurrentTime.wDay = (USHORT) m_Set[INDX_Day].Next(1);
}
else
{
wCurrValue = m_CurrentTime.wSecond;
m_CurrentTime.wSecond = (USHORT) m_Set[INDX_Second].Next(wCurrValue);
if(m_CurrentTime.wSecond < wCurrValue)
m_CurrentTime.wMinute += 1;
wCurrValue = m_CurrentTime.wMinute;
m_CurrentTime.wMinute = (USHORT) m_Set[INDX_Minute].Next(wCurrValue);
if(m_CurrentTime.wMinute < wCurrValue)
m_CurrentTime.wHour += 1;
wCurrValue = m_CurrentTime.wHour;
m_CurrentTime.wHour = (USHORT) m_Set[INDX_Hour].Next(wCurrValue);
if(m_CurrentTime.wHour < wCurrValue)
m_CurrentTime.wDay += 1;
wCurrValue = m_CurrentTime.wDay;
m_CurrentTime.wDay = (USHORT) m_Set[INDX_Day].Next(wCurrValue);
while((SETEMPTY == m_Set[INDX_Day].m_BitField) ||
(m_CurrentTime.wDay < wCurrValue))
{
wCurrValue = m_CurrentTime.wMonth + 1;
m_CurrentTime.wMonth = (USHORT) m_Set[INDX_Month].Next(wCurrValue);
if(m_CurrentTime.wMonth < wCurrValue)
m_CurrentTime.wYear
= (USHORT) m_Pattern[INDX_Year].GetNextValue(m_CurrentTime.wYear + 1);
if(m_CurrentTime.wYear == (USHORT)-1)
return -1;
GetDaysInMonth(m_CurrentTime.wYear, m_CurrentTime.wMonth);
wCurrValue = 1;
m_CurrentTime.wDay = (USHORT) m_Set[INDX_Day].Next(wCurrValue);
}
}
SystemTimeToFileTime(&m_CurrentTime, &FileTime);
NewTime = FileTime.dwHighDateTime;
NewTime = (NewTime << 32) + FileTime.dwLowDateTime;
return NewTime;
}
/******************************************************************/
HRESULT WQLDateTime::Init(QL_LEVEL_1_RPN_EXPRESSION *pExp)
{
HRESULT
hres = WBEM_S_NO_ERROR;
int i, j;
CDNFExpression
DNFExpression;
CConjunction
*pConjunction;
QL_LEVEL_1_TOKEN
*pToken,
*pTokens;
pTokens = pExp->pArrayOfTokens + pExp->nNumTokens - 1;
DNFExpression.CreateFromTokens(pTokens);
if(pTokens != pExp->pArrayOfTokens - 1)
return WBEM_E_CRITICAL_ERROR;
DNFExpression.Sort();
// **** first, if there is a previous definition, delete it
if(m_NLeaves > 0)
{
m_NLeaves = 0;
delete[] m_ParseTreeLeaves;
}
// **** now, build new logic
m_NLeaves = DNFExpression.GetNumTerms();
m_ParseTreeLeaves = new _DatePattern[m_NLeaves];
if(NULL == m_ParseTreeLeaves)
return WBEM_E_OUT_OF_MEMORY;
for(i = 0; (i < m_NLeaves) && SUCCEEDED(hres); i++)
{
#ifdef WQLDEBUG
if(i > 0) printf(" V ");
#endif
pConjunction = DNFExpression.GetTermAt(i);
m_ParseTreeLeaves[i].m_Datum = new CDatePattern;
if(NULL == m_ParseTreeLeaves[i].m_Datum)
return WBEM_E_OUT_OF_MEMORY;
#ifdef WQLDEBUG
printf("(");
#endif
for(j = 0; j < pConjunction->GetNumTokens(); j++)
{
#ifdef WQLDEBUG
if(j > 0) printf(" ^ ");
#endif
pToken = pConjunction->GetTokenAt(j);
#ifdef WQLDEBUG
wprintf(L"%s", pToken->GetText());
#endif
hres = m_ParseTreeLeaves[i].m_Datum->AugmentPattern(pToken);
if(FAILED(hres)) return WBEM_E_INVALID_QUERY;
}
m_ParseTreeLeaves[i].m_Index = 0;
m_ParseTreeLeaves[i].m_Next = NULL;
#ifdef WQLDEBUG
printf(")");
#endif
hres = m_ParseTreeLeaves[i].m_Datum->BuildSetsFromPatterns();
if(FAILED(hres)) return WBEM_E_INVALID_QUERY;
}
return hres;
}
ULONGLONG WQLDateTime::SetStartTime(SYSTEMTIME *StartTime)
{
int i;
if(NULL == StartTime)
return -1;
// **** insert all alternatives into ordered list
m_ListHead = NULL;
for(i = 0; i < m_NLeaves; i++)
{
m_ParseTreeLeaves[i].m_Next = NULL;
m_ParseTreeLeaves[i].m_Index = m_ParseTreeLeaves[i].m_Datum->SetStartTime(*StartTime);
if((ULONGLONG)-1 != m_ParseTreeLeaves[i].m_Index)
InsertOrdered(m_ParseTreeLeaves + i);
}
return GetNextTime(StartTime);
}
void WQLDateTime::InsertOrdered(_DatePattern *pNode)
{
_DatePattern
*pPrevDatePattern = NULL,
*pDatePattern = m_ListHead;
while(NULL != pDatePattern && (pNode->m_Index > pDatePattern->m_Index))
{
pPrevDatePattern = pDatePattern;
pDatePattern = pDatePattern->m_Next;
}
pNode->m_Next = pDatePattern;
if(NULL != pPrevDatePattern)
pPrevDatePattern->m_Next = pNode;
else
m_ListHead = pNode;
}
ULONGLONG WQLDateTime::GetNextTime(SYSTEMTIME *NextTime)
{
_DatePattern
*pDate;
ULONGLONG
FiringTime;
if(NULL != m_ListHead)
{
pDate = m_ListHead;
m_ListHead = m_ListHead->m_Next;
FiringTime = pDate->m_Index;
if(NULL != NextTime)
*NextTime = pDate->m_Datum->m_CurrentTime;
pDate->m_Index = pDate->m_Datum->GetNextTime();
// **** if next time is -1 then there are no future times
// **** so don't add back into list
if((ULONGLONG)-1 != pDate->m_Index)
InsertOrdered(pDate);
return FiringTime;
}
return -1;
}