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.

672 lines
13 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. MSPutils.h
  5. Abstract:
  6. This file defines several utility classes used by the MSP base classes.
  7. --*/
  8. #ifndef __MSPUTILS_H_
  9. #define __MSPUTILS_H_
  10. #if _ATL_VER >= 0x0300
  11. //
  12. // ATL 3.0 contains an equivalent of DECLARE_VQI in its END_COM_MAP(), so
  13. // DECLARE_VQI() is not needed
  14. //
  15. #define DECLARE_VQI()
  16. #else
  17. #define DECLARE_VQI() \
  18. STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) = 0; \
  19. STDMETHOD_(ULONG, AddRef)() = 0; \
  20. STDMETHOD_(ULONG, Release)() = 0;
  21. #endif
  22. //
  23. // this macro expands to the appropriate MSP_x value, depending on hr.
  24. // this is useful for logging. for instance, the statements:
  25. //
  26. // .....
  27. //
  28. // if (FAILED(hr))
  29. // {
  30. // LOG((MSP_ERROR, "MyClass::MyFunc - exit. hr = 0x%lx", hr));
  31. // }
  32. // else
  33. // {
  34. // LOG((MSP_TRACE, "MyClass::MyFunc - exit. hr = 0x%lx", hr));
  35. // }
  36. //
  37. // return hr;
  38. // }
  39. //
  40. // can be replaced with:
  41. //
  42. // ....
  43. //
  44. // LOG((MSP_(hr), "MyClass::MyFunc - exit. hr = 0x%lx", hr));
  45. //
  46. // return hr;
  47. // }
  48. //
  49. #define MSP_(hr) (FAILED(hr)?MSP_ERROR:MSP_TRACE)
  50. //
  51. // return TRUE if the (possibly aggregated) media type that was passed in is valid.
  52. //
  53. // here is the criteria for a valid aggregated media type:
  54. //
  55. // 1. there is one or more bit set
  56. // 2. all bits that are set match the possible media types
  57. // 3. there are no set bits that don't correspond to valid meda types
  58. //
  59. inline BOOL IsValidAggregatedMediaType(DWORD dwAggregatedMediaType)
  60. {
  61. //
  62. // these are all possible media types
  63. //
  64. const DWORD dwAllPossibleMediaTypes = TAPIMEDIATYPE_AUDIO |
  65. TAPIMEDIATYPE_VIDEO |
  66. TAPIMEDIATYPE_DATAMODEM |
  67. TAPIMEDIATYPE_G3FAX |
  68. TAPIMEDIATYPE_MULTITRACK;
  69. //
  70. // return value
  71. //
  72. BOOL bValidMediaType = FALSE;
  73. //
  74. // make sure that there is at least one allowed media type
  75. //
  76. // and
  77. //
  78. // there are no invalid media types
  79. //
  80. if ( (0 == (dwAggregatedMediaType & dwAllPossibleMediaTypes ) ) || // any valid bits set
  81. (0 != (dwAggregatedMediaType & (~dwAllPossibleMediaTypes)) ) ) // no invalid bits are set
  82. {
  83. //
  84. // the media type is invalid.
  85. //
  86. bValidMediaType = FALSE;
  87. }
  88. else
  89. {
  90. //
  91. // the media type is valid.
  92. //
  93. bValidMediaType = TRUE;
  94. }
  95. return bValidMediaType;
  96. }
  97. //
  98. // Make sure we have exactly one media type. That's not the case if
  99. // dwMediaType is 0 or more than one bit is set in dwMediaType. Note
  100. // that DWORD is unsigned so this should be safe.
  101. //
  102. inline BOOL IsSingleMediaType(DWORD dwMediaType)
  103. {
  104. return !((dwMediaType == 0) || ((dwMediaType & (dwMediaType - 1)) != 0));
  105. }
  106. //
  107. // Check to see if the mediatype is a single type and is in the mask.
  108. //
  109. inline BOOL IsValidSingleMediaType(DWORD dwMediaType, DWORD dwMask)
  110. {
  111. return IsSingleMediaType(dwMediaType)
  112. && ((dwMediaType & dwMask) == dwMediaType);
  113. }
  114. /*++
  115. CMSPArray template Description:
  116. Definitions for a simple vector template. The implementaion is borrowed
  117. from CMSPArray in atlapp.h. Modified only the allocation behavior.
  118. This array should only be used to store simple types. It doesn't call the
  119. constructor nor the destructor for each element in the array.
  120. --*/
  121. const DWORD INITIAL = 8;
  122. const DWORD DELTA = 8;
  123. template <class T, DWORD dwInitial = INITIAL, DWORD dwDelta = DELTA>
  124. class CMSPArray
  125. {
  126. protected:
  127. T* m_aT;
  128. int m_nSize;
  129. int m_nAllocSize;
  130. public:
  131. // Construction/destruction
  132. CMSPArray() : m_aT(NULL), m_nSize(0), m_nAllocSize(0)
  133. { }
  134. ~CMSPArray()
  135. {
  136. RemoveAll();
  137. }
  138. // Operations
  139. int GetSize() const
  140. {
  141. return m_nSize;
  142. }
  143. BOOL Grow()
  144. {
  145. T* aT;
  146. int nNewAllocSize =
  147. (m_nAllocSize == 0) ? dwInitial : (m_nSize + DELTA);
  148. aT = (T*)realloc(m_aT, nNewAllocSize * sizeof(T));
  149. if(aT == NULL)
  150. return FALSE;
  151. m_nAllocSize = nNewAllocSize;
  152. m_aT = aT;
  153. return TRUE;
  154. }
  155. BOOL Add(T& t)
  156. {
  157. if(m_nSize == m_nAllocSize)
  158. {
  159. if (!Grow()) return FALSE;
  160. }
  161. m_nSize++;
  162. SetAtIndex(m_nSize - 1, t);
  163. return TRUE;
  164. }
  165. BOOL Remove(T& t)
  166. {
  167. int nIndex = Find(t);
  168. if(nIndex == -1)
  169. return FALSE;
  170. return RemoveAt(nIndex);
  171. }
  172. BOOL RemoveAt(int nIndex)
  173. {
  174. if(nIndex != (m_nSize - 1))
  175. memmove((void*)&m_aT[nIndex], (void*)&m_aT[nIndex + 1],
  176. (m_nSize - (nIndex + 1)) * sizeof(T));
  177. m_nSize--;
  178. return TRUE;
  179. }
  180. void RemoveAll()
  181. {
  182. if(m_nAllocSize > 0)
  183. {
  184. free(m_aT);
  185. m_aT = NULL;
  186. m_nSize = 0;
  187. m_nAllocSize = 0;
  188. }
  189. }
  190. T& operator[] (int nIndex) const
  191. {
  192. _ASSERTE(nIndex >= 0 && nIndex < m_nSize);
  193. return m_aT[nIndex];
  194. }
  195. T* GetData() const
  196. {
  197. return m_aT;
  198. }
  199. // Implementation
  200. void SetAtIndex(int nIndex, T& t)
  201. {
  202. _ASSERTE(nIndex >= 0 && nIndex < m_nSize);
  203. m_aT[nIndex] = t;
  204. }
  205. int Find(T& t) const
  206. {
  207. for(int i = 0; i < m_nSize; i++)
  208. {
  209. if(m_aT[i] == t)
  210. return i;
  211. }
  212. return -1; // not found
  213. }
  214. };
  215. /*++
  216. CMSPCritSection Description:
  217. Definitions for a auto initialize critical section.
  218. --*/
  219. class CMSPCritSection
  220. {
  221. private:
  222. CRITICAL_SECTION m_CritSec;
  223. public:
  224. CMSPCritSection()
  225. {
  226. InitializeCriticalSection(&m_CritSec);
  227. }
  228. ~CMSPCritSection()
  229. {
  230. DeleteCriticalSection(&m_CritSec);
  231. }
  232. void Lock()
  233. {
  234. EnterCriticalSection(&m_CritSec);
  235. }
  236. BOOL TryLock()
  237. {
  238. return TryEnterCriticalSection(&m_CritSec);
  239. }
  240. void Unlock()
  241. {
  242. LeaveCriticalSection(&m_CritSec);
  243. }
  244. };
  245. /*++
  246. CMSPCritSection Description:
  247. Definitions for a auto lock that unlocks when the variable is out
  248. of scope.
  249. --*/
  250. class CLock
  251. {
  252. private:
  253. CMSPCritSection &m_CriticalSection;
  254. public:
  255. CLock(CMSPCritSection &CriticalSection)
  256. : m_CriticalSection(CriticalSection)
  257. {
  258. m_CriticalSection.Lock();
  259. }
  260. ~CLock()
  261. {
  262. m_CriticalSection.Unlock();
  263. }
  264. };
  265. ///////////////////////////////////////////////////////////////////////////////
  266. //
  267. // CCSLock
  268. //
  269. // a plain old automatic lock that takes a pointer to CRITICAL_SECTION
  270. //
  271. // constructore enters crit section, destructor leaves critical section
  272. //
  273. // class client is responsible for passing a valid critical section
  274. //
  275. class CCSLock
  276. {
  277. private:
  278. CRITICAL_SECTION *m_pCritSec;
  279. public:
  280. CCSLock(CRITICAL_SECTION *pCritSec)
  281. : m_pCritSec(pCritSec)
  282. {
  283. EnterCriticalSection(m_pCritSec);
  284. }
  285. ~CCSLock()
  286. {
  287. LeaveCriticalSection(m_pCritSec);
  288. }
  289. };
  290. /*++
  291. LINK list:
  292. Definitions for a double link list.
  293. --*/
  294. //
  295. // Calculate the address of the base of the structure given its type, and an
  296. // address of a field within the structure.
  297. //
  298. #ifndef CONTAINING_RECORD
  299. #define CONTAINING_RECORD(address, type, field) \
  300. ((type *)((PCHAR)(address) - (ULONG_PTR)(&((type *)0)->field)))
  301. #endif
  302. #ifndef InitializeListHead
  303. //
  304. // VOID
  305. // InitializeListHead(
  306. // PLIST_ENTRY ListHead
  307. // );
  308. //
  309. #define InitializeListHead(ListHead) (\
  310. (ListHead)->Flink = (ListHead)->Blink = (ListHead))
  311. //
  312. // BOOLEAN
  313. // IsListEmpty(
  314. // PLIST_ENTRY ListHead
  315. // );
  316. //
  317. #define IsListEmpty(ListHead) \
  318. ((ListHead)->Flink == (ListHead))
  319. //
  320. // PLIST_ENTRY
  321. // RemoveHeadList(
  322. // PLIST_ENTRY ListHead
  323. // );
  324. //
  325. #define RemoveHeadList(ListHead) \
  326. (ListHead)->Flink;\
  327. {RemoveEntryList((ListHead)->Flink)}
  328. //
  329. // PLIST_ENTRY
  330. // RemoveTailList(
  331. // PLIST_ENTRY ListHead
  332. // );
  333. //
  334. #define RemoveTailList(ListHead) \
  335. (ListHead)->Blink;\
  336. {RemoveEntryList((ListHead)->Blink)}
  337. //
  338. // VOID
  339. // RemoveEntryList(
  340. // PLIST_ENTRY Entry
  341. // );
  342. //
  343. #define RemoveEntryList(Entry) {\
  344. PLIST_ENTRY _EX_Blink;\
  345. PLIST_ENTRY _EX_Flink;\
  346. _EX_Flink = (Entry)->Flink;\
  347. _EX_Blink = (Entry)->Blink;\
  348. _EX_Blink->Flink = _EX_Flink;\
  349. _EX_Flink->Blink = _EX_Blink;\
  350. }
  351. //
  352. // VOID
  353. // InsertTailList(
  354. // PLIST_ENTRY ListHead,
  355. // PLIST_ENTRY Entry
  356. // );
  357. //
  358. #define InsertTailList(ListHead,Entry) {\
  359. PLIST_ENTRY _EX_Blink;\
  360. PLIST_ENTRY _EX_ListHead;\
  361. _EX_ListHead = (ListHead);\
  362. _EX_Blink = _EX_ListHead->Blink;\
  363. (Entry)->Flink = _EX_ListHead;\
  364. (Entry)->Blink = _EX_Blink;\
  365. _EX_Blink->Flink = (Entry);\
  366. _EX_ListHead->Blink = (Entry);\
  367. }
  368. //
  369. // VOID
  370. // InsertHeadList(
  371. // PLIST_ENTRY ListHead,
  372. // PLIST_ENTRY Entry
  373. // );
  374. //
  375. #define InsertHeadList(ListHead,Entry) {\
  376. PLIST_ENTRY _EX_Flink;\
  377. PLIST_ENTRY _EX_ListHead;\
  378. _EX_ListHead = (ListHead);\
  379. _EX_Flink = _EX_ListHead->Flink;\
  380. (Entry)->Flink = _EX_Flink;\
  381. (Entry)->Blink = _EX_ListHead;\
  382. _EX_Flink->Blink = (Entry);\
  383. _EX_ListHead->Flink = (Entry);\
  384. }
  385. BOOL IsNodeOnList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry);
  386. #endif //InitializeListHead
  387. //
  388. // Templates for private addref and release. See Platform SDK documentation.
  389. //
  390. template <class T> ULONG MSPAddRefHelper (T * pMyThis)
  391. {
  392. LOG((MSP_INFO, "MSPAddRefHelper - this = 0x%08x", pMyThis));
  393. typedef CComAggObject<T> AggClass;
  394. AggClass * p = CONTAINING_RECORD(pMyThis, AggClass, m_contained);
  395. return p->AddRef();
  396. }
  397. template <class T> ULONG MSPReleaseHelper (T * pMyThis)
  398. {
  399. LOG((MSP_INFO, "MSPReleaseHelper - this = 0x%08x", pMyThis));
  400. typedef CComAggObject<T> AggClass;
  401. AggClass * p = CONTAINING_RECORD(pMyThis, AggClass, m_contained);
  402. return p->Release();
  403. }
  404. //
  405. // Basic implementation for IObjectSafety.
  406. //
  407. // Derive from this class to make your object safe for scripting on all its
  408. // interfaces
  409. //
  410. #include <Objsafe.h>
  411. class CMSPObjectSafetyImpl : public IObjectSafety
  412. {
  413. public:
  414. CMSPObjectSafetyImpl()
  415. :m_dwSafety(0)
  416. {}
  417. //
  418. // we support the following safety options:
  419. //
  420. enum { SUPPORTED_SAFETY_OPTIONS =
  421. INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA };
  422. STDMETHOD(SetInterfaceSafetyOptions)(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions)
  423. {
  424. //
  425. // any options requested that we do not support?
  426. //
  427. if ( (~SUPPORTED_SAFETY_OPTIONS & dwOptionSetMask) != 0 )
  428. {
  429. return E_FAIL;
  430. }
  431. //
  432. // see if the interface is supported at all
  433. //
  434. IUnknown *pUnk = NULL;
  435. HRESULT hr = QueryInterface(riid, (void**)&pUnk);
  436. if (SUCCEEDED(hr))
  437. {
  438. //
  439. // we don't need the interface, just wanted to see if it
  440. // was supported. so release.
  441. //
  442. pUnk->Release();
  443. pUnk = NULL;
  444. //
  445. // the object supports the interface. Set options
  446. //
  447. s_CritSection.Lock();
  448. //
  449. // set the bits specified by the mask to the values specified by
  450. // dwEnabledOptions
  451. //
  452. m_dwSafety = (dwEnabledOptions & dwOptionSetMask) |
  453. (m_dwSafety & ~dwOptionSetMask);
  454. s_CritSection.Unlock();
  455. }
  456. return hr;
  457. }
  458. STDMETHOD(GetInterfaceSafetyOptions)(REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
  459. {
  460. //
  461. // check caller's pointers
  462. //
  463. if ( IsBadWritePtr(pdwSupportedOptions, sizeof(DWORD)) ||
  464. IsBadWritePtr(pdwEnabledOptions, sizeof(DWORD)) )
  465. {
  466. return E_POINTER;
  467. }
  468. //
  469. // if we fail, return something meaningful
  470. //
  471. *pdwSupportedOptions = 0;
  472. *pdwEnabledOptions = 0;
  473. //
  474. // see if the interface is supported at all
  475. //
  476. IUnknown *pUnk = NULL;
  477. HRESULT hr = QueryInterface(riid, (void**)&pUnk);
  478. if (SUCCEEDED(hr))
  479. {
  480. //
  481. // we don't need the interface, just wanted to see if it
  482. // was supported. so release.
  483. //
  484. pUnk->Release();
  485. pUnk = NULL;
  486. //
  487. // the object supports the interface. get safe scripting options
  488. //
  489. *pdwSupportedOptions = SUPPORTED_SAFETY_OPTIONS;
  490. s_CritSection.Lock();
  491. *pdwEnabledOptions = m_dwSafety;
  492. s_CritSection.Unlock();
  493. }
  494. return hr;
  495. }
  496. private:
  497. DWORD m_dwSafety;
  498. //
  499. // thread safety
  500. //
  501. // the critical section is shared among all instances of this class
  502. //
  503. static CMSPCritSection s_CritSection;
  504. };
  505. #endif //__MSPUTILS_H_
  506. // eof