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.

670 lines
24 KiB

  1. /***
  2. *rtti.cxx - C++ runtime type information
  3. *
  4. * Copyright (c) 1994-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Implementation of C++ standard runtime type information
  8. *
  9. *Revision History:
  10. * 10-17-94 JWM File created.
  11. * 10-17-94 BWT Disable code for PPC.
  12. * 11-11-94 JWM Now includes windows.h
  13. * 12-01-94 JWM Added optimized cases for single & multiple inheritance
  14. * 02-03-95 JWM FindVITargetTypeInstance() now checks offsets to
  15. * determine ambiguity, not pointer equality
  16. * 02-09-95 JWM Mac merge.
  17. * 03-22-95 PML Add const for read-only compiler-gen'd structs
  18. * 05-03-95 JWM Test visibility in FindSITargetTypeInstance().
  19. * 08-28-95 JWM dynamic-cast of NULL ptr now returns NULL (bug 502).
  20. * 05-10-99 PML Win64 fix: int -> ptrdiff_t
  21. * 05-17-99 PML Remove all Macintosh support.
  22. * 10-19-99 TGL Win64 fix: ptrdiff_t -> __int32 in PMDtoOffset.
  23. * 03-15-00 PML Remove CC_P7_SOFT25.
  24. * 04-21-00 PML Add exception specifications to extern "C" helpers.
  25. * 08-23-00 PML IA64 fix: _ImageBase can't be a static global, since
  26. * that's not thread-safe (VS7#154575).
  27. * 08-28-00 PML IA64 fix: _ImageBase needs to be set from the address
  28. * of the _RTTICompleteObjectLocator, not the return
  29. * address (VS7#156255)
  30. * 09-07-00 PML Get rid of /lib:libcp directive in obj (vs7#159463)
  31. *
  32. ****/
  33. #define _USE_ANSI_CPP /* Don't emit /lib:libcp directive */
  34. #include <windows.h>
  35. #include <rtti.h>
  36. #include <typeinfo.h>
  37. #if defined(_M_IA64) || defined(_M_AMD64)
  38. static unsigned __int64 GetImageBase(PVOID);
  39. #undef BCD_PTD
  40. #undef CHD_PBCA
  41. #undef CHD_PBCD
  42. #undef COL_PTD
  43. #undef COL_PCHD
  44. #define BCD_PTD(bcd) BCD_PTD_IB((bcd),_ImageBase)
  45. #define CHD_PBCA(chd) CHD_PBCA_IB((chd),_ImageBase)
  46. #define CHD_PBCD(chd) CHD_PBCD_IB((chd),_ImageBase)
  47. #define COL_PTD(col) COL_PTD_IB((col),_ImageBase)
  48. #define COL_PCHD(col) COL_PCHD_IB((col),_ImageBase)
  49. extern "C" PVOID RtlPcToFileHeader(PVOID, PVOID*);
  50. #endif
  51. static PVOID __cdecl FindCompleteObject(PVOID *);
  52. static _RTTIBaseClassDescriptor * __cdecl
  53. FindSITargetTypeInstance(PVOID,
  54. _RTTICompleteObjectLocator *,
  55. _RTTITypeDescriptor *,
  56. ptrdiff_t,
  57. _RTTITypeDescriptor *
  58. #if defined(_M_IA64) || defined(_M_AMD64)
  59. , unsigned __int64
  60. #endif
  61. );
  62. static _RTTIBaseClassDescriptor * __cdecl
  63. FindMITargetTypeInstance(PVOID,
  64. _RTTICompleteObjectLocator *,
  65. _RTTITypeDescriptor *,
  66. ptrdiff_t,
  67. _RTTITypeDescriptor *
  68. #if defined(_M_IA64) || defined(_M_AMD64)
  69. , unsigned __int64
  70. #endif
  71. );
  72. static _RTTIBaseClassDescriptor * __cdecl
  73. FindVITargetTypeInstance(PVOID,
  74. _RTTICompleteObjectLocator *,
  75. _RTTITypeDescriptor *,
  76. ptrdiff_t,
  77. _RTTITypeDescriptor *
  78. #if defined(_M_IA64) || defined(_M_AMD64)
  79. , unsigned __int64
  80. #endif
  81. );
  82. static ptrdiff_t __cdecl PMDtoOffset(PVOID, const PMD&);
  83. /////////////////////////////////////////////////////////////////////////////
  84. //
  85. // __RTCastToVoid - Implements dynamic_cast<void*>
  86. //
  87. // Output: Pointer to complete object containing *inptr
  88. //
  89. // Side-effects: NONE.
  90. //
  91. extern "C" PVOID __cdecl __RTCastToVoid (
  92. PVOID inptr) // Pointer to polymorphic object
  93. throw(...)
  94. {
  95. if (inptr == NULL)
  96. return NULL;
  97. __try {
  98. return FindCompleteObject((PVOID *)inptr);
  99. }
  100. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
  101. ? EXCEPTION_EXECUTE_HANDLER: EXCEPTION_CONTINUE_SEARCH)
  102. {
  103. throw __non_rtti_object ("Access violation - no RTTI data!");
  104. return NULL;
  105. }
  106. }
  107. /////////////////////////////////////////////////////////////////////////////
  108. //
  109. // __RTtypeid - Implements typeid() operator
  110. //
  111. // Output: Pointer to type descriptor of complete object containing *inptr
  112. //
  113. // Side-effects: NONE.
  114. //
  115. extern "C" PVOID __cdecl __RTtypeid (
  116. PVOID inptr) // Pointer to polymorphic object
  117. throw(...)
  118. {
  119. if (!inptr) {
  120. throw bad_typeid ("Attempted a typeid of NULL pointer!"); // WP 5.2.7
  121. return NULL;
  122. }
  123. __try {
  124. // Ptr to CompleteObjectLocator should be stored at vfptr[-1]
  125. _RTTICompleteObjectLocator *pCompleteLocator =
  126. (_RTTICompleteObjectLocator *) ((*((void***)inptr))[-1]);
  127. #if defined(_M_IA64) || defined(_M_AMD64)
  128. unsigned __int64 _ImageBase = GetImageBase((PVOID)pCompleteLocator);
  129. #endif
  130. if (!IsBadReadPtr((const void *)COL_PTD(*pCompleteLocator),
  131. sizeof(TypeDescriptor)))
  132. {
  133. return (PVOID) COL_PTD(*pCompleteLocator);
  134. }
  135. else {
  136. throw __non_rtti_object ("Bad read pointer - no RTTI data!");
  137. return NULL;
  138. }
  139. }
  140. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
  141. ? EXCEPTION_EXECUTE_HANDLER: EXCEPTION_CONTINUE_SEARCH)
  142. {
  143. throw __non_rtti_object ("Access violation - no RTTI data!");
  144. return NULL;
  145. }
  146. }
  147. /////////////////////////////////////////////////////////////////////////////
  148. //
  149. // __RTDynamicCast - Runtime implementation of dynamic_cast<> operator
  150. //
  151. // Output: Pointer to the appropriate sub-object, if possible; NULL otherwise
  152. //
  153. // Side-effects: Throws bad_cast() if cast fails & input of dynamic_cast<> is
  154. // a reference
  155. //
  156. extern "C" PVOID __cdecl __RTDynamicCast (
  157. PVOID inptr, // Pointer to polymorphic object
  158. LONG VfDelta, // Offset of vfptr in object
  159. PVOID SrcType, // Static type of object pointed to by inptr
  160. PVOID TargetType, // Desired result of cast
  161. BOOL isReference) // TRUE if input is reference, FALSE if input is ptr
  162. throw(...)
  163. {
  164. PVOID pResult;
  165. _RTTIBaseClassDescriptor *pBaseClass;
  166. if (inptr == NULL)
  167. return NULL;
  168. __try {
  169. PVOID pCompleteObject = FindCompleteObject((PVOID *)inptr);
  170. _RTTICompleteObjectLocator *pCompleteLocator =
  171. (_RTTICompleteObjectLocator *) ((*((void***)inptr))[-1]);
  172. #if defined(_M_IA64) || defined(_M_AMD64)
  173. unsigned __int64 _ImageBase = GetImageBase((PVOID)pCompleteLocator);
  174. #endif
  175. // Adjust by vfptr displacement, if any
  176. inptr = (PVOID *) ((char *)inptr - VfDelta);
  177. // Calculate offset of source object in complete object
  178. ptrdiff_t inptr_delta = (char *)inptr - (char *)pCompleteObject;
  179. if (!(CHD_ATTRIBUTES(*COL_PCHD(*pCompleteLocator)) & CHD_MULTINH)) {
  180. // if not multiple inheritance
  181. pBaseClass = FindSITargetTypeInstance(
  182. pCompleteObject,
  183. pCompleteLocator,
  184. (_RTTITypeDescriptor *) SrcType,
  185. inptr_delta,
  186. (_RTTITypeDescriptor *) TargetType
  187. #if defined(_M_IA64) || defined(_M_AMD64)
  188. , _ImageBase
  189. #endif
  190. );
  191. }
  192. else if (!(CHD_ATTRIBUTES(*COL_PCHD(*pCompleteLocator)) & CHD_VIRTINH)) {
  193. // if multiple, but not virtual, inheritance
  194. pBaseClass = FindMITargetTypeInstance(
  195. pCompleteObject,
  196. pCompleteLocator,
  197. (_RTTITypeDescriptor *) SrcType,
  198. inptr_delta,
  199. (_RTTITypeDescriptor *) TargetType
  200. #if defined(_M_IA64) || defined(_M_AMD64)
  201. , _ImageBase
  202. #endif
  203. );
  204. }
  205. else {
  206. // if virtual inheritance
  207. pBaseClass = FindVITargetTypeInstance(
  208. pCompleteObject,
  209. pCompleteLocator,
  210. (_RTTITypeDescriptor *) SrcType,
  211. inptr_delta,
  212. (_RTTITypeDescriptor *) TargetType
  213. #if defined(_M_IA64) || defined(_M_AMD64)
  214. , _ImageBase
  215. #endif
  216. );
  217. }
  218. if (pBaseClass != NULL) {
  219. // Calculate ptr to result base class from pBaseClass->where
  220. pResult = ((char *) pCompleteObject) +
  221. PMDtoOffset(pCompleteObject, pBaseClass->where);
  222. }
  223. else {
  224. pResult = NULL;
  225. if (isReference)
  226. throw bad_cast("Bad dynamic_cast!");
  227. }
  228. }
  229. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
  230. ? EXCEPTION_EXECUTE_HANDLER: EXCEPTION_CONTINUE_SEARCH)
  231. {
  232. pResult = NULL;
  233. throw __non_rtti_object ("Access violation - no RTTI data!");
  234. }
  235. return pResult;
  236. }
  237. /////////////////////////////////////////////////////////////////////////////
  238. //
  239. // FindCompleteObject - Calculate member offset from PMD & this
  240. //
  241. // Output: pointer to the complete object containing class *inptr
  242. //
  243. // Side-effects: NONE.
  244. //
  245. static PVOID __cdecl FindCompleteObject (
  246. PVOID *inptr) // Pointer to polymorphic object
  247. {
  248. // Ptr to CompleteObjectLocator should be stored at vfptr[-1]
  249. _RTTICompleteObjectLocator *pCompleteLocator =
  250. (_RTTICompleteObjectLocator *) ((*((void***)inptr))[-1]);
  251. char *pCompleteObject = (char *)inptr - pCompleteLocator->offset;
  252. // Adjust by construction displacement, if any
  253. if (pCompleteLocator->cdOffset)
  254. pCompleteObject += *(ptrdiff_t *)((char *)inptr - pCompleteLocator->cdOffset);
  255. return (PVOID) pCompleteObject;
  256. }
  257. /////////////////////////////////////////////////////////////////////////////
  258. //
  259. // FindSITargetTypeInstance - workhorse routine of __RTDynamicCast() in a
  260. // Single-Inheritance hierarchy
  261. //
  262. // Output: pointer to the appropriate sub-object of targetted type; NULL if
  263. // cast fails
  264. //
  265. // Side-effects: NONE.
  266. //
  267. static _RTTIBaseClassDescriptor * __cdecl FindSITargetTypeInstance (
  268. PVOID pCompleteObject, // pointer to complete object
  269. _RTTICompleteObjectLocator *pCOLocator, // pointer to Locator of complete object
  270. _RTTITypeDescriptor *pSrcTypeID, // pointer to TypeDescriptor of source object
  271. ptrdiff_t SrcOffset, // offset of source object in complete object
  272. _RTTITypeDescriptor *pTargetTypeID // pointer to TypeDescriptor of result of cast
  273. #if defined(_M_IA64) || defined(_M_AMD64)
  274. , unsigned __int64 _ImageBase
  275. #endif
  276. )
  277. {
  278. _RTTIBaseClassDescriptor *pBase;
  279. #if defined(_M_IA64) || defined(_M_AMD64)
  280. _RTTIBaseClassArray *pBaseClassArray;
  281. #else
  282. _RTTIBaseClassDescriptor * const *pBasePtr;
  283. #endif
  284. DWORD i;
  285. #if defined(_M_IA64) || defined(_M_AMD64)
  286. for (i = 0, pBaseClassArray = CHD_PBCA(*COL_PCHD(*pCOLocator));
  287. i < CHD_NUMBASES(*COL_PCHD(*pCOLocator));
  288. i++)
  289. {
  290. pBase = CHD_PBCD(pBaseClassArray->arrayOfBaseClassDescriptors[i]);
  291. // Test type of selected base class
  292. if (TYPEIDS_EQ(BCD_PTD(*pBase), pTargetTypeID) &&
  293. !(BCD_ATTRIBUTES(*pBase) & BCD_NOTVISIBLE))
  294. {
  295. return pBase;
  296. }
  297. }
  298. #else
  299. for (i = 0, pBasePtr = pCOLocator->pClassDescriptor->
  300. pBaseClassArray->
  301. arrayOfBaseClassDescriptors;
  302. i < pCOLocator->pClassDescriptor->numBaseClasses;
  303. i++, pBasePtr++)
  304. {
  305. pBase = *pBasePtr;
  306. // Test type of selected base class
  307. if (TYPEIDS_EQ(pBase->pTypeDescriptor, pTargetTypeID) &&
  308. !(BCD_ATTRIBUTES(*pBase) & BCD_NOTVISIBLE))
  309. {
  310. return pBase;
  311. }
  312. }
  313. #endif
  314. return NULL;
  315. }
  316. /////////////////////////////////////////////////////////////////////////////
  317. //
  318. // FindMITargetTypeInstance - workhorse routine of __RTDynamicCast() in a
  319. // Multiple-Inheritance hierarchy
  320. //
  321. // Output: pointer to the appropriate sub-object of targetted type; NULL if
  322. // cast fails
  323. //
  324. // Side-effects: NONE.
  325. //
  326. static _RTTIBaseClassDescriptor * __cdecl FindMITargetTypeInstance (
  327. PVOID pCompleteObject, // pointer to complete object
  328. _RTTICompleteObjectLocator *pCOLocator, // pointer to Locator of complete object
  329. _RTTITypeDescriptor *pSrcTypeID, // pointer to TypeDescriptor of source object
  330. ptrdiff_t SrcOffset, // offset of source object in complete object
  331. _RTTITypeDescriptor *pTargetTypeID // pointer to TypeDescriptor of result of cast
  332. #if defined(_M_IA64) || defined(_M_AMD64)
  333. , unsigned __int64 _ImageBase
  334. #endif
  335. )
  336. {
  337. _RTTIBaseClassDescriptor *pBase, *pSubBase;
  338. #if defined(_M_IA64) || defined(_M_AMD64)
  339. _RTTIBaseClassArray *pBaseClassArray;
  340. #else
  341. _RTTIBaseClassDescriptor * const *pBasePtr, * const *pSubBasePtr;
  342. #endif
  343. DWORD i, j;
  344. #if defined(_M_IA64) || defined(_M_AMD64)
  345. // First, try down-casts
  346. for (i = 0, pBaseClassArray = CHD_PBCA(*COL_PCHD(*pCOLocator));
  347. i < CHD_NUMBASES(*COL_PCHD(*pCOLocator));
  348. i++)
  349. {
  350. pBase = CHD_PBCD(pBaseClassArray->arrayOfBaseClassDescriptors[i]);
  351. // Test type of selected base class
  352. if (TYPEIDS_EQ(BCD_PTD(*pBase), pTargetTypeID)) {
  353. // If base class is proper type, see if it contains our instance
  354. // of source class
  355. for (j = 0;
  356. j < pBase->numContainedBases;
  357. j++)
  358. {
  359. pSubBase = CHD_PBCD(pBaseClassArray->arrayOfBaseClassDescriptors[i+1+j]);
  360. if (TYPEIDS_EQ(BCD_PTD(*pSubBase), pSrcTypeID) &&
  361. (PMDtoOffset(pCompleteObject, pSubBase->where) == SrcOffset))
  362. {
  363. // Yes, this is the proper instance of source class
  364. return pBase;
  365. }
  366. }
  367. }
  368. }
  369. // Down-cast failed, try cross-cast
  370. for (i = 0, pBaseClassArray = CHD_PBCA(*COL_PCHD(*pCOLocator));
  371. i < CHD_NUMBASES(*COL_PCHD(*pCOLocator));
  372. i++)
  373. {
  374. pBase = CHD_PBCD(pBaseClassArray->arrayOfBaseClassDescriptors[i]);
  375. // Check if base class has proper type, is accessible & is unambiguous
  376. if (TYPEIDS_EQ(BCD_PTD(*pBase), pTargetTypeID) &&
  377. !(BCD_ATTRIBUTES(*pBase) & BCD_NOTVISIBLE) &&
  378. !(BCD_ATTRIBUTES(*pBase) & BCD_AMBIGUOUS))
  379. {
  380. return pBase;
  381. }
  382. }
  383. #else
  384. // First, try down-casts
  385. for (i = 0, pBasePtr = pCOLocator->pClassDescriptor->
  386. pBaseClassArray->
  387. arrayOfBaseClassDescriptors;
  388. i < pCOLocator->pClassDescriptor->numBaseClasses;
  389. i++, pBasePtr++)
  390. {
  391. pBase = *pBasePtr;
  392. // Test type of selected base class
  393. if (TYPEIDS_EQ(pBase->pTypeDescriptor, pTargetTypeID)) {
  394. // If base class is proper type, see if it contains our instance
  395. // of source class
  396. for (j = 0, pSubBasePtr = pBasePtr+1;
  397. j < pBase->numContainedBases;
  398. j++, pSubBasePtr++)
  399. {
  400. pSubBase = *pSubBasePtr;
  401. if (TYPEIDS_EQ(pSubBase->pTypeDescriptor, pSrcTypeID) &&
  402. (PMDtoOffset(pCompleteObject, pSubBase->where) == SrcOffset))
  403. {
  404. // Yes, this is the proper instance of source class
  405. return pBase;
  406. }
  407. }
  408. }
  409. }
  410. // Down-cast failed, try cross-cast
  411. for (i = 0, pBasePtr = pCOLocator->pClassDescriptor->
  412. pBaseClassArray->
  413. arrayOfBaseClassDescriptors;
  414. i < pCOLocator->pClassDescriptor->numBaseClasses;
  415. i++, pBasePtr++)
  416. {
  417. pBase = *pBasePtr;
  418. // Check if base class has proper type, is accessible & is unambiguous
  419. if (TYPEIDS_EQ(pBase->pTypeDescriptor, pTargetTypeID) &&
  420. !(BCD_ATTRIBUTES(*pBase) & BCD_NOTVISIBLE) &&
  421. !(BCD_ATTRIBUTES(*pBase) & BCD_AMBIGUOUS))
  422. {
  423. return pBase;
  424. }
  425. }
  426. #endif
  427. return NULL;
  428. }
  429. /////////////////////////////////////////////////////////////////////////////
  430. //
  431. // FindVITargetTypeInstance - workhorse routine of __RTDynamicCast() in a
  432. // Virtual-Inheritance hierarchy
  433. //
  434. // Output: pointer to the appropriate sub-object of targetted type; NULL if
  435. // cast fails
  436. //
  437. // Side-effects: NONE.
  438. //
  439. static _RTTIBaseClassDescriptor * __cdecl FindVITargetTypeInstance (
  440. PVOID pCompleteObject, // pointer to complete object
  441. _RTTICompleteObjectLocator *pCOLocator, // pointer to Locator of complete object
  442. _RTTITypeDescriptor *pSrcTypeID, // pointer to TypeDescriptor of source object
  443. ptrdiff_t SrcOffset, // offset of source object in complete object
  444. _RTTITypeDescriptor *pTargetTypeID // pointer to TypeDescriptor of result of cast
  445. #if defined(_M_IA64) || defined(_M_AMD64)
  446. , unsigned __int64 _ImageBase
  447. #endif
  448. )
  449. {
  450. _RTTIBaseClassDescriptor *pBase, *pSubBase;
  451. #if defined(_M_IA64) || defined(_M_AMD64)
  452. _RTTIBaseClassArray *pBaseClassArray;
  453. #else
  454. _RTTIBaseClassDescriptor * const *pBasePtr, * const *pSubBasePtr;
  455. #endif
  456. _RTTIBaseClassDescriptor *pResult = NULL;
  457. DWORD i, j;
  458. #if defined(_M_IA64) || defined(_M_AMD64)
  459. for (i = 0, pBaseClassArray = CHD_PBCA(*COL_PCHD(*pCOLocator));
  460. i < CHD_NUMBASES(*COL_PCHD(*pCOLocator));
  461. i++)
  462. {
  463. pBase = CHD_PBCD(pBaseClassArray->arrayOfBaseClassDescriptors[i]);
  464. // Test type of selected base class
  465. if (TYPEIDS_EQ(BCD_PTD(*pBase), pTargetTypeID)) {
  466. // If base class is proper type, see if it contains our instance
  467. // of source class
  468. for (j = 0;
  469. j < pBase->numContainedBases;
  470. j++)
  471. {
  472. pSubBase = CHD_PBCD(pBaseClassArray->arrayOfBaseClassDescriptors[i+1+j]);
  473. if (TYPEIDS_EQ(BCD_PTD(*pSubBase), pSrcTypeID) &&
  474. (PMDtoOffset(pCompleteObject, pSubBase->where) == SrcOffset))
  475. {
  476. // Yes, this is the proper instance of source class - make
  477. // sure it is unambiguous. Ambiguity now determined by
  478. // inequality of offsets of source class within complete
  479. // object, not pointer inequality
  480. if ((pResult != NULL) &&
  481. (PMDtoOffset(pCompleteObject, pResult->where) !=
  482. PMDtoOffset(pCompleteObject, pBase->where)))
  483. {
  484. // We already found an earlier instance, hence
  485. // ambiguity
  486. return NULL;
  487. }
  488. else {
  489. // Unambiguous
  490. pResult = pBase;
  491. }
  492. }
  493. }
  494. }
  495. }
  496. if (pResult != NULL)
  497. return pResult;
  498. // Down-cast failed, try cross-cast
  499. for (i = 0, pBaseClassArray = CHD_PBCA(*COL_PCHD(*pCOLocator));
  500. i < CHD_NUMBASES(*COL_PCHD(*pCOLocator));
  501. i++)
  502. {
  503. pBase = CHD_PBCD(pBaseClassArray->arrayOfBaseClassDescriptors[i]);
  504. // Check if base class has proper type, is accessible & is unambiguous
  505. if (TYPEIDS_EQ(BCD_PTD(*pBase), pTargetTypeID) &&
  506. !(BCD_ATTRIBUTES(*pBase) & BCD_NOTVISIBLE) &&
  507. !(BCD_ATTRIBUTES(*pBase) & BCD_AMBIGUOUS))
  508. {
  509. return pBase;
  510. }
  511. }
  512. #else
  513. // First, try down-casts
  514. for (i = 0, pBasePtr = pCOLocator->pClassDescriptor->
  515. pBaseClassArray->
  516. arrayOfBaseClassDescriptors;
  517. i < pCOLocator->pClassDescriptor->numBaseClasses;
  518. i++, pBasePtr++)
  519. {
  520. pBase = *pBasePtr;
  521. // Test type of selected base class
  522. if (TYPEIDS_EQ(pBase->pTypeDescriptor, pTargetTypeID)) {
  523. // If base class is proper type, see if it contains our instance
  524. // of source class
  525. for (j = 0, pSubBasePtr = pBasePtr+1;
  526. j < pBase->numContainedBases;
  527. j++, pSubBasePtr++)
  528. {
  529. pSubBase = *pSubBasePtr;
  530. if (TYPEIDS_EQ(pSubBase->pTypeDescriptor, pSrcTypeID) &&
  531. (PMDtoOffset(pCompleteObject, pSubBase->where) == SrcOffset))
  532. {
  533. // Yes, this is the proper instance of source class - make
  534. // sure it is unambiguous. Ambiguity now determined by
  535. // inequality of offsets of source class within complete
  536. // object, not pointer inequality
  537. if ((pResult != NULL) &&
  538. (PMDtoOffset(pCompleteObject, pResult->where) !=
  539. PMDtoOffset(pCompleteObject, pBase->where)))
  540. {
  541. // We already found an earlier instance, hence
  542. // ambiguity
  543. return NULL;
  544. }
  545. else {
  546. // Unambiguous
  547. pResult = pBase;
  548. }
  549. }
  550. }
  551. }
  552. }
  553. if (pResult != NULL)
  554. return pResult;
  555. // Down-cast failed, try cross-cast
  556. for (i = 0, pBasePtr = pCOLocator->pClassDescriptor->
  557. pBaseClassArray->
  558. arrayOfBaseClassDescriptors;
  559. i < pCOLocator->pClassDescriptor->numBaseClasses;
  560. i++, pBasePtr++)
  561. {
  562. pBase = *pBasePtr;
  563. // Check if base class has proper type, is accessible & is unambiguous
  564. if (TYPEIDS_EQ(pBase->pTypeDescriptor, pTargetTypeID) &&
  565. !(BCD_ATTRIBUTES(*pBase) & BCD_NOTVISIBLE) &&
  566. !(BCD_ATTRIBUTES(*pBase) & BCD_AMBIGUOUS))
  567. {
  568. return pBase;
  569. }
  570. }
  571. #endif
  572. return NULL;
  573. }
  574. /////////////////////////////////////////////////////////////////////////////
  575. //
  576. // PMDtoOffset - Calculate member offset from PMD & this
  577. //
  578. // Output: The offset of the base within the complete object.
  579. //
  580. // Side-effects: NONE.
  581. //
  582. static ptrdiff_t __cdecl PMDtoOffset(
  583. PVOID pThis, // ptr to complete object
  584. const PMD& pmd) // pointer-to-member-data structure
  585. {
  586. ptrdiff_t RetOff = 0;
  587. if (pmd.pdisp >= 0) {
  588. // if base is in the virtual part of class
  589. RetOff = pmd.pdisp;
  590. RetOff += *(__int32*)((char*)*(ptrdiff_t*)((char*)pThis + RetOff) +
  591. pmd.vdisp);
  592. }
  593. RetOff += pmd.mdisp;
  594. return RetOff;
  595. }
  596. #if defined(_M_IA64) || defined(_M_AMD64)
  597. static unsigned __int64 GetImageBase(PVOID pCallerPC)
  598. {
  599. unsigned __int64 _ImageBase;
  600. _ImageBase = (unsigned __int64)RtlPcToFileHeader(
  601. pCallerPC,
  602. (PVOID*)&_ImageBase);
  603. return _ImageBase;
  604. }
  605. #endif