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.

504 lines
14 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. ccompont.cpp
  7. base classes for IComponent and IComponentData
  8. FILE HISTORY:
  9. */
  10. #include "stdafx.h"
  11. #include "util.h"
  12. #ifdef _DEBUG
  13. #define new DEBUG_NEW
  14. #undef THIS_FILE
  15. static char THIS_FILE[] = __FILE__;
  16. #endif
  17. TFSCORE_API(HRESULT)
  18. InitWatermarkInfo
  19. (
  20. HINSTANCE hInstance,
  21. LPWATERMARKINFO pWatermarkInfo,
  22. UINT uIDHeader,
  23. UINT uIDWatermark,
  24. HPALETTE hPalette,
  25. BOOL bStretch
  26. )
  27. {
  28. pWatermarkInfo->hHeader = ::LoadBitmap(hInstance, MAKEINTRESOURCE(uIDHeader));
  29. if (pWatermarkInfo->hHeader == NULL)
  30. return E_FAIL;
  31. pWatermarkInfo->hWatermark = ::LoadBitmap(hInstance, MAKEINTRESOURCE(uIDWatermark));
  32. if (pWatermarkInfo->hWatermark == NULL)
  33. return E_FAIL;
  34. pWatermarkInfo->hPalette = hPalette;
  35. pWatermarkInfo->bStretch = bStretch;
  36. return S_OK;
  37. }
  38. TFSCORE_API(HRESULT)
  39. ResetWatermarkInfo(LPWATERMARKINFO pWatermarkInfo)
  40. {
  41. if(pWatermarkInfo->hHeader)
  42. {
  43. DeleteObject(pWatermarkInfo->hHeader);
  44. pWatermarkInfo->hHeader = NULL;
  45. }
  46. if(pWatermarkInfo->hWatermark)
  47. {
  48. DeleteObject(pWatermarkInfo->hWatermark);
  49. pWatermarkInfo->hWatermark = NULL;
  50. }
  51. return S_OK;
  52. }
  53. /*!--------------------------------------------------------------------------
  54. InterfaceUtilities::SetI
  55. Encapsulates the common Release/Assign/AddRef sequence.
  56. Handles null ptrs.
  57. Author: GaryBu
  58. ---------------------------------------------------------------------------*/
  59. TFSCORE_API(void) SetI(IUnknown * volatile *ppunkL, IUnknown *punkR)
  60. {
  61. if (*ppunkL)
  62. {
  63. IUnknown *punkRel = *ppunkL;
  64. *ppunkL = 0;
  65. punkRel->Release();
  66. }
  67. *ppunkL = punkR;
  68. if (punkR)
  69. punkR->AddRef();
  70. }
  71. /*!--------------------------------------------------------------------------
  72. InterfaceUtilities::ReleaseI
  73. Release interface, handles null interface pointer.
  74. Use Set(&pFoo, 0) if you want to set interface pointer to zero.
  75. Author: GaryBu
  76. ---------------------------------------------------------------------------*/
  77. TFSCORE_API(void) ReleaseI(IUnknown *punk)
  78. {
  79. #if 0
  80. __try
  81. #endif
  82. {
  83. if (punk)
  84. {
  85. if (IsBadReadPtr(punk,sizeof(void *)))
  86. {
  87. AssertSz(FALSE,"Bad Punk");
  88. return;
  89. }
  90. if (IsBadReadPtr(*((LPVOID FAR *) punk),sizeof(void *) * 3))
  91. {
  92. AssertSz(FALSE, "Bad Vtable");
  93. return;
  94. }
  95. // if (IsBadCodePtr((FARPROC) punk->Release))
  96. // {
  97. // AssertSz(fFalse, "Bad Release Address");
  98. // return;
  99. // }
  100. punk->Release();
  101. }
  102. }
  103. #if 0
  104. __except(1)
  105. {
  106. Trace0("Exception ignored in ReleaseI()\n");
  107. }
  108. #endif
  109. }
  110. TFSCORE_API(HRESULT) HrQueryInterface(IUnknown *punk, REFIID iid, LPVOID *ppv)
  111. {
  112. HRESULT hr;
  113. #ifdef DEBUG
  114. if (IsBadReadPtr(punk,sizeof(void *)))
  115. {
  116. AssertSz(FALSE,"CRASHING BUG! Bad Punk in QueryInterface");
  117. return ResultFromScode(E_NOINTERFACE);
  118. }
  119. if (IsBadReadPtr(*((LPVOID FAR *) punk),sizeof(void *) * 3))
  120. {
  121. AssertSz(FALSE, "CRASHING BUG! Bad Vtable in QueryInterface");
  122. return ResultFromScode(E_NOINTERFACE);
  123. }
  124. #endif
  125. IfDebug(*ppv = (void*)0xCCCCCCCC;)
  126. hr = punk->QueryInterface(iid, ppv);
  127. if (FHrFailed(hr))
  128. {
  129. *ppv = 0;
  130. }
  131. return hr;
  132. }
  133. TFSCORE_API(HRESULT) LoadAndAddMenuItem
  134. (
  135. IContextMenuCallback* pIContextMenuCallback,
  136. LPCTSTR pszMenuString, // has text & status text separated by '\n'
  137. LONG lCommandID,
  138. LONG lInsertionPointID,
  139. LONG fFlags,
  140. LPCTSTR pszLangIndStr
  141. )
  142. {
  143. Assert( pIContextMenuCallback != NULL );
  144. // load the resource
  145. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  146. CString strText(pszMenuString);
  147. CString strStatusText;
  148. if (!(fFlags & MF_SEPARATOR))
  149. {
  150. Assert( !strText.IsEmpty() );
  151. // split the resource into the menu text and status text
  152. int iSeparator = strText.Find(_T('\n'));
  153. if (0 > iSeparator)
  154. {
  155. Panic0("Could not find separator between menu text and status text");
  156. strStatusText = strText;
  157. }
  158. else
  159. {
  160. strStatusText = strText.Right( strText.GetLength()-(iSeparator+1) );
  161. strText = strText.Left( iSeparator );
  162. }
  163. }
  164. // add the menu item
  165. USES_CONVERSION;
  166. HRESULT hr = S_OK;
  167. BOOL bAdded = FALSE;
  168. // if language independent string is specified, then try to use IContextMenuCallback2
  169. if(pszLangIndStr)
  170. {
  171. CONTEXTMENUITEM2 contextmenuitem;
  172. IContextMenuCallback2* pIContextMenuCallback2 = NULL;
  173. hr = pIContextMenuCallback->QueryInterface(IID_IContextMenuCallback2, (void**)&pIContextMenuCallback2);
  174. if(hr == S_OK && pIContextMenuCallback2 != NULL)
  175. {
  176. ::ZeroMemory( &contextmenuitem, sizeof(contextmenuitem) );
  177. contextmenuitem.strName = T2OLE(const_cast<LPTSTR>((LPCWSTR)strText));
  178. contextmenuitem.strStatusBarText = T2OLE(const_cast<LPTSTR>((LPCWSTR)strStatusText));
  179. contextmenuitem.lCommandID = lCommandID;
  180. contextmenuitem.lInsertionPointID = lInsertionPointID;
  181. contextmenuitem.fFlags = fFlags;
  182. contextmenuitem.fSpecialFlags = ((fFlags & MF_POPUP) ? CCM_SPECIAL_SUBMENU : 0L);
  183. contextmenuitem.fSpecialFlags |= ((fFlags & MF_SEPARATOR) ? CCM_SPECIAL_SEPARATOR : 0L);
  184. contextmenuitem.strLanguageIndependentName = T2OLE(const_cast<LPTSTR>((LPCWSTR)pszLangIndStr));
  185. hr = pIContextMenuCallback2->AddItem( &contextmenuitem );
  186. if( hr == S_OK)
  187. bAdded = TRUE;
  188. pIContextMenuCallback2->Release();
  189. pIContextMenuCallback2 = NULL;
  190. }
  191. }
  192. // if not added above for any reason, we try to use the IContextMenuCallback
  193. if (!bAdded)
  194. {
  195. CONTEXTMENUITEM contextmenuitem;
  196. ::ZeroMemory( &contextmenuitem, sizeof(contextmenuitem) );
  197. contextmenuitem.strName = T2OLE(const_cast<LPTSTR>((LPCWSTR)strText));
  198. contextmenuitem.strStatusBarText = T2OLE(const_cast<LPTSTR>((LPCWSTR)strStatusText));
  199. contextmenuitem.lCommandID = lCommandID;
  200. contextmenuitem.lInsertionPointID = lInsertionPointID;
  201. contextmenuitem.fFlags = fFlags;
  202. contextmenuitem.fSpecialFlags = ((fFlags & MF_POPUP) ? CCM_SPECIAL_SUBMENU : 0L);
  203. contextmenuitem.fSpecialFlags |= ((fFlags & MF_SEPARATOR) ? CCM_SPECIAL_SEPARATOR : 0L);
  204. hr = pIContextMenuCallback->AddItem( &contextmenuitem );
  205. }
  206. Assert(hr == S_OK);
  207. return hr;
  208. }
  209. /*---------------------------------------------------------------------------
  210. CHiddenWnd implementation
  211. ---------------------------------------------------------------------------*/
  212. DEBUG_DECLARE_INSTANCE_COUNTER(CHiddenWnd);
  213. BEGIN_MESSAGE_MAP( CHiddenWnd, CWnd )
  214. ON_MESSAGE(WM_HIDDENWND_REGISTER, OnNotifyRegister)
  215. END_MESSAGE_MAP( )
  216. /*!--------------------------------------------------------------------------
  217. CHiddenWnd::Create
  218. -
  219. Author: KennT
  220. ---------------------------------------------------------------------------*/
  221. BOOL CHiddenWnd::Create()
  222. {
  223. CString s_szHiddenWndClass = AfxRegisterWndClass(
  224. 0x0, //UINT nClassStyle,
  225. NULL, //HCURSOR hCursor,
  226. NULL, //HBRUSH hbrBackground,
  227. NULL //HICON hIcon
  228. );
  229. // Initialize our bit mask to 0
  230. ::ZeroMemory(&m_bitMask, sizeof(m_bitMask));
  231. // Reserve position 0. This means that
  232. // we can use from WM_USER to WM_USER+15 for our own purposes.
  233. SetBitMask(m_bitMask, 0);
  234. m_iLastObjectIdSet = 1;
  235. return CreateEx(
  236. 0x0, //DWORD dwExStyle,
  237. s_szHiddenWndClass, //LPCTSTR lpszClassName,
  238. NULL, //LPCTSTR lpszWindowName,
  239. 0x0, //DWORD dwStyle,
  240. 0, //int x,
  241. 0, //int y,
  242. 0, //int nWidth,
  243. 0, //int nHeight,
  244. NULL, //HWND hwndParent,
  245. NULL, //HMENU nIDorHMenu,
  246. NULL //LPVOID lpParam = NULL
  247. );
  248. }
  249. /*!--------------------------------------------------------------------------
  250. CHiddenWnd::WindowProc
  251. -
  252. Author: KennT
  253. ---------------------------------------------------------------------------*/
  254. LRESULT CHiddenWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
  255. {
  256. LRESULT lReturn = 0;
  257. if ((message >= (WM_USER+16)) && (message < (WM_USER+(HIDDENWND_MAXTHREADS*16))))
  258. {
  259. // Ok, this is one of our special messages
  260. UINT uObjectId = WM_TO_OBJECTID(message);
  261. UINT uMsgId = WM_TO_MSGID(message);
  262. // look up the object id in our list of registered users
  263. if (FIsIdRegistered(uObjectId))
  264. {
  265. // forward the message down to the right window
  266. if (uMsgId == WM_HIDDENWND_INDEX_HAVEDATA)
  267. lReturn = OnNotifyHaveData(wParam, lParam);
  268. else if (uMsgId == WM_HIDDENWND_INDEX_ERROR)
  269. lReturn = OnNotifyError(wParam, lParam);
  270. else if (uMsgId == WM_HIDDENWND_INDEX_EXITING)
  271. lReturn = OnNotifyExiting(wParam, lParam);
  272. #ifdef DEBUG
  273. else
  274. {
  275. Panic1("Unknown message %d", uMsgId);
  276. }
  277. #endif
  278. }
  279. else if (uObjectId != 0)
  280. {
  281. // If we get a message that is not registered, go into
  282. // our message queue and remove any other messages that
  283. // have the same id. This will reduce accidents that
  284. // occur because different threads were assigned the
  285. // same id.
  286. MSG msg;
  287. Assert(GetSafeHwnd());
  288. while(::PeekMessage(&msg,
  289. GetSafeHwnd(),
  290. OBJECTID_TO_WM(uObjectId),
  291. OBJECTID_TO_WM(uObjectId)+WM_HIDDENWND_INDEX_MAX,
  292. PM_REMOVE))
  293. ;
  294. // Trace1("Ignoring message: 0x%08x, removing other msgs\n", message);
  295. }
  296. // If the object is not registered, eat up the message
  297. return lReturn;
  298. }
  299. return CWnd::WindowProc(message, wParam, lParam);
  300. }
  301. /*!--------------------------------------------------------------------------
  302. CHiddenWnd::FIsIdRegistered
  303. -
  304. Author: KennT
  305. ---------------------------------------------------------------------------*/
  306. BOOL CHiddenWnd::FIsIdRegistered(UINT uObjectId)
  307. {
  308. Assert(uObjectId > 0);
  309. Assert(uObjectId < HIDDENWND_MAXTHREADS);
  310. // 0 is not allowed as an object id
  311. return (uObjectId != 0) && !!(IsBitMaskSet(m_bitMask, uObjectId));
  312. }
  313. /*!--------------------------------------------------------------------------
  314. CHiddenWnd::OnNotifyRegister
  315. If we fail to find an empty slot, return 0.
  316. Author: KennT
  317. ---------------------------------------------------------------------------*/
  318. LONG CHiddenWnd::OnNotifyRegister(WPARAM wParam, LPARAM lParam)
  319. {
  320. LONG lReturn = 0;
  321. // Look for a valid hole in our mask
  322. // The point of using the m_iLastObjectIdSet is to avoid the
  323. // problem of reusing ids. This doesn't totally eliminate the
  324. // problem but it should reduce the likelihood to practically 0.
  325. // That is, unless someone actually runs a snapin that utilizes
  326. // 512 threads!
  327. if (wParam)
  328. {
  329. if (((m_iLastObjectIdSet+1) < HIDDENWND_MAXTHREADS) &&
  330. !IsBitMaskSet(m_bitMask, m_iLastObjectIdSet))
  331. {
  332. SetBitMask(m_bitMask, m_iLastObjectIdSet);
  333. lReturn = OBJECTID_TO_WM(m_iLastObjectIdSet);
  334. m_iLastObjectIdSet++;
  335. }
  336. else
  337. {
  338. // do this the painful way
  339. Assert(IsBitMaskSet(m_bitMask, 0));
  340. for (int iLoop=0; iLoop<2; iLoop++)
  341. {
  342. for (int i=m_iLastObjectIdSet; i<HIDDENWND_MAXTHREADS; i++)
  343. {
  344. if (!IsBitMaskSet(m_bitMask, i))
  345. {
  346. m_iLastObjectIdSet = i;
  347. SetBitMask(m_bitMask, m_iLastObjectIdSet);
  348. lReturn = OBJECTID_TO_WM(i);
  349. break;
  350. }
  351. }
  352. if (lReturn || (m_iLastObjectIdSet == 1))
  353. break;
  354. // restart the loop from the beginning
  355. m_iLastObjectIdSet = 1;
  356. }
  357. }
  358. }
  359. else
  360. {
  361. LONG_PTR uObjectId = WM_TO_OBJECTID(lParam);
  362. Assert(uObjectId > 0);
  363. Assert(IsBitMaskSet(m_bitMask, uObjectId));
  364. ClearBitMask(m_bitMask, uObjectId);
  365. }
  366. return lReturn;
  367. }
  368. /*!--------------------------------------------------------------------------
  369. CHiddenWnd::OnNotifyHaveData
  370. -
  371. Author: KennT
  372. ---------------------------------------------------------------------------*/
  373. afx_msg LONG CHiddenWnd::OnNotifyHaveData(WPARAM wParam, LPARAM lParam)
  374. {
  375. HRESULT hr = hrOK;
  376. COM_PROTECT_TRY
  377. {
  378. //Trace0("CHiddenWnd::OnNotifyHaveData()\n");
  379. ITFSThreadHandler *phandler = reinterpret_cast<ITFSThreadHandler*>(wParam);
  380. Assert(phandler);
  381. // If there is an error, we can't do anything
  382. phandler->OnNotifyHaveData(lParam);
  383. }
  384. COM_PROTECT_CATCH
  385. return 0;
  386. }
  387. /*!--------------------------------------------------------------------------
  388. CHiddenWnd::OnNotifyError
  389. -
  390. Author: KennT
  391. ---------------------------------------------------------------------------*/
  392. afx_msg LONG CHiddenWnd::OnNotifyError(WPARAM wParam, LPARAM lParam)
  393. {
  394. HRESULT hr = hrOK;
  395. COM_PROTECT_TRY
  396. {
  397. // Trace0("CHiddenWnd::OnNotifyError()\n");
  398. ITFSThreadHandler *phandler = reinterpret_cast<ITFSThreadHandler*>(wParam);
  399. Assert(phandler);
  400. // If there is an error, we can't do anything
  401. phandler->OnNotifyError(lParam);
  402. }
  403. COM_PROTECT_CATCH
  404. return 0;
  405. }
  406. /*!--------------------------------------------------------------------------
  407. CHiddenWnd::OnNotifyExiting
  408. -
  409. Author: KennT
  410. ---------------------------------------------------------------------------*/
  411. afx_msg LONG CHiddenWnd::OnNotifyExiting(WPARAM wParam, LPARAM lParam)
  412. {
  413. HRESULT hr = hrOK;
  414. COM_PROTECT_TRY
  415. {
  416. // Trace0("CHiddenWnd::OnNotifyExiting()\n");
  417. ITFSThreadHandler *phandler = reinterpret_cast<ITFSThreadHandler*>(wParam);
  418. Assert(phandler);
  419. // If there is an error, we can't do anything
  420. phandler->OnNotifyExiting(lParam);
  421. }
  422. COM_PROTECT_CATCH
  423. return 0;
  424. }