/* 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 #include #include #undef _ASSERT #include #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 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 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 // **** .="" 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; }