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.

403 lines
9.2 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1995 - 1999
  3. All rights reserved.
  4. Module Name:
  5. spllibex.cxx
  6. Abstract:
  7. spllib extentions
  8. Author:
  9. Lazar Ivanov (LazarI) 29-Mar-2000
  10. Revision History:
  11. --*/
  12. #include "precomp.hxx"
  13. #pragma hdrstop
  14. #include "spllibex.hxx"
  15. ////////////////////////////////////////////////
  16. //
  17. // class CMsgBoxCounter
  18. //
  19. // this class counts the popups which have come up
  20. // during it's lifetime.
  21. //
  22. static DWORD g_dwTlsMsgsCounterCookie = -1;
  23. CMsgBoxCounter::CMsgBoxCounter(UINT uFlags)
  24. : m_uCount(0),
  25. m_uFlags(uFlags),
  26. m_uMsgID(0)
  27. {
  28. if( IsInitialized() )
  29. {
  30. // Only one instance of CMsgBoxCounter at a time can use
  31. // the TLS cookie
  32. ASSERT(NULL == TlsGetValue(g_dwTlsMsgsCounterCookie));
  33. TlsSetValue(g_dwTlsMsgsCounterCookie, reinterpret_cast<LPVOID>(this));
  34. }
  35. }
  36. CMsgBoxCounter::~CMsgBoxCounter()
  37. {
  38. if( IsInitialized() )
  39. {
  40. ASSERT(this == TlsGetValue(g_dwTlsMsgsCounterCookie));
  41. TlsSetValue(g_dwTlsMsgsCounterCookie, NULL);
  42. }
  43. }
  44. BOOL CMsgBoxCounter::Initialize()
  45. {
  46. // allocate TLS cookies
  47. if( !IsInitialized() )
  48. {
  49. g_dwTlsMsgsCounterCookie = TlsAlloc();
  50. }
  51. return IsInitialized();
  52. }
  53. BOOL CMsgBoxCounter::Uninitialize()
  54. {
  55. // free up the TLS cookies
  56. if( -1 != g_dwTlsMsgsCounterCookie )
  57. {
  58. VERIFY(TlsFree(g_dwTlsMsgsCounterCookie));
  59. g_dwTlsMsgsCounterCookie = -1;
  60. }
  61. return TRUE;
  62. }
  63. UINT CMsgBoxCounter::GetCount()
  64. {
  65. UINT uReturn = INVALID_COUNT;
  66. if( IsInitialized() )
  67. {
  68. // lookup the value in the TLS
  69. CMsgBoxCounter *pThis = reinterpret_cast<CMsgBoxCounter*>(TlsGetValue(g_dwTlsMsgsCounterCookie));
  70. uReturn = pThis->m_uCount;
  71. }
  72. return uReturn;
  73. }
  74. BOOL CMsgBoxCounter::IsInitialized()
  75. {
  76. // the TLS cookie should be valid to assume success
  77. return (-1 != g_dwTlsMsgsCounterCookie);
  78. }
  79. void CMsgBoxCounter::LogMessage(UINT uFlags)
  80. {
  81. if( IsInitialized() )
  82. {
  83. CMsgBoxCounter *pThis = reinterpret_cast<CMsgBoxCounter*>(TlsGetValue(g_dwTlsMsgsCounterCookie));
  84. if( pThis && (pThis->m_uFlags & uFlags) )
  85. {
  86. // increment the message box counter
  87. pThis->m_uCount++;
  88. }
  89. }
  90. }
  91. void CMsgBoxCounter::SetMsg(UINT uMsgID)
  92. {
  93. if( IsInitialized() )
  94. {
  95. CMsgBoxCounter *pThis = reinterpret_cast<CMsgBoxCounter*>(TlsGetValue(g_dwTlsMsgsCounterCookie));
  96. if( pThis )
  97. {
  98. pThis->m_uMsgID = uMsgID;
  99. }
  100. }
  101. }
  102. UINT CMsgBoxCounter::GetMsg()
  103. {
  104. UINT uMsgID = 0;
  105. if( IsInitialized() )
  106. {
  107. CMsgBoxCounter *pThis = reinterpret_cast<CMsgBoxCounter*>(TlsGetValue(g_dwTlsMsgsCounterCookie));
  108. if( pThis )
  109. {
  110. uMsgID = pThis->m_uMsgID;
  111. }
  112. }
  113. return uMsgID;
  114. }
  115. ////////////////////////////////////////////////
  116. //
  117. // class CPrintNotify
  118. //
  119. // printer notifications listener
  120. //
  121. CPrintNotify::CPrintNotify(
  122. IPrinterChangeCallback *pClient,
  123. DWORD dwCount,
  124. const PPRINTER_NOTIFY_OPTIONS_TYPE arrNotifications,
  125. DWORD dwFlags
  126. ):
  127. m_bRegistered(FALSE),
  128. m_uCookie(0),
  129. m_dwCount(dwCount),
  130. m_arrNotifications(arrNotifications),
  131. m_dwFlags(dwFlags)
  132. {
  133. SINGLETHREADRESET(TrayUIThread)
  134. ASSERT(pClient);
  135. m_spClient.CopyFrom(pClient);
  136. }
  137. CPrintNotify::~CPrintNotify()
  138. {
  139. SINGLETHREAD(TrayUIThread)
  140. // make sure we uninitialize here
  141. Uninitialize();
  142. }
  143. HRESULT CPrintNotify::Initialize(LPCTSTR pszPrinter)
  144. {
  145. SINGLETHREAD(TrayUIThread)
  146. ASSERT(!m_shPrinter);
  147. ASSERT(!m_shNotify);
  148. ASSERT(pszPrinter);
  149. HRESULT hr = E_FAIL;
  150. SetLastError(0);
  151. if( NULL == m_pPrintLib.pGet() )
  152. {
  153. // aquire a reference to the printui lib object. this will be used
  154. // to register/unregister notification handles in the folder cache.
  155. TPrintLib::bGetSingleton(m_pPrintLib);
  156. }
  157. if( m_pPrintLib.pGet() )
  158. {
  159. m_strPrinter.bUpdate(pszPrinter);
  160. DWORD dwAccess = 0; // whatever
  161. DWORD dwErr = TPrinter::sOpenPrinter(m_strPrinter, &dwAccess, &m_shPrinter);
  162. hr = HRESULT_FROM_WIN32(dwErr);
  163. if( SUCCEEDED(hr) )
  164. {
  165. ASSERT(m_dwFlags);
  166. PRINTER_NOTIFY_OPTIONS opt = {2, 0, m_dwCount, m_arrNotifications};
  167. m_shNotify = FindFirstPrinterChangeNotification(m_shPrinter, m_dwFlags, 0, &opt);
  168. // setup the HRESULT here
  169. hr = m_shNotify ? S_OK : CreateHRFromWin32();
  170. }
  171. }
  172. else
  173. {
  174. // build an appropriate HRESULT
  175. hr = CreateHRFromWin32();
  176. }
  177. if( FAILED(hr) )
  178. {
  179. // if something has failed we don't want to
  180. // keep the handles around in this case
  181. m_shNotify = NULL;
  182. m_shPrinter = NULL;
  183. m_strPrinter.bUpdate(NULL);
  184. }
  185. return hr;
  186. }
  187. HRESULT CPrintNotify::Uninitialize()
  188. {
  189. SINGLETHREAD(TrayUIThread)
  190. // make sure we don't listen anymore
  191. HRESULT hr = StopListen();
  192. // clear the handles
  193. m_shNotify = NULL;
  194. m_shPrinter = NULL;
  195. m_strPrinter.bUpdate(NULL);
  196. return hr;
  197. }
  198. // this is just wrappers around _NotifyRegister
  199. HRESULT CPrintNotify::StartListen()
  200. {
  201. SINGLETHREAD(TrayUIThread)
  202. ASSERT(m_shNotify);
  203. ASSERT(m_spClient);
  204. // register ourselves in the wait list
  205. return _NotifyRegister(TRUE);
  206. }
  207. HRESULT CPrintNotify::Refresh(LPVOID lpCookie, PFN_PrinterChange pfn)
  208. {
  209. SINGLETHREAD(TrayUIThread)
  210. ASSERT(m_shNotify);
  211. ASSERT(m_spClient);
  212. ASSERT(m_dwFlags);
  213. HRESULT hr = S_OK;
  214. DWORD dwChange = 0;
  215. CAutoPtrPrinterNotify pInfo;
  216. PRINTER_NOTIFY_OPTIONS opt = {2, PRINTER_NOTIFY_OPTIONS_REFRESH, m_dwCount, m_arrNotifications };
  217. if( FindNextPrinterChangeNotification(m_shNotify, &dwChange, &opt, pInfo.GetPPV()) )
  218. {
  219. // we hope the client callback will process this call quickly as there shouldn't
  220. // be any delays here if we don't want to loose notifications.
  221. // we don't really care what the retirn value is here.
  222. if( pfn )
  223. {
  224. pfn(lpCookie, m_uCookie, dwChange, pInfo);
  225. }
  226. else
  227. {
  228. m_spClient->PrinterChange(m_uCookie, dwChange, pInfo);
  229. }
  230. }
  231. else
  232. {
  233. hr = HRESULT_FROM_WIN32(GetLastError());
  234. }
  235. return hr;
  236. }
  237. // this is just wrappers around _NotifyRegister
  238. HRESULT CPrintNotify::StopListen()
  239. {
  240. SINGLETHREAD(TrayUIThread)
  241. // unregister ourselves from the wait list
  242. return _NotifyRegister(FALSE);
  243. }
  244. HRESULT CPrintNotify::SetCookie(ULONG_PTR uCookie)
  245. {
  246. SINGLETHREAD(TrayUIThread)
  247. m_uCookie = uCookie;
  248. return S_OK;
  249. }
  250. LPCTSTR CPrintNotify::GetPrinter() const
  251. {
  252. // !!MT NOTES!!
  253. // this function can be invoked only from the bkgnd threads,
  254. // but it never touches the object state.
  255. return (0 == m_strPrinter.uLen() ? NULL : m_strPrinter);
  256. }
  257. HANDLE CPrintNotify::GetPrinterHandle() const
  258. {
  259. SINGLETHREAD(TrayUIThread)
  260. return m_shPrinter;
  261. }
  262. HRESULT CPrintNotify::_NotifyRegister(BOOL bRegister)
  263. {
  264. SINGLETHREAD(TrayUIThread)
  265. HRESULT hr = E_FAIL;
  266. ASSERT(m_pPrintLib.pGet());
  267. if( bRegister )
  268. {
  269. // register request
  270. hr = (m_bRegistered ? S_OK : HRESULT_FROM_WIN32(m_pPrintLib->pNotify()->sRegister(this)));
  271. m_bRegistered = SUCCEEDED(hr) ? TRUE : m_bRegistered;
  272. }
  273. else
  274. {
  275. // unregister request
  276. hr = (!m_bRegistered ? S_OK : HRESULT_FROM_WIN32(m_pPrintLib->pNotify()->sUnregister(this)));
  277. m_bRegistered = SUCCEEDED(hr) ? FALSE : m_bRegistered;
  278. }
  279. return hr;
  280. }
  281. HANDLE CPrintNotify::hEvent() const
  282. {
  283. // !!MT NOTES!!
  284. // this function can be invoked only from the bkgnd threads,
  285. // but it never touches the object state.
  286. ASSERT(m_shNotify);
  287. return m_shNotify;
  288. }
  289. void CPrintNotify::vProcessNotifyWork(TNotify *pNotify)
  290. {
  291. // !!MT NOTES!!
  292. // this function can be invoked only from the bkgnd threads,
  293. // but it never touches the object state.
  294. ASSERT(m_shNotify);
  295. ASSERT(m_spClient);
  296. DWORD dwChange = 0;
  297. CAutoPtrPrinterNotify pInfo;
  298. PRINTER_NOTIFY_OPTIONS opt = {2, 0, m_dwCount, m_arrNotifications };
  299. if( FindNextPrinterChangeNotification(m_shNotify, &dwChange, &opt, pInfo.GetPPV()) )
  300. {
  301. // we hope the client callback will process this call quickly as there shouldn't
  302. // be any delays here if we don't want to loose notifications.
  303. // we don't really care what the retirn value is here.
  304. m_spClient->PrinterChange(m_uCookie, dwChange, pInfo);
  305. }
  306. }
  307. ////////////////////////////////////////////////
  308. // class CMultilineEditBug
  309. //
  310. LRESULT CMultilineEditBug::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  311. {
  312. HWND hDlg = GetParent(hwnd);
  313. if( hDlg && GetParent(hDlg) )
  314. {
  315. hDlg = GetParent(hDlg);
  316. }
  317. if( hDlg && WM_KEYDOWN == uMsg && VK_RETURN == wParam && GetKeyState(VK_CONTROL) >= 0 )
  318. {
  319. LRESULT lr = SendMessage(hDlg, DM_GETDEFID, 0, 0);
  320. if( lr && LOWORD(lr) && DC_HASDEFID == HIWORD(lr) )
  321. {
  322. HWND hwndButton = GetDlgItem(hDlg, LOWORD(lr));
  323. PostMessage(hDlg, WM_COMMAND, MAKEWPARAM(LOWORD(lr), BN_CLICKED), (LPARAM)hwndButton);
  324. }
  325. }
  326. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  327. }