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.

431 lines
12 KiB

  1. // Copyright (c) 1993-2000 Microsoft Corporation
  2. #include <windows.h>
  3. #include <ole2.h>
  4. #include <oleauto.h>
  5. #include <typegen.h>
  6. #include <tiutil.h>
  7. #define ASSERT(x)
  8. #define UNREACHED 0
  9. //---------------------------------------------------------------------
  10. // Utilities
  11. //---------------------------------------------------------------------
  12. /***
  13. *PUBLIC HRESULT GetPrimaryInterface
  14. *Purpose:
  15. * Given a TypeInfo describing a Coclass, search for and return
  16. * type TypeInfo that describes that class' primary interface.
  17. *
  18. *Entry:
  19. * ptinfo = the TypeInfo of the base class.
  20. *
  21. *Exit:
  22. * return value = HRESULT
  23. *
  24. * *ptinfoPrimary = the TypeInfo of the primary interface, NULL
  25. * if the class does not have a primary interface.
  26. *
  27. ***********************************************************************/
  28. HRESULT
  29. GetPrimaryInterface(ITypeInfo *ptinfo, ITypeInfo **pptinfoPri)
  30. {
  31. BOOL fIsDual;
  32. TYPEKIND tkind;
  33. HRESULT hresult;
  34. HREFTYPE hreftype;
  35. int impltypeflags;
  36. TYPEATTR *ptattr;
  37. unsigned int iImplType, cImplTypes;
  38. ITypeInfo *ptinfoRef;
  39. ptinfoRef = NULL;
  40. IfFailGo(ptinfo->GetTypeAttr(&ptattr), Error);
  41. cImplTypes = ptattr->cImplTypes;
  42. tkind = ptattr->typekind;
  43. ptinfo->ReleaseTypeAttr(ptattr);
  44. if(tkind != TKIND_COCLASS)
  45. return E_INVALIDARG;
  46. // Look for the interface marked [default] and not [source]
  47. for(iImplType = 0; iImplType < cImplTypes; ++iImplType){
  48. IfFailGo(ptinfo->GetImplTypeFlags(iImplType, &impltypeflags), Error);
  49. if(IMPLTYPEFLAG_FDEFAULT == (impltypeflags & (IMPLTYPEFLAG_FDEFAULT | IMPLTYPEFLAG_FSOURCE)))
  50. {
  51. // Found It!
  52. IfFailGo(ptinfo->GetRefTypeOfImplType(iImplType, &hreftype), Error);
  53. IfFailGo(ptinfo->GetRefTypeInfo(hreftype, &ptinfoRef), Error);
  54. // If its dual, get the interface portion
  55. IfFailGo(ptinfoRef->GetTypeAttr(&ptattr), Error);
  56. fIsDual = (ptattr->wTypeFlags & TYPEFLAG_FDUAL)
  57. && (ptattr->typekind == TKIND_DISPATCH);
  58. ptinfoRef->ReleaseTypeAttr(ptattr);
  59. if (fIsDual) {
  60. IfFailGo(ptinfoRef->GetRefTypeOfImplType((UINT)-1, &hreftype), Error);
  61. IfFailGo(ptinfoRef->GetRefTypeInfo(hreftype, pptinfoPri), Error);
  62. ptinfoRef->Release();
  63. }
  64. else {
  65. *pptinfoPri = ptinfoRef;
  66. }
  67. return NOERROR;
  68. }
  69. }
  70. // NotFound
  71. *pptinfoPri = NULL;
  72. return NOERROR;
  73. Error:
  74. if(ptinfoRef != NULL)
  75. ptinfoRef->Release();
  76. return hresult;
  77. }
  78. HRESULT
  79. VarVtOfIface(ITypeInfo FAR* ptinfo,
  80. TYPEATTR FAR* ptattr,
  81. PARAMINFO *pPinfo)
  82. {
  83. HRESULT hresult;
  84. switch(ptattr->typekind){
  85. case TKIND_DISPATCH:
  86. if ((ptattr->wTypeFlags & TYPEFLAG_FDUAL) == 0) {
  87. // regular (non-dual) dispinterface is just VT_DISPATCH.
  88. pPinfo->vt = VT_DISPATCH;
  89. // don't have to set up *pguid, since not VT_INTERFACE
  90. break;
  91. }
  92. // The interface typeinfo version of a dual interface has the same
  93. // same guid as the dispinterface portion does, hence we can just use
  94. // the dispinterface guid here.
  95. /* FALLTHROUGH */
  96. case TKIND_INTERFACE:
  97. pPinfo->vt = VT_INTERFACE;
  98. pPinfo->iid = ptattr->guid;
  99. break;
  100. default:
  101. ASSERT(UNREACHED);
  102. hresult = DISP_E_BADVARTYPE;
  103. goto Error;
  104. }
  105. hresult = NOERROR;
  106. Error:;
  107. return hresult;
  108. }
  109. HRESULT
  110. VarVtOfUDT(ITypeInfo FAR* ptinfo,
  111. TYPEDESC FAR* ptdesc,
  112. PARAMINFO *pPinfo)
  113. {
  114. HRESULT hresult;
  115. TYPEATTR FAR* ptattrRef;
  116. ITypeInfo FAR* ptinfoRef;
  117. BOOLEAN fReleaseAttr = TRUE;
  118. ASSERT(ptdesc->vt == VT_USERDEFINED);
  119. ptinfoRef = NULL;
  120. ptattrRef = NULL;
  121. IfFailGo(ptinfo->GetRefTypeInfo(ptdesc->hreftype, &ptinfoRef), Error);
  122. IfFailGo(ptinfoRef->GetTypeAttr(&ptattrRef), Error);
  123. pPinfo->cbAlignment = ptattrRef->cbAlignment - 1;
  124. switch (ptattrRef->typekind) {
  125. case TKIND_ENUM:
  126. pPinfo->vt = VT_I4;
  127. hresult = NOERROR;
  128. break;
  129. case TKIND_ALIAS:
  130. hresult = VarVtOfTypeDesc(ptinfoRef,
  131. &ptattrRef->tdescAlias,
  132. pPinfo);
  133. if ((pPinfo->vt & (~VT_BYREF)) == VT_CARRAY)
  134. {
  135. if (pPinfo->pArray != NULL && pPinfo->pTypeAttr == NULL) // immediate upper level
  136. {
  137. fReleaseAttr = FALSE;
  138. pPinfo->pTypeInfo->AddRef();
  139. pPinfo->pTypeAttr = ptattrRef;
  140. }
  141. }
  142. break;
  143. case TKIND_DISPATCH:
  144. case TKIND_INTERFACE:
  145. hresult = VarVtOfIface(ptinfoRef, ptattrRef, pPinfo);
  146. break;
  147. case TKIND_COCLASS:
  148. { TYPEATTR FAR* ptattrPri;
  149. ITypeInfo FAR* ptinfoPri;
  150. if((hresult = GetPrimaryInterface(ptinfoRef, &ptinfoPri)) == NOERROR){
  151. if((hresult = ptinfoPri->GetTypeAttr(&ptattrPri)) == NOERROR){
  152. hresult = VarVtOfIface(ptinfoPri, ptattrPri, pPinfo);
  153. ptinfoPri->ReleaseTypeAttr(ptattrPri);
  154. }
  155. ptinfoPri->Release();
  156. }
  157. }
  158. break;
  159. // this is a struct, handle indiviudal member later.
  160. case TKIND_RECORD:
  161. pPinfo->vt= VT_USERDEFINED;
  162. (*pPinfo).pTypeInfo = ptinfoRef;
  163. ptinfoRef->AddRef();
  164. break;
  165. default:
  166. IfFailGo(DISP_E_BADVARTYPE, Error);
  167. break;
  168. }
  169. Error:;
  170. if(ptinfoRef != NULL){
  171. if(ptattrRef != NULL && fReleaseAttr)
  172. ptinfoRef->ReleaseTypeAttr(ptattrRef);
  173. ptinfoRef->Release();
  174. }
  175. return hresult;
  176. }
  177. /***
  178. *PRIVATE HRESULT VarVtOfTypeDesc
  179. *Purpose:
  180. * Convert the given typeinfo TYPEDESC into a VARTYPE that can be
  181. * represented in a VARIANT. For some this is a 1:1 mapping, for
  182. * others we convert to a (possibly machine dependent, eg VT_INT->VT_I2)
  183. * base type, and others we cant represent in a VARIANT.
  184. *
  185. * Now we are supporting multiple levels of pointer indirection. To support
  186. * this, we created an internal VT_MULTIINDIRECTIONS. If vt in PARAMINFO is
  187. * VT_MULTIINDIRECTIONS, the real vt is on PARAMINFO::realvt, and VT_BYREF
  188. * must be true; additional levels of indirection is saved in PARAMINFO::
  189. * lLevelCount.
  190. *
  191. *Entry:
  192. * ptinfo =
  193. * ptdesc = * to the typedesc to convert
  194. * pvt =
  195. * pguid =
  196. *
  197. *Exit:
  198. * return value = HRESULT
  199. *
  200. * *pvt = a VARTYPE that may be stored in a VARIANT.
  201. * *pguid = a guid for a custom interface.
  202. *
  203. *
  204. * Following is a summary of how types are represented in typeinfo.
  205. * Note the difference between the apparent levels of indirection
  206. * between IDispatch* / DispFoo*, and DualFoo*.
  207. *
  208. * I2 => VT_I2
  209. * I2* => VT_PTR - VT_I2
  210. *
  211. * IDispatch * => VT_DISPATCH
  212. * IDispatch ** => VT_PTR - VT_DISPATCH
  213. * DispFoo * => VT_DISPATCH
  214. * DispFoo ** => VT_PTR - VT_DISPATCH
  215. * DualFoo * => VT_PTR - VT_INTERFACE (DispIID)
  216. * DualFoo ** => VT_PTR - VT_PTR - VT_INTERFACE (DispIID)
  217. * IFoo * => VT_PTR - VT_INTERFACE (IID)
  218. * IFoo ** => VT_PTR - VT_PTR - VT_INTERFACE (IID)
  219. *
  220. ***********************************************************************/
  221. HRESULT
  222. VarVtOfTypeDesc(ITypeInfo FAR* ptinfo,
  223. TYPEDESC FAR* ptdesc,
  224. PARAMINFO *pPinfo)
  225. {
  226. HRESULT hresult = NOERROR;
  227. switch (ptdesc->vt) {
  228. case VT_I2:
  229. case VT_I4:
  230. case VT_R4:
  231. case VT_R8:
  232. case VT_CY:
  233. case VT_DATE:
  234. case VT_BSTR:
  235. case VT_DISPATCH:
  236. case VT_ERROR:
  237. case VT_BOOL:
  238. case VT_VARIANT:
  239. case VT_UNKNOWN:
  240. case VT_DECIMAL:
  241. case VT_I1:
  242. case VT_UI1:
  243. case VT_UI2:
  244. case VT_UI4:
  245. case VT_I8:
  246. case VT_UI8:
  247. case VT_HRESULT:
  248. case VT_LPSTR:
  249. case VT_LPWSTR:
  250. case VT_FILETIME:
  251. case VT_STREAM:
  252. case VT_STORAGE:
  253. pPinfo->vt = ptdesc->vt;
  254. break;
  255. case VT_INT:
  256. pPinfo->vt = VT_I4;
  257. break;
  258. case VT_UINT:
  259. pPinfo->vt = VT_UI4;
  260. break;
  261. case VT_USERDEFINED:
  262. hresult = VarVtOfUDT(ptinfo, ptdesc, pPinfo);
  263. break;
  264. case VT_PTR:
  265. switch (ptdesc->lptdesc->vt)
  266. {
  267. // VT_PTR + VT_DISPATCH: it's IDispatch**
  268. case VT_DISPATCH:
  269. case VT_UNKNOWN:
  270. case VT_STREAM:
  271. case VT_STORAGE:
  272. pPinfo->vt = ptdesc->lptdesc->vt |VT_BYREF;
  273. hresult = NOERROR;
  274. break;
  275. // Special case: dispinterface** (represented by VT_PTR-VT_PTR-VT_USERDEFINED-TKIND_DISPATCH
  276. case VT_PTR:
  277. if ( VT_USERDEFINED == ptdesc->lptdesc->lptdesc->vt )
  278. {
  279. // we need to read forward in VT_PTR-VT_PTR-VT_UDT case for
  280. // dispinterface **
  281. hresult = VarVtOfUDT(ptinfo, ptdesc->lptdesc->lptdesc,pPinfo);
  282. if (hresult == NOERROR)
  283. {
  284. if (pPinfo->vt == VT_INTERFACE)
  285. {
  286. pPinfo->vt = (VT_BYREF | VT_INTERFACE);
  287. }
  288. else if (pPinfo->vt == VT_DISPATCH)
  289. {
  290. pPinfo->vt = (VT_BYREF | VT_DISPATCH);
  291. }
  292. else if ( pPinfo->vt == VT_MULTIINDIRECTIONS )
  293. {
  294. // add an additional level if it's ** already
  295. pPinfo->lLevelCount++;
  296. }
  297. else
  298. {
  299. // VT_PTR-VT_PTR-something_other_than_interface:
  300. pPinfo->realvt = pPinfo->vt;
  301. pPinfo->vt = VT_MULTIINDIRECTIONS;
  302. if ( pPinfo->realvt & VT_BYREF )
  303. pPinfo->lLevelCount = 2;
  304. else
  305. {
  306. pPinfo->realvt = pPinfo->realvt | VT_BYREF;
  307. pPinfo->lLevelCount = 1;
  308. }
  309. }
  310. }
  311. break;
  312. }
  313. // fall through if not VT_PTR-VT_PTR-VT_USERDEFINED case
  314. default:
  315. hresult = VarVtOfTypeDesc(ptinfo, ptdesc->lptdesc, pPinfo);
  316. if(hresult == NOERROR)
  317. {
  318. if(pPinfo->vt & VT_BYREF)
  319. {
  320. pPinfo->realvt = pPinfo->vt;
  321. pPinfo->vt = VT_MULTIINDIRECTIONS;
  322. pPinfo->lLevelCount = 1;
  323. }
  324. else if ( pPinfo->vt == VT_MULTIINDIRECTIONS )
  325. {
  326. pPinfo->lLevelCount++;
  327. }
  328. else if ((pPinfo->vt != VT_INTERFACE) && (pPinfo->vt != VT_DISPATCH))
  329. {
  330. // need to get rid of one level of indirection for interface
  331. pPinfo->vt |= VT_BYREF;
  332. }
  333. break;
  334. }
  335. }
  336. break;
  337. case VT_SAFEARRAY:
  338. hresult = VarVtOfTypeDesc(ptinfo, ptdesc->lptdesc, pPinfo);
  339. if(hresult == NOERROR){
  340. if(pPinfo->vt & (VT_BYREF | VT_ARRAY)){
  341. // error if nested array or array of pointers
  342. hresult = DISP_E_BADVARTYPE;
  343. break;
  344. }
  345. pPinfo->vt |= VT_ARRAY;
  346. }
  347. break;
  348. // VT_CARRAY in fact is fix length array.
  349. case VT_CARRAY:
  350. pPinfo->vt = ptdesc->vt;
  351. (*pPinfo).pArray = ptdesc->lpadesc;
  352. (*pPinfo).pTypeInfo = ptinfo;
  353. ptinfo->AddRef();
  354. break;
  355. default:
  356. ASSERT(UNREACHED);
  357. hresult = DISP_E_BADVARTYPE;
  358. break;
  359. }
  360. return hresult;
  361. }
  362. //
  363. // Simple wrapper for VarVtOfTypeDesc that only returns
  364. // the vt, not an entire PARAMINFO structure. Used
  365. // by the callframe code in ole32.
  366. //
  367. EXTERN_C
  368. HRESULT NdrpVarVtOfTypeDesc(IN ITypeInfo *pTypeInfo,
  369. IN TYPEDESC *ptdesc,
  370. OUT VARTYPE *vt)
  371. {
  372. PARAMINFO pinfo;
  373. HRESULT hr;
  374. if (vt == NULL)
  375. return E_POINTER;
  376. *vt = VT_EMPTY;
  377. hr = VarVtOfTypeDesc(pTypeInfo, ptdesc, &pinfo);
  378. if (SUCCEEDED(hr))
  379. *vt = pinfo.vt;
  380. return hr;
  381. }