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.

378 lines
13 KiB

  1. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // FactoryRouter.cpp -- Generic Com Class factory class
  4. //
  5. // Copyright (c) 2000-2001 Microsoft Corporation, All Rights Reserved
  6. //
  7. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  8. #include "precomp.h"
  9. #include "dllmain.h"
  10. #include "cautolock.h"
  11. using namespace std;
  12. #include "FactoryRouter.h"
  13. #define DUPLICATE_RELEASE FALSE
  14. extern CFactoryRouterData g_FactoryRouterData;
  15. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  16. //*************************************************************************************************************
  17. // Utility functions
  18. //*************************************************************************************************************
  19. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  20. void ClsToString( CHString &a_chsClsId, REFGUID a_rClsId )
  21. {
  22. WCHAR wcID[128] ;
  23. StringFromGUID2( a_rClsId, wcID, 128 ) ;
  24. a_chsClsId = wcID ;
  25. a_chsClsId.MakeUpper() ;
  26. }
  27. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  28. //*************************************************************************************************************
  29. // The CFactoryRouter Class
  30. //*************************************************************************************************************
  31. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  32. CFactoryRouter::CFactoryRouter(REFGUID a_rClsId, LPCWSTR a_pClassName):m_Register( 0 )
  33. {
  34. m_ClsId = a_rClsId ;
  35. m_sDescription = a_pClassName ;
  36. g_FactoryRouterData.AddToMap( a_rClsId,this ) ;
  37. }
  38. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  39. CFactoryRouter::~CFactoryRouter()
  40. {
  41. }
  42. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  43. STDMETHODIMP_( ULONG ) CFactoryRouter::AddRef()
  44. {
  45. return g_FactoryRouterData.AddRef();
  46. }
  47. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  48. STDMETHODIMP_(ULONG) CFactoryRouter::Release()
  49. {
  50. ULONG nRet = g_FactoryRouterData.Release();
  51. if ( nRet == 0 )
  52. {
  53. try
  54. {
  55. LogMessage(L"CFactoryRouter Ref Count = 0");
  56. }
  57. catch ( ... )
  58. {
  59. }
  60. // delete this; Can't delete this, because these hang around the whole time the dll is loaded
  61. // the ptr to this factory is deleted upon dll being detached
  62. }
  63. else if (nRet > 0x80000000)
  64. {
  65. ASSERT_BREAK(DUPLICATE_RELEASE);
  66. LogErrorMessage(L"Duplicate CFactoryRouter Release()");
  67. }
  68. return nRet;
  69. }
  70. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  71. STDMETHODIMP CFactoryRouter::QueryInterface( REFIID a_riid, PPVOID a_ppv )
  72. {
  73. *a_ppv = NULL ;
  74. if ( IID_IUnknown == a_riid || IID_IClassFactory == a_riid )
  75. {
  76. *a_ppv = this ;
  77. }
  78. if ( NULL != *a_ppv )
  79. {
  80. AddRef() ;
  81. return NOERROR ;
  82. }
  83. return ResultFromScode( E_NOINTERFACE ) ;
  84. }
  85. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  86. //
  87. // CFactoryRouter::LockServer
  88. //
  89. // Purpose:
  90. // Increments or decrements the lock count of the DLL. If the
  91. // lock count goes to zero and there are no objects, the DLL
  92. // is allowed to unload. See DllCanUnloadNow.
  93. //
  94. // Parameters:
  95. // fLock BOOL specifying whether to increment or
  96. // decrement the lock count.
  97. //
  98. // Return Value:
  99. // HRESULT NOERROR always.
  100. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  101. STDMETHODIMP CFactoryRouter::LockServer( BOOL a_fLock )
  102. {
  103. if ( a_fLock )
  104. {
  105. g_FactoryRouterData.AddLock();
  106. }
  107. else
  108. {
  109. g_FactoryRouterData.ReleaseLock();
  110. }
  111. return S_OK ;
  112. }
  113. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  114. //
  115. // CFactoryRouter::CreateInstance
  116. //
  117. // Purpose: Instantiates a Event Provider object returning an interface pointer.
  118. //
  119. // Parameters:
  120. // pUnkOuter LPUNKNOWN to the controlling IUnknown if we are
  121. // being used in an aggregation.
  122. // riid REFIID identifying the interface the caller
  123. // desires to have for the new object.
  124. // ppvObj PPVOID in which to store the desired
  125. // interface pointer for the new object.
  126. //
  127. // Return Value:
  128. // HRESULT NOERROR if successful, otherwise E_NOINTERFACE
  129. // if we cannot support the requested interface.
  130. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  131. STDMETHODIMP CFactoryRouter::CreateInstance (LPUNKNOWN a_pUnkOuter ,REFIID a_riid ,LPVOID FAR *a_ppvObject)
  132. {
  133. HRESULT t_status = S_OK ;
  134. if ( a_pUnkOuter )
  135. {
  136. t_status = CLASS_E_NOAGGREGATION ;
  137. }
  138. else
  139. {
  140. // resolve request to whomever derived from us
  141. IUnknown *t_lpunk = (IUnknown *) CreateInstance( a_riid, a_ppvObject ) ;
  142. if ( t_lpunk == NULL )
  143. {
  144. t_status = E_OUTOFMEMORY ;
  145. }
  146. else
  147. {
  148. // declare interface support
  149. t_status = t_lpunk->QueryInterface ( a_riid , a_ppvObject ) ;
  150. if ( FAILED ( t_status ) )
  151. {
  152. delete t_lpunk ;
  153. }
  154. }
  155. }
  156. return t_status ;
  157. }
  158. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  159. REFGUID CFactoryRouter::GetClsId()
  160. {
  161. return m_ClsId;
  162. }
  163. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  164. LPCWSTR CFactoryRouter::GetClassDescription()
  165. {
  166. return (LPCWSTR)m_sDescription;
  167. }
  168. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  169. DWORD CFactoryRouter::GetRegister()
  170. {
  171. return m_Register;
  172. }
  173. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  174. void CFactoryRouter::SetRegister( DWORD a_dwRegister )
  175. {
  176. m_Register = a_dwRegister;
  177. }
  178. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  179. //*************************************************************************************************************
  180. //
  181. //*************************************************************************************************************
  182. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  183. CFactoryRouterData::CFactoryRouterData()
  184. {
  185. s_LocksInProgress = s_ObjectsInProgress = m_ReferenceCount = 0;
  186. }
  187. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  188. CFactoryRouterData::~CFactoryRouterData()
  189. {
  190. CAutoLock cal( m_cs);
  191. LogMessage(L"************ Clearing the FactoryRouterMap");
  192. mg_oFactoryMap.clear() ;
  193. }
  194. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  195. void CFactoryRouterData::AddToMap( REFGUID a_rClsId, CFactoryRouter * pFactory )
  196. {
  197. CHString t_chsClsId ;
  198. ClsToString( t_chsClsId, a_rClsId ) ;
  199. CAutoLock cal( m_cs);
  200. LogMessage2(L"************ Adding to map %s", (WCHAR*)(const WCHAR*) t_chsClsId);
  201. // map class and instance
  202. mg_oFactoryMap[ t_chsClsId ] = pFactory ;
  203. }
  204. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  205. /*void CFactoryRouterData::RemoveFromMap( REFGUID a_rClsId )
  206. {
  207. CHString t_chsClsId ;
  208. ClsToString( t_chsClsId, a_rClsId ) ;
  209. CAutoLock cal( m_cs);
  210. mg_oFactoryMap.erase( t_chsClsId ) ;
  211. }*/
  212. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  213. BOOL CFactoryRouterData::DllCanUnloadNow()
  214. {
  215. return !(s_ObjectsInProgress || s_LocksInProgress) ;
  216. }
  217. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  218. void CFactoryRouterData::AddLock()
  219. {
  220. InterlockedIncrement ( &s_LocksInProgress ) ;
  221. }
  222. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  223. void CFactoryRouterData::ReleaseLock()
  224. {
  225. InterlockedDecrement ( &s_LocksInProgress ) ;
  226. }
  227. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  228. STDMETHODIMP_( ULONG ) CFactoryRouterData::AddRef()
  229. {
  230. InterlockedIncrement ( &s_ObjectsInProgress ) ;
  231. return InterlockedIncrement ( &m_ReferenceCount ) ;
  232. }
  233. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  234. STDMETHODIMP_(ULONG) CFactoryRouterData::Release()
  235. {
  236. InterlockedDecrement ( &s_ObjectsInProgress ) ;
  237. return InterlockedDecrement( &m_ReferenceCount ) ;
  238. }
  239. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  240. HRESULT CFactoryRouterData::DllGetClassObject( REFCLSID a_rclsid, REFIID a_riid, PPVOID a_ppv )
  241. {
  242. HRESULT t_hResult = E_FAIL ;
  243. CHString t_chsClsId ;
  244. Factory_Map::iterator t_FactoryIter;
  245. ClsToString( t_chsClsId, a_rclsid ) ;
  246. CAutoLock cal(m_cs);
  247. LogMessage2(L"************ Looking for %s in DllGetClassObject", (WCHAR*)(const WCHAR*) t_chsClsId);
  248. t_FactoryIter = mg_oFactoryMap.find( t_chsClsId ) ;
  249. if( t_FactoryIter != mg_oFactoryMap.end() )
  250. {
  251. t_hResult = t_FactoryIter->second->QueryInterface( a_riid, a_ppv ) ;
  252. }
  253. LogMessage2(L"************ DllGetClassObject QueryInterface returned %x",t_hResult);
  254. return t_hResult ;
  255. }
  256. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  257. HRESULT CFactoryRouterData::DllRegisterServer()
  258. {
  259. HRESULT t_hResult = NOERROR;
  260. CAutoLock cal(m_cs);
  261. Factory_Map::iterator t_FactoryIter ;
  262. t_FactoryIter = mg_oFactoryMap.begin() ;
  263. while( t_FactoryIter != mg_oFactoryMap.end() )
  264. {
  265. bstr_t t_bstrPreface( "WMI instrumentation: " ) ;
  266. bstr_t t_bstrClassDescription( t_FactoryIter->second->GetClassDescription() ) ;
  267. t_bstrPreface += t_bstrClassDescription ;
  268. t_hResult = ::RegisterServer( t_bstrPreface, t_FactoryIter->second->GetClsId() ) ;
  269. if( NOERROR != t_hResult )
  270. {
  271. break ;
  272. }
  273. ++t_FactoryIter ;
  274. }
  275. return t_hResult ;
  276. }
  277. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  278. HRESULT CFactoryRouterData::DllUnregisterServer()
  279. {
  280. HRESULT t_hResult = NOERROR ;
  281. CAutoLock cal(m_cs);
  282. Factory_Map::iterator t_FactoryIter ;
  283. t_FactoryIter = mg_oFactoryMap.begin() ;
  284. while( t_FactoryIter != mg_oFactoryMap.end() )
  285. {
  286. t_hResult = ::UnregisterServer( t_FactoryIter->second->GetClsId() ) ;
  287. if( NOERROR != t_hResult )
  288. {
  289. break ;
  290. }
  291. ++t_FactoryIter ;
  292. }
  293. return t_hResult ;
  294. }
  295. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  296. HRESULT CFactoryRouterData::InitComServer()
  297. {
  298. HRESULT t_hResult = S_OK ;
  299. CAutoLock cal(m_cs);
  300. Factory_Map::iterator t_FactoryIter ;
  301. t_FactoryIter = mg_oFactoryMap.begin() ;
  302. while( t_FactoryIter != mg_oFactoryMap.end() )
  303. {
  304. DWORD t_ClassContext = CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER ;
  305. DWORD t_Flags = REGCLS_MULTIPLEUSE ;
  306. DWORD t_dwRegister = 0 ;
  307. t_hResult = CoRegisterClassObject(t_FactoryIter->second->GetClsId(),t_FactoryIter->second,t_ClassContext,t_Flags,&t_dwRegister);
  308. if( NOERROR != t_hResult )
  309. {
  310. break ;
  311. }
  312. t_FactoryIter->second->SetRegister( t_dwRegister ) ;
  313. ++t_FactoryIter ;
  314. }
  315. return t_hResult ;
  316. }
  317. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  318. HRESULT CFactoryRouterData::UninitComServer()
  319. {
  320. HRESULT t_hResult = S_OK ;
  321. CAutoLock cal( m_cs);
  322. Factory_Map::iterator t_FactoryIter ;
  323. t_FactoryIter = mg_oFactoryMap.begin() ;
  324. while( t_FactoryIter != mg_oFactoryMap.end() )
  325. {
  326. DWORD t_ClassContext = CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER ;
  327. DWORD t_Flags = REGCLS_MULTIPLEUSE ;
  328. DWORD t_dwRegister = t_FactoryIter->second->GetRegister() ;
  329. if( t_dwRegister )
  330. {
  331. t_hResult = CoRevokeClassObject ( t_dwRegister ) ;
  332. t_FactoryIter->second->SetRegister( 0 ) ;
  333. }
  334. if( NOERROR != t_hResult )
  335. {
  336. break ;
  337. }
  338. ++t_FactoryIter ;
  339. }
  340. return t_hResult ;
  341. }