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.

453 lines
8.3 KiB

  1. //****************************************************************************
  2. // Module: NMCHAT.EXE
  3. // File: CLUTIL.CPP
  4. // Content:
  5. //
  6. //
  7. // Copyright (c) Microsoft Corporation 1997
  8. //
  9. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  10. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  11. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  12. // PARTICULAR PURPOSE.
  13. //****************************************************************************
  14. #include "precomp.h"
  15. ///////////////////////////////////////////////////////////////////////////
  16. // RefCount
  17. /* R E F C O U N T */
  18. /*-------------------------------------------------------------------------
  19. %%Function: RefCount
  20. -------------------------------------------------------------------------*/
  21. RefCount::RefCount(void)
  22. {
  23. m_cRef = 1;
  24. }
  25. RefCount::~RefCount(void)
  26. {
  27. }
  28. ULONG STDMETHODCALLTYPE RefCount::AddRef(void)
  29. {
  30. ASSERT(m_cRef >= 0);
  31. InterlockedIncrement(&m_cRef);
  32. return (ULONG) m_cRef;
  33. }
  34. ULONG STDMETHODCALLTYPE RefCount::Release(void)
  35. {
  36. if (0 == InterlockedDecrement(&m_cRef))
  37. {
  38. delete this;
  39. return 0;
  40. }
  41. ASSERT(m_cRef > 0);
  42. return (ULONG) m_cRef;
  43. }
  44. ///////////////////////////////////////////////////////////////////////////
  45. // CNotify
  46. /* C N O T I F Y */
  47. /*-------------------------------------------------------------------------
  48. %%Function: CNotify
  49. -------------------------------------------------------------------------*/
  50. CNotify::CNotify() :
  51. m_pcnpcnt(NULL),
  52. m_pcnp(NULL),
  53. m_dwCookie(0),
  54. m_pUnk(NULL)
  55. {
  56. }
  57. CNotify::~CNotify()
  58. {
  59. Disconnect(); // Make sure we're disconnected
  60. }
  61. /* C O N N E C T */
  62. /*-------------------------------------------------------------------------
  63. %%Function: Connect
  64. -------------------------------------------------------------------------*/
  65. HRESULT CNotify::Connect(IUnknown *pUnk, REFIID riid, IUnknown *pUnkN)
  66. {
  67. HRESULT hr;
  68. ASSERT(0 == m_dwCookie);
  69. // Get the connection container
  70. hr = pUnk->QueryInterface(IID_IConnectionPointContainer, (void **)&m_pcnpcnt);
  71. if (SUCCEEDED(hr))
  72. {
  73. // Find an appropriate connection point
  74. hr = m_pcnpcnt->FindConnectionPoint(riid, &m_pcnp);
  75. if (SUCCEEDED(hr))
  76. {
  77. ASSERT(NULL != m_pcnp);
  78. // Connect the sink object
  79. hr = m_pcnp->Advise((IUnknown *)pUnkN, &m_dwCookie);
  80. }
  81. }
  82. if (FAILED(hr))
  83. {
  84. ERROR_OUT(("MNMSRVC: CNotify::Connect failed: %x", hr));
  85. m_dwCookie = 0;
  86. }
  87. else
  88. {
  89. m_pUnk = pUnk; // keep around for caller
  90. }
  91. return hr;
  92. }
  93. /* D I S C O N N E C T */
  94. /*-------------------------------------------------------------------------
  95. %%Function: Disconnect
  96. -------------------------------------------------------------------------*/
  97. HRESULT CNotify::Disconnect (void)
  98. {
  99. if (0 != m_dwCookie)
  100. {
  101. // Disconnect the sink object
  102. m_pcnp->Unadvise(m_dwCookie);
  103. m_dwCookie = 0;
  104. m_pcnp->Release();
  105. m_pcnp = NULL;
  106. m_pcnpcnt->Release();
  107. m_pcnpcnt = NULL;
  108. m_pUnk = NULL;
  109. }
  110. return S_OK;
  111. }
  112. ///////////////////////////////////////////////////////////////////////////
  113. // COBLIST
  114. COBLIST::~COBLIST()
  115. {
  116. ASSERT(IsEmpty());
  117. }
  118. #ifdef DEBUG
  119. VOID* COBLIST::GetHead()
  120. {
  121. ASSERT(m_pHead);
  122. return m_pHead->pItem;
  123. }
  124. VOID* COBLIST::GetTail()
  125. {
  126. ASSERT(m_pTail);
  127. return m_pTail->pItem;
  128. }
  129. #endif /* DEBUG */
  130. VOID* COBLIST::GetNext(POSITION& rPos)
  131. {
  132. ASSERT(rPos);
  133. VOID* pReturn = rPos->pItem;
  134. rPos = rPos->pNext;
  135. return pReturn;
  136. }
  137. VOID* COBLIST::RemoveAt(POSITION Pos)
  138. {
  139. VOID* pReturn = NULL;
  140. if (m_pHead)
  141. {
  142. if (m_pHead == Pos)
  143. {
  144. // Removing the first element in the list
  145. m_pHead = Pos->pNext;
  146. pReturn = Pos->pItem;
  147. delete Pos;
  148. m_cItem--;
  149. ASSERT(0 <= m_cItem);
  150. if (NULL == m_pHead)
  151. {
  152. // Removing the only element!
  153. m_pTail = NULL;
  154. }
  155. }
  156. else
  157. {
  158. POSITION pCur = m_pHead;
  159. while (pCur && pCur->pNext)
  160. {
  161. if (pCur->pNext == Pos)
  162. {
  163. // Removing
  164. pCur->pNext = Pos->pNext;
  165. if (m_pTail == Pos)
  166. {
  167. m_pTail = pCur;
  168. }
  169. pReturn = Pos->pItem;
  170. delete Pos;
  171. m_cItem--;
  172. ASSERT(0 <= m_cItem);
  173. }
  174. pCur = pCur->pNext;
  175. }
  176. }
  177. }
  178. return pReturn;
  179. }
  180. POSITION COBLIST::AddTail(VOID* pItem)
  181. {
  182. POSITION posRet = NULL;
  183. if (m_pTail)
  184. {
  185. if (m_pTail->pNext = new COBNODE)
  186. {
  187. m_pTail = m_pTail->pNext;
  188. m_pTail->pItem = pItem;
  189. m_pTail->pNext = NULL;
  190. m_cItem++;
  191. }
  192. }
  193. else
  194. {
  195. ASSERT(!m_pHead);
  196. if (m_pHead = new COBNODE)
  197. {
  198. m_pTail = m_pHead;
  199. m_pTail->pItem = pItem;
  200. m_pTail->pNext = NULL;
  201. m_cItem++;
  202. }
  203. }
  204. return m_pTail;
  205. }
  206. void COBLIST::EmptyList()
  207. {
  208. while (!IsEmpty()) {
  209. RemoveAt(GetHeadPosition());
  210. }
  211. }
  212. #ifdef DEBUG
  213. VOID* COBLIST::RemoveTail()
  214. {
  215. ASSERT(m_pHead);
  216. ASSERT(m_pTail);
  217. return RemoveAt(m_pTail);
  218. }
  219. VOID* COBLIST::RemoveHead()
  220. {
  221. ASSERT(m_pHead);
  222. ASSERT(m_pTail);
  223. return RemoveAt(m_pHead);
  224. }
  225. void * COBLIST::GetFromPosition(POSITION Pos)
  226. {
  227. void * Result = SafeGetFromPosition(Pos);
  228. ASSERT(Result);
  229. return Result;
  230. }
  231. #endif /* DEBUG */
  232. POSITION COBLIST::GetPosition(void* _pItem)
  233. {
  234. POSITION Position = m_pHead;
  235. while (Position) {
  236. if (Position->pItem == _pItem) {
  237. break;
  238. }
  239. GetNext(Position);
  240. }
  241. return Position;
  242. }
  243. POSITION COBLIST::Lookup(void* pComparator)
  244. {
  245. POSITION Position = m_pHead;
  246. while (Position) {
  247. if (Compare(Position->pItem, pComparator)) {
  248. break;
  249. }
  250. GetNext(Position);
  251. }
  252. return Position;
  253. }
  254. void * COBLIST::SafeGetFromPosition(POSITION Pos)
  255. {
  256. // Safe way to validate that an entry is still in the list,
  257. // which ensures bugs that would reference deleted memory,
  258. // reference a NULL pointer instead
  259. // (e.g. an event handler fires late/twice).
  260. // Note that versioning on entries would provide an additional
  261. // safeguard against re-use of a position.
  262. // Walk list to find entry.
  263. POSITION PosWork = m_pHead;
  264. while (PosWork) {
  265. if (PosWork == Pos) {
  266. return Pos->pItem;
  267. }
  268. GetNext(PosWork);
  269. }
  270. return NULL;
  271. }
  272. /////////////////////////////
  273. // COBLIST Utility routines
  274. /* A D D N O D E */
  275. /*-------------------------------------------------------------------------
  276. %%Function: AddNode
  277. Add a node to a list.
  278. Initializes the ObList, if necessary.
  279. Returns the position in the list or NULL if there was a problem.
  280. -------------------------------------------------------------------------*/
  281. POSITION AddNode(PVOID pv, COBLIST ** ppList)
  282. {
  283. ASSERT(NULL != ppList);
  284. if (NULL == *ppList)
  285. {
  286. *ppList = new COBLIST();
  287. if (NULL == *ppList)
  288. return NULL;
  289. }
  290. return (*ppList)->AddTail(pv);
  291. }
  292. /* R E M O V E N O D E */
  293. /*-------------------------------------------------------------------------
  294. %%Function: RemoveNode
  295. Remove a node from a list.
  296. Sets pPos to NULL
  297. -------------------------------------------------------------------------*/
  298. PVOID RemoveNode(POSITION * pPos, COBLIST *pList)
  299. {
  300. if ((NULL == pList) || (NULL == pPos))
  301. return NULL;
  302. PVOID pv = pList->RemoveAt(*pPos);
  303. *pPos = NULL;
  304. return pv;
  305. }
  306. ////////////////////////////////////////////////////////////////////////////
  307. // BSTRING
  308. // We don't support construction from an ANSI string in the Unicode build.
  309. #if !defined(UNICODE)
  310. BSTRING::BSTRING(LPCSTR lpcString)
  311. {
  312. m_bstr = NULL;
  313. // Compute the length of the required BSTR, including the null
  314. int cWC = MultiByteToWideChar(CP_ACP, 0, lpcString, -1, NULL, 0);
  315. if (cWC <= 0)
  316. return;
  317. // Allocate the BSTR, including the null
  318. m_bstr = SysAllocStringLen(NULL, cWC - 1); // SysAllocStringLen adds another 1
  319. ASSERT(NULL != m_bstr);
  320. if (NULL == m_bstr)
  321. {
  322. return;
  323. }
  324. // Copy the string
  325. MultiByteToWideChar(CP_ACP, 0, lpcString, -1, (LPWSTR) m_bstr, cWC);
  326. // Verify that the string is null terminated
  327. ASSERT(0 == m_bstr[cWC - 1]);
  328. }
  329. #endif // !defined(UNICODE)
  330. ///////////////////////////
  331. // BTSTR
  332. BTSTR::BTSTR(BSTR bstr)
  333. {
  334. m_psz = PszFromBstr(bstr);
  335. }
  336. BTSTR::~BTSTR()
  337. {
  338. if (NULL != m_psz)
  339. LocalFree(m_psz);
  340. }
  341. LPTSTR PszFromBstr(BSTR bstr)
  342. {
  343. if (NULL == bstr)
  344. return NULL;
  345. int cch = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)bstr, -1, NULL, 0, NULL, NULL);
  346. if (cch <= 0)
  347. return NULL;
  348. LPTSTR psz = (LPTSTR)LocalAlloc(LMEM_FIXED, sizeof(TCHAR) * (cch+1) );
  349. if (NULL == psz)
  350. return NULL;
  351. WideCharToMultiByte(CP_ACP, 0, (LPWSTR)bstr, -1, psz, cch+1, NULL, NULL);
  352. return psz;
  353. }