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.

323 lines
8.3 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 2000.
  5. //
  6. // File: ShtOle.hxx
  7. //
  8. // Contents: 'Short' OLE -- Minimal persistent handler implementation
  9. //
  10. // Classes: CShtOle
  11. //
  12. // History: 01-Feb-96 KyleP Added header
  13. // 31-Jan-96 KyleP Added support for embeddings
  14. //
  15. //----------------------------------------------------------------------------
  16. #pragma once
  17. //+---------------------------------------------------------------------------
  18. //
  19. // Class: CShtOle
  20. //
  21. // Purpose: 'Short-OLE' -- Minimal persistent handler implementation
  22. //
  23. // History: 01-Feb-96 KyleP Added header
  24. // 31-Jan-96 KyleP Added support for embeddings
  25. // 18-Dec-97 KLam Added ability to flush idle filters
  26. //
  27. //----------------------------------------------------------------------------
  28. class CShtOle
  29. {
  30. public:
  31. CShtOle()
  32. : _pclassList( 0 ),
  33. _pserverList( 0 ),
  34. _ulFilterIdleTimeout( 0xffffffff ),
  35. _mutex( FALSE ),
  36. _fInit( FALSE )
  37. {
  38. }
  39. void Init()
  40. {
  41. _mutex.Init();
  42. _fInit = TRUE;
  43. }
  44. ~CShtOle() { Shutdown(); }
  45. void Shutdown();
  46. void FlushIdle (); // Ask idle classes and servers to unload
  47. SCODE Bind( WCHAR const * pwszPath,
  48. REFIID riid,
  49. IUnknown * pUnkOuter,
  50. void ** ppvObject,
  51. BOOL fFreeThreadedOnly = FALSE );
  52. SCODE Bind( WCHAR const * pwszPath,
  53. GUID const & classid,
  54. REFIID riid,
  55. IUnknown * pUnkOuter,
  56. void ** ppvObject,
  57. BOOL fFreeThreadedOnly = FALSE );
  58. SCODE Bind( IStorage * pStg,
  59. REFIID riid,
  60. IUnknown * pUnkOuter,
  61. void ** ppvObject,
  62. BOOL fFreeThreadedOnly = FALSE );
  63. SCODE Bind( IStream * pStm,
  64. REFIID riid,
  65. IUnknown * pUnkOuter,
  66. void ** ppvObject,
  67. BOOL fFreeThreadedOnly = FALSE );
  68. SCODE NewInstance( GUID const & classid, REFIID riid, void ** ppvObject );
  69. static void StringToGuid( WCHAR * pwcsGuid, GUID & guid );
  70. static void GuidToString( GUID const & guid, WCHAR * pwcsGuid );
  71. private:
  72. //
  73. // InProcServer node
  74. //
  75. class CServerNode
  76. {
  77. public:
  78. CServerNode( GUID guid, CServerNode * pNext )
  79. : _guid( guid ),
  80. _pNext( pNext ),
  81. _pCF( 0 ),
  82. _hModule( 0 ),
  83. _pfnCanUnloadNow ( 0 )
  84. {
  85. _cLastUsed = GetTickCount ();
  86. }
  87. ~CServerNode()
  88. {
  89. if( _pCF )
  90. _pCF->Release();
  91. if ( 0 != _hModule )
  92. FreeLibrary( _hModule );
  93. }
  94. SCODE CreateInstance( IUnknown * pUnkOuter,
  95. REFIID riid,
  96. void ** ppv );
  97. //IClassFactory * GetCF() { return _pCF; }
  98. BOOL IsMatch( GUID guid ) { return( guid == _guid ); }
  99. BOOL IsSingleThreaded() { return _fSingleThreaded; }
  100. void SetSingleThreaded( BOOL fSingleThreaded )
  101. {
  102. _fSingleThreaded = fSingleThreaded;
  103. }
  104. void SetCF( IClassFactory * pCF ) { _pCF = pCF; }
  105. void SetModule( HMODULE hmod );
  106. //
  107. // Link traversal
  108. //
  109. CServerNode * Next() { return _pNext; }
  110. void Link( CServerNode * pNext ) { _pNext = pNext; }
  111. //
  112. // Usage
  113. //
  114. void Touch () { _cLastUsed = GetTickCount (); }
  115. BOOL CanUnloadNow (DWORD cMaxIdle);
  116. private:
  117. CServerNode * _pNext;
  118. GUID _guid;
  119. IClassFactory * _pCF;
  120. HMODULE _hModule;
  121. BOOL _fSingleThreaded;
  122. DWORD _cLastUsed;
  123. LPFNCANUNLOADNOW _pfnCanUnloadNow;
  124. };
  125. CServerNode * FindServer( GUID const & classid, REFIID riid );
  126. CServerNode * FindServerFromPHandler( GUID const & classid, REFIID riid );
  127. //
  128. // File class node
  129. //
  130. class CClassNode
  131. {
  132. public:
  133. CClassNode( WCHAR const * pwcExt, CClassNode * pNext )
  134. : _pNext( pNext ),
  135. _pserver( 0 )
  136. {
  137. memset( &_classid, 0, sizeof(_classid) );
  138. wcscpy( _wcExt, pwcExt );
  139. _cLastUsed = GetTickCount ();
  140. }
  141. CClassNode( GUID const & classid, CClassNode * pNext )
  142. : _pNext( pNext ),
  143. _pserver( 0 )
  144. {
  145. memcpy( &_classid, &classid, sizeof(_classid) );
  146. _wcExt[0] = 0;
  147. _cLastUsed = GetTickCount ();
  148. }
  149. void SetClassId( GUID const & classid )
  150. {
  151. memcpy( &_classid, &classid, sizeof(_classid) );
  152. }
  153. #if 0
  154. IClassFactory * GetCF()
  155. {
  156. if( _pserver )
  157. return _pserver->GetCF();
  158. else
  159. return 0;
  160. }
  161. #endif
  162. BOOL IsSingleThreaded()
  163. {
  164. if( _pserver )
  165. return _pserver->IsSingleThreaded();
  166. else
  167. return FALSE;
  168. }
  169. BOOL IsMatch( WCHAR const * pext ) { return( _wcsicmp(pext, _wcExt) == 0 ); }
  170. BOOL IsMatch( GUID const & classid ) { return( memcmp( &classid, &_classid, sizeof(classid) ) == 0 ); }
  171. void SetServer( CServerNode * pserver ) { _pserver = pserver; }
  172. //
  173. // Link traversal
  174. //
  175. CClassNode * Next() { return _pNext; }
  176. void Link( CClassNode * pNext ) { _pNext = pNext; }
  177. //
  178. // Usage
  179. //
  180. SCODE CreateInstance( IUnknown * pUnkOuter,
  181. REFIID riid,
  182. void ** ppv )
  183. {
  184. Touch();
  185. if ( _pserver )
  186. return _pserver->CreateInstance( pUnkOuter, riid, ppv );
  187. else
  188. return E_FAIL;
  189. }
  190. void Touch ()
  191. {
  192. _cLastUsed = GetTickCount ();
  193. // If we are touching the class then we are touching its server
  194. if ( _pserver )
  195. _pserver->Touch ();
  196. }
  197. BOOL CanUnloadNow (DWORD cMaxIdle)
  198. {
  199. return (GetTickCount() - _cLastUsed > cMaxIdle);
  200. }
  201. enum EExtLen
  202. {
  203. ccExtLen = 10
  204. };
  205. private:
  206. CClassNode * _pNext;
  207. WCHAR _wcExt[ccExtLen + 1];
  208. GUID _classid;
  209. CServerNode * _pserver;
  210. DWORD _cLastUsed;
  211. };
  212. //
  213. // Private methods
  214. //
  215. CClassNode * InsertByClass( GUID const & classid, CClassNode * pnode );
  216. CServerNode * InsertByClass( GUID const & classid, CServerNode * pnode );
  217. ULONG GetFilterIdleTimeout ();
  218. template<class T> T FlushList ( T ptNodeList )
  219. {
  220. if ( 0xffffffff == _ulFilterIdleTimeout )
  221. _ulFilterIdleTimeout = GetFilterIdleTimeout();
  222. T ptnHead = ptNodeList;
  223. T ptnCurrent = ptnHead;
  224. T ptnPrev = 0;
  225. while ( ptnCurrent )
  226. {
  227. if ( ptnCurrent->CanUnloadNow ( _ulFilterIdleTimeout ) )
  228. {
  229. if ( ptnPrev )
  230. {
  231. // Removing a node from the middle of the list
  232. // or end of the list
  233. ptnPrev->Link( ptnCurrent->Next() );
  234. delete ptnCurrent;
  235. ptnCurrent = ptnPrev->Next ();
  236. }
  237. else
  238. {
  239. // Removing a node from the head of the list
  240. ptnHead = ptnCurrent->Next();
  241. delete ptnCurrent;
  242. ptnCurrent = ptnHead;
  243. }
  244. }
  245. else
  246. {
  247. ptnPrev = ptnCurrent;
  248. ptnCurrent = ptnCurrent->Next();
  249. }
  250. }
  251. return ptnHead;
  252. }
  253. CClassNode * _pclassList;
  254. CServerNode * _pserverList;
  255. ULONG _ulFilterIdleTimeout;
  256. BOOL _fInit;
  257. CMutexSem _mutex;
  258. };