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.

506 lines
10 KiB

  1. /*
  2. * clsiface.c - Class interface cache ADT module.
  3. */
  4. /*
  5. */
  6. /* Headers
  7. **********/
  8. #include "project.h"
  9. #pragma hdrstop
  10. #include "oleutil.h"
  11. /* Constants
  12. ************/
  13. /* class interface cache pointer array allocation parameters */
  14. #define NUM_START_CLS_IFACES (0)
  15. #define NUM_CLS_IFACES_TO_ADD (16)
  16. /* Types
  17. ********/
  18. /* class interface cache */
  19. typedef struct _clsifacecache
  20. {
  21. HPTRARRAY hpa;
  22. }
  23. CLSIFACECACHE;
  24. DECLARE_STANDARD_TYPES(CLSIFACECACHE);
  25. /* class interface */
  26. typedef struct _clsiface
  27. {
  28. /* class ID */
  29. PCCLSID pcclsid;
  30. /* interface ID */
  31. PCIID pciid;
  32. /* interface */
  33. PVOID pvInterface;
  34. }
  35. CLSIFACE;
  36. DECLARE_STANDARD_TYPES(CLSIFACE);
  37. /* class interface search structure for ClassInterfaceSearchCmp() */
  38. typedef struct _clsifacesearchinfo
  39. {
  40. /* class ID */
  41. PCCLSID pcclsid;
  42. /* interface ID */
  43. PCIID pciid;
  44. }
  45. CLSIFACESEARCHINFO;
  46. DECLARE_STANDARD_TYPES(CLSIFACESEARCHINFO);
  47. /***************************** Private Functions *****************************/
  48. /* Module Prototypes
  49. ********************/
  50. PRIVATE_CODE BOOL CreateClassInterfacePtrArray(PHPTRARRAY);
  51. PRIVATE_CODE void DestroyClassInterfacePtrArray(HPTRARRAY);
  52. PRIVATE_CODE HRESULT CreateClassInterface(PCCLSIFACECACHE, PCCLSID, PCIID, PCLSIFACE *);
  53. PRIVATE_CODE void DestroyClassInterface(PCLSIFACE);
  54. PRIVATE_CODE COMPARISONRESULT ClassInterfaceSortCmp(PCVOID, PCVOID);
  55. PRIVATE_CODE COMPARISONRESULT ClassInterfaceSearchCmp(PCVOID, PCVOID);
  56. #ifdef DEBUG
  57. PRIVATE_CODE BOOL IsValidPCCLSIFACECACHE(PCCLSIFACECACHE);
  58. PRIVATE_CODE BOOL IsValidPCCLSIFACE(PCCLSIFACE);
  59. PRIVATE_CODE BOOL IsValidPCCLSIFACESEARCHINFO(PCCLSIFACESEARCHINFO);
  60. #endif
  61. /*
  62. ** CreateClassInterfacePtrArray()
  63. **
  64. **
  65. **
  66. ** Arguments:
  67. **
  68. ** Returns:
  69. **
  70. ** Side Effects: none
  71. */
  72. PRIVATE_CODE BOOL CreateClassInterfacePtrArray(PHPTRARRAY phpa)
  73. {
  74. NEWPTRARRAY npa;
  75. ASSERT(IS_VALID_WRITE_PTR(phpa, HPTRARRAY));
  76. npa.aicInitialPtrs = NUM_START_CLS_IFACES;
  77. npa.aicAllocGranularity = NUM_CLS_IFACES_TO_ADD;
  78. npa.dwFlags = NPA_FL_SORTED_ADD;
  79. return(CreatePtrArray(&npa, phpa));
  80. }
  81. /*
  82. ** DestroyClassInterfacePtrArray()
  83. **
  84. **
  85. **
  86. ** Arguments:
  87. **
  88. ** Returns:
  89. **
  90. ** Side Effects: none
  91. */
  92. PRIVATE_CODE void DestroyClassInterfacePtrArray(HPTRARRAY hpa)
  93. {
  94. ARRAYINDEX aicPtrs;
  95. ARRAYINDEX ai;
  96. ASSERT(IS_VALID_HANDLE(hpa, PTRARRAY));
  97. /* First free all class interfaces in array. */
  98. aicPtrs = GetPtrCount(hpa);
  99. for (ai = 0; ai < aicPtrs; ai++)
  100. DestroyClassInterface(GetPtr(hpa, ai));
  101. /* Now wipe out the array. */
  102. DestroyPtrArray(hpa);
  103. return;
  104. }
  105. /*
  106. ** CreateClassInterface()
  107. **
  108. **
  109. **
  110. ** Arguments:
  111. **
  112. ** Returns:
  113. **
  114. ** Side Effects: none
  115. */
  116. PRIVATE_CODE HRESULT CreateClassInterface(PCCLSIFACECACHE pccic,
  117. PCCLSID pcclsid, PCIID pciid,
  118. PCLSIFACE *ppci)
  119. {
  120. HRESULT hr;
  121. ASSERT(IS_VALID_STRUCT_PTR(pccic, CCLSIFACECACHE));
  122. ASSERT(IS_VALID_STRUCT_PTR(pcclsid, CCLSID));
  123. ASSERT(IS_VALID_STRUCT_PTR(pciid, CIID));
  124. ASSERT(IS_VALID_WRITE_PTR(ppci, PCLSIFACE));
  125. if (AllocateMemory(sizeof(**ppci), ppci))
  126. {
  127. /* Use inproc servers and local servers. */
  128. // Security: Per the comment above removing CLSCTS_SERVER and
  129. // replacing with just inproc and local (no remote).
  130. hr = CoCreateInstance(pcclsid, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
  131. pciid, &((*ppci)->pvInterface));
  132. if (SUCCEEDED(hr))
  133. {
  134. ARRAYINDEX ai;
  135. (*ppci)->pcclsid = pcclsid;
  136. (*ppci)->pciid = pciid;
  137. if (! AddPtr(pccic->hpa, ClassInterfaceSortCmp, *ppci, &ai))
  138. {
  139. hr = E_OUTOFMEMORY;
  140. CREATECLASSINTERFACE_BAIL:
  141. FreeMemory(*ppci);
  142. }
  143. }
  144. else
  145. {
  146. WARNING_OUT((TEXT("CreateClassInterface(): CoCreateInstance() failed, returning %s."),
  147. GetHRESULTString(hr)));
  148. goto CREATECLASSINTERFACE_BAIL;
  149. }
  150. }
  151. else
  152. hr = E_OUTOFMEMORY;
  153. ASSERT(FAILED(hr) ||
  154. IS_VALID_STRUCT_PTR(*ppci, CCLSIFACE));
  155. return(hr);
  156. }
  157. /*
  158. ** DestroyClassInterface()
  159. **
  160. **
  161. **
  162. ** Arguments:
  163. **
  164. ** Returns:
  165. **
  166. ** Side Effects: none
  167. */
  168. PRIVATE_CODE void DestroyClassInterface(PCLSIFACE pci)
  169. {
  170. ASSERT(IS_VALID_STRUCT_PTR(pci, CCLSIFACE));
  171. ((PCIUnknown)(pci->pvInterface))->lpVtbl->Release(pci->pvInterface);
  172. FreeMemory(pci);
  173. return;
  174. }
  175. /*
  176. ** ClassInterfaceSortCmp()
  177. **
  178. ** Pointer comparison function used to sort an array of pointers to class
  179. ** interfaces.
  180. **
  181. ** Arguments: pcci1 - pointer to first class interface
  182. ** pcci2 - pointer to second class interface
  183. **
  184. ** Returns:
  185. **
  186. ** Side Effects: none
  187. **
  188. ** The class interfaces are sorted by:
  189. ** 1) CLSID
  190. ** 2) IID
  191. */
  192. PRIVATE_CODE COMPARISONRESULT ClassInterfaceSortCmp(PCVOID pcci1, PCVOID pcci2)
  193. {
  194. COMPARISONRESULT cr;
  195. ASSERT(IS_VALID_STRUCT_PTR(pcci1, CCLSIFACE));
  196. ASSERT(IS_VALID_STRUCT_PTR(pcci2, CCLSIFACE));
  197. cr = CompareClassIDs(((PCCLSIFACE)pcci1)->pcclsid,
  198. ((PCCLSIFACE)pcci2)->pcclsid);
  199. if (cr == CR_EQUAL)
  200. cr = CompareInterfaceIDs(((PCCLSIFACE)pcci1)->pciid,
  201. ((PCCLSIFACE)pcci2)->pciid);
  202. return(cr);
  203. }
  204. /*
  205. ** ClassInterfaceSearchCmp()
  206. **
  207. ** Pointer comparison function used to search an array of pointers to class
  208. ** interfaces.
  209. **
  210. ** Arguments: pccisi - pointer to class interface search information
  211. ** pcci - pointer to class interface to examine
  212. **
  213. ** Returns:
  214. **
  215. ** Side Effects: none
  216. */
  217. PRIVATE_CODE COMPARISONRESULT ClassInterfaceSearchCmp(PCVOID pccisi,
  218. PCVOID pcci)
  219. {
  220. COMPARISONRESULT cr;
  221. ASSERT(IS_VALID_STRUCT_PTR(pccisi, CCLSIFACESEARCHINFO));
  222. ASSERT(IS_VALID_STRUCT_PTR(pcci, CCLSIFACE));
  223. cr = CompareClassIDs(((PCCLSIFACESEARCHINFO)pccisi)->pcclsid,
  224. ((PCCLSIFACE)pcci)->pcclsid);
  225. if (cr == CR_EQUAL)
  226. cr = CompareInterfaceIDs(((PCCLSIFACESEARCHINFO)pccisi)->pciid,
  227. ((PCCLSIFACE)pcci)->pciid);
  228. return(cr);
  229. }
  230. #ifdef DEBUG
  231. /*
  232. ** IsValidPCCLSIFACECACHE()
  233. **
  234. **
  235. **
  236. ** Arguments:
  237. **
  238. ** Returns:
  239. **
  240. ** Side Effects: none
  241. */
  242. PRIVATE_CODE BOOL IsValidPCCLSIFACECACHE(PCCLSIFACECACHE pccic)
  243. {
  244. return(IS_VALID_READ_PTR(pccic, CLSIFACECACHE) &&
  245. IS_VALID_HANDLE(pccic->hpa, PTRARRAY));
  246. }
  247. /*
  248. ** IsValidPCCLSIFACE()
  249. **
  250. **
  251. **
  252. ** Arguments:
  253. **
  254. ** Returns:
  255. **
  256. ** Side Effects: none
  257. */
  258. PRIVATE_CODE BOOL IsValidPCCLSIFACE(PCCLSIFACE pcci)
  259. {
  260. return(IS_VALID_READ_PTR(pcci, CCLSIFACE) &&
  261. IS_VALID_STRUCT_PTR(pcci->pcclsid, CCLSID) &&
  262. IS_VALID_STRUCT_PTR(pcci->pciid, CIID) &&
  263. IS_VALID_STRUCT_PTR(pcci->pvInterface, CInterface));
  264. }
  265. /*
  266. ** IsValidPCCLSIFACESEARCHINFO()
  267. **
  268. **
  269. **
  270. ** Arguments:
  271. **
  272. ** Returns:
  273. **
  274. ** Side Effects: none
  275. */
  276. PRIVATE_CODE BOOL IsValidPCCLSIFACESEARCHINFO(PCCLSIFACESEARCHINFO pccisi)
  277. {
  278. return(IS_VALID_READ_PTR(pccisi, CCLSIFACESEARCHINFO) &&
  279. IS_VALID_STRUCT_PTR(pccisi->pcclsid, CCLSID) &&
  280. IS_VALID_STRUCT_PTR(pccisi->pciid, CIID));
  281. }
  282. #endif
  283. /****************************** Public Functions *****************************/
  284. /*
  285. ** CreateClassInterfaceCache()
  286. **
  287. **
  288. **
  289. ** Arguments:
  290. **
  291. ** Returns:
  292. **
  293. ** Side Effects: none
  294. */
  295. PUBLIC_CODE BOOL CreateClassInterfaceCache(PHCLSIFACECACHE phcic)
  296. {
  297. BOOL bResult = FALSE;
  298. PCLSIFACECACHE pcic;
  299. ASSERT(IS_VALID_WRITE_PTR(phcic, HCLSIFACECACHE));
  300. if (AllocateMemory(sizeof(*pcic), &pcic))
  301. {
  302. if (CreateClassInterfacePtrArray(&(pcic->hpa)))
  303. {
  304. *phcic = (HCLSIFACECACHE)pcic;
  305. bResult = TRUE;
  306. }
  307. else
  308. FreeMemory(pcic);
  309. }
  310. ASSERT(! bResult ||
  311. IS_VALID_HANDLE(*phcic, CLSIFACECACHE));
  312. return(bResult);
  313. }
  314. /*
  315. ** DestroyClassInterfaceCache()
  316. **
  317. **
  318. **
  319. ** Arguments:
  320. **
  321. ** Returns:
  322. **
  323. ** Side Effects: none
  324. */
  325. PUBLIC_CODE void DestroyClassInterfaceCache(HCLSIFACECACHE hcic)
  326. {
  327. ASSERT(IS_VALID_HANDLE(hcic, CLSIFACECACHE));
  328. DestroyClassInterfacePtrArray(((PCLSIFACECACHE)hcic)->hpa);
  329. FreeMemory(hcic);
  330. return;
  331. }
  332. /*
  333. ** GetClassInterface()
  334. **
  335. **
  336. **
  337. ** Arguments:
  338. **
  339. ** Returns:
  340. **
  341. ** Side Effects: none
  342. **
  343. ** N.b., this function assumes that pcclsid and pciid are valid until hcic is
  344. ** destroyed with DestroyClassInterfaceCache().
  345. */
  346. PUBLIC_CODE HRESULT GetClassInterface(HCLSIFACECACHE hcic, PCCLSID pcclsid,
  347. PCIID pciid, PVOID *ppvInterface)
  348. {
  349. HRESULT hr;
  350. CLSIFACESEARCHINFO cisi;
  351. ARRAYINDEX ai;
  352. PCLSIFACE pci;
  353. ASSERT(IS_VALID_HANDLE(hcic, CLSIFACECACHE));
  354. /* Is this class interface already in the cache? */
  355. cisi.pcclsid = pcclsid;
  356. cisi.pciid = pciid;
  357. if (SearchSortedArray(((PCCLSIFACECACHE)hcic)->hpa,
  358. &ClassInterfaceSearchCmp, &cisi, &ai))
  359. {
  360. /* Yes. Use it. */
  361. pci = GetPtr(((PCCLSIFACECACHE)hcic)->hpa, ai);
  362. hr = S_OK;
  363. }
  364. else
  365. /* No. Add it. */
  366. hr = CreateClassInterface((PCCLSIFACECACHE)hcic, pcclsid, pciid, &pci);
  367. if (SUCCEEDED(hr))
  368. {
  369. ASSERT(IS_VALID_STRUCT_PTR(pci, CCLSIFACE));
  370. *ppvInterface = pci->pvInterface;
  371. }
  372. ASSERT(FAILED(hr) ||
  373. IS_VALID_STRUCT_PTR(*ppvInterface, CInterface));
  374. return(hr);
  375. }
  376. #ifdef DEBUG
  377. /*
  378. ** IsValidHCLSIFACECACHE()
  379. **
  380. **
  381. **
  382. ** Arguments:
  383. **
  384. ** Returns:
  385. **
  386. ** Side Effects: none
  387. */
  388. PUBLIC_CODE BOOL IsValidHCLSIFACECACHE(HCLSIFACECACHE hcic)
  389. {
  390. return(IS_VALID_STRUCT_PTR((PCCLSIFACECACHE)hcic, CCLSIFACECACHE));
  391. }
  392. #endif