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.

1078 lines
26 KiB

  1. #include "pch.cxx"
  2. #pragma hdrstop
  3. #define TRKDATA_ALLOCATE
  4. #include "trkwks.hxx"
  5. const TCHAR *g_tszDefaultName = TEXT("TimerTestDefault");
  6. const TCHAR *g_tszContinueName = TEXT("TimerTestContinue");
  7. DWORD g_Debug = TRKDBG_ERROR | TRKDBG_TIMER;
  8. ULONG g_ulDefaultPeriod = 4; // Seconds
  9. ULONG g_ulMinRetry = g_ulDefaultPeriod * 3 / 2;
  10. ULONG g_ulMaxRetry = g_ulMinRetry * 4;
  11. ULONG g_ulTimerContext = 0;
  12. CFILETIME g_cftDeltaMargin = 10*1000*1000; // 1 second
  13. #include "ttimer.hxx"
  14. void
  15. CTimerTest::Initialize( PTimerCallback *pTimerCallback,
  16. const TCHAR *ptszName,
  17. ULONG ulTimerContext,
  18. ULONG ulPeriodInSeconds,
  19. CNewTimer::TimerRetryType retrytype,
  20. ULONG ulLowerRetryTime,
  21. ULONG ulUpperRetryTime,
  22. ULONG ulMaxLifetime )
  23. {
  24. _ptszName = ptszName;
  25. _fInitialized = TRUE;
  26. _timer.Initialize(pTimerCallback, ptszName,
  27. ulTimerContext, ulPeriodInSeconds, retrytype,
  28. ulLowerRetryTime, ulUpperRetryTime, ulMaxLifetime );
  29. _hEvent = CreateEvent( NULL, FALSE, FALSE, TEXT("TTimer Test") );
  30. if( INVALID_HANDLE_VALUE == _hEvent )
  31. TrkRaiseLastError( );
  32. }
  33. void
  34. CTimerTest::SetTimerRegistryValue( const TCHAR *ptszName,
  35. const CFILETIME &cftSet, const CFILETIME cftDue,
  36. ULONG ulRetry )
  37. {
  38. HKEY hkey;
  39. LONG lRet;
  40. if( ERROR_SUCCESS != RegOpenKeyEx( HKEY_LOCAL_MACHINE, s_tszKeyNameLinkTrack,
  41. 0, KEY_ALL_ACCESS, &hkey ))
  42. {
  43. TrkLog((TRKDBG_ERROR, TEXT("Couldn't open persistent registry key") ));
  44. TrkRaiseLastError( );
  45. }
  46. CNewTimer::PersistentState TimerPersistence;
  47. TimerPersistence.cftDue = cftDue;
  48. TimerPersistence.cftSet = cftSet;
  49. TimerPersistence.ulCurrentRetryTime = ulRetry;
  50. RegDeleteValue( hkey, ptszName );
  51. lRet = RegSetValueEx( hkey,
  52. ptszName,
  53. 0,
  54. REG_BINARY,
  55. (CONST BYTE *)&TimerPersistence,
  56. sizeof(TimerPersistence) );
  57. if( ERROR_SUCCESS != lRet )
  58. {
  59. TrkLog((TRKDBG_ERROR, TEXT("Couldn't write to registry") ));
  60. TrkRaiseWin32Error( lRet );
  61. }
  62. RegCloseKey( hkey );
  63. }
  64. void
  65. CTimerTest::VerifyRegistryDataCorrect()
  66. {
  67. LONG lRet = ERROR_SUCCESS;
  68. CFILETIME cftDelta(0), cftNow;
  69. CNewTimer::PersistentState persist;
  70. DWORD dwType = 0, cbData = sizeof(persist);
  71. HKEY hkey;
  72. lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, s_tszKeyNameLinkTrack,
  73. 0, KEY_ALL_ACCESS, &hkey );
  74. if( ERROR_SUCCESS != lRet )
  75. {
  76. TrkLog((TRKDBG_ERROR, TEXT("Couldn't open primary registry key")));
  77. TrkRaiseWin32Error( lRet );
  78. }
  79. lRet = RegQueryValueEx( hkey,
  80. _ptszName,
  81. NULL,
  82. &dwType,
  83. (BYTE *)&persist,
  84. &cbData );
  85. RegCloseKey( hkey );
  86. cftDelta = _cftExpected - persist.cftDue;
  87. if( lRet != ERROR_SUCCESS
  88. ||
  89. dwType != REG_BINARY
  90. ||
  91. cbData != sizeof(persist)
  92. ||
  93. persist.cftDue > _cftExpected
  94. ||
  95. cftDelta > g_cftDeltaMargin )
  96. {
  97. TrkLog(( TRKDBG_ERROR, TEXT("Registry data isn't correct (%d, %d, %d,\n %s,\n %s"),
  98. lRet, dwType, cbData, CDebugString(persist.cftDue)._tsz, CDebugString(_cftExpected)._tsz ));
  99. TrkRaiseWin32Error( E_FAIL );
  100. }
  101. }
  102. void
  103. CTimerTest::VerifyRegistryDataRemoved()
  104. {
  105. LONG lRet = ERROR_SUCCESS;
  106. CNewTimer::PersistentState persist;
  107. DWORD dwType = 0, cbData = sizeof(persist);
  108. HKEY hkey;
  109. lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, s_tszKeyNameLinkTrack,
  110. 0, KEY_ALL_ACCESS, &hkey );
  111. if( ERROR_SUCCESS != lRet )
  112. {
  113. TrkLog((TRKDBG_ERROR, TEXT("Couldn't open primary registry key")));
  114. TrkRaiseWin32Error( lRet );
  115. }
  116. lRet = RegQueryValueEx( hkey, g_tszDefaultName, NULL, &dwType, (BYTE*)&persist, &cbData );
  117. RegCloseKey( hkey );
  118. if( ERROR_FILE_NOT_FOUND != lRet )
  119. {
  120. TrkLog(( TRKDBG_ERROR, TEXT("Registry data wasn't removed") ));
  121. TrkRaiseWin32Error( E_FAIL );
  122. return;
  123. }
  124. return;
  125. }
  126. PTimerCallback::TimerContinuation
  127. CTimerTest0::Timer( ULONG ulTimerContext)
  128. {
  129. CFILETIME cftDelta(0);
  130. if( ulTimerContext != 0 )
  131. {
  132. TrkLog((TRKDBG_ERROR, TEXT("Incorrect context from timer")));
  133. TrkRaiseWin32Error( E_FAIL );
  134. }
  135. // Verify that we got called at approximately the right time.
  136. cftDelta = abs( static_cast<int>(CFILETIME() - _cftExpected) );
  137. if( cftDelta > g_cftDeltaMargin )
  138. {
  139. TrkLog((TRKDBG_ERROR, TEXT("Timer expired too late in phase 0")));
  140. TrkRaiseWin32Error( E_FAIL );
  141. }
  142. // Release the main test controller
  143. MarkTestCompleted();
  144. return( CONTINUE_TIMER );
  145. }
  146. PTimerCallback::TimerContinuation
  147. CTimerTest1::Timer( ULONG ulTimerContext)
  148. {
  149. TimerContinuation continuation = BREAK_TIMER;
  150. CFILETIME cftDelta(0), cftNow;
  151. CNewTimer::PersistentState persist;
  152. DWORD dwType = 0, cbData = sizeof(persist);
  153. HKEY hkey;
  154. LONG lRet = ERROR_SUCCESS;
  155. ULONG ulRetryPeriod;
  156. static CFILETIME cftBeforeRetries(0);
  157. if( ulTimerContext != 1 )
  158. {
  159. TrkLog((TRKDBG_ERROR, TEXT("Incorrect context from timer")));
  160. TrkRaiseWin32Error( E_FAIL );
  161. }
  162. // We shouldn't be called in the final sub-phase.
  163. if( FINAL == _SubPhase )
  164. {
  165. TrkLog(( TRKDBG_ERROR, TEXT("Called after the timer was stopped\n")));
  166. TrkRaiseWin32Error( E_FAIL );
  167. }
  168. // Verify that we got called at approximately the right time.
  169. cftDelta = abs(static_cast<int>(cftNow - _cftExpected));
  170. if( cftDelta > g_cftDeltaMargin )
  171. {
  172. TrkLog((TRKDBG_ERROR, TEXT("Timer expired too late in phase 1")));
  173. TrkRaiseWin32Error( E_FAIL );
  174. }
  175. // Verify that this time was stored in the Registry
  176. lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, s_tszKeyNameLinkTrack,
  177. 0, KEY_ALL_ACCESS, &hkey );
  178. if( ERROR_SUCCESS != lRet )
  179. {
  180. TrkLog((TRKDBG_ERROR, TEXT("Couldn't open primary registry key") ));
  181. TrkRaiseWin32Error( lRet );
  182. }
  183. lRet = RegQueryValueEx( hkey,
  184. _ptszName,
  185. NULL,
  186. &dwType,
  187. (BYTE *)&persist,
  188. &cbData );
  189. RegCloseKey( hkey );
  190. if( lRet != ERROR_SUCCESS
  191. ||
  192. dwType != REG_BINARY
  193. ||
  194. cbData != sizeof(persist)
  195. ||
  196. cftNow - persist.cftDue > g_cftDeltaMargin )
  197. {
  198. TrkLog((TRKDBG_ERROR, TEXT("Value in registry wasn't correct") ));
  199. TrkRaiseWin32Error( E_FAIL );
  200. }
  201. // -----------------------------
  202. // Move on to the next sub-phase
  203. // -----------------------------
  204. ulRetryPeriod = g_ulMinRetry;
  205. // Switch on the sub-phase which just completed.
  206. switch( _SubPhase )
  207. {
  208. case INITIAL:
  209. _tprintf( TEXT(" Letting recur\n") );
  210. continuation = CONTINUE_TIMER;
  211. _cftExpected.SetToUTC();
  212. _cftExpected.IncrementSeconds( g_ulDefaultPeriod );
  213. break;
  214. case THIRD_RETRY:
  215. case SECOND_RETRY:
  216. ulRetryPeriod *= 2;
  217. case FIRST_RETRY:
  218. ulRetryPeriod *= 2;
  219. case FIRST_RECURRENCE:
  220. _tprintf( TEXT(" Retrying timer (%ds)\n"), ulRetryPeriod );
  221. _cftExpected.SetToUTC();
  222. _cftExpected.IncrementSeconds( ulRetryPeriod );
  223. continuation = RETRY_TIMER;
  224. break;
  225. case FOURTH_RETRY:
  226. _tprintf( TEXT(" Letting timer recur\n") );
  227. continuation = CONTINUE_TIMER;
  228. _cftExpected.SetToUTC();
  229. _cftExpected.IncrementSeconds( g_ulDefaultPeriod );
  230. break;
  231. case SECOND_RECURRENCE:
  232. VerifyRegistryDataCorrect();
  233. _tprintf( TEXT(" Retrying one more time (%ds)\n"), g_ulMinRetry );
  234. _cftExpected.SetToUTC();
  235. _cftExpected.IncrementSeconds( g_ulMinRetry );
  236. continuation = RETRY_TIMER;
  237. break;
  238. case LAST_RETRY:
  239. _tprintf( TEXT(" Stopping timer\n") );
  240. continuation = BREAK_TIMER;
  241. MarkTestCompleted();
  242. break;
  243. default:
  244. TrkLog((TRKDBG_ERROR, TEXT("Invalid sub-phase in phase 1 (%d)"), _SubPhase ));
  245. TrkRaiseWin32Error( E_FAIL );
  246. break;
  247. } // switch
  248. _SubPhase++;
  249. return( continuation );
  250. }
  251. PTimerCallback::TimerContinuation
  252. CTimerTest2::Timer( ULONG ulTimerContext)
  253. {
  254. TimerContinuation continuation = BREAK_TIMER;
  255. CFILETIME cftDelta(0), cftNow;
  256. CNewTimer::PersistentState persist;
  257. DWORD dwType = 0, cbData = sizeof(persist);
  258. HKEY hkey;
  259. LONG lRet = ERROR_SUCCESS;
  260. ULONG ulRetryPeriod;
  261. static CFILETIME cftBeforeRetries(0);
  262. if( ulTimerContext != 2 )
  263. {
  264. TrkLog((TRKDBG_ERROR, TEXT("Incorrect context from timer")));
  265. TrkRaiseWin32Error( E_FAIL );
  266. }
  267. // We shouldn't be called in the final sub-phase.
  268. if( FINAL == _SubPhase )
  269. {
  270. TrkLog(( TRKDBG_ERROR, TEXT("Called after the timer was stopped\n")));
  271. TrkRaiseWin32Error( E_FAIL );
  272. }
  273. // Verify that we got called at approximately the right time.
  274. cftDelta = abs(static_cast<int>(cftNow - _cftExpected));
  275. if( cftDelta > g_cftDeltaMargin )
  276. {
  277. TrkLog((TRKDBG_ERROR, TEXT("Timer expired too late in phase 1")));
  278. TrkRaiseWin32Error( E_FAIL );
  279. }
  280. // -----------------------------
  281. // Move on to the next sub-phase
  282. // -----------------------------
  283. switch( _SubPhase )
  284. {
  285. case INITIAL:
  286. // Verify that the registry was set correctly
  287. VerifyRegistryDataCorrect();
  288. // Restart the timer to a new time
  289. _tprintf( TEXT(" Restarting timer (%ds), still recurring and non-retrying\n"),
  290. g_ulDefaultPeriod * 2 );
  291. _timer.ReInitialize( g_ulDefaultPeriod * 2 );
  292. continuation = CONTINUE_TIMER;
  293. _cftExpected.SetToUTC();
  294. _cftExpected.IncrementSeconds( g_ulDefaultPeriod * 2 );
  295. break;
  296. case RESET:
  297. // Verify that the registry was set correctly
  298. VerifyRegistryDataCorrect();
  299. // Release the main test controller
  300. MarkTestCompleted();
  301. break;
  302. default:
  303. TrkLog((TRKDBG_ERROR, TEXT("Invalid sub-phase in phase 2 (%d)"), _SubPhase ));
  304. TrkRaiseWin32Error( E_FAIL );
  305. break;
  306. } // switch( (SUB_PHASE2_ENUM) g_SubPhase )
  307. _SubPhase++;
  308. return( continuation );
  309. }
  310. PTimerCallback::TimerContinuation
  311. CTimerTest3::Timer( ULONG ulTimerContext)
  312. {
  313. TimerContinuation continuation = BREAK_TIMER;
  314. CFILETIME cftDelta(0), cftNow;
  315. if( ulTimerContext != 3 )
  316. {
  317. TrkLog((TRKDBG_ERROR, TEXT("Incorrect context from timer")));
  318. TrkRaiseWin32Error( E_FAIL );
  319. }
  320. // Verify that we got called at approximately the right time.
  321. cftDelta = abs(static_cast<int>(cftNow - _cftExpected));
  322. if( cftDelta > g_cftDeltaMargin )
  323. {
  324. TrkLog((TRKDBG_ERROR, TEXT("Timer expired too late in phase 3")));
  325. TrkRaiseWin32Error( E_FAIL );
  326. }
  327. // Switch on the sub-phase which *just completed* to determine what to
  328. // do next.
  329. switch( _SubPhase )
  330. {
  331. case INITIAL:
  332. VerifyRegistryDataCorrect();
  333. // We're done
  334. continuation = BREAK_TIMER;
  335. // Release the main test controller
  336. MarkTestCompleted();
  337. break;
  338. default:
  339. TrkLog((TRKDBG_ERROR, TEXT("Invalid sub-phase in phase 3 (%d)"), _SubPhase ));
  340. TrkRaiseWin32Error( E_FAIL );
  341. break;
  342. } // switch( _SubPhase )
  343. _SubPhase++;
  344. return( continuation );
  345. }
  346. PTimerCallback::TimerContinuation
  347. CTimerTest4::Timer( ULONG ulTimerContext)
  348. {
  349. TimerContinuation continuation = BREAK_TIMER;
  350. CFILETIME cftDelta(0), cftNow;
  351. if( ulTimerContext != 4 )
  352. {
  353. TrkLog((TRKDBG_ERROR, TEXT("Incorrect context from timer")));
  354. TrkRaiseWin32Error( E_FAIL );
  355. }
  356. // Verify that we got called at approximately the right time.
  357. cftDelta = abs(static_cast<int>(cftNow - _cftExpected));
  358. if( cftDelta > g_cftDeltaMargin )
  359. {
  360. TrkLog((TRKDBG_ERROR, TEXT("Timer expired too late in phase 1")));
  361. TrkRaiseWin32Error( E_FAIL );
  362. }
  363. // Switch on the sub-phase which *just completed* to determine what to
  364. // do next.
  365. switch( _SubPhase )
  366. {
  367. case INITIAL:
  368. _tprintf( TEXT(" Retrying (%ds)\n"), g_ulDefaultPeriod/2 );
  369. VerifyRegistryDataRemoved();
  370. continuation = RETRY_TIMER;
  371. _cftExpected.SetToUTC();
  372. _cftExpected.IncrementSeconds( g_ulDefaultPeriod / 2 );
  373. break;
  374. case SECOND:
  375. _tprintf( TEXT(" Retrying (%ds)\n"), g_ulDefaultPeriod );
  376. continuation = RETRY_TIMER;
  377. _cftExpected.SetToUTC();
  378. _cftExpected.IncrementSeconds( g_ulDefaultPeriod );
  379. break;
  380. case THIRD:
  381. _tprintf( TEXT(" Retrying (%ds)\n"), g_ulDefaultPeriod*2 );
  382. continuation = RETRY_TIMER;
  383. _cftExpected.SetToUTC();
  384. _cftExpected.IncrementSeconds( g_ulDefaultPeriod * 2 );
  385. break;
  386. case FOURTH:
  387. _tprintf( TEXT(" Retrying (%ds)\n"), g_ulDefaultPeriod/4 );
  388. continuation = RETRY_TIMER;
  389. _cftExpected.SetToUTC();
  390. _cftExpected.IncrementSeconds( g_ulDefaultPeriod / 4 );
  391. break;
  392. case FINAL:
  393. continuation = BREAK_TIMER;
  394. MarkTestCompleted();
  395. break;
  396. default:
  397. TrkLog((TRKDBG_ERROR, TEXT("Unexpected sub-phase in phase 4"), _SubPhase ));
  398. TrkRaiseWin32Error( E_FAIL );
  399. break;
  400. } // switch( _SubPhase )
  401. _SubPhase++;
  402. return( continuation );
  403. }
  404. PTimerCallback::TimerContinuation
  405. CTimerTest5::Timer( ULONG ulTimerContext)
  406. {
  407. TimerContinuation continuation = BREAK_TIMER;
  408. CFILETIME cftDelta(0), cftNow;
  409. if( ulTimerContext != 5 )
  410. {
  411. TrkLog((TRKDBG_ERROR, TEXT("Incorrect context from timer")));
  412. TrkRaiseWin32Error( E_FAIL );
  413. }
  414. // Verify that we got called at approximately the right time.
  415. cftDelta = abs(static_cast<int>(cftNow - _cftExpected));
  416. if( cftDelta > g_cftDeltaMargin )
  417. {
  418. TrkLog((TRKDBG_ERROR, TEXT("Timer expired too late in phase 1")));
  419. TrkRaiseWin32Error( E_FAIL );
  420. }
  421. // Switch on the sub-phase which *just completed* to determine what to
  422. // do next.
  423. switch( _SubPhase )
  424. {
  425. case INITIAL:
  426. continuation = BREAK_TIMER;
  427. VerifyRegistryDataRemoved(); // Since this is a non-persistent timer
  428. MarkTestCompleted();
  429. break;
  430. default:
  431. TrkLog((TRKDBG_ERROR, TEXT("Unexpected sub-phase in phase 5"), _SubPhase ));
  432. TrkRaiseWin32Error( E_FAIL );
  433. break;
  434. } // switch( _SubPhase )
  435. _SubPhase++;
  436. return( continuation );
  437. }
  438. PTimerCallback::TimerContinuation
  439. CTimerTest6::Timer( ULONG ulTimerContext )
  440. {
  441. CFILETIME cftDelta(0), cftNow;
  442. PTimerCallback::TimerContinuation continuation = BREAK_TIMER;
  443. if( ulTimerContext != 6 )
  444. {
  445. TrkLog((TRKDBG_ERROR, TEXT("Incorrect context from timer")));
  446. TrkRaiseWin32Error( E_FAIL );
  447. }
  448. // Validate the fire time
  449. if( _SubPhase == INITIAL )
  450. {
  451. cftDelta = abs(static_cast<int>(cftNow - _cftExpected));
  452. if( cftDelta > g_cftDeltaMargin )
  453. {
  454. TrkLog((TRKDBG_ERROR, TEXT("Timer expired too soon/late in phase 4") ));
  455. TrkRaiseWin32Error( E_FAIL );
  456. }
  457. }
  458. else
  459. {
  460. if( cftNow < _cftLower - g_cftDeltaMargin
  461. ||
  462. cftNow > _cftUpper + g_cftDeltaMargin )
  463. {
  464. TrkLog((TRKDBG_ERROR, TEXT("Timer expired too soon/late in phase 6") ));
  465. TrkRaiseWin32Error( E_FAIL );
  466. }
  467. }
  468. // Switch on the sub-phase which *just completed* to determine what to
  469. // do next.
  470. switch( _SubPhase )
  471. {
  472. case INITIAL:
  473. _tprintf( TEXT(" Letting recur\n") );
  474. continuation = CONTINUE_TIMER;
  475. // Set the due time
  476. _cftLastSet = _cftLower = cftNow;
  477. _cftLower.IncrementSeconds( g_ulDefaultPeriod );
  478. _cftUpper = _cftLower;
  479. break;
  480. case FIRST_RECURRENCE:
  481. _tprintf( TEXT(" Retrying ") );
  482. continuation = RETRY_TIMER;
  483. _cftLastSet = _cftLower = _cftUpper = cftNow;
  484. _cftLower.IncrementSeconds( g_ulMinRetry );
  485. _cftUpper.IncrementSeconds( g_ulMaxRetry );
  486. break;
  487. case FIRST_RETRY:
  488. case SECOND_RETRY:
  489. case THIRD_RETRY:
  490. // Show how long the retry was
  491. _tprintf( TEXT("(%2ds)\n"), static_cast<LONG>(cftNow-_cftLastSet)/10000000 );
  492. _tprintf( TEXT(" Retrying ") );
  493. continuation = RETRY_TIMER;
  494. _cftLastSet = _cftLower = _cftUpper = cftNow;
  495. _cftLower.IncrementSeconds( g_ulMinRetry );
  496. _cftUpper.IncrementSeconds( g_ulMaxRetry );
  497. break;
  498. case FOURTH_RETRY:
  499. // Show how long the retry was
  500. _tprintf( TEXT("(%2ds)\n"), static_cast<LONG>(cftNow-_cftLastSet)/10000000 );
  501. _tprintf( TEXT(" Recurring one last time (%ds)\n"), g_ulDefaultPeriod );
  502. continuation = CONTINUE_TIMER;
  503. _cftLastSet = _cftLower = cftNow;
  504. _cftLower.IncrementSeconds( g_ulDefaultPeriod );
  505. _cftUpper = _cftLower;
  506. break;
  507. case FINAL:
  508. continuation = BREAK_TIMER;
  509. MarkTestCompleted();
  510. break;
  511. default:
  512. TrkLog((TRKDBG_ERROR, TEXT("Unexpected sub-phase %d in test 6"), _SubPhase ));
  513. TrkRaiseWin32Error( E_FAIL );
  514. break;
  515. } // switch( (SUB_PHASE4_ENUM) g_SubPhase )
  516. _SubPhase++;
  517. return( continuation );
  518. }
  519. PTimerCallback::TimerContinuation
  520. CTimerTest7::Timer( ULONG ulTimerContext )
  521. {
  522. CFILETIME cftDelta(0), cftNow;
  523. PTimerCallback::TimerContinuation continuation = BREAK_TIMER;
  524. if( ulTimerContext != 7 )
  525. {
  526. TrkLog((TRKDBG_ERROR, TEXT("Incorrect context from timer")));
  527. TrkRaiseWin32Error( E_FAIL );
  528. }
  529. // Verify that we got called at approximately the right time.
  530. cftDelta = abs(static_cast<int>(cftNow - _cftExpected));
  531. if( cftDelta > g_cftDeltaMargin )
  532. {
  533. TrkLog((TRKDBG_ERROR, TEXT("Timer expired too late in phase 1")));
  534. TrkRaiseWin32Error( E_FAIL );
  535. }
  536. // Switch on the sub-phase which *just completed* to determine what to
  537. // do next.
  538. switch( _SubPhase )
  539. {
  540. case INITIAL:
  541. _tprintf( TEXT(" Starting again from the callback, while returning retry_timer\n") );
  542. _tprintf( TEXT(" Ensure the timer doesn't fire while we're in the callback\n") );
  543. Set();
  544. Sleep( _ulPeriod * 2 );
  545. _timer.Cancel();
  546. Set();
  547. continuation = RETRY_TIMER;
  548. break;
  549. case FINAL:
  550. continuation = BREAK_TIMER;
  551. MarkTestCompleted();
  552. break;
  553. default:
  554. TrkLog((TRKDBG_ERROR, TEXT("Unexpected sub-phase %d in test 7"), _SubPhase ));
  555. TrkRaiseWin32Error( E_FAIL );
  556. break;
  557. } // switch( g_SubPhase )
  558. _SubPhase++;
  559. return( continuation );
  560. }
  561. PTimerCallback::TimerContinuation
  562. CTimerTest8::Timer( ULONG ulTimerContext)
  563. {
  564. TimerContinuation continuation = BREAK_TIMER;
  565. CFILETIME cftDelta(0), cftNow;
  566. if( ulTimerContext != 8 )
  567. {
  568. TrkLog((TRKDBG_ERROR, TEXT("Incorrect context from timer")));
  569. TrkRaiseWin32Error( E_FAIL );
  570. }
  571. // Verify that we got called at approximately the right time.
  572. cftDelta = abs(static_cast<int>(cftNow - _cftExpected));
  573. if( cftDelta > g_cftDeltaMargin )
  574. {
  575. TrkLog((TRKDBG_ERROR, TEXT("Timer expired too late in phase 8 (%s - %s)"),
  576. CDebugString(cftNow)._tsz, CDebugString(_cftExpected)._tsz ));
  577. TrkRaiseWin32Error( E_FAIL );
  578. }
  579. // Switch on the sub-phase which *just completed* to determine what to
  580. // do next.
  581. switch( _SubPhase )
  582. {
  583. case INITIAL:
  584. continuation = RETRY_TIMER;
  585. _cftExpected = CFILETIME();
  586. _cftExpected.IncrementSeconds( _ulPeriod*4 ); // The second retry
  587. break;
  588. case FIRST_RETRY:
  589. continuation = RETRY_TIMER;
  590. _cftExpected = CFILETIME();
  591. _cftExpected.IncrementSeconds( _ulPeriod ); // Up to max lifetime
  592. break;
  593. case FINAL:
  594. continuation = BREAK_TIMER;
  595. MarkTestCompleted();
  596. break;
  597. default:
  598. TrkLog((TRKDBG_ERROR, TEXT("Unexpected sub-phase in phase 8"), _SubPhase ));
  599. TrkRaiseWin32Error( E_FAIL );
  600. break;
  601. } // switch( _SubPhase )
  602. _SubPhase++;
  603. return( continuation );
  604. }
  605. BOOL
  606. IsRegistryEntryExtant()
  607. {
  608. LONG lRet = ERROR_SUCCESS;
  609. CNewTimer::PersistentState persist;
  610. DWORD dwType = 0, cbData = sizeof(persist);
  611. HKEY hkey;
  612. lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, s_tszKeyNameLinkTrack,
  613. 0, KEY_ALL_ACCESS, &hkey );
  614. if( ERROR_SUCCESS != lRet )
  615. {
  616. TrkLog((TRKDBG_ERROR, TEXT("Couldn't open primary registry key")));
  617. TrkRaiseWin32Error( lRet );
  618. }
  619. lRet = RegQueryValueEx( hkey, g_tszDefaultName, NULL, &dwType, (BYTE*)&persist, &cbData );
  620. RegCloseKey( hkey );
  621. if( ERROR_FILE_NOT_FOUND == lRet )
  622. return FALSE;
  623. else
  624. return TRUE;
  625. }
  626. BOOL
  627. IsRegistryEntryCorrect( const CFILETIME &cftExpected )
  628. {
  629. LONG lRet = ERROR_SUCCESS;
  630. CFILETIME cftDelta(0), cftNow;
  631. CNewTimer::PersistentState persist;
  632. DWORD dwType = 0, cbData = sizeof(persist);
  633. HKEY hkey;
  634. lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, s_tszKeyNameLinkTrack,
  635. 0, KEY_ALL_ACCESS, &hkey );
  636. if( ERROR_SUCCESS != lRet )
  637. {
  638. TrkLog((TRKDBG_ERROR, TEXT("Couldn't open primary registry key")));
  639. TrkRaiseWin32Error( lRet );
  640. }
  641. lRet = RegQueryValueEx( hkey,
  642. g_tszDefaultName,
  643. NULL,
  644. &dwType,
  645. (BYTE *)&persist,
  646. &cbData );
  647. RegCloseKey( hkey );
  648. cftDelta = cftExpected - persist.cftDue;
  649. if( lRet != ERROR_SUCCESS
  650. ||
  651. dwType != REG_BINARY
  652. ||
  653. cbData != sizeof(persist)
  654. ||
  655. persist.cftDue > cftExpected
  656. ||
  657. cftDelta > g_cftDeltaMargin )
  658. {
  659. return FALSE;
  660. }
  661. else
  662. {
  663. return TRUE;
  664. }
  665. }
  666. EXTERN_C void __cdecl _tmain( int argc, TCHAR **argv )
  667. {
  668. HRESULT hr = S_OK;
  669. CNewTimer::PersistentState TimerPersistence;
  670. __try
  671. {
  672. LONG lRet = ERROR_SUCCESS;
  673. ULONG ulMaxLifetime;
  674. CFILETIME cftTimer0(0);
  675. TrkDebugCreate( TRK_DBG_FLAGS_WRITE_TO_DBG | TRK_DBG_FLAGS_WRITE_TO_STDOUT, "TTimer" );
  676. RegDeleteValue( HKEY_LOCAL_MACHINE, s_tszKeyNameLinkTrack );
  677. CTimerTest0 cTimer0;
  678. CTimerTest1 cTimer1;
  679. CTimerTest2 cTimer2;
  680. CTimerTest3 cTimer3;
  681. CTimerTest4 cTimer4;
  682. CTimerTest5 cTimer5;
  683. CTimerTest6 cTimer6;
  684. CTimerTest7 cTimer7;
  685. CTimerTest8 cTimer8;
  686. //goto phase8;
  687. // -------
  688. // Phase 0
  689. // -------
  690. cTimer0.Initialize( );
  691. cTimer0.Set();
  692. cTimer0.WaitForTestToComplete();
  693. cTimer0.EnsureTimerIsStopped( );
  694. // -------
  695. // Phase 1
  696. // -------
  697. phase1:
  698. cTimer1.Initialize( );
  699. cTimer1.Set();
  700. cTimer1.WaitForTestToComplete();
  701. cTimer1.EnsureTimerIsStopped( );
  702. // -------
  703. // Phase 2
  704. // -------
  705. cTimer2.Initialize( );
  706. cTimer2.Set();
  707. cTimer2.WaitForTestToComplete();
  708. cTimer2.EnsureTimerIsStopped( );
  709. // -------
  710. // Phase 3
  711. // -------
  712. phase3:
  713. cTimer3.Initialize();
  714. cTimer3.Set();
  715. cTimer3.WaitForTestToComplete();
  716. cTimer3.EnsureTimerIsStopped();
  717. // Pause to ensure that the timer clears itself
  718. Sleep( 1000 );
  719. // -------
  720. // Phase 4
  721. // -------
  722. cTimer4.Initialize();
  723. cTimer4.Set();
  724. cTimer4.WaitForTestToComplete();
  725. cTimer3.EnsureTimerIsStopped();
  726. // -------
  727. // Phase 5
  728. // -------
  729. phase5:
  730. cTimer5.Initialize();
  731. cTimer5.Set();
  732. cTimer5.WaitForTestToComplete();
  733. cTimer5.EnsureTimerIsStopped();
  734. // -------
  735. // Phase 6
  736. // -------
  737. phase6:
  738. cTimer6.Initialize( );
  739. cTimer6.Set();
  740. cTimer6.WaitForTestToComplete();
  741. cTimer6.EnsureTimerIsStopped( );
  742. phase7:
  743. cTimer7.Initialize();
  744. cTimer7.Set();
  745. cTimer7.WaitForTestToComplete();
  746. cTimer7.EnsureTimerIsStopped();
  747. phase8:
  748. cTimer8.Initialize();
  749. cTimer8.Set();
  750. cTimer8.WaitForTestToComplete();
  751. cTimer8.EnsureTimerIsStopped();
  752. }
  753. __except( BreakOnDebuggableException() )
  754. {
  755. hr = GetExceptionCode();
  756. }
  757. if( FAILED(hr) )
  758. _tprintf( TEXT("\nFailed: hr = %#08x\n"), hr );
  759. else
  760. _tprintf( TEXT("\nPassed\n") );
  761. }