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.

1163 lines
27 KiB

  1. /*
  2. CWin32Clock.CPP
  3. Module: WMI Current Time Instance Provider
  4. Purpose: The methods of CWin32Clock class are defined here.
  5. Copyright (c)1999 Microsoft Corporation, All Rights Reserved
  6. */
  7. #include <wbemcli.h>
  8. #include <wbemprov.h>
  9. #include <wbemcomn.h>
  10. #undef _ASSERT
  11. #include <atlbase.h>
  12. #include "genlex.h"
  13. #include "objpath.h"
  14. #include "dnf.h"
  15. #include "datep.h"
  16. #include "Win32Clock.h"
  17. // **** long glNumInst = sizeof(MyDefs)/sizeof(InstDef);
  18. /****************************************************************************/
  19. CWin32Clock::CScheduledEvent::CScheduledEvent(void)
  20. {
  21. m_Type = TypeNONE;
  22. m_cRef = 0;
  23. m_dwId = -1;
  24. m_stLastFiringTime = 0;
  25. m_pWin32Clock = NULL;
  26. m_WQLStmt = NULL;
  27. }
  28. CWin32Clock::CScheduledEvent::~CScheduledEvent(void)
  29. {
  30. if(0 != m_cRef)
  31. {
  32. // **** error
  33. }
  34. if(NULL != m_WQLStmt)
  35. delete[] m_WQLStmt;
  36. }
  37. HRESULT CWin32Clock::CScheduledEvent::Init(CWin32Clock *pClock,
  38. wchar_t *WQLStmt,
  39. ULONG dwId)
  40. {
  41. HRESULT
  42. hr = S_OK;
  43. // **** check for valid arguments
  44. if((NULL == pClock) || (NULL == WQLStmt) || (-1 == dwId))
  45. return WBEM_E_FAILED;
  46. // **** copy to local arguments
  47. if((NULL != m_pWin32Clock) || (NULL != m_WQLStmt))
  48. return WBEM_E_FAILED;
  49. m_dwId = dwId;
  50. m_pWin32Clock = pClock; // **** note: no AddRef() is done here because
  51. // **** the lifetime of this CScheduledEvent obj is
  52. // **** ALWAYS encapsulated within that of pClock
  53. // **** now parse m_WQLStmt to determine values for timer start and interval
  54. hr = ReInit(WQLStmt);
  55. return hr;
  56. }
  57. HRESULT CWin32Clock::CScheduledEvent::ReInit(wchar_t *WQLStmt)
  58. {
  59. HRESULT
  60. hr = WBEM_E_FAILED;
  61. int
  62. nRes;
  63. if(NULL != m_WQLStmt)
  64. delete[] m_WQLStmt;
  65. // **** save WQL expression
  66. m_WQLStmt = new wchar_t[wcslen(WQLStmt) + 1];
  67. if(NULL == m_WQLStmt)
  68. return WBEM_E_OUT_OF_MEMORY;
  69. wcscpy(m_WQLStmt, WQLStmt);
  70. // **** parse WQL expression
  71. CTextLexSource src(m_WQLStmt);
  72. QL1_Parser parser(&src);
  73. QL_LEVEL_1_RPN_EXPRESSION *pExp = NULL;
  74. QL_LEVEL_1_TOKEN *pToken = NULL;
  75. #ifdef WQLDEBUG
  76. wchar_t classbuf[128];
  77. *classbuf = 0;
  78. printf("[1] ----GetQueryClass----\n");
  79. nRes = parser.GetQueryClass(classbuf, 128);
  80. if (nRes)
  81. {
  82. printf("ERROR %d: line %d, token %S\n",
  83. nRes,
  84. parser.CurrentLine(),
  85. parser.CurrentToken());
  86. }
  87. printf("Query class is %S\n", classbuf);
  88. #endif
  89. if(nRes = parser.Parse(&pExp))
  90. {
  91. #ifdef WQLDEBUG
  92. if (nRes)
  93. {
  94. printf("ERROR %d: line %d, token %S\n",
  95. nRes,
  96. parser.CurrentLine(),
  97. parser.CurrentToken());
  98. }
  99. else
  100. {
  101. printf("No errors.\n");
  102. }
  103. #endif
  104. hr = WBEM_E_INVALID_QUERY;
  105. goto cleanup;
  106. }
  107. // **** validate WQL statement
  108. if((NULL == pExp) ||
  109. (NULL == pExp->bsClassName) ||
  110. (wbem_wcsicmp(L"__InstanceModificationEvent", pExp->bsClassName)) ||
  111. (pExp->nNumTokens < 1))
  112. {
  113. #ifdef WQLDEBUG
  114. printf("WQL statement failed validation\n");
  115. #endif
  116. hr = WBEM_E_INVALID_QUERY;
  117. goto cleanup;
  118. }
  119. // **** determine type
  120. for(int i = 0; i < pExp->nNumTokens && (m_Type == TypeNONE); i++)
  121. {
  122. pToken = pExp->pArrayOfTokens + i;
  123. if(NULL == pToken) continue;
  124. if ( (pToken->nTokenType == QL_LEVEL_1_TOKEN::OP_EXPRESSION) &&
  125. (pToken->vConstValue.vt == VT_BSTR))
  126. {
  127. long nElts = pToken->PropertyName.GetNumElements();
  128. LPCWSTR pAttrName = pToken->PropertyName.GetStringAt(nElts -1);
  129. if ( pAttrName != NULL &&
  130. 0 == wbem_wcsicmp(L"targetinstance", pAttrName))
  131. {
  132. if(0 == wbem_wcsicmp(WIN32LOCALTIMECLASS, pToken->vConstValue.bstrVal)) m_Type = TypeLocal;
  133. else if(0 == wbem_wcsicmp(WIN32UTCTIMECLASS, pToken->vConstValue.bstrVal)) m_Type = TypeUTC;
  134. }
  135. }
  136. }
  137. if(TypeNONE == m_Type)
  138. {
  139. hr = WBEM_E_INVALID_QUERY;
  140. goto cleanup;
  141. }
  142. // **** interpret WQL Expression
  143. #ifdef WQLDEBUG
  144. printf("\n[2] ----ShowParseTree----\n");
  145. pExp->Dump("CON");
  146. printf("\n[3] ----ShowRebuiltQuery----\n");
  147. LPWSTR wszText = pExp->GetText();
  148. printf("--WQL passed to provider--\n");
  149. printf("%S\n", wszText);
  150. printf("\n[4] ----ShowInterpretation----\n");
  151. #endif
  152. try
  153. {
  154. hr = m_WQLTime.Init(pExp);
  155. }
  156. catch(...)
  157. {
  158. hr = WBEM_E_FAILED;
  159. goto cleanup;
  160. }
  161. #ifdef WQLDEBUG
  162. printf("\n\n[5] ----End of WQL Compilation----\n");
  163. delete [] wszText;
  164. #endif
  165. cleanup:
  166. delete pExp;
  167. return hr;
  168. }
  169. void CWin32Clock::CScheduledEvent::AddRef()
  170. {
  171. InterlockedIncrement((long *)&m_cRef);
  172. }
  173. void CWin32Clock::CScheduledEvent::Release()
  174. {
  175. ULONG nNewCount = InterlockedDecrement((long *)&m_cRef);
  176. if(0L == nNewCount)
  177. delete this;
  178. }
  179. int CWin32Clock::CScheduledEvent::GetInstructionType()
  180. {
  181. return INSTTYPE_WBEM;
  182. }
  183. CWbemTime CWin32Clock::CScheduledEvent::GetNextFiringTime(CWbemTime LastFiringTime,
  184. long *plFiringCount) const
  185. {
  186. FILETIME
  187. FileTime,
  188. FileTime2;
  189. ULONGLONG
  190. NextFiringTime,
  191. CurrentTime;
  192. CWbemTime
  193. ResultTime;
  194. int
  195. nMisses = 0;
  196. // **** save the firing time for event just fired from LastFiringTime
  197. ((CWin32Clock::CScheduledEvent*)this)->m_stLastFiringTime = LastFiringTime.Get100nss();
  198. // **** calculate the next firing time after LastFiringTime and after the current time
  199. GetFileTime(&FileTime);
  200. CurrentTime = FileTime.dwHighDateTime;
  201. CurrentTime = (CurrentTime << 32) + FileTime.dwLowDateTime;
  202. while((NextFiringTime = ((WQLDateTime*)&m_WQLTime)->GetNextTime()) <= CurrentTime)
  203. nMisses += 1;
  204. if(-1 == NextFiringTime)
  205. {
  206. // **** no future event to be scheduled so, so indicate
  207. return CWbemTime::GetInfinity();
  208. }
  209. if(NULL != plFiringCount)
  210. *plFiringCount = nMisses;
  211. // **** if local time, convert to UTC time for the scheduling logic
  212. if(TypeLocal == m_Type)
  213. {
  214. FileTime.dwLowDateTime = ((NextFiringTime << 32) >> 32);
  215. FileTime.dwHighDateTime = (NextFiringTime >> 32);
  216. LocalFileTimeToFileTime(&FileTime, &FileTime2);
  217. NextFiringTime = FileTime2.dwHighDateTime;
  218. NextFiringTime = (NextFiringTime << 32) + FileTime2.dwLowDateTime;
  219. }
  220. ResultTime.Set100nss(NextFiringTime);
  221. return ResultTime;
  222. }
  223. CWbemTime CWin32Clock::CScheduledEvent::GetFirstFiringTime() const
  224. {
  225. SYSTEMTIME
  226. CurrentTime;
  227. CWbemTime
  228. ResultTime;
  229. ULONGLONG
  230. ullStartTime;
  231. GetTime(&CurrentTime);
  232. /*
  233. Since the finest granularity used by the time provider is seconds, set milliseconds
  234. to zero so that we can compare two FILETIME values in the Fire method and have
  235. the numbers agree.
  236. */
  237. CurrentTime.wMilliseconds = 0;
  238. ullStartTime = ((WQLDateTime*)&m_WQLTime)->SetStartTime(&CurrentTime);
  239. if(TypeLocal == m_Type)
  240. {
  241. FILETIME
  242. FileTime,
  243. FileTime2;
  244. FileTime.dwLowDateTime = ((ullStartTime << 32) >> 32);
  245. FileTime.dwHighDateTime = (ullStartTime >> 32);
  246. LocalFileTimeToFileTime(&FileTime, &FileTime2);
  247. ullStartTime = FileTime2.dwHighDateTime;
  248. ullStartTime = (ullStartTime << 32) + FileTime2.dwLowDateTime;
  249. }
  250. ResultTime.Set100nss(ullStartTime);
  251. return ResultTime;
  252. }
  253. HRESULT CWin32Clock::CScheduledEvent::Fire(long lNumTimes,
  254. CWbemTime NextFiringTime)
  255. {
  256. HRESULT
  257. hr = WBEM_E_FAILED;
  258. FILETIME
  259. ft,
  260. ft2;
  261. SYSTEMTIME
  262. SystemTime;
  263. CComPtr<IWbemClassObject>
  264. pSystemTime;
  265. // **** Do a check of arguments and make sure we have pointer to sink obj
  266. if((NULL == m_pWin32Clock) || (NULL == m_pWin32Clock->m_ClockResetThread))
  267. {
  268. hr = WBEM_E_INVALID_PARAMETER;
  269. }
  270. // **** create an instance of Win32_CurrentTime for each timezone
  271. else
  272. {
  273. CInCritSec
  274. ics(&(m_pWin32Clock->m_csWin32Clock));
  275. // **** reconstitute a SYSTEMTIME from the current firing time
  276. ft.dwLowDateTime = ((m_stLastFiringTime << 32) >> 32);
  277. ft.dwHighDateTime = (m_stLastFiringTime >> 32);
  278. if(((TypeLocal == m_Type) && (m_pWin32Clock->m_MostRecentLocalFiringTime != m_stLastFiringTime)) ||
  279. ((TypeUTC == m_Type) && (m_pWin32Clock->m_MostRecentUTCFiringTime != m_stLastFiringTime)))
  280. {
  281. if(TypeLocal == m_Type)
  282. {
  283. m_pWin32Clock->m_MostRecentLocalFiringTime = m_stLastFiringTime;
  284. FileTimeToLocalFileTime(&ft, &ft2);
  285. ft = ft2;
  286. }
  287. else if(TypeUTC == m_Type)
  288. m_pWin32Clock->m_MostRecentUTCFiringTime = m_stLastFiringTime;
  289. if(FileTimeToSystemTime(&ft, &SystemTime))
  290. {
  291. #ifdef WQLDEBUG
  292. printf("[%d] Fire: Misses(%d) %d/%d/%d %d:%d:%d",
  293. m_dwId,
  294. lNumTimes,
  295. SystemTime.wMonth,
  296. SystemTime.wDay,
  297. SystemTime.wYear,
  298. SystemTime.wHour,
  299. SystemTime.wMinute,
  300. SystemTime.wSecond);
  301. #else
  302. // **** Send the object to the caller
  303. if(TypeUTC == m_Type)
  304. hr = CWin32Clock::SystemTimeToWin32_CurrentTime(m_pWin32Clock->m_pUTCTimeClassDef, &pSystemTime, &SystemTime);
  305. else if(TypeLocal == m_Type)
  306. hr = CWin32Clock::SystemTimeToWin32_CurrentTime(m_pWin32Clock->m_pLocalTimeClassDef, &pSystemTime, &SystemTime);
  307. hr = m_pWin32Clock->SendEvent(pSystemTime);
  308. #endif
  309. }
  310. else
  311. hr = WBEM_E_FAILED;
  312. }
  313. }
  314. return hr;
  315. }
  316. /******************************************************************/
  317. LRESULT CALLBACK Win32ClockProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  318. {
  319. return DefWindowProc(hWnd, msg, wParam, lParam);
  320. }
  321. DWORD CWin32Clock::AsyncEventThread(LPVOID pArg)
  322. {
  323. if(NULL == pArg)
  324. return -1;
  325. CWin32Clock
  326. *pCWin32Clock = (CWin32Clock*)pArg;
  327. WNDCLASS wndclass;
  328. MSG msg;
  329. BOOL bRet;
  330. // **** create top level window to receive system messages
  331. wndclass.style = 0;
  332. wndclass.lpfnWndProc = Win32ClockProc;
  333. wndclass.cbClsExtra = 0;
  334. wndclass.cbWndExtra = sizeof(DWORD);
  335. wndclass.hInstance = GetModuleHandle(NULL);
  336. wndclass.hIcon = NULL;
  337. wndclass.hCursor = NULL;
  338. wndclass.hbrBackground = NULL;
  339. wndclass.lpszMenuName = NULL;
  340. wndclass.lpszClassName = TEXT("Win32Clock");
  341. if(!RegisterClass(&wndclass))
  342. {
  343. if(GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
  344. {
  345. return NULL;
  346. }
  347. }
  348. HMODULE
  349. hModule = GetModuleHandle(NULL);
  350. if(NULL == hModule)
  351. return -1;
  352. try
  353. {
  354. pCWin32Clock->m_hEventWindowHandle = CreateWindow(TEXT("Win32Clock"),
  355. TEXT("Win32ClockMsgs"),
  356. WS_OVERLAPPED,
  357. CW_USEDEFAULT,
  358. CW_USEDEFAULT,
  359. CW_USEDEFAULT,
  360. CW_USEDEFAULT,
  361. HWND_MESSAGE,
  362. NULL,
  363. hModule,
  364. NULL);
  365. }
  366. catch(...)
  367. {
  368. return -1;
  369. }
  370. if(NULL == pCWin32Clock->m_hEventWindowHandle)
  371. {
  372. return NULL;
  373. }
  374. ShowWindow(pCWin32Clock->m_hEventWindowHandle, SW_HIDE);
  375. // **** start the message loop
  376. while(GetMessage(&msg, pCWin32Clock->m_hEventWindowHandle, 0, 0))
  377. {
  378. switch (msg.message)
  379. {
  380. case WM_TIMECHANGE:
  381. pCWin32Clock->ReAlignToCurrentTime();
  382. break;
  383. default:
  384. DefWindowProc(pCWin32Clock->m_hEventWindowHandle, msg.message, msg.wParam, msg.lParam);
  385. }
  386. }
  387. // **** cleanup
  388. bRet = DestroyWindow(pCWin32Clock->m_hEventWindowHandle);
  389. bRet = UnregisterClass(TEXT("Win32Clock"), 0);
  390. return 0;
  391. }
  392. void CWin32Clock::CScheduledEvent::GetTime(SYSTEMTIME *TheTime) const
  393. {
  394. if(NULL != TheTime)
  395. {
  396. memset(TheTime, 0, sizeof(SYSTEMTIME));
  397. if(TypeLocal == m_Type)
  398. GetLocalTime(TheTime);
  399. else if(TypeUTC == m_Type)
  400. GetSystemTime(TheTime);
  401. }
  402. }
  403. void CWin32Clock::CScheduledEvent::GetFileTime(FILETIME *TheTime) const
  404. {
  405. SYSTEMTIME
  406. SysTime;
  407. if(NULL != TheTime)
  408. {
  409. memset(TheTime, 0, sizeof(FILETIME));
  410. if(TypeLocal == m_Type)
  411. {
  412. GetLocalTime(&SysTime);
  413. SystemTimeToFileTime(&SysTime, TheTime);
  414. }
  415. else if(TypeUTC == m_Type)
  416. {
  417. GetSystemTime(&SysTime);
  418. SystemTimeToFileTime(&SysTime, TheTime);
  419. }
  420. }
  421. }
  422. HRESULT CWin32Clock::SendEvent(IWbemClassObject *pSystemTime)
  423. {
  424. HRESULT
  425. hr = WBEM_E_FAILED;
  426. CComPtr<IWbemClassObject>
  427. pInstanceModEvnt;
  428. CComVariant
  429. v;
  430. // **** if m_pSink has not been provided by winmgmt just drop
  431. // **** generated events on the floor
  432. if((NULL != m_pSink) && (NULL != pSystemTime))
  433. {
  434. // **** create and init instance of __InstanceModificationEvent
  435. hr = m_pInstModClassDef->SpawnInstance(0, &pInstanceModEvnt);
  436. if(FAILED(hr)) return hr;
  437. // **** put Win32_CurrentTime into __InstanceModificationEvent
  438. v.vt = VT_UNKNOWN;
  439. v.punkVal = NULL;
  440. hr = pSystemTime->QueryInterface(IID_IUnknown, (void**)&(v.punkVal));
  441. if(FAILED(hr)) return hr;
  442. hr = pInstanceModEvnt->Put(L"TargetInstance", 0, &v, 0);
  443. if(FAILED(hr)) return hr;
  444. // **** deliver new event to WMI
  445. hr = m_pSink->Indicate(1, &pInstanceModEvnt);
  446. }
  447. return hr;
  448. }
  449. HRESULT CWin32Clock::ReAlignToCurrentTime()
  450. {
  451. CInCritSec
  452. ics(&m_csWin32Clock);
  453. HRESULT
  454. hr = S_OK;
  455. ULONG
  456. i,
  457. nElts;
  458. CScheduledEvent
  459. *pcEvent;
  460. #ifdef WQLDEBUG
  461. printf("System Clock Resync\n");
  462. #endif
  463. m_EventArray.Lock();
  464. nElts = *(ULONG *)(&(this->m_EventArray)); // voodoo
  465. m_MostRecentLocalFiringTime = 0;
  466. m_MostRecentUTCFiringTime = 0;
  467. for(i = 0; i < nElts; i++)
  468. {
  469. // **** pull event from the event queue
  470. pcEvent = m_EventArray[i];
  471. if(NULL != pcEvent)
  472. {
  473. // **** change time for event obj and re-queue
  474. m_Timer.Remove(&CIdentityTest(pcEvent));
  475. m_Timer.Set(pcEvent);
  476. }
  477. }
  478. m_EventArray.UnLock();
  479. return hr;
  480. }
  481. CWin32Clock::CWin32Clock(CLifeControl* pControl)
  482. : m_Timer(), m_EventArray(), m_pControl(pControl)
  483. {
  484. pControl->ObjectCreated((IWbemServices*)this);
  485. m_cRef = 0;
  486. m_MostRecentLocalFiringTime = 0;
  487. m_MostRecentUTCFiringTime = 0;
  488. m_pNs = NULL;
  489. m_pSink = NULL;
  490. m_pInstModClassDef = NULL;
  491. m_pLocalTimeClassDef = NULL;
  492. m_pUTCTimeClassDef = NULL;
  493. m_ClockResetThread = NULL;
  494. m_hEventWindowHandle = NULL;
  495. }
  496. CWin32Clock::~CWin32Clock(void)
  497. {
  498. // **** Kill Async thread if it has been started
  499. if(NULL != m_ClockResetThread)
  500. {
  501. BOOL
  502. bRes;
  503. do
  504. {
  505. bRes = PostMessage(m_hEventWindowHandle, WM_QUIT, 0, 0);
  506. }
  507. while(WAIT_TIMEOUT == WaitForSingleObject(m_ClockResetThread, 6000));
  508. }
  509. // **** shutdown event thread
  510. m_Timer.Shutdown();
  511. // **** release all held COM objects
  512. if(NULL != m_pNs) m_pNs->Release();
  513. if(NULL != m_pSink) m_pSink->Release();
  514. if(NULL != m_pInstModClassDef) m_pInstModClassDef->Release();
  515. if(NULL != m_pLocalTimeClassDef) m_pLocalTimeClassDef->Release();
  516. if(NULL != m_pUTCTimeClassDef) m_pUTCTimeClassDef->Release();
  517. m_pControl->ObjectDestroyed((IWbemServices*)this);
  518. }
  519. // **** ***************************************************************************
  520. // ****
  521. // **** CWin32Clock::QueryInterface
  522. // **** CWin32Clock::AddRef
  523. // **** CWin32Clock::Release
  524. // ****
  525. // **** Purpose: IUnknown members for CWin32Clock object.
  526. // **** ***************************************************************************
  527. STDMETHODIMP CWin32Clock::QueryInterface(REFIID riid, PVOID *ppv)
  528. {
  529. *ppv=NULL;
  530. // **** cast to the type of the base class specified by riid
  531. if(IID_IWbemEventProvider == riid)
  532. {
  533. *ppv = (IWbemEventProvider *)this;
  534. }
  535. else if(IID_IWbemEventProviderQuerySink == riid)
  536. {
  537. *ppv = (IWbemEventProviderQuerySink *)this;
  538. }
  539. else if(IID_IWbemServices == riid)
  540. {
  541. *ppv=(IWbemServices*)this;
  542. }
  543. else if(IID_IUnknown == riid || IID_IWbemProviderInit == riid)
  544. {
  545. *ppv=(IWbemProviderInit*)this;
  546. }
  547. if(NULL!=*ppv)
  548. {
  549. AddRef();
  550. return S_OK;
  551. }
  552. else
  553. return E_NOINTERFACE;
  554. }
  555. STDMETHODIMP_(ULONG) CWin32Clock::AddRef(void)
  556. {
  557. return InterlockedIncrement((long *)&m_cRef);
  558. }
  559. STDMETHODIMP_(ULONG) CWin32Clock::Release(void)
  560. {
  561. ULONG nNewCount = InterlockedDecrement((long *)&m_cRef);
  562. if(0L == nNewCount)
  563. delete this;
  564. return nNewCount;
  565. }
  566. /*
  567. IWbemProviderInit::Initialize
  568. Purpose: This is the implementation of IWbemProviderInit. The method
  569. is need to initialize with CIMOM.
  570. The members set up include:
  571. m_pNs
  572. m_pLocalTimeClassDef
  573. m_pUTCTimeClassDef
  574. m_pInstModClassDef
  575. */
  576. HRESULT CWin32Clock::Initialize(LPWSTR pszUser,
  577. LONG lFlags,
  578. LPWSTR pszNamespace,
  579. LPWSTR pszLocale,
  580. IWbemServices *pNamespace,
  581. IWbemContext *pCtx,
  582. IWbemProviderInitSink *pInitSink)
  583. {
  584. HRESULT
  585. hr = WBEM_E_FAILED;
  586. if((NULL != pNamespace) && (NULL != pInitSink))
  587. {
  588. m_pNs = pNamespace;
  589. m_pNs->AddRef();
  590. // **** get needed class definitions
  591. hr = m_pNs->GetObject(WIN32LOCALTIMECLASS,
  592. 0, pCtx, &m_pLocalTimeClassDef, 0);
  593. if(SUCCEEDED(hr))
  594. hr = m_pNs->GetObject(WIN32UTCTIMECLASS,
  595. 0, pCtx, &m_pUTCTimeClassDef, 0);
  596. if(SUCCEEDED(hr))
  597. hr = m_pNs->GetObject(INSTMODEVCLASS,
  598. 0, pCtx, &m_pInstModClassDef, 0);
  599. if(WBEM_S_NO_ERROR == hr)
  600. {
  601. pInitSink->SetStatus(WBEM_S_INITIALIZED,0);
  602. hr = WBEM_NO_ERROR;
  603. }
  604. }
  605. // **** if there was a problem, release the resources we have aquired
  606. if(FAILED(hr))
  607. {
  608. if(NULL != m_pLocalTimeClassDef) { m_pLocalTimeClassDef->Release(); m_pLocalTimeClassDef = NULL; }
  609. if(NULL != m_pUTCTimeClassDef) { m_pUTCTimeClassDef->Release(); m_pUTCTimeClassDef = NULL; }
  610. if(NULL != m_pInstModClassDef) { m_pInstModClassDef->Release(); m_pInstModClassDef = NULL; }
  611. }
  612. return hr;
  613. }
  614. /*
  615. IWbemEventProvider::ProvideEvents
  616. Purpose: register to provide events to the WMI service
  617. */
  618. HRESULT CWin32Clock::ProvideEvents(IWbemObjectSink *pSink,
  619. long lFlags)
  620. {
  621. HRESULT
  622. hr = WBEM_S_NO_ERROR;
  623. // **** copy object sink for future event registrations
  624. m_pSink = pSink;
  625. if(NULL != m_pSink)
  626. m_pSink->AddRef();
  627. else
  628. hr = WBEM_E_FAILED;
  629. // **** start system clock change adj. thread
  630. DWORD dwThreadId;
  631. if(NULL == m_ClockResetThread)
  632. {
  633. m_ClockResetThread = CreateThread(
  634. NULL, // pointer to thread security attributes
  635. 0, // initial thread stack size, in bytes
  636. (LPTHREAD_START_ROUTINE)AsyncEventThread, // pointer to thread function
  637. (LPVOID)this, // argument for new thread
  638. 0, // creation flags
  639. &dwThreadId); // pointer to returned thread identifier
  640. if(NULL == m_ClockResetThread)
  641. hr = WBEM_E_FAILED;
  642. }
  643. else
  644. hr = WBEM_E_FAILED;
  645. return hr;
  646. }
  647. /*
  648. IWbemEventProviderQuerySink::NewQuery
  649. Purpose: add a new query for event generation
  650. */
  651. HRESULT CWin32Clock::NewQuery(ULONG dwId,
  652. wchar_t *wszQueryLanguage,
  653. wchar_t *wszQuery)
  654. {
  655. HRESULT
  656. hr = WBEM_E_FAILED;
  657. CScheduledEvent
  658. *pNewEvent = NULL;
  659. if(wbem_wcsicmp(L"WQL", wszQueryLanguage) || (NULL == wszQuery))
  660. return WBEM_E_FAILED;
  661. // **** see if event obj with dwId is already in queue
  662. pNewEvent = m_EventArray(dwId, TRUE); // find registered event query
  663. if(NULL != pNewEvent)
  664. {
  665. #ifdef WQLDEBUG
  666. printf("[%d] Redefinition: %s\n", dwId, wszQuery);
  667. #endif
  668. if(wbem_wcsicmp(wszQuery, pNewEvent->m_WQLStmt))
  669. {
  670. hr = m_Timer.Remove(&CIdentityTest(pNewEvent)); // may or may not be in queue
  671. hr = pNewEvent->ReInit(wszQuery); // on failure, NewEvent is preserved
  672. m_Timer.Set(pNewEvent);
  673. }
  674. m_EventArray.UnLock();
  675. }
  676. // **** this is a new event, create it and place it in the event queue
  677. else
  678. {
  679. #ifdef WQLDEBUG
  680. printf("[%d] Definition: %s\n", dwId, wszQuery);
  681. #endif
  682. // **** create new event and initialize
  683. pNewEvent = new CScheduledEvent();
  684. if(NULL == pNewEvent)
  685. hr = WBEM_E_OUT_OF_MEMORY;
  686. else
  687. {
  688. pNewEvent->AddRef();
  689. hr = pNewEvent->Init(this, wszQuery, dwId);
  690. // **** add event to queue
  691. if(SUCCEEDED(hr))
  692. {
  693. m_EventArray.Insert(pNewEvent, dwId);
  694. hr = m_Timer.Set(pNewEvent);
  695. }
  696. else
  697. {
  698. pNewEvent->Release();
  699. pNewEvent = NULL;
  700. }
  701. }
  702. }
  703. return hr;
  704. }
  705. /*
  706. IWbemEventProviderQuerySink::CancelQuery
  707. Purpose: remove an event generator from the queue
  708. */
  709. HRESULT CWin32Clock::CancelQuery(ULONG dwId)
  710. {
  711. CInCritSec
  712. ics(&m_csWin32Clock);
  713. CScheduledEvent
  714. *pDeadEvent = NULL;
  715. HRESULT hr = WBEM_S_NO_ERROR;
  716. // **** first find element in list and remove it
  717. pDeadEvent = m_EventArray(dwId, TRUE);
  718. if(NULL != pDeadEvent)
  719. {
  720. m_EventArray.Remove(pDeadEvent);
  721. m_EventArray.UnLock();
  722. hr = m_Timer.Remove(&CIdentityTest(pDeadEvent));
  723. // **** now kill it dead
  724. pDeadEvent->Release();
  725. pDeadEvent = NULL;
  726. }
  727. return hr;
  728. }
  729. /*
  730. IWbemServices::CreateInstanceEnumAsync
  731. Purpose: Asynchronously enumerates the instances.
  732. */
  733. HRESULT CWin32Clock::CreateInstanceEnumAsync(const BSTR RefStr,
  734. long lFlags,
  735. IWbemContext *pCtx,
  736. IWbemObjectSink FAR* pHandler)
  737. {
  738. HRESULT
  739. sc = WBEM_E_FAILED;
  740. IWbemClassObject
  741. FAR* pNewInst = NULL;
  742. SYSTEMTIME
  743. TheTime;
  744. // **** Do a check of arguments and make sure we have pointer to Namespace
  745. if(NULL == pHandler)
  746. {
  747. return WBEM_E_INVALID_PARAMETER;
  748. }
  749. // **** Create Win32_CurrentTime instance
  750. else if(0 == wbem_wcsicmp(RefStr, WIN32LOCALTIMECLASS))
  751. {
  752. GetLocalTime(&TheTime);
  753. sc = SystemTimeToWin32_CurrentTime(m_pLocalTimeClassDef, &pNewInst, &TheTime);
  754. // **** Send the object to the caller
  755. pHandler->Indicate(1,&pNewInst);
  756. pNewInst->Release();
  757. }
  758. // **** Create Win32_CurrentTime instance
  759. else if(0 == wbem_wcsicmp(RefStr, WIN32UTCTIMECLASS))
  760. {
  761. GetSystemTime(&TheTime);
  762. sc = SystemTimeToWin32_CurrentTime(m_pUTCTimeClassDef, &pNewInst, &TheTime);
  763. // **** Send the object to the caller
  764. pHandler->Indicate(1,&pNewInst);
  765. pNewInst->Release();
  766. }
  767. else if(0 == wbem_wcsicmp(RefStr, L"Win32_CurrentTime"))
  768. {}
  769. else
  770. {
  771. sc = WBEM_E_INVALID_CLASS;
  772. }
  773. // **** Set status
  774. pHandler->SetStatus(0, sc, NULL, NULL);
  775. return sc;
  776. }
  777. /*
  778. IWbemServices::GetObjectByPathAsync
  779. Purpose: Creates an instance given a particular path value.
  780. */
  781. HRESULT CWin32Clock::GetObjectAsync(const BSTR ObjectPath,
  782. long lFlags,
  783. IWbemContext *pCtx,
  784. IWbemObjectSink FAR* pHandler)
  785. {
  786. HRESULT
  787. sc = WBEM_E_FAILED;
  788. IWbemClassObject
  789. FAR* pObj = NULL;
  790. WCHAR
  791. *pwcTest = NULL,
  792. *pwcVALUE = NULL;
  793. CObjectPathParser
  794. ObjPath(e_ParserAcceptRelativeNamespace);
  795. ParsedObjectPath
  796. *pParsedObjectPath = NULL;
  797. SYSTEMTIME
  798. SystemTime;
  799. // **** Parse ObjectPath into a key member name and value
  800. // **** <CLASS>.<MEMBER>="<VALUE>"
  801. if(NULL == ObjectPath)
  802. return WBEM_E_INVALID_OBJECT_PATH;
  803. // **** parse object path
  804. if((ObjPath.NoError != ObjPath.Parse(ObjectPath, &pParsedObjectPath)) || (NULL == pParsedObjectPath))
  805. {
  806. ERRORTRACE((LOG_ESS, "Win32_LocalTime: Parse error for object: %S\n", ObjectPath));
  807. sc = WBEM_E_INVALID_QUERY;
  808. }
  809. // **** do the get, pass the object on to the notify
  810. if(0 == wbem_wcsicmp(WIN32LOCALTIMECLASS, pParsedObjectPath->m_pClass))
  811. {
  812. GetLocalTime(&SystemTime);
  813. sc = SystemTimeToWin32_CurrentTime(m_pLocalTimeClassDef, &pObj, &SystemTime);
  814. if(WBEM_S_NO_ERROR == sc)
  815. {
  816. pHandler->Indicate(1,&pObj);
  817. pObj->Release();
  818. }
  819. }
  820. else if(0 == wbem_wcsicmp(WIN32UTCTIMECLASS, pParsedObjectPath->m_pClass))
  821. {
  822. GetSystemTime(&SystemTime);
  823. sc = SystemTimeToWin32_CurrentTime(m_pUTCTimeClassDef, &pObj, &SystemTime);
  824. if(WBEM_S_NO_ERROR == sc)
  825. {
  826. pHandler->Indicate(1,&pObj);
  827. pObj->Release();
  828. }
  829. }
  830. else
  831. {
  832. ERRORTRACE((LOG_ESS, "Win32_LocalTime: Parse error for object: %S\n", ObjectPath));
  833. sc = WBEM_E_INVALID_QUERY;
  834. }
  835. // **** Set Status
  836. pHandler->SetStatus(0,sc, NULL, NULL);
  837. return sc;
  838. }
  839. /*
  840. CWin32Clock::CreateInstCurrentTime
  841. Purpose: creates an instance of the object Win32_CurrentTime representing
  842. the current time with the given offset UTCOffset
  843. */
  844. HRESULT CWin32Clock::SystemTimeToWin32_CurrentTime(IWbemClassObject *pClassDef, IWbemClassObject ** pNewInst, SYSTEMTIME *TheTime)
  845. {
  846. HRESULT
  847. sc = WBEM_E_FAILED;
  848. VARIANT
  849. v;
  850. // **** create blank instance of class InstTime
  851. sc = pClassDef->SpawnInstance(0, pNewInst);
  852. if(FAILED(sc))
  853. return sc;
  854. // **** Create Win32_CurrentTime instance
  855. v.vt = VT_I4;
  856. v.lVal = TheTime->wYear;
  857. sc = (*pNewInst)->Put(L"Year", 0, &v, 0);
  858. v.lVal = TheTime->wMonth;
  859. sc = (*pNewInst)->Put(L"Month", 0, &v, 0);
  860. v.lVal = TheTime->wDay;
  861. sc = (*pNewInst)->Put(L"Day", 0, &v, 0);
  862. v.lVal = TheTime->wDayOfWeek;
  863. sc = (*pNewInst)->Put(L"DayOfWeek", 0, &v, 0);
  864. v.lVal = (((8 - (TheTime->wDay - TheTime->wDayOfWeek + 7) % 7) % 7) + TheTime->wDay -1) / 7 + 1;
  865. sc = (*pNewInst)->Put(L"WeekInMonth", 0, &v, 0);
  866. v.lVal = (TheTime->wMonth - 1) / 3 + 1;
  867. sc = (*pNewInst)->Put(L"Quarter", 0, &v, 0);
  868. v.lVal = TheTime->wHour;
  869. sc = (*pNewInst)->Put(L"Hour", 0, &v, 0);
  870. v.lVal = TheTime->wMinute;
  871. sc = (*pNewInst)->Put(L"Minute", 0, &v, 0);
  872. v.lVal = TheTime->wSecond;
  873. sc = (*pNewInst)->Put(L"Second", 0, &v, 0);
  874. VariantClear(&v);
  875. return sc;
  876. }