WTimer.cpp
上传用户:dengkfang
上传日期:2008-12-30
资源大小:5233k
文件大小:10k
源码类别:

CA认证

开发平台:

Visual C++

  1. /*
  2. Module : WTimer.cpp
  3. Purpose: Implementation for an MFC wrapper class for waitable timers
  4. Created: PJN / 06-08-2000
  5. History: PJN / 08-11-2002 1. Removed some unnecessary comments in the module
  6.                           2. Updated copyright details in the module
  7.          PJN / 08-02-2004 1. Completion routine can now be passed an LPVOID parameter just like 
  8.                           the SDK equivalent. Thanks to Erenst F. Wepener for suggesting this 
  9.                           addition.
  10.                           2. Minor updates to the code to allow the code to compile on VC 5 
  11.                           without the requirement for the Platform SDK to be installed.
  12. Copyright (c) 2000 - 2004 by PJ Naughter.  (Web: www.naughter.com, Email: pjna@naughter.com)
  13. All rights reserved.
  14. Copyright / Usage Details:
  15. You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise) 
  16. when your product is released in binary form. You are allowed to modify the source code in any way you want 
  17. except you cannot modify the copyright details at the top of each module. If you want to distribute source 
  18. code with your application, then you are only allowed to distribute versions released by the author. This is 
  19. to maintain a single distribution point for the source code. 
  20. */
  21. //////////////// Includes ////////////////////////////////////////////
  22. #include "stdafx.h"
  23. #include "WTimer.h"
  24. //////////////// Macros / Locals /////////////////////////////////////
  25. #ifdef _DEBUG
  26. #define new DEBUG_NEW
  27. #undef THIS_FILE
  28. static char THIS_FILE[] = __FILE__;
  29. #endif
  30. //////////////// Implementation //////////////////////////////////////
  31. //Class which handles dynamically calling function which must be constructed at run time
  32. //since waitable timers are not implemented on NT 3.51 or Windows 95. To avoid the loader
  33. //bringing up a message such as "Failed to load due to missing export...", the
  34. //function is constructed using GetProcAddress. The CWaitableTimer function then checks 
  35. //to see if these function pointer is NULL and if it returns FALSE and sets the last error
  36. //to ERROR_CALL_NOT_IMPLEMENTED which is what 95/NT 3.51 would have done if it had implemented 
  37. //a stub for it in the first place !!
  38. class _WAITABLE_TIMER_DATA
  39. {
  40. public:
  41. //Constructors /Destructors
  42.   _WAITABLE_TIMER_DATA();
  43.   ~_WAITABLE_TIMER_DATA();
  44.   HINSTANCE m_hKernel32;
  45.   typedef HANDLE (__stdcall OPENWAITABLETIMER)(DWORD, BOOL, LPCTSTR);
  46.   typedef OPENWAITABLETIMER* LPOPENWAITABLETIMER;
  47.   typedef HANDLE (__stdcall CREATEWAITABLETIMER)(LPSECURITY_ATTRIBUTES, BOOL, LPCTSTR);
  48.   typedef CREATEWAITABLETIMER* LPCREATEWAITABLETIMER;
  49.   typedef VOID (APIENTRY *PTIMERAPCROUTINE)(LPVOID, DWORD, DWORD);
  50.   typedef BOOL (__stdcall SETWAITABLETIMER)(HANDLE, const LARGE_INTEGER*, LONG, PTIMERAPCROUTINE, LPVOID, BOOL);
  51.   typedef SETWAITABLETIMER* LPSETWAITABLETIMER;
  52.   typedef BOOL (__stdcall CANCELWAITABLETIMER)(HANDLE);
  53.   typedef CANCELWAITABLETIMER* LPCANCELWAITABLETIMER;
  54.   LPOPENWAITABLETIMER   m_lpfnOpenWaitableTimer;
  55.   LPCREATEWAITABLETIMER m_lpfnCreateWaitableTimer;
  56.   LPSETWAITABLETIMER    m_lpfnSetWaitableTimer;
  57.   LPCANCELWAITABLETIMER m_lpfnCancelWaitableTimer;
  58. };
  59. _WAITABLE_TIMER_DATA::_WAITABLE_TIMER_DATA()
  60. {
  61.   m_hKernel32 = LoadLibrary(_T("KERNEL32.DLL"));
  62.   VERIFY(m_hKernel32 != NULL);
  63. #ifdef _UNICODE
  64.   m_lpfnOpenWaitableTimer = (LPOPENWAITABLETIMER) GetProcAddress(m_hKernel32, "OpenWaitableTimerW");
  65.   m_lpfnCreateWaitableTimer = (LPCREATEWAITABLETIMER) GetProcAddress(m_hKernel32, "CreateWaitableTimerW");
  66. #else
  67.   m_lpfnOpenWaitableTimer = (LPOPENWAITABLETIMER) GetProcAddress(m_hKernel32, "OpenWaitableTimerA");
  68.   m_lpfnCreateWaitableTimer = (LPCREATEWAITABLETIMER) GetProcAddress(m_hKernel32, "CreateWaitableTimerA");
  69. #endif
  70.   m_lpfnSetWaitableTimer = (LPSETWAITABLETIMER) GetProcAddress(m_hKernel32, "SetWaitableTimer");
  71.   m_lpfnCancelWaitableTimer = (LPCANCELWAITABLETIMER) GetProcAddress(m_hKernel32, "CancelWaitableTimer");
  72. }
  73. _WAITABLE_TIMER_DATA::~_WAITABLE_TIMER_DATA()
  74. {
  75.   FreeLibrary(m_hKernel32);
  76.   m_hKernel32 = NULL;
  77. }
  78. //The local variable which handle the function pointers
  79. _WAITABLE_TIMER_DATA _WaitableTimerData;
  80. CWaitableTimer::CWaitableTimer()
  81. {
  82.   m_hTimer = NULL;
  83.   m_bSignalWhenSuspended = FALSE;
  84.   m_lpfnCompletionRoutine = NULL;
  85.   m_lpArgToCompletionRoutine = NULL;
  86. }
  87. CWaitableTimer::~CWaitableTimer()
  88. {
  89.   Close();
  90. }
  91. BOOL CWaitableTimer::Attach(HANDLE hTimer)
  92. {
  93.   Close();
  94.   m_hTimer = hTimer;
  95.   return TRUE;
  96. }
  97. HANDLE CWaitableTimer::Detach()
  98. {
  99.   HANDLE hReturn = m_hTimer;
  100.   m_hTimer = NULL;
  101.   return hReturn;
  102. }
  103. BOOL CWaitableTimer::Open(LPCTSTR pszName, BOOL bInherit, DWORD dwAccess)
  104. {
  105.   //Free up any existant timer
  106.   Close();
  107.   //Call the SDK function
  108.   if (_WaitableTimerData.m_lpfnOpenWaitableTimer)
  109.   {
  110.     m_hTimer = _WaitableTimerData.m_lpfnOpenWaitableTimer(dwAccess, bInherit, pszName);
  111.     return (m_hTimer != NULL);
  112.   }
  113.   else
  114.   {
  115.     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  116.     return FALSE;
  117.   }
  118. }
  119. BOOL CWaitableTimer::Create(BOOL bManualReset, LPCTSTR pszName, LPSECURITY_ATTRIBUTES lpTimerAttributes)
  120. {
  121.   //Free up any existant timer
  122.   Close();
  123.   //Call the SDK function
  124.   if (_WaitableTimerData.m_lpfnCreateWaitableTimer)
  125.   {
  126.     m_hTimer = _WaitableTimerData.m_lpfnCreateWaitableTimer(lpTimerAttributes, bManualReset, pszName);
  127.     return (m_hTimer != NULL);
  128.   }
  129.   else
  130.   {
  131.     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  132.     return FALSE;
  133.   }
  134. }
  135. void CWaitableTimer::Close()
  136. {
  137.   if (m_hTimer)
  138.   {
  139.     //Free up any existant timer
  140.     ::CloseHandle(m_hTimer);
  141.     m_hTimer = NULL;
  142.     m_bSignalWhenSuspended = FALSE;
  143.   }
  144. }
  145. BOOL CWaitableTimer::SetOnceOffAbsolute(const SYSTEMTIME& DueTime)
  146. {
  147.   ASSERT(m_hTimer); //Timer must be valid
  148.   //Call the SDK function
  149.   if (_WaitableTimerData.m_lpfnSetWaitableTimer)
  150.   {
  151.     //Convert from the SystemTime to the filetime struct
  152.     FILETIME ft;
  153.     if (!::SystemTimeToFileTime(&DueTime, &ft))
  154.     {
  155.       TRACE(_T("Failed in call to SystemTimeToFileTime in SetOnceOffAbsoluten"));
  156.       return FALSE;
  157.     }
  158.     LARGE_INTEGER li;
  159.     li.LowPart = ft.dwLowDateTime;
  160.     li.HighPart = ft.dwHighDateTime; 
  161.     return _WaitableTimerData.m_lpfnSetWaitableTimer(m_hTimer, &li, 0, m_lpfnCompletionRoutine ? 
  162.                                                      _CompletionRoutine : NULL, this, m_bSignalWhenSuspended);
  163.   }
  164.   else
  165.   {
  166.     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  167.     return FALSE;
  168.   }
  169. }
  170. BOOL CWaitableTimer::SetOnceOffRelative(DWORD dwMilliseconds)
  171. {
  172.   ASSERT(m_hTimer); //Timer must be valid
  173.   //Call the SDK function
  174.   if (_WaitableTimerData.m_lpfnSetWaitableTimer)
  175.   {
  176.     //Convert from the milliseconds to FILETIME representation (100-nanoseconds)
  177.     //We also need to make it negative
  178.     __int64 nFileTimes = ((__int64)-10000) * ((__int64)dwMilliseconds);
  179.     LARGE_INTEGER li;
  180.     li.LowPart = (DWORD) (nFileTimes & 0xFFFFFFFF);
  181.     li.HighPart = (LONG) (nFileTimes >> 32); 
  182.     return _WaitableTimerData.m_lpfnSetWaitableTimer(m_hTimer, &li, 0, m_lpfnCompletionRoutine ? 
  183.                                                      _CompletionRoutine : NULL, this, m_bSignalWhenSuspended);
  184.   }
  185.   else
  186.   {
  187.     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  188.     return FALSE;
  189.   }
  190. }
  191. BOOL CWaitableTimer::SetPeriodicAbsolute(const SYSTEMTIME& DueTime, DWORD dwPeriod)
  192. {
  193.   ASSERT(m_hTimer); //Timer must be valid
  194.   //Call the SDK function
  195.   if (_WaitableTimerData.m_lpfnSetWaitableTimer)
  196.   {
  197.     //Convert from the SystemTime to the filetime struct
  198.     FILETIME ft;
  199.     if (!::SystemTimeToFileTime(&DueTime, &ft))
  200.     {
  201.       TRACE(_T("Failed in call to SystemTimeToFileTime in SetPeriodicAbsoluten"));
  202.       return FALSE;
  203.     }
  204.     LARGE_INTEGER li;
  205.     li.LowPart = ft.dwLowDateTime;
  206.     li.HighPart = ft.dwHighDateTime; 
  207.     return _WaitableTimerData.m_lpfnSetWaitableTimer(m_hTimer, &li, dwPeriod, m_lpfnCompletionRoutine ? 
  208.                                                      _CompletionRoutine : NULL, this, m_bSignalWhenSuspended);
  209.   }
  210.   else
  211.   {
  212.     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  213.     return FALSE;
  214.   }
  215. }
  216. BOOL CWaitableTimer::SetPeriodicRelative(DWORD dwMilliseconds, DWORD dwPeriod)
  217. {
  218.   ASSERT(m_hTimer); //Timer must be valid
  219.   //Call the SDK function
  220.   if (_WaitableTimerData.m_lpfnSetWaitableTimer)
  221.   {
  222.     //Convert from the milliseconds to FILETIME representation (100-nanoseconds)
  223.     //We also need to make it negative
  224.     __int64 nFileTimes = ((__int64)-10000) * ((__int64)dwMilliseconds);
  225.     LARGE_INTEGER li;
  226.     li.LowPart = (DWORD) (nFileTimes & 0xFFFFFFFF);
  227.     li.HighPart = (LONG) (nFileTimes >> 32); 
  228.     return _WaitableTimerData.m_lpfnSetWaitableTimer(m_hTimer, &li, dwPeriod, m_lpfnCompletionRoutine ? 
  229.                                                      _CompletionRoutine : NULL, this, m_bSignalWhenSuspended);
  230.   }
  231.   else
  232.   {
  233.     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  234.     return FALSE;
  235.   }
  236. }
  237. BOOL CWaitableTimer::Cancel()
  238. {
  239.   ASSERT(m_hTimer); //Timer must be valid
  240.   //Call the SDK function
  241.   if (_WaitableTimerData.m_lpfnCancelWaitableTimer)
  242.     return _WaitableTimerData.m_lpfnCancelWaitableTimer(m_hTimer);
  243.   else
  244.   {
  245.     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  246.     return FALSE;
  247.   }
  248. }
  249. VOID CWaitableTimer::_CompletionRoutine(LPVOID lpArgToCompletionRoutine, DWORD dwTimerLowValue, DWORD dwTimerHighValue)
  250. {
  251.   //Convert from the SDK world to the C++ world
  252.   CWaitableTimer* pTimer = (CWaitableTimer*) lpArgToCompletionRoutine;
  253.   ASSERT(pTimer);
  254.   //Call the C++ callback method if there is one
  255.   if (pTimer->m_lpfnCompletionRoutine)
  256.   {
  257.     FILETIME ft;
  258.     ft.dwLowDateTime = dwTimerLowValue;
  259.     ft.dwHighDateTime = dwTimerHighValue;
  260.     //Call the C++ callback method
  261.     pTimer->m_lpfnCompletionRoutine(pTimer->m_lpArgToCompletionRoutine, ft);
  262.   }
  263. }