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.
1163 lines
27 KiB
1163 lines
27 KiB
/*
|
|
CWin32Clock.CPP
|
|
|
|
Module: WMI Current Time Instance Provider
|
|
|
|
Purpose: The methods of CWin32Clock class are defined here.
|
|
|
|
Copyright (c)1999 Microsoft Corporation, All Rights Reserved
|
|
*/
|
|
|
|
#include <wbemcli.h>
|
|
#include <wbemprov.h>
|
|
#include <wbemcomn.h>
|
|
#undef _ASSERT
|
|
#include <atlbase.h>
|
|
#include "genlex.h"
|
|
#include "objpath.h"
|
|
#include "dnf.h"
|
|
#include "datep.h"
|
|
#include "Win32Clock.h"
|
|
|
|
// **** long glNumInst = sizeof(MyDefs)/sizeof(InstDef);
|
|
|
|
/****************************************************************************/
|
|
|
|
CWin32Clock::CScheduledEvent::CScheduledEvent(void)
|
|
{
|
|
|
|
m_Type = TypeNONE;
|
|
m_cRef = 0;
|
|
m_dwId = -1;
|
|
m_stLastFiringTime = 0;
|
|
m_pWin32Clock = NULL;
|
|
m_WQLStmt = NULL;
|
|
}
|
|
|
|
CWin32Clock::CScheduledEvent::~CScheduledEvent(void)
|
|
{
|
|
if(0 != m_cRef)
|
|
{
|
|
// **** error
|
|
}
|
|
|
|
if(NULL != m_WQLStmt)
|
|
delete[] m_WQLStmt;
|
|
}
|
|
|
|
HRESULT CWin32Clock::CScheduledEvent::Init(CWin32Clock *pClock,
|
|
wchar_t *WQLStmt,
|
|
ULONG dwId)
|
|
{
|
|
HRESULT
|
|
hr = S_OK;
|
|
|
|
// **** check for valid arguments
|
|
|
|
if((NULL == pClock) || (NULL == WQLStmt) || (-1 == dwId))
|
|
return WBEM_E_FAILED;
|
|
|
|
// **** copy to local arguments
|
|
|
|
if((NULL != m_pWin32Clock) || (NULL != m_WQLStmt))
|
|
return WBEM_E_FAILED;
|
|
|
|
m_dwId = dwId;
|
|
|
|
m_pWin32Clock = pClock; // **** note: no AddRef() is done here because
|
|
// **** the lifetime of this CScheduledEvent obj is
|
|
// **** ALWAYS encapsulated within that of pClock
|
|
|
|
// **** now parse m_WQLStmt to determine values for timer start and interval
|
|
|
|
hr = ReInit(WQLStmt);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWin32Clock::CScheduledEvent::ReInit(wchar_t *WQLStmt)
|
|
{
|
|
HRESULT
|
|
hr = WBEM_E_FAILED;
|
|
|
|
int
|
|
nRes;
|
|
|
|
if(NULL != m_WQLStmt)
|
|
delete[] m_WQLStmt;
|
|
|
|
// **** save WQL expression
|
|
|
|
m_WQLStmt = new wchar_t[wcslen(WQLStmt) + 1];
|
|
if(NULL == m_WQLStmt)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
wcscpy(m_WQLStmt, WQLStmt);
|
|
|
|
// **** parse WQL expression
|
|
|
|
CTextLexSource src(m_WQLStmt);
|
|
QL1_Parser parser(&src);
|
|
QL_LEVEL_1_RPN_EXPRESSION *pExp = NULL;
|
|
QL_LEVEL_1_TOKEN *pToken = NULL;
|
|
|
|
#ifdef WQLDEBUG
|
|
wchar_t classbuf[128];
|
|
*classbuf = 0;
|
|
printf("[1] ----GetQueryClass----\n");
|
|
nRes = parser.GetQueryClass(classbuf, 128);
|
|
if (nRes)
|
|
{
|
|
printf("ERROR %d: line %d, token %S\n",
|
|
nRes,
|
|
parser.CurrentLine(),
|
|
parser.CurrentToken());
|
|
}
|
|
printf("Query class is %S\n", classbuf);
|
|
#endif
|
|
|
|
if(nRes = parser.Parse(&pExp))
|
|
{
|
|
#ifdef WQLDEBUG
|
|
if (nRes)
|
|
{
|
|
printf("ERROR %d: line %d, token %S\n",
|
|
nRes,
|
|
parser.CurrentLine(),
|
|
parser.CurrentToken());
|
|
}
|
|
else
|
|
{
|
|
printf("No errors.\n");
|
|
}
|
|
#endif
|
|
|
|
hr = WBEM_E_INVALID_QUERY;
|
|
goto cleanup;
|
|
}
|
|
|
|
// **** validate WQL statement
|
|
|
|
if((NULL == pExp) ||
|
|
(NULL == pExp->bsClassName) ||
|
|
(wbem_wcsicmp(L"__InstanceModificationEvent", pExp->bsClassName)) ||
|
|
(pExp->nNumTokens < 1))
|
|
{
|
|
#ifdef WQLDEBUG
|
|
printf("WQL statement failed validation\n");
|
|
#endif
|
|
|
|
hr = WBEM_E_INVALID_QUERY;
|
|
goto cleanup;
|
|
}
|
|
|
|
// **** determine type
|
|
|
|
for(int i = 0; i < pExp->nNumTokens && (m_Type == TypeNONE); i++)
|
|
{
|
|
pToken = pExp->pArrayOfTokens + i;
|
|
|
|
if(NULL == pToken) continue;
|
|
|
|
if ( (pToken->nTokenType == QL_LEVEL_1_TOKEN::OP_EXPRESSION) &&
|
|
(pToken->vConstValue.vt == VT_BSTR))
|
|
{
|
|
long nElts = pToken->PropertyName.GetNumElements();
|
|
LPCWSTR pAttrName = pToken->PropertyName.GetStringAt(nElts -1);
|
|
|
|
if ( pAttrName != NULL &&
|
|
0 == wbem_wcsicmp(L"targetinstance", pAttrName))
|
|
{
|
|
if(0 == wbem_wcsicmp(WIN32LOCALTIMECLASS, pToken->vConstValue.bstrVal)) m_Type = TypeLocal;
|
|
else if(0 == wbem_wcsicmp(WIN32UTCTIMECLASS, pToken->vConstValue.bstrVal)) m_Type = TypeUTC;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(TypeNONE == m_Type)
|
|
{
|
|
hr = WBEM_E_INVALID_QUERY;
|
|
goto cleanup;
|
|
}
|
|
|
|
// **** interpret WQL Expression
|
|
|
|
#ifdef WQLDEBUG
|
|
printf("\n[2] ----ShowParseTree----\n");
|
|
pExp->Dump("CON");
|
|
printf("\n[3] ----ShowRebuiltQuery----\n");
|
|
LPWSTR wszText = pExp->GetText();
|
|
printf("--WQL passed to provider--\n");
|
|
printf("%S\n", wszText);
|
|
printf("\n[4] ----ShowInterpretation----\n");
|
|
#endif
|
|
|
|
try
|
|
{
|
|
hr = m_WQLTime.Init(pExp);
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
goto cleanup;
|
|
}
|
|
|
|
#ifdef WQLDEBUG
|
|
printf("\n\n[5] ----End of WQL Compilation----\n");
|
|
delete [] wszText;
|
|
#endif
|
|
|
|
cleanup:
|
|
|
|
delete pExp;
|
|
|
|
return hr;
|
|
}
|
|
|
|
void CWin32Clock::CScheduledEvent::AddRef()
|
|
{
|
|
InterlockedIncrement((long *)&m_cRef);
|
|
}
|
|
|
|
void CWin32Clock::CScheduledEvent::Release()
|
|
{
|
|
ULONG nNewCount = InterlockedDecrement((long *)&m_cRef);
|
|
|
|
if(0L == nNewCount)
|
|
delete this;
|
|
}
|
|
|
|
int CWin32Clock::CScheduledEvent::GetInstructionType()
|
|
{
|
|
return INSTTYPE_WBEM;
|
|
}
|
|
|
|
CWbemTime CWin32Clock::CScheduledEvent::GetNextFiringTime(CWbemTime LastFiringTime,
|
|
long *plFiringCount) const
|
|
{
|
|
FILETIME
|
|
FileTime,
|
|
FileTime2;
|
|
|
|
ULONGLONG
|
|
NextFiringTime,
|
|
CurrentTime;
|
|
|
|
CWbemTime
|
|
ResultTime;
|
|
|
|
int
|
|
nMisses = 0;
|
|
|
|
// **** save the firing time for event just fired from LastFiringTime
|
|
|
|
((CWin32Clock::CScheduledEvent*)this)->m_stLastFiringTime = LastFiringTime.Get100nss();
|
|
|
|
// **** calculate the next firing time after LastFiringTime and after the current time
|
|
|
|
GetFileTime(&FileTime);
|
|
|
|
CurrentTime = FileTime.dwHighDateTime;
|
|
CurrentTime = (CurrentTime << 32) + FileTime.dwLowDateTime;
|
|
|
|
while((NextFiringTime = ((WQLDateTime*)&m_WQLTime)->GetNextTime()) <= CurrentTime)
|
|
nMisses += 1;
|
|
|
|
if(-1 == NextFiringTime)
|
|
{
|
|
// **** no future event to be scheduled so, so indicate
|
|
|
|
return CWbemTime::GetInfinity();
|
|
}
|
|
|
|
if(NULL != plFiringCount)
|
|
*plFiringCount = nMisses;
|
|
|
|
// **** if local time, convert to UTC time for the scheduling logic
|
|
|
|
if(TypeLocal == m_Type)
|
|
{
|
|
FileTime.dwLowDateTime = ((NextFiringTime << 32) >> 32);
|
|
FileTime.dwHighDateTime = (NextFiringTime >> 32);
|
|
|
|
LocalFileTimeToFileTime(&FileTime, &FileTime2);
|
|
|
|
NextFiringTime = FileTime2.dwHighDateTime;
|
|
NextFiringTime = (NextFiringTime << 32) + FileTime2.dwLowDateTime;
|
|
}
|
|
|
|
ResultTime.Set100nss(NextFiringTime);
|
|
|
|
return ResultTime;
|
|
}
|
|
|
|
CWbemTime CWin32Clock::CScheduledEvent::GetFirstFiringTime() const
|
|
{
|
|
SYSTEMTIME
|
|
CurrentTime;
|
|
|
|
CWbemTime
|
|
ResultTime;
|
|
|
|
ULONGLONG
|
|
ullStartTime;
|
|
|
|
GetTime(&CurrentTime);
|
|
|
|
/*
|
|
Since the finest granularity used by the time provider is seconds, set milliseconds
|
|
to zero so that we can compare two FILETIME values in the Fire method and have
|
|
the numbers agree.
|
|
*/
|
|
|
|
CurrentTime.wMilliseconds = 0;
|
|
|
|
ullStartTime = ((WQLDateTime*)&m_WQLTime)->SetStartTime(&CurrentTime);
|
|
|
|
if(TypeLocal == m_Type)
|
|
{
|
|
FILETIME
|
|
FileTime,
|
|
FileTime2;
|
|
|
|
FileTime.dwLowDateTime = ((ullStartTime << 32) >> 32);
|
|
FileTime.dwHighDateTime = (ullStartTime >> 32);
|
|
|
|
LocalFileTimeToFileTime(&FileTime, &FileTime2);
|
|
|
|
ullStartTime = FileTime2.dwHighDateTime;
|
|
ullStartTime = (ullStartTime << 32) + FileTime2.dwLowDateTime;
|
|
}
|
|
|
|
ResultTime.Set100nss(ullStartTime);
|
|
|
|
return ResultTime;
|
|
}
|
|
|
|
HRESULT CWin32Clock::CScheduledEvent::Fire(long lNumTimes,
|
|
CWbemTime NextFiringTime)
|
|
{
|
|
HRESULT
|
|
hr = WBEM_E_FAILED;
|
|
|
|
FILETIME
|
|
ft,
|
|
ft2;
|
|
|
|
SYSTEMTIME
|
|
SystemTime;
|
|
|
|
CComPtr<IWbemClassObject>
|
|
pSystemTime;
|
|
|
|
// **** Do a check of arguments and make sure we have pointer to sink obj
|
|
|
|
if((NULL == m_pWin32Clock) || (NULL == m_pWin32Clock->m_ClockResetThread))
|
|
{
|
|
hr = WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
// **** create an instance of Win32_CurrentTime for each timezone
|
|
|
|
else
|
|
{
|
|
CInCritSec
|
|
ics(&(m_pWin32Clock->m_csWin32Clock));
|
|
|
|
// **** reconstitute a SYSTEMTIME from the current firing time
|
|
|
|
ft.dwLowDateTime = ((m_stLastFiringTime << 32) >> 32);
|
|
ft.dwHighDateTime = (m_stLastFiringTime >> 32);
|
|
|
|
if(((TypeLocal == m_Type) && (m_pWin32Clock->m_MostRecentLocalFiringTime != m_stLastFiringTime)) ||
|
|
((TypeUTC == m_Type) && (m_pWin32Clock->m_MostRecentUTCFiringTime != m_stLastFiringTime)))
|
|
{
|
|
if(TypeLocal == m_Type)
|
|
{
|
|
m_pWin32Clock->m_MostRecentLocalFiringTime = m_stLastFiringTime;
|
|
FileTimeToLocalFileTime(&ft, &ft2);
|
|
ft = ft2;
|
|
}
|
|
else if(TypeUTC == m_Type)
|
|
m_pWin32Clock->m_MostRecentUTCFiringTime = m_stLastFiringTime;
|
|
|
|
if(FileTimeToSystemTime(&ft, &SystemTime))
|
|
{
|
|
#ifdef WQLDEBUG
|
|
printf("[%d] Fire: Misses(%d) %d/%d/%d %d:%d:%d",
|
|
m_dwId,
|
|
lNumTimes,
|
|
SystemTime.wMonth,
|
|
SystemTime.wDay,
|
|
SystemTime.wYear,
|
|
SystemTime.wHour,
|
|
SystemTime.wMinute,
|
|
SystemTime.wSecond);
|
|
#else
|
|
// **** Send the object to the caller
|
|
|
|
if(TypeUTC == m_Type)
|
|
hr = CWin32Clock::SystemTimeToWin32_CurrentTime(m_pWin32Clock->m_pUTCTimeClassDef, &pSystemTime, &SystemTime);
|
|
else if(TypeLocal == m_Type)
|
|
hr = CWin32Clock::SystemTimeToWin32_CurrentTime(m_pWin32Clock->m_pLocalTimeClassDef, &pSystemTime, &SystemTime);
|
|
|
|
hr = m_pWin32Clock->SendEvent(pSystemTime);
|
|
#endif
|
|
}
|
|
else
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************************************************/
|
|
|
|
LRESULT CALLBACK Win32ClockProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
return DefWindowProc(hWnd, msg, wParam, lParam);
|
|
}
|
|
|
|
DWORD CWin32Clock::AsyncEventThread(LPVOID pArg)
|
|
{
|
|
if(NULL == pArg)
|
|
return -1;
|
|
|
|
CWin32Clock
|
|
*pCWin32Clock = (CWin32Clock*)pArg;
|
|
|
|
WNDCLASS wndclass;
|
|
MSG msg;
|
|
|
|
BOOL bRet;
|
|
|
|
// **** create top level window to receive system messages
|
|
|
|
wndclass.style = 0;
|
|
wndclass.lpfnWndProc = Win32ClockProc;
|
|
wndclass.cbClsExtra = 0;
|
|
wndclass.cbWndExtra = sizeof(DWORD);
|
|
wndclass.hInstance = GetModuleHandle(NULL);
|
|
wndclass.hIcon = NULL;
|
|
wndclass.hCursor = NULL;
|
|
wndclass.hbrBackground = NULL;
|
|
wndclass.lpszMenuName = NULL;
|
|
wndclass.lpszClassName = TEXT("Win32Clock");
|
|
|
|
if(!RegisterClass(&wndclass))
|
|
{
|
|
if(GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
HMODULE
|
|
hModule = GetModuleHandle(NULL);
|
|
|
|
if(NULL == hModule)
|
|
return -1;
|
|
|
|
try
|
|
{
|
|
pCWin32Clock->m_hEventWindowHandle = CreateWindow(TEXT("Win32Clock"),
|
|
TEXT("Win32ClockMsgs"),
|
|
WS_OVERLAPPED,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
HWND_MESSAGE,
|
|
NULL,
|
|
hModule,
|
|
NULL);
|
|
}
|
|
catch(...)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if(NULL == pCWin32Clock->m_hEventWindowHandle)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
ShowWindow(pCWin32Clock->m_hEventWindowHandle, SW_HIDE);
|
|
|
|
// **** start the message loop
|
|
|
|
while(GetMessage(&msg, pCWin32Clock->m_hEventWindowHandle, 0, 0))
|
|
{
|
|
switch (msg.message)
|
|
{
|
|
case WM_TIMECHANGE:
|
|
pCWin32Clock->ReAlignToCurrentTime();
|
|
break;
|
|
|
|
default:
|
|
DefWindowProc(pCWin32Clock->m_hEventWindowHandle, msg.message, msg.wParam, msg.lParam);
|
|
}
|
|
}
|
|
|
|
// **** cleanup
|
|
|
|
bRet = DestroyWindow(pCWin32Clock->m_hEventWindowHandle);
|
|
|
|
bRet = UnregisterClass(TEXT("Win32Clock"), 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void CWin32Clock::CScheduledEvent::GetTime(SYSTEMTIME *TheTime) const
|
|
{
|
|
if(NULL != TheTime)
|
|
{
|
|
memset(TheTime, 0, sizeof(SYSTEMTIME));
|
|
|
|
if(TypeLocal == m_Type)
|
|
GetLocalTime(TheTime);
|
|
else if(TypeUTC == m_Type)
|
|
GetSystemTime(TheTime);
|
|
}
|
|
}
|
|
|
|
void CWin32Clock::CScheduledEvent::GetFileTime(FILETIME *TheTime) const
|
|
{
|
|
SYSTEMTIME
|
|
SysTime;
|
|
|
|
if(NULL != TheTime)
|
|
{
|
|
memset(TheTime, 0, sizeof(FILETIME));
|
|
|
|
if(TypeLocal == m_Type)
|
|
{
|
|
GetLocalTime(&SysTime);
|
|
SystemTimeToFileTime(&SysTime, TheTime);
|
|
}
|
|
else if(TypeUTC == m_Type)
|
|
{
|
|
GetSystemTime(&SysTime);
|
|
SystemTimeToFileTime(&SysTime, TheTime);
|
|
}
|
|
}
|
|
}
|
|
|
|
HRESULT CWin32Clock::SendEvent(IWbemClassObject *pSystemTime)
|
|
{
|
|
HRESULT
|
|
hr = WBEM_E_FAILED;
|
|
|
|
CComPtr<IWbemClassObject>
|
|
pInstanceModEvnt;
|
|
|
|
CComVariant
|
|
v;
|
|
|
|
// **** if m_pSink has not been provided by winmgmt just drop
|
|
// **** generated events on the floor
|
|
|
|
if((NULL != m_pSink) && (NULL != pSystemTime))
|
|
{
|
|
// **** create and init instance of __InstanceModificationEvent
|
|
|
|
hr = m_pInstModClassDef->SpawnInstance(0, &pInstanceModEvnt);
|
|
if(FAILED(hr)) return hr;
|
|
|
|
// **** put Win32_CurrentTime into __InstanceModificationEvent
|
|
|
|
v.vt = VT_UNKNOWN;
|
|
v.punkVal = NULL;
|
|
hr = pSystemTime->QueryInterface(IID_IUnknown, (void**)&(v.punkVal));
|
|
if(FAILED(hr)) return hr;
|
|
|
|
hr = pInstanceModEvnt->Put(L"TargetInstance", 0, &v, 0);
|
|
if(FAILED(hr)) return hr;
|
|
|
|
// **** deliver new event to WMI
|
|
|
|
hr = m_pSink->Indicate(1, &pInstanceModEvnt);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWin32Clock::ReAlignToCurrentTime()
|
|
{
|
|
CInCritSec
|
|
ics(&m_csWin32Clock);
|
|
|
|
HRESULT
|
|
hr = S_OK;
|
|
|
|
ULONG
|
|
i,
|
|
nElts;
|
|
|
|
CScheduledEvent
|
|
*pcEvent;
|
|
|
|
#ifdef WQLDEBUG
|
|
printf("System Clock Resync\n");
|
|
#endif
|
|
|
|
m_EventArray.Lock();
|
|
|
|
nElts = *(ULONG *)(&(this->m_EventArray)); // voodoo
|
|
|
|
m_MostRecentLocalFiringTime = 0;
|
|
m_MostRecentUTCFiringTime = 0;
|
|
|
|
for(i = 0; i < nElts; i++)
|
|
{
|
|
// **** pull event from the event queue
|
|
|
|
pcEvent = m_EventArray[i];
|
|
|
|
if(NULL != pcEvent)
|
|
{
|
|
// **** change time for event obj and re-queue
|
|
|
|
m_Timer.Remove(&CIdentityTest(pcEvent));
|
|
m_Timer.Set(pcEvent);
|
|
}
|
|
}
|
|
|
|
m_EventArray.UnLock();
|
|
|
|
return hr;
|
|
}
|
|
|
|
CWin32Clock::CWin32Clock(CLifeControl* pControl)
|
|
: m_Timer(), m_EventArray(), m_pControl(pControl)
|
|
{
|
|
pControl->ObjectCreated((IWbemServices*)this);
|
|
|
|
m_cRef = 0;
|
|
m_MostRecentLocalFiringTime = 0;
|
|
m_MostRecentUTCFiringTime = 0;
|
|
m_pNs = NULL;
|
|
m_pSink = NULL;
|
|
m_pInstModClassDef = NULL;
|
|
m_pLocalTimeClassDef = NULL;
|
|
m_pUTCTimeClassDef = NULL;
|
|
m_ClockResetThread = NULL;
|
|
m_hEventWindowHandle = NULL;
|
|
}
|
|
|
|
CWin32Clock::~CWin32Clock(void)
|
|
{
|
|
// **** Kill Async thread if it has been started
|
|
|
|
if(NULL != m_ClockResetThread)
|
|
{
|
|
BOOL
|
|
bRes;
|
|
|
|
do
|
|
{
|
|
bRes = PostMessage(m_hEventWindowHandle, WM_QUIT, 0, 0);
|
|
}
|
|
while(WAIT_TIMEOUT == WaitForSingleObject(m_ClockResetThread, 6000));
|
|
}
|
|
|
|
// **** shutdown event thread
|
|
|
|
m_Timer.Shutdown();
|
|
|
|
// **** release all held COM objects
|
|
|
|
if(NULL != m_pNs) m_pNs->Release();
|
|
if(NULL != m_pSink) m_pSink->Release();
|
|
if(NULL != m_pInstModClassDef) m_pInstModClassDef->Release();
|
|
if(NULL != m_pLocalTimeClassDef) m_pLocalTimeClassDef->Release();
|
|
if(NULL != m_pUTCTimeClassDef) m_pUTCTimeClassDef->Release();
|
|
|
|
m_pControl->ObjectDestroyed((IWbemServices*)this);
|
|
}
|
|
|
|
// **** ***************************************************************************
|
|
// ****
|
|
// **** CWin32Clock::QueryInterface
|
|
// **** CWin32Clock::AddRef
|
|
// **** CWin32Clock::Release
|
|
// ****
|
|
// **** Purpose: IUnknown members for CWin32Clock object.
|
|
// **** ***************************************************************************
|
|
|
|
|
|
STDMETHODIMP CWin32Clock::QueryInterface(REFIID riid, PVOID *ppv)
|
|
{
|
|
*ppv=NULL;
|
|
|
|
// **** cast to the type of the base class specified by riid
|
|
|
|
if(IID_IWbemEventProvider == riid)
|
|
{
|
|
*ppv = (IWbemEventProvider *)this;
|
|
}
|
|
else if(IID_IWbemEventProviderQuerySink == riid)
|
|
{
|
|
*ppv = (IWbemEventProviderQuerySink *)this;
|
|
}
|
|
else if(IID_IWbemServices == riid)
|
|
{
|
|
*ppv=(IWbemServices*)this;
|
|
}
|
|
else if(IID_IUnknown == riid || IID_IWbemProviderInit == riid)
|
|
{
|
|
*ppv=(IWbemProviderInit*)this;
|
|
}
|
|
|
|
if(NULL!=*ppv)
|
|
{
|
|
AddRef();
|
|
|
|
return S_OK;
|
|
}
|
|
else
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) CWin32Clock::AddRef(void)
|
|
{
|
|
return InterlockedIncrement((long *)&m_cRef);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CWin32Clock::Release(void)
|
|
{
|
|
ULONG nNewCount = InterlockedDecrement((long *)&m_cRef);
|
|
|
|
if(0L == nNewCount)
|
|
delete this;
|
|
|
|
return nNewCount;
|
|
}
|
|
|
|
/*
|
|
IWbemProviderInit::Initialize
|
|
|
|
Purpose: This is the implementation of IWbemProviderInit. The method
|
|
is need to initialize with CIMOM.
|
|
|
|
The members set up include:
|
|
m_pNs
|
|
m_pLocalTimeClassDef
|
|
m_pUTCTimeClassDef
|
|
m_pInstModClassDef
|
|
*/
|
|
|
|
HRESULT CWin32Clock::Initialize(LPWSTR pszUser,
|
|
LONG lFlags,
|
|
LPWSTR pszNamespace,
|
|
LPWSTR pszLocale,
|
|
IWbemServices *pNamespace,
|
|
IWbemContext *pCtx,
|
|
IWbemProviderInitSink *pInitSink)
|
|
{
|
|
HRESULT
|
|
hr = WBEM_E_FAILED;
|
|
|
|
if((NULL != pNamespace) && (NULL != pInitSink))
|
|
{
|
|
m_pNs = pNamespace;
|
|
m_pNs->AddRef();
|
|
|
|
// **** get needed class definitions
|
|
|
|
hr = m_pNs->GetObject(WIN32LOCALTIMECLASS,
|
|
0, pCtx, &m_pLocalTimeClassDef, 0);
|
|
|
|
if(SUCCEEDED(hr))
|
|
hr = m_pNs->GetObject(WIN32UTCTIMECLASS,
|
|
0, pCtx, &m_pUTCTimeClassDef, 0);
|
|
|
|
if(SUCCEEDED(hr))
|
|
hr = m_pNs->GetObject(INSTMODEVCLASS,
|
|
0, pCtx, &m_pInstModClassDef, 0);
|
|
|
|
if(WBEM_S_NO_ERROR == hr)
|
|
{
|
|
pInitSink->SetStatus(WBEM_S_INITIALIZED,0);
|
|
|
|
hr = WBEM_NO_ERROR;
|
|
}
|
|
}
|
|
|
|
// **** if there was a problem, release the resources we have aquired
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
if(NULL != m_pLocalTimeClassDef) { m_pLocalTimeClassDef->Release(); m_pLocalTimeClassDef = NULL; }
|
|
if(NULL != m_pUTCTimeClassDef) { m_pUTCTimeClassDef->Release(); m_pUTCTimeClassDef = NULL; }
|
|
if(NULL != m_pInstModClassDef) { m_pInstModClassDef->Release(); m_pInstModClassDef = NULL; }
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*
|
|
IWbemEventProvider::ProvideEvents
|
|
|
|
Purpose: register to provide events to the WMI service
|
|
*/
|
|
|
|
HRESULT CWin32Clock::ProvideEvents(IWbemObjectSink *pSink,
|
|
long lFlags)
|
|
{
|
|
HRESULT
|
|
hr = WBEM_S_NO_ERROR;
|
|
|
|
// **** copy object sink for future event registrations
|
|
|
|
m_pSink = pSink;
|
|
if(NULL != m_pSink)
|
|
m_pSink->AddRef();
|
|
else
|
|
hr = WBEM_E_FAILED;
|
|
|
|
// **** start system clock change adj. thread
|
|
|
|
DWORD dwThreadId;
|
|
|
|
if(NULL == m_ClockResetThread)
|
|
{
|
|
m_ClockResetThread = CreateThread(
|
|
NULL, // pointer to thread security attributes
|
|
0, // initial thread stack size, in bytes
|
|
(LPTHREAD_START_ROUTINE)AsyncEventThread, // pointer to thread function
|
|
(LPVOID)this, // argument for new thread
|
|
0, // creation flags
|
|
&dwThreadId); // pointer to returned thread identifier
|
|
|
|
if(NULL == m_ClockResetThread)
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
else
|
|
hr = WBEM_E_FAILED;
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*
|
|
IWbemEventProviderQuerySink::NewQuery
|
|
|
|
Purpose: add a new query for event generation
|
|
*/
|
|
|
|
HRESULT CWin32Clock::NewQuery(ULONG dwId,
|
|
wchar_t *wszQueryLanguage,
|
|
wchar_t *wszQuery)
|
|
{
|
|
HRESULT
|
|
hr = WBEM_E_FAILED;
|
|
|
|
CScheduledEvent
|
|
*pNewEvent = NULL;
|
|
|
|
if(wbem_wcsicmp(L"WQL", wszQueryLanguage) || (NULL == wszQuery))
|
|
return WBEM_E_FAILED;
|
|
|
|
// **** see if event obj with dwId is already in queue
|
|
|
|
pNewEvent = m_EventArray(dwId, TRUE); // find registered event query
|
|
|
|
if(NULL != pNewEvent)
|
|
{
|
|
#ifdef WQLDEBUG
|
|
printf("[%d] Redefinition: %s\n", dwId, wszQuery);
|
|
#endif
|
|
|
|
if(wbem_wcsicmp(wszQuery, pNewEvent->m_WQLStmt))
|
|
{
|
|
hr = m_Timer.Remove(&CIdentityTest(pNewEvent)); // may or may not be in queue
|
|
hr = pNewEvent->ReInit(wszQuery); // on failure, NewEvent is preserved
|
|
m_Timer.Set(pNewEvent);
|
|
}
|
|
|
|
m_EventArray.UnLock();
|
|
}
|
|
|
|
// **** this is a new event, create it and place it in the event queue
|
|
|
|
else
|
|
{
|
|
#ifdef WQLDEBUG
|
|
printf("[%d] Definition: %s\n", dwId, wszQuery);
|
|
#endif
|
|
|
|
// **** create new event and initialize
|
|
|
|
pNewEvent = new CScheduledEvent();
|
|
|
|
if(NULL == pNewEvent)
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
else
|
|
{
|
|
pNewEvent->AddRef();
|
|
|
|
hr = pNewEvent->Init(this, wszQuery, dwId);
|
|
|
|
// **** add event to queue
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
m_EventArray.Insert(pNewEvent, dwId);
|
|
hr = m_Timer.Set(pNewEvent);
|
|
}
|
|
else
|
|
{
|
|
pNewEvent->Release();
|
|
pNewEvent = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*
|
|
IWbemEventProviderQuerySink::CancelQuery
|
|
|
|
Purpose: remove an event generator from the queue
|
|
*/
|
|
|
|
HRESULT CWin32Clock::CancelQuery(ULONG dwId)
|
|
{
|
|
CInCritSec
|
|
ics(&m_csWin32Clock);
|
|
|
|
CScheduledEvent
|
|
*pDeadEvent = NULL;
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
// **** first find element in list and remove it
|
|
|
|
pDeadEvent = m_EventArray(dwId, TRUE);
|
|
|
|
if(NULL != pDeadEvent)
|
|
{
|
|
m_EventArray.Remove(pDeadEvent);
|
|
m_EventArray.UnLock();
|
|
|
|
hr = m_Timer.Remove(&CIdentityTest(pDeadEvent));
|
|
|
|
// **** now kill it dead
|
|
|
|
pDeadEvent->Release();
|
|
pDeadEvent = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*
|
|
IWbemServices::CreateInstanceEnumAsync
|
|
|
|
Purpose: Asynchronously enumerates the instances.
|
|
*/
|
|
|
|
HRESULT CWin32Clock::CreateInstanceEnumAsync(const BSTR RefStr,
|
|
long lFlags,
|
|
IWbemContext *pCtx,
|
|
IWbemObjectSink FAR* pHandler)
|
|
{
|
|
HRESULT
|
|
sc = WBEM_E_FAILED;
|
|
|
|
IWbemClassObject
|
|
FAR* pNewInst = NULL;
|
|
|
|
SYSTEMTIME
|
|
TheTime;
|
|
|
|
// **** Do a check of arguments and make sure we have pointer to Namespace
|
|
|
|
if(NULL == pHandler)
|
|
{
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
// **** Create Win32_CurrentTime instance
|
|
|
|
else if(0 == wbem_wcsicmp(RefStr, WIN32LOCALTIMECLASS))
|
|
{
|
|
|
|
GetLocalTime(&TheTime);
|
|
sc = SystemTimeToWin32_CurrentTime(m_pLocalTimeClassDef, &pNewInst, &TheTime);
|
|
|
|
// **** Send the object to the caller
|
|
|
|
pHandler->Indicate(1,&pNewInst);
|
|
pNewInst->Release();
|
|
}
|
|
|
|
// **** Create Win32_CurrentTime instance
|
|
|
|
else if(0 == wbem_wcsicmp(RefStr, WIN32UTCTIMECLASS))
|
|
{
|
|
GetSystemTime(&TheTime);
|
|
sc = SystemTimeToWin32_CurrentTime(m_pUTCTimeClassDef, &pNewInst, &TheTime);
|
|
|
|
// **** Send the object to the caller
|
|
|
|
pHandler->Indicate(1,&pNewInst);
|
|
pNewInst->Release();
|
|
}
|
|
else if(0 == wbem_wcsicmp(RefStr, L"Win32_CurrentTime"))
|
|
{}
|
|
else
|
|
{
|
|
sc = WBEM_E_INVALID_CLASS;
|
|
}
|
|
|
|
// **** Set status
|
|
|
|
pHandler->SetStatus(0, sc, NULL, NULL);
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*
|
|
IWbemServices::GetObjectByPathAsync
|
|
|
|
Purpose: Creates an instance given a particular path value.
|
|
*/
|
|
|
|
HRESULT CWin32Clock::GetObjectAsync(const BSTR ObjectPath,
|
|
long lFlags,
|
|
IWbemContext *pCtx,
|
|
IWbemObjectSink FAR* pHandler)
|
|
{
|
|
HRESULT
|
|
sc = WBEM_E_FAILED;
|
|
|
|
IWbemClassObject
|
|
FAR* pObj = NULL;
|
|
|
|
WCHAR
|
|
*pwcTest = NULL,
|
|
*pwcVALUE = NULL;
|
|
|
|
CObjectPathParser
|
|
ObjPath(e_ParserAcceptRelativeNamespace);
|
|
|
|
ParsedObjectPath
|
|
*pParsedObjectPath = NULL;
|
|
|
|
SYSTEMTIME
|
|
SystemTime;
|
|
|
|
// **** Parse ObjectPath into a key member name and value
|
|
// **** <CLASS>.<MEMBER>="<VALUE>"
|
|
|
|
if(NULL == ObjectPath)
|
|
return WBEM_E_INVALID_OBJECT_PATH;
|
|
|
|
// **** parse object path
|
|
|
|
if((ObjPath.NoError != ObjPath.Parse(ObjectPath, &pParsedObjectPath)) || (NULL == pParsedObjectPath))
|
|
{
|
|
ERRORTRACE((LOG_ESS, "Win32_LocalTime: Parse error for object: %S\n", ObjectPath));
|
|
sc = WBEM_E_INVALID_QUERY;
|
|
}
|
|
|
|
// **** do the get, pass the object on to the notify
|
|
|
|
if(0 == wbem_wcsicmp(WIN32LOCALTIMECLASS, pParsedObjectPath->m_pClass))
|
|
{
|
|
GetLocalTime(&SystemTime);
|
|
sc = SystemTimeToWin32_CurrentTime(m_pLocalTimeClassDef, &pObj, &SystemTime);
|
|
|
|
if(WBEM_S_NO_ERROR == sc)
|
|
{
|
|
pHandler->Indicate(1,&pObj);
|
|
pObj->Release();
|
|
}
|
|
}
|
|
else if(0 == wbem_wcsicmp(WIN32UTCTIMECLASS, pParsedObjectPath->m_pClass))
|
|
{
|
|
GetSystemTime(&SystemTime);
|
|
sc = SystemTimeToWin32_CurrentTime(m_pUTCTimeClassDef, &pObj, &SystemTime);
|
|
|
|
if(WBEM_S_NO_ERROR == sc)
|
|
{
|
|
pHandler->Indicate(1,&pObj);
|
|
pObj->Release();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ERRORTRACE((LOG_ESS, "Win32_LocalTime: Parse error for object: %S\n", ObjectPath));
|
|
sc = WBEM_E_INVALID_QUERY;
|
|
}
|
|
|
|
// **** Set Status
|
|
|
|
pHandler->SetStatus(0,sc, NULL, NULL);
|
|
|
|
return sc;
|
|
}
|
|
|
|
/*
|
|
CWin32Clock::CreateInstCurrentTime
|
|
|
|
Purpose: creates an instance of the object Win32_CurrentTime representing
|
|
the current time with the given offset UTCOffset
|
|
*/
|
|
|
|
HRESULT CWin32Clock::SystemTimeToWin32_CurrentTime(IWbemClassObject *pClassDef, IWbemClassObject ** pNewInst, SYSTEMTIME *TheTime)
|
|
{
|
|
HRESULT
|
|
sc = WBEM_E_FAILED;
|
|
|
|
VARIANT
|
|
v;
|
|
|
|
// **** create blank instance of class InstTime
|
|
|
|
sc = pClassDef->SpawnInstance(0, pNewInst);
|
|
|
|
if(FAILED(sc))
|
|
return sc;
|
|
|
|
// **** Create Win32_CurrentTime instance
|
|
|
|
v.vt = VT_I4;
|
|
|
|
v.lVal = TheTime->wYear;
|
|
sc = (*pNewInst)->Put(L"Year", 0, &v, 0);
|
|
|
|
v.lVal = TheTime->wMonth;
|
|
sc = (*pNewInst)->Put(L"Month", 0, &v, 0);
|
|
|
|
v.lVal = TheTime->wDay;
|
|
sc = (*pNewInst)->Put(L"Day", 0, &v, 0);
|
|
|
|
v.lVal = TheTime->wDayOfWeek;
|
|
sc = (*pNewInst)->Put(L"DayOfWeek", 0, &v, 0);
|
|
|
|
v.lVal = (((8 - (TheTime->wDay - TheTime->wDayOfWeek + 7) % 7) % 7) + TheTime->wDay -1) / 7 + 1;
|
|
sc = (*pNewInst)->Put(L"WeekInMonth", 0, &v, 0);
|
|
|
|
v.lVal = (TheTime->wMonth - 1) / 3 + 1;
|
|
sc = (*pNewInst)->Put(L"Quarter", 0, &v, 0);
|
|
|
|
v.lVal = TheTime->wHour;
|
|
sc = (*pNewInst)->Put(L"Hour", 0, &v, 0);
|
|
|
|
v.lVal = TheTime->wMinute;
|
|
sc = (*pNewInst)->Put(L"Minute", 0, &v, 0);
|
|
|
|
v.lVal = TheTime->wSecond;
|
|
sc = (*pNewInst)->Put(L"Second", 0, &v, 0);
|
|
|
|
VariantClear(&v);
|
|
|
|
return sc;
|
|
}
|
|
|