Source code of Windows XP (NT5)
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.

895 lines
22 KiB

  1. // WTL Version 3.1
  2. // Copyright (C) 1997-2000 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This file is a part of Windows Template Library.
  6. // The code and information is provided "as-is" without
  7. // warranty of any kind, either expressed or implied.
  8. #ifndef __ATLAPP_H__
  9. #define __ATLAPP_H__
  10. #pragma once
  11. #ifndef __cplusplus
  12. #error ATL requires C++ compilation (use a .cpp suffix)
  13. #endif
  14. #ifndef __ATLBASE_H__
  15. #error atlapp.h requires atlbase.h to be included first
  16. #endif
  17. #if (WINVER < 0x0400)
  18. #error WTL requires Windows version 4.0 or higher
  19. #endif
  20. #include <limits.h>
  21. #if !defined(_ATL_MIN_CRT) & defined(_MT)
  22. #include <process.h> // for _beginthreadex, _endthreadex
  23. #endif
  24. #include <commctrl.h>
  25. #pragma comment(lib, "comctl32.lib")
  26. #include <atlres.h>
  27. // WTL version number
  28. #define _WTL_VER 0x0310
  29. // This is to support using original VC++ 6.0 headers with WTL
  30. #ifndef _ATL_NO_OLD_HEADERS_WIN64
  31. #if !defined(_WIN64) && !defined(_ATL_TMP_IMPL2)
  32. #ifndef GetWindowLongPtr
  33. #define GetWindowLongPtrA GetWindowLongA
  34. #define GetWindowLongPtrW GetWindowLongW
  35. #ifdef UNICODE
  36. #define GetWindowLongPtr GetWindowLongPtrW
  37. #else
  38. #define GetWindowLongPtr GetWindowLongPtrA
  39. #endif // !UNICODE
  40. #endif // !GetWindowLongPtr
  41. #ifndef SetWindowLongPtr
  42. #define SetWindowLongPtrA SetWindowLongA
  43. #define SetWindowLongPtrW SetWindowLongW
  44. #ifdef UNICODE
  45. #define SetWindowLongPtr SetWindowLongPtrW
  46. #else
  47. #define SetWindowLongPtr SetWindowLongPtrA
  48. #endif // !UNICODE
  49. #endif // !SetWindowLongPtr
  50. #ifndef GWLP_WNDPROC
  51. #define GWLP_WNDPROC (-4)
  52. #endif
  53. #ifndef GWLP_HINSTANCE
  54. #define GWLP_HINSTANCE (-6)
  55. #endif
  56. #ifndef GWLP_HWNDPARENT
  57. #define GWLP_HWNDPARENT (-8)
  58. #endif
  59. #ifndef GWLP_USERDATA
  60. #define GWLP_USERDATA (-21)
  61. #endif
  62. #ifndef GWLP_ID
  63. #define GWLP_ID (-12)
  64. #endif
  65. #ifndef DWLP_MSGRESULT
  66. #define DWLP_MSGRESULT 0
  67. #endif
  68. typedef long LONG_PTR;
  69. typedef unsigned long ULONG_PTR;
  70. typedef ULONG_PTR DWORD_PTR;
  71. #ifndef HandleToUlong
  72. #define HandleToUlong( h ) ((ULONG)(ULONG_PTR)(h) )
  73. #endif
  74. #ifndef HandleToLong
  75. #define HandleToLong( h ) ((LONG)(LONG_PTR) (h) )
  76. #endif
  77. #ifndef LongToHandle
  78. #define LongToHandle( h) ((HANDLE)(LONG_PTR) (h))
  79. #endif
  80. #ifndef PtrToUlong
  81. #define PtrToUlong( p ) ((ULONG)(ULONG_PTR) (p) )
  82. #endif
  83. #ifndef PtrToLong
  84. #define PtrToLong( p ) ((LONG)(LONG_PTR) (p) )
  85. #endif
  86. #ifndef PtrToUint
  87. #define PtrToUint( p ) ((UINT)(UINT_PTR) (p) )
  88. #endif
  89. #ifndef PtrToInt
  90. #define PtrToInt( p ) ((INT)(INT_PTR) (p) )
  91. #endif
  92. #ifndef PtrToUshort
  93. #define PtrToUshort( p ) ((unsigned short)(ULONG_PTR)(p) )
  94. #endif
  95. #ifndef PtrToShort
  96. #define PtrToShort( p ) ((short)(LONG_PTR)(p) )
  97. #endif
  98. #ifndef IntToPtr
  99. #define IntToPtr( i ) ((VOID *)(INT_PTR)((int)i))
  100. #endif
  101. #ifndef UIntToPtr
  102. #define UIntToPtr( ui ) ((VOID *)(UINT_PTR)((unsigned int)ui))
  103. #endif
  104. #ifndef LongToPtr
  105. #define LongToPtr( l ) ((VOID *)(LONG_PTR)((long)l))
  106. #endif
  107. #ifndef ULongToPtr
  108. #define ULongToPtr( ul ) ((VOID *)(ULONG_PTR)((unsigned long)ul))
  109. #endif
  110. #endif //!defined(_WIN64) && !defined(_ATL_TMP_IMPL2)
  111. #endif //!_ATL_NO_OLD_HEADERS_WIN64
  112. namespace WTL
  113. {
  114. enum wtlTraceFlags
  115. {
  116. atlTraceUI = 0x10000000
  117. };
  118. // Windows version helper
  119. inline bool AtlIsOldWindows()
  120. {
  121. OSVERSIONINFO ovi;
  122. ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  123. BOOL bRet = ::GetVersionEx(&ovi);
  124. return (!bRet || !((ovi.dwMajorVersion >= 5) || (ovi.dwMajorVersion == 4 && ovi.dwMinorVersion >= 90)));
  125. }
  126. // default GUI font helper
  127. inline HFONT AtlGetDefaultGuiFont()
  128. {
  129. return (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
  130. }
  131. /////////////////////////////////////////////////////////////////////////////
  132. // Forward declarations
  133. class CMessageFilter;
  134. class CIdleHandler;
  135. class CMessageLoop;
  136. class CAppModule;
  137. class CServerAppModule;
  138. #ifndef _ATL_TMP_IMPL2
  139. class _U_RECT;
  140. class _U_MENUorID;
  141. class _U_STRINGorID;
  142. #endif //!_ATL_TMP_IMPL2
  143. /////////////////////////////////////////////////////////////////////////////
  144. // CMessageFilter - Interface for message filter support
  145. class CMessageFilter
  146. {
  147. public:
  148. virtual BOOL PreTranslateMessage(MSG* pMsg) = 0;
  149. };
  150. /////////////////////////////////////////////////////////////////////////////
  151. // CIdleHandler - Interface for idle processing
  152. class CIdleHandler
  153. {
  154. public:
  155. virtual BOOL OnIdle() = 0;
  156. };
  157. #ifndef _ATL_NO_OLD_NAMES
  158. // for compatilibility with old names only
  159. typedef CIdleHandler CUpdateUIObject;
  160. #define DoUpdate OnIdle
  161. #endif //!_ATL_NO_OLD_NAMES
  162. /////////////////////////////////////////////////////////////////////////////
  163. // CMessageLoop - message loop implementation
  164. class CMessageLoop
  165. {
  166. public:
  167. CSimpleArray<CMessageFilter*> m_aMsgFilter;
  168. CSimpleArray<CIdleHandler*> m_aIdleHandler;
  169. MSG m_msg;
  170. // Message filter operations
  171. BOOL AddMessageFilter(CMessageFilter* pMessageFilter)
  172. {
  173. return m_aMsgFilter.Add(pMessageFilter);
  174. }
  175. BOOL RemoveMessageFilter(CMessageFilter* pMessageFilter)
  176. {
  177. return m_aMsgFilter.Remove(pMessageFilter);
  178. }
  179. // Idle handler operations
  180. BOOL AddIdleHandler(CIdleHandler* pIdleHandler)
  181. {
  182. return m_aIdleHandler.Add(pIdleHandler);
  183. }
  184. BOOL RemoveIdleHandler(CIdleHandler* pIdleHandler)
  185. {
  186. return m_aIdleHandler.Remove(pIdleHandler);
  187. }
  188. #ifndef _ATL_NO_OLD_NAMES
  189. // for compatilibility with old names only
  190. BOOL AddUpdateUI(CIdleHandler* pIdleHandler)
  191. {
  192. ATLTRACE2(atlTraceUI, 0, "CUpdateUIObject and AddUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n");
  193. return AddIdleHandler(pIdleHandler);
  194. }
  195. BOOL RemoveUpdateUI(CIdleHandler* pIdleHandler)
  196. {
  197. ATLTRACE2(atlTraceUI, 0, "CUpdateUIObject and RemoveUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n");
  198. return RemoveIdleHandler(pIdleHandler);
  199. }
  200. #endif //!_ATL_NO_OLD_NAMES
  201. // message loop
  202. int Run()
  203. {
  204. BOOL bDoIdle = TRUE;
  205. int nIdleCount = 0;
  206. BOOL bRet;
  207. for(;;)
  208. {
  209. while(!::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE) && bDoIdle)
  210. {
  211. if(!OnIdle(nIdleCount++))
  212. bDoIdle = FALSE;
  213. }
  214. bRet = ::GetMessage(&m_msg, NULL, 0, 0);
  215. if(bRet == -1)
  216. {
  217. ATLTRACE2(atlTraceUI, 0, _T("::GetMessage returned -1 (error)\n"));
  218. continue; // error, don't process
  219. }
  220. else if(!bRet)
  221. {
  222. ATLTRACE2(atlTraceUI, 0, _T("CMessageLoop::Run - exiting\n"));
  223. break; // WM_QUIT, exit message loop
  224. }
  225. if(!PreTranslateMessage(&m_msg))
  226. {
  227. ::TranslateMessage(&m_msg);
  228. ::DispatchMessage(&m_msg);
  229. }
  230. if(IsIdleMessage(&m_msg))
  231. {
  232. bDoIdle = TRUE;
  233. nIdleCount = 0;
  234. }
  235. }
  236. return (int)m_msg.wParam;
  237. }
  238. static BOOL IsIdleMessage(MSG* pMsg)
  239. {
  240. // These messages should NOT cause idle processing
  241. switch(pMsg->message)
  242. {
  243. case WM_MOUSEMOVE:
  244. case WM_NCMOUSEMOVE:
  245. case WM_PAINT:
  246. case 0x0118: // WM_SYSTIMER (caret blink)
  247. return FALSE;
  248. }
  249. return TRUE;
  250. }
  251. // Overrideables
  252. // Override to change message filtering
  253. virtual BOOL PreTranslateMessage(MSG* pMsg)
  254. {
  255. // loop backwards
  256. for(int i = m_aMsgFilter.GetSize() - 1; i >= 0; i--)
  257. {
  258. CMessageFilter* pMessageFilter = m_aMsgFilter[i];
  259. if(pMessageFilter != NULL && pMessageFilter->PreTranslateMessage(pMsg))
  260. return TRUE;
  261. }
  262. return FALSE; // not translated
  263. }
  264. // override to change idle processing
  265. virtual BOOL OnIdle(int /*nIdleCount*/)
  266. {
  267. for(int i = 0; i < m_aIdleHandler.GetSize(); i++)
  268. {
  269. CIdleHandler* pIdleHandler = m_aIdleHandler[i];
  270. if(pIdleHandler != NULL)
  271. pIdleHandler->OnIdle();
  272. }
  273. return FALSE; // don't continue
  274. }
  275. };
  276. /////////////////////////////////////////////////////////////////////////////
  277. // CAppModule - module class for an application
  278. class CAppModule : public CComModule
  279. {
  280. public:
  281. DWORD m_dwMainThreadID;
  282. CSimpleMap<DWORD, CMessageLoop*>* m_pMsgLoopMap;
  283. CSimpleArray<HWND>* m_pSettingChangeNotify;
  284. // Overrides of CComModule::Init and Term
  285. HRESULT Init(_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL)
  286. {
  287. HRESULT hRet = CComModule::Init(pObjMap, hInstance, pLibID);
  288. if(FAILED(hRet))
  289. return hRet;
  290. m_dwMainThreadID = ::GetCurrentThreadId();
  291. typedef CSimpleMap<DWORD, CMessageLoop*> mapClass;
  292. m_pMsgLoopMap = NULL;
  293. ATLTRY(m_pMsgLoopMap = new mapClass);
  294. if(m_pMsgLoopMap == NULL)
  295. return E_OUTOFMEMORY;
  296. m_pSettingChangeNotify = NULL;
  297. return hRet;
  298. }
  299. void Term()
  300. {
  301. if(m_pSettingChangeNotify != NULL && m_pSettingChangeNotify->GetSize() > 0)
  302. {
  303. ::DestroyWindow((*m_pSettingChangeNotify)[0]);
  304. }
  305. delete m_pSettingChangeNotify;
  306. delete m_pMsgLoopMap;
  307. CComModule::Term();
  308. }
  309. // Message loop map methods
  310. BOOL AddMessageLoop(CMessageLoop* pMsgLoop)
  311. {
  312. ATLASSERT(pMsgLoop != NULL);
  313. ATLASSERT(m_pMsgLoopMap->Lookup(::GetCurrentThreadId()) == NULL); // not in map yet
  314. return m_pMsgLoopMap->Add(::GetCurrentThreadId(), pMsgLoop);
  315. }
  316. BOOL RemoveMessageLoop()
  317. {
  318. return m_pMsgLoopMap->Remove(::GetCurrentThreadId());
  319. }
  320. CMessageLoop* GetMessageLoop(DWORD dwThreadID = ::GetCurrentThreadId()) const
  321. {
  322. return m_pMsgLoopMap->Lookup(dwThreadID);
  323. }
  324. // Setting change notify methods
  325. BOOL AddSettingChangeNotify(HWND hWnd)
  326. {
  327. ATLASSERT(::IsWindow(hWnd));
  328. if(m_pSettingChangeNotify == NULL)
  329. {
  330. typedef CSimpleArray<HWND> notifyClass;
  331. ATLTRY(m_pSettingChangeNotify = new notifyClass);
  332. ATLASSERT(m_pSettingChangeNotify != NULL);
  333. if(m_pSettingChangeNotify == NULL)
  334. return FALSE;
  335. }
  336. if(m_pSettingChangeNotify->GetSize() == 0)
  337. {
  338. // init everything
  339. _ATL_EMPTY_DLGTEMPLATE templ;
  340. HWND hNtfWnd = ::CreateDialogIndirect(GetModuleInstance(), &templ, NULL, _SettingChangeDlgProc);
  341. ATLASSERT(::IsWindow(hNtfWnd));
  342. if(::IsWindow(hNtfWnd))
  343. {
  344. ::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, (LONG_PTR)this);
  345. m_pSettingChangeNotify->Add(hNtfWnd);
  346. }
  347. }
  348. return m_pSettingChangeNotify->Add(hWnd);
  349. }
  350. BOOL RemoveSettingChangeNotify(HWND hWnd)
  351. {
  352. if(m_pSettingChangeNotify == NULL)
  353. return FALSE;
  354. return m_pSettingChangeNotify->Remove(hWnd);
  355. }
  356. // Implementation - setting change notify dialog template and dialog procedure
  357. struct _ATL_EMPTY_DLGTEMPLATE : DLGTEMPLATE
  358. {
  359. _ATL_EMPTY_DLGTEMPLATE()
  360. {
  361. memset(this, 0, sizeof(_ATL_EMPTY_DLGTEMPLATE));
  362. style = WS_POPUP;
  363. }
  364. WORD wMenu, wClass, wTitle;
  365. };
  366. #ifdef _WIN64
  367. static INT_PTR CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  368. #else
  369. static BOOL CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  370. #endif
  371. {
  372. if(uMsg == WM_SETTINGCHANGE)
  373. {
  374. CAppModule* pModule = (CAppModule*)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
  375. ATLASSERT(pModule != NULL);
  376. ATLASSERT(pModule->m_pSettingChangeNotify != NULL);
  377. for(int i = 1; i < pModule->m_pSettingChangeNotify->GetSize(); i++)
  378. ::SendMessageTimeout((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam, SMTO_ABORTIFHUNG, 1500, NULL);
  379. return TRUE;
  380. }
  381. return FALSE;
  382. }
  383. };
  384. /////////////////////////////////////////////////////////////////////////////
  385. // CServerAppModule - module class for a COM server application
  386. class CServerAppModule : public CAppModule
  387. {
  388. public:
  389. HANDLE m_hEventShutdown;
  390. bool m_bActivity;
  391. DWORD m_dwTimeOut;
  392. DWORD m_dwPause;
  393. // Override of CAppModule::Init
  394. HRESULT Init(_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL)
  395. {
  396. m_dwTimeOut = 5000;
  397. m_dwPause = 1000;
  398. return CAppModule::Init(pObjMap, hInstance, pLibID);
  399. }
  400. void Term()
  401. {
  402. if(m_hEventShutdown != NULL && ::CloseHandle(m_hEventShutdown))
  403. m_hEventShutdown = NULL;
  404. CAppModule::Term();
  405. }
  406. // COM Server methods
  407. LONG Unlock()
  408. {
  409. LONG lRet = CComModule::Unlock();
  410. if(lRet == 0)
  411. {
  412. m_bActivity = true;
  413. ::SetEvent(m_hEventShutdown); // tell monitor that we transitioned to zero
  414. }
  415. return lRet;
  416. }
  417. void MonitorShutdown()
  418. {
  419. while(1)
  420. {
  421. ::WaitForSingleObject(m_hEventShutdown, INFINITE);
  422. DWORD dwWait = 0;
  423. do
  424. {
  425. m_bActivity = false;
  426. dwWait = ::WaitForSingleObject(m_hEventShutdown, m_dwTimeOut);
  427. }
  428. while(dwWait == WAIT_OBJECT_0);
  429. // timed out
  430. if(!m_bActivity && m_nLockCnt == 0) // if no activity let's really bail
  431. {
  432. #if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) & defined(_ATL_FREE_THREADED)
  433. ::CoSuspendClassObjects();
  434. if(!m_bActivity && m_nLockCnt == 0)
  435. #endif
  436. break;
  437. }
  438. }
  439. // This handle should be valid now. If it isn't,
  440. // check if _Module.Term was called first (it shouldn't)
  441. if(::CloseHandle(m_hEventShutdown))
  442. m_hEventShutdown = NULL;
  443. ::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0);
  444. }
  445. bool StartMonitor()
  446. {
  447. m_hEventShutdown = ::CreateEvent(NULL, false, false, NULL);
  448. if(m_hEventShutdown == NULL)
  449. return false;
  450. DWORD dwThreadID;
  451. #if !defined(_ATL_MIN_CRT) & defined(_MT)
  452. HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))MonitorProc, this, 0, (UINT*)&dwThreadID);
  453. #else
  454. HANDLE hThread = ::CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID);
  455. #endif
  456. bool bRet = (hThread != NULL);
  457. if(bRet)
  458. ::CloseHandle(hThread);
  459. return bRet;
  460. }
  461. static DWORD WINAPI MonitorProc(void* pv)
  462. {
  463. CServerAppModule* p = (CServerAppModule*)pv;
  464. p->MonitorShutdown();
  465. #if !defined(_ATL_MIN_CRT) & defined(_MT)
  466. _endthreadex(0);
  467. #endif
  468. return 0;
  469. }
  470. // Scan command line and perform registration
  471. // Return value specifies if server should run
  472. // Parses the command line and registers/unregisters the rgs file if necessary
  473. bool ParseCommandLine(LPCTSTR lpCmdLine, UINT nResId, HRESULT* pnRetCode)
  474. {
  475. TCHAR szTokens[] = _T("-/");
  476. *pnRetCode = S_OK;
  477. LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
  478. while(lpszToken != NULL)
  479. {
  480. if(lstrcmpi(lpszToken, _T("UnregServer"))==0)
  481. {
  482. *pnRetCode = UnregisterServer(TRUE);
  483. ATLASSERT(SUCCEEDED(*pnRetCode));
  484. if(FAILED(*pnRetCode))
  485. return false;
  486. *pnRetCode = UpdateRegistryFromResource(nResId, FALSE);
  487. return false;
  488. }
  489. // Register as Local Server
  490. if(lstrcmpi(lpszToken, _T("RegServer"))==0)
  491. {
  492. *pnRetCode = UpdateRegistryFromResource(nResId, TRUE);
  493. ATLASSERT(SUCCEEDED(*pnRetCode));
  494. if(FAILED(*pnRetCode))
  495. return false;
  496. *pnRetCode = RegisterServer(TRUE);
  497. return false;
  498. }
  499. lpszToken = FindOneOf(lpszToken, szTokens);
  500. }
  501. return true;
  502. }
  503. // Parses the command line and registers/unregisters the appid if necessary
  504. bool ParseCommandLine(LPCTSTR lpCmdLine, LPCTSTR pAppId, HRESULT* pnRetCode)
  505. {
  506. TCHAR szTokens[] = _T("-/");
  507. *pnRetCode = S_OK;
  508. LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
  509. while(lpszToken != NULL)
  510. {
  511. if(lstrcmpi(lpszToken, _T("UnregServer"))==0)
  512. {
  513. *pnRetCode = UnregisterAppId(pAppId);
  514. ATLASSERT(SUCCEEDED(*pnRetCode));
  515. if(FAILED(*pnRetCode))
  516. return false;
  517. *pnRetCode = UnregisterServer(TRUE);
  518. return false;
  519. }
  520. // Register as Local Server
  521. if(lstrcmpi(lpszToken, _T("RegServer"))==0)
  522. {
  523. *pnRetCode = RegisterAppId(pAppId);
  524. ATLASSERT(SUCCEEDED(*pnRetCode));
  525. if(FAILED(*pnRetCode))
  526. return false;
  527. *pnRetCode = RegisterServer(TRUE);
  528. return false;
  529. }
  530. lpszToken = FindOneOf(lpszToken, szTokens);
  531. }
  532. return true;
  533. }
  534. #if !defined(_ATL_TMP_IMPL1) && !defined(_ATL_TMP_IMPL2)
  535. // search for an occurence of string p2 in string p1
  536. static LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2)
  537. {
  538. while(p1 != NULL && *p1 != NULL)
  539. {
  540. LPCTSTR p = p2;
  541. while(p != NULL && *p != NULL)
  542. {
  543. if(*p1 == *p)
  544. return ::CharNext(p1);
  545. p = ::CharNext(p);
  546. }
  547. p1 = ::CharNext(p1);
  548. }
  549. return NULL;
  550. }
  551. HRESULT RegisterAppId(LPCTSTR pAppId)
  552. {
  553. CRegKey keyAppID;
  554. if(keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_READ) == ERROR_SUCCESS)
  555. {
  556. TCHAR szModule1[_MAX_PATH];
  557. TCHAR szModule2[_MAX_PATH];
  558. TCHAR* pszFileName;
  559. ::GetModuleFileName(GetModuleInstance(), szModule1, _MAX_PATH);
  560. ::GetFullPathName(szModule1, _MAX_PATH, szModule2, &pszFileName);
  561. CRegKey keyAppIDEXE;
  562. if(keyAppIDEXE.Create(keyAppID, pszFileName, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE) == ERROR_SUCCESS)
  563. keyAppIDEXE.SetValue(pAppId, _T("AppID"));
  564. if(keyAppIDEXE.Create(keyAppID, pAppId, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE) == ERROR_SUCCESS)
  565. keyAppIDEXE.SetValue(pszFileName);
  566. }
  567. return S_OK;
  568. }
  569. HRESULT UnregisterAppId(LPCTSTR pAppId)
  570. {
  571. CRegKey keyAppID;
  572. if(keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_READ) == ERROR_SUCCESS)
  573. {
  574. TCHAR szModule1[_MAX_PATH];
  575. TCHAR szModule2[_MAX_PATH];
  576. TCHAR* pszFileName;
  577. ::GetModuleFileName(GetModuleInstance(), szModule1, _MAX_PATH);
  578. ::GetFullPathName(szModule1, _MAX_PATH, szModule2, &pszFileName);
  579. keyAppID.RecurseDeleteKey(pszFileName);
  580. keyAppID.RecurseDeleteKey(pAppId);
  581. }
  582. return S_OK;
  583. }
  584. #endif //!defined(_ATL_TMP_IMPL1) && !defined(_ATL_TMP_IMPL2)
  585. };
  586. /////////////////////////////////////////////////////////////////////////////
  587. // ATL 3.0 Add-ons
  588. // protect template members from windowsx.h macros
  589. #ifdef _INC_WINDOWSX
  590. #undef SubclassWindow
  591. #endif //_INC_WINDOWSX
  592. // define useful macros from windowsx.h
  593. #ifndef GET_X_LPARAM
  594. #define GET_X_LPARAM(lParam) ((int)(short)LOWORD(lParam))
  595. #endif
  596. #ifndef GET_Y_LPARAM
  597. #define GET_Y_LPARAM(lParam) ((int)(short)HIWORD(lParam))
  598. #endif
  599. /////////////////////////////////////////////////////////////////////////////
  600. // Dual argument helper classes
  601. #ifndef _ATL_TMP_IMPL2
  602. class _U_RECT
  603. {
  604. public:
  605. _U_RECT(LPRECT lpRect) : m_lpRect(lpRect)
  606. { }
  607. _U_RECT(RECT& rc) : m_lpRect(&rc)
  608. { }
  609. LPRECT m_lpRect;
  610. };
  611. class _U_MENUorID
  612. {
  613. public:
  614. _U_MENUorID(HMENU hMenu) : m_hMenu(hMenu)
  615. { }
  616. _U_MENUorID(UINT nID) : m_hMenu((HMENU)LongToHandle(nID))
  617. { }
  618. HMENU m_hMenu;
  619. };
  620. class _U_STRINGorID
  621. {
  622. public:
  623. _U_STRINGorID(LPCTSTR lpString) : m_lpstr(lpString)
  624. { }
  625. _U_STRINGorID(UINT nID) : m_lpstr(MAKEINTRESOURCE(nID))
  626. { }
  627. LPCTSTR m_lpstr;
  628. };
  629. #endif //!_ATL_TMP_IMPL2
  630. /////////////////////////////////////////////////////////////////////////////
  631. // Forward notifications support for message maps
  632. #if !defined(_ATL_TMP_IMPL1) && !defined(_ATL_TMP_IMPL2)
  633. // forward notifications support
  634. #define FORWARD_NOTIFICATIONS() \
  635. { \
  636. bHandled = TRUE; \
  637. lResult = Atl3ForwardNotifications(m_hWnd, uMsg, wParam, lParam, bHandled); \
  638. if(bHandled) \
  639. return TRUE; \
  640. }
  641. static LRESULT Atl3ForwardNotifications(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  642. {
  643. LRESULT lResult = 0;
  644. switch(uMsg)
  645. {
  646. case WM_COMMAND:
  647. case WM_NOTIFY:
  648. case WM_PARENTNOTIFY:
  649. case WM_DRAWITEM:
  650. case WM_MEASUREITEM:
  651. case WM_COMPAREITEM:
  652. case WM_DELETEITEM:
  653. case WM_VKEYTOITEM:
  654. case WM_CHARTOITEM:
  655. case WM_HSCROLL:
  656. case WM_VSCROLL:
  657. case WM_CTLCOLORBTN:
  658. case WM_CTLCOLORDLG:
  659. case WM_CTLCOLOREDIT:
  660. case WM_CTLCOLORLISTBOX:
  661. case WM_CTLCOLORMSGBOX:
  662. case WM_CTLCOLORSCROLLBAR:
  663. case WM_CTLCOLORSTATIC:
  664. lResult = ::SendMessage(::GetParent(hWnd), uMsg, wParam, lParam);
  665. break;
  666. default:
  667. bHandled = FALSE;
  668. break;
  669. }
  670. return lResult;
  671. }
  672. /////////////////////////////////////////////////////////////////////////////
  673. // Reflected message handler macros for message maps
  674. #define REFLECTED_COMMAND_HANDLER(id, code, func) \
  675. if(uMsg == OCM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \
  676. { \
  677. bHandled = TRUE; \
  678. lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
  679. if(bHandled) \
  680. return TRUE; \
  681. }
  682. #define REFLECTED_COMMAND_ID_HANDLER(id, func) \
  683. if(uMsg == OCM_COMMAND && id == LOWORD(wParam)) \
  684. { \
  685. bHandled = TRUE; \
  686. lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
  687. if(bHandled) \
  688. return TRUE; \
  689. }
  690. #define REFLECTED_COMMAND_CODE_HANDLER(code, func) \
  691. if(uMsg == OCM_COMMAND && code == HIWORD(wParam)) \
  692. { \
  693. bHandled = TRUE; \
  694. lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
  695. if(bHandled) \
  696. return TRUE; \
  697. }
  698. #define REFLECTED_COMMAND_RANGE_HANDLER(idFirst, idLast, func) \
  699. if(uMsg == OCM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
  700. { \
  701. bHandled = TRUE; \
  702. lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
  703. if(bHandled) \
  704. return TRUE; \
  705. }
  706. #define REFLECTED_COMMAND_RANGE_CODE_HANDLER(idFirst, idLast, code, func) \
  707. if(uMsg == OCM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
  708. { \
  709. bHandled = TRUE; \
  710. lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
  711. if(bHandled) \
  712. return TRUE; \
  713. }
  714. #define REFLECTED_NOTIFY_HANDLER(id, cd, func) \
  715. if(uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \
  716. { \
  717. bHandled = TRUE; \
  718. lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
  719. if(bHandled) \
  720. return TRUE; \
  721. }
  722. #define REFLECTED_NOTIFY_ID_HANDLER(id, func) \
  723. if(uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \
  724. { \
  725. bHandled = TRUE; \
  726. lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
  727. if(bHandled) \
  728. return TRUE; \
  729. }
  730. #define REFLECTED_NOTIFY_CODE_HANDLER(cd, func) \
  731. if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
  732. { \
  733. bHandled = TRUE; \
  734. lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
  735. if(bHandled) \
  736. return TRUE; \
  737. }
  738. #define REFLECTED_NOTIFY_RANGE_HANDLER(idFirst, idLast, func) \
  739. if(uMsg == OCM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
  740. { \
  741. bHandled = TRUE; \
  742. lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
  743. if(bHandled) \
  744. return TRUE; \
  745. }
  746. #define REFLECTED_NOTIFY_RANGE_CODE_HANDLER(idFirst, idLast, cd, func) \
  747. if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
  748. { \
  749. bHandled = TRUE; \
  750. lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
  751. if(bHandled) \
  752. return TRUE; \
  753. }
  754. /////////////////////////////////////////////////////////////////////////////
  755. // CString forward reference (to be used with atluser.h and atlgdi.h)
  756. #ifdef _WTL_FORWARD_DECLARE_CSTRING
  757. #define __ATLSTR_H__
  758. class CString; // forward declaration (include atlmisc.h for the whole class)
  759. #endif //_WTL_FORWARD_DECLARE_CSTRING
  760. #endif //!defined(_ATL_TMP_IMPL1) && !defined(_ATL_TMP_IMPL2)
  761. }; //namespace WTL
  762. // These are always included
  763. #include <atluser.h>
  764. #include <atlgdi.h>
  765. // old names compatibility
  766. #ifdef _ATL_TMP_IMPL1
  767. namespace WTL
  768. {
  769. typedef CFontHandle CWinFont;
  770. typedef CMenuHandle CWinMenu;
  771. #define CWinPropertyPageImpl CPropertyPageImpl
  772. typedef CDCHandle CWinDC;
  773. }; //namespace WTL
  774. #endif //_ATL_TMP_IMPL1
  775. #ifndef _WTL_NO_AUTOMATIC_NAMESPACE
  776. using namespace WTL;
  777. #endif //!_WTL_NO_AUTOMATIC_NAMESPACE
  778. #endif // __ATLAPP_H__