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.

413 lines
11 KiB

  1. //+------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1997
  5. //
  6. // File: cclsto.cxx
  7. //
  8. // Contents: Class Factory and IUnknown methods for CAppContainer
  9. //
  10. // Author: DebiM
  11. //
  12. //-------------------------------------------------------------------------
  13. #include "cstore.hxx"
  14. //
  15. // Constructor for App Container Class factory
  16. //
  17. unsigned long gulcappcon = 0;
  18. extern CRITICAL_SECTION ClassStoreBindList;
  19. ClassStoreCacheType ClassStoreCache;
  20. CAppContainerCF::CAppContainerCF()
  21. {
  22. m_uRefs = 1;
  23. InterlockedIncrement((long *) &gulcappcon );
  24. ClassStoreCache.sz = 0;
  25. ClassStoreCache.start = 0;
  26. ClassStoreCache.end = 0;
  27. }
  28. void ReleaseBindings(BindingsType *pbd)
  29. {
  30. CSDBGPrint((L"Cleaning up entry in Cache. %s", pbd->szStorePath));
  31. if (pbd->pIClassAccess)
  32. {
  33. (pbd->pIClassAccess)->Release();
  34. }
  35. CoTaskMemFree(pbd->Sid);
  36. CoTaskMemFree(pbd->szStorePath);
  37. }
  38. //
  39. // Destructor
  40. //
  41. CAppContainerCF::~CAppContainerCF()
  42. {
  43. //
  44. // Cleanup the cache
  45. //
  46. for (UINT i=ClassStoreCache.start; i != ClassStoreCache.end;
  47. i = (i+1)%(MAXCLASSSTORES))
  48. {
  49. ReleaseBindings(ClassStoreCache.Bindings+i);
  50. }
  51. InterlockedDecrement((long *) &gulcappcon );
  52. }
  53. HRESULT __stdcall CAppContainerCF::QueryInterface(REFIID riid, void * * ppvObject)
  54. {
  55. IUnknown *pUnkTemp = NULL;
  56. SCODE sc = S_OK;
  57. if( IsEqualIID( IID_IUnknown, riid ) )
  58. {
  59. pUnkTemp = (IUnknown *)(ITypeLib *)this;
  60. }
  61. else if( IsEqualIID( IID_IClassFactory, riid ) )
  62. {
  63. pUnkTemp = (IUnknown *)(IClassFactory *)this;
  64. }
  65. else if( IsEqualIID( IID_IParseDisplayName, riid ) )
  66. {
  67. pUnkTemp = (IUnknown *)(IParseDisplayName *)this;
  68. }
  69. else
  70. {
  71. sc = (E_NOINTERFACE);
  72. }
  73. if((pUnkTemp != NULL) && (SUCCEEDED(sc)))
  74. {
  75. *ppvObject = (void * )pUnkTemp;
  76. pUnkTemp->AddRef();
  77. }
  78. return(sc);
  79. }
  80. ULONG __stdcall CAppContainerCF::AddRef()
  81. {
  82. InterlockedIncrement(( long * )&m_uRefs );
  83. return m_uRefs;
  84. }
  85. ULONG __stdcall CAppContainerCF::Release()
  86. {
  87. unsigned long uTmp = InterlockedDecrement((long *)&m_uRefs);
  88. unsigned long cRef = m_uRefs;
  89. // 0 is the only valid value to check
  90. if (uTmp == 0)
  91. {
  92. delete this;
  93. }
  94. return(cRef);
  95. }
  96. //
  97. // IClassFactory Overide
  98. //
  99. HRESULT __stdcall CAppContainerCF::CreateInstance(IUnknown * pUnkOuter, REFIID riid,
  100. void ** ppvObject)
  101. {
  102. CAppContainer * pIUnk = NULL;
  103. SCODE sc = S_OK;
  104. if( pUnkOuter == NULL )
  105. {
  106. if( (pIUnk = new CAppContainer()) != NULL)
  107. {
  108. sc = pIUnk->QueryInterface( riid , ppvObject );
  109. if(FAILED(sc))
  110. {
  111. sc = E_UNEXPECTED;
  112. }
  113. pIUnk->Release();
  114. }
  115. else
  116. sc = E_OUTOFMEMORY;
  117. }
  118. else
  119. {
  120. return E_INVALIDARG;
  121. }
  122. return (sc);
  123. }
  124. //---------------------------------------------------------------
  125. //
  126. // Function: CreateConnectedInstance
  127. //
  128. // Synopsis: Returns IClassAccess Pointer, given a class store
  129. // path.
  130. //
  131. // Arguments:
  132. // [in]
  133. // pszPath Class Store Path without the leading ADCS:
  134. //
  135. // pUserSid
  136. // Sid under which the calling thread is running.
  137. // fCache
  138. // Boolean that decides whether to use a cached pointer or
  139. // not.
  140. // [out]
  141. // ppvObject
  142. // IClassAccess Interface pointer
  143. //
  144. // Returns:
  145. // S_OK, E_NOINTERFACE, E_OUTOFMEMORY, CS_E_XXX
  146. //
  147. // if (fCache)
  148. // Looks in the cache to see if we have already tried to bind to the same
  149. // ClassStore Path under the same SID. If it finds it, then we just QI for
  150. // IClassAccess and return. o/w create a new class store pointer and caches it.
  151. // else
  152. // Just binds to a new ClassStore and returns.
  153. //----------------------------------------------------------------
  154. HRESULT __stdcall
  155. CAppContainerCF::CreateConnectedInstance(LPOLESTR pszPath, PSID pUserSid,
  156. BOOL fCache, void ** ppvObject)
  157. {
  158. CAppContainer * pIUnk = NULL;
  159. SCODE sc = S_OK;
  160. HRESULT hr = S_OK;
  161. BOOL fFound = FALSE;
  162. if (fCache)
  163. {
  164. //
  165. // Look in cache
  166. //
  167. EnterCriticalSection (&ClassStoreBindList);
  168. for (UINT i=ClassStoreCache.start; i != ClassStoreCache.end;
  169. i = (i+1)%(MAXCLASSSTORES))
  170. {
  171. // compare cached sids and Class Store path
  172. if ((wcscmp(pszPath, ClassStoreCache.Bindings[i].szStorePath) == 0) &&
  173. (EqualSid(pUserSid, ClassStoreCache.Bindings[i].Sid)))
  174. {
  175. //
  176. // Found in cache
  177. //
  178. CSDBGPrint((L"Found %s in Cache.", pszPath));
  179. fFound = TRUE;
  180. if (ClassStoreCache.Bindings[i].pIClassAccess)
  181. {
  182. sc = (ClassStoreCache.Bindings[i].pIClassAccess)->
  183. QueryInterface( IID_IClassAccess, ppvObject );
  184. }
  185. else
  186. {
  187. sc = ClassStoreCache.Bindings[i].Hr;
  188. // return the same error code.
  189. }
  190. break;
  191. }
  192. }
  193. LeaveCriticalSection (&ClassStoreBindList);
  194. if (fFound)
  195. return sc;
  196. }
  197. if ((pIUnk = new CAppContainer(pszPath, &sc)) != NULL)
  198. {
  199. if (SUCCEEDED(sc))
  200. {
  201. sc = pIUnk->QueryInterface( IID_IClassAccess, ppvObject );
  202. if(FAILED(sc))
  203. {
  204. sc = E_UNEXPECTED;
  205. }
  206. }
  207. else
  208. CSDBGPrint((L"Connect to Store Failed. hr = 0x%x", sc));
  209. pIUnk->Release();
  210. }
  211. else
  212. sc = E_OUTOFMEMORY;
  213. //
  214. // Store the result in the cache
  215. //
  216. if (fCache)
  217. {
  218. //
  219. // Should not cache situations out of network failures
  220. // BUGBUG: For now we are only caching successes OR CS does not exist cases
  221. //
  222. if ((sc == S_OK) || (sc == CS_E_OBJECT_NOTFOUND))
  223. {
  224. EnterCriticalSection (&ClassStoreBindList);
  225. for (UINT i=ClassStoreCache.start; i != ClassStoreCache.end;
  226. i = (i+1)%(MAXCLASSSTORES))
  227. {
  228. if ((wcscmp(pszPath, ClassStoreCache.Bindings[i].szStorePath) == 0) &&
  229. (EqualSid(pUserSid, ClassStoreCache.Bindings[i].Sid)))
  230. {
  231. //
  232. // Found in cache after bind attempt
  233. //
  234. CSDBGPrint((L"Found in Cache after binding !!!."));
  235. //
  236. // If we already got an existing object, release the one we grabbed
  237. // above
  238. //
  239. if (*ppvObject) {
  240. ((IClassAccess *)(*ppvObject))->Release();
  241. *ppvObject = NULL;
  242. } else {
  243. ASSERT(CS_E_OBJECT_NOTFOUND == sc);
  244. }
  245. //
  246. // Now we can get the object from the cache to satisfy
  247. // the caller's request
  248. //
  249. if (ClassStoreCache.Bindings[i].pIClassAccess)
  250. {
  251. sc = (ClassStoreCache.Bindings[i].pIClassAccess)->
  252. QueryInterface( IID_IClassAccess, ppvObject );
  253. }
  254. else
  255. {
  256. sc = ClassStoreCache.Bindings[i].Hr;
  257. // return the same error code.
  258. }
  259. }
  260. }
  261. if (i == ClassStoreCache.end)
  262. {
  263. if (ClassStoreCache.sz == (MAXCLASSSTORES-1))
  264. {
  265. ReleaseBindings(ClassStoreCache.Bindings+ClassStoreCache.start);
  266. ClassStoreCache.start = (ClassStoreCache.start+1)%MAXCLASSSTORES;
  267. ClassStoreCache.sz--;
  268. }
  269. // allocate space for the guid and the Class store path.
  270. ClassStoreCache.Bindings[i].szStorePath =
  271. (LPOLESTR) CoTaskMemAlloc (sizeof(WCHAR) * (wcslen (pszPath) + 1));
  272. UINT dwBytesRequired = GetLengthSid(pUserSid);
  273. ClassStoreCache.Bindings[i].Sid = CoTaskMemAlloc(dwBytesRequired);
  274. // if memory was allocated.
  275. if ((ClassStoreCache.Bindings[i].szStorePath) &&
  276. (ClassStoreCache.Bindings[i].Sid))
  277. {
  278. // copy the class store path.
  279. wcscpy (ClassStoreCache.Bindings[i].szStorePath, pszPath);
  280. ClassStoreCache.Bindings[i].pIClassAccess = NULL;
  281. // get the IClassAccess pointer and cache it.
  282. if (sc == S_OK)
  283. {
  284. ((IClassAccess *)(*ppvObject))->QueryInterface( IID_IClassAccess,
  285. (void **)&ClassStoreCache.Bindings[i].pIClassAccess);
  286. }
  287. ClassStoreCache.Bindings[i].Hr = sc;
  288. // copy the SIDs
  289. CopySid(dwBytesRequired, ClassStoreCache.Bindings[i].Sid, pUserSid);
  290. ClassStoreCache.sz++;
  291. ClassStoreCache.end = (ClassStoreCache.end + 1)% MAXCLASSSTORES;
  292. }
  293. }
  294. LeaveCriticalSection (&ClassStoreBindList);
  295. }
  296. }
  297. return (sc);
  298. }
  299. HRESULT __stdcall CAppContainerCF::LockServer(BOOL fLock)
  300. {
  301. if(fLock)
  302. { InterlockedIncrement((long *) &gulcappcon ); }
  303. else
  304. { InterlockedDecrement((long *) &gulcappcon ); }
  305. return(S_OK);
  306. }
  307. //
  308. // IUnknown methods for CAppContainer
  309. //
  310. //
  311. HRESULT __stdcall CAppContainer::QueryInterface(REFIID riid, void * * ppvObject)
  312. {
  313. IUnknown *pUnkTemp = NULL;
  314. SCODE sc = S_OK;
  315. if( IsEqualIID( IID_IUnknown, riid ) )
  316. {
  317. pUnkTemp = (IUnknown *)(IClassAccess *)this;
  318. }
  319. else if( IsEqualIID( IID_IClassAccess, riid ) )
  320. {
  321. pUnkTemp = (IUnknown *)(IClassAccess *)this;
  322. }
  323. /*
  324. else if( IsEqualIID( IID_IClassRefresh, riid ) )
  325. {
  326. pUnkTemp = (IUnknown *)(IClassRefresh *)this;
  327. }
  328. else if( IsEqualIID( IID_ICatInformation, riid ) )
  329. {
  330. pUnkTemp = (IUnknown *)(ICatInformation *)this;
  331. }
  332. */
  333. else
  334. {
  335. sc = (E_NOINTERFACE);
  336. }
  337. if((pUnkTemp != NULL) && (SUCCEEDED(sc)))
  338. {
  339. *ppvObject = (void * )pUnkTemp;
  340. pUnkTemp->AddRef();
  341. }
  342. return(sc);
  343. }
  344. ULONG __stdcall CAppContainer::AddRef()
  345. {
  346. InterlockedIncrement(( long * )&m_uRefs );
  347. return m_uRefs;
  348. }
  349. ULONG __stdcall CAppContainer::Release()
  350. {
  351. unsigned long uTmp = InterlockedDecrement((long *)&m_uRefs);
  352. unsigned long cRef = m_uRefs;
  353. if (uTmp == 0)
  354. {
  355. delete this;
  356. }
  357. return(cRef);
  358. }