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
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;
|
|
}
|