private void determineParentClassInfoFromBaseClassArray(List<RecoveredClass> recoveredClasses)
			throws Exception {

		for (RecoveredClass recoveredClass : recoveredClasses) {
			monitor.checkCancelled();

			boolean hasVirtualAncestor = false;
			int vbaseOffset = NONE;

			// iterate over base class array and for each parent class of the given recovered class 
			// get the mdisp, pdisp, vdisp info
			List<Symbol> baseClassArray = extendedFlatAPI.getListOfSymbolsByNameInNamespace(
				RTTI_BASE_CLASS_ARRAY_LABEL, recoveredClass.getClassNamespace(), false);

			// this should never happen
			if (baseClassArray.size() != 1) {
				throw new Exception(
					recoveredClass.getName() + " has more than one RTTI base class array");
			}

			Address baseClassArrayAddress = baseClassArray.get(0).getAddress();
			Data baseClassArrayData = api.getDataAt(baseClassArrayAddress);

			if (!baseClassArrayData.isArray()) {
				throw new Exception(
					recoveredClass.getName() + " RTTI base class array is not an array data type " +
						baseClassArrayAddress.toString());

			}

			StructureDataType vbaseStructure = new StructureDataType(recoveredClass.getClassPath(),
				recoveredClass.getName() + CLASS_VTABLE_STRUCT_NAME, 0, dataTypeManager);

			IntegerDataType integerDataType = new IntegerDataType();

			int numPointers = baseClassArrayData.getNumComponents();

			for (int i = 0; i < numPointers; ++i) {
				monitor.checkCancelled();

				// Get the address it is pointing to
				Address pointerAddress = baseClassArrayData.getComponent(i).getAddress();

				Address baseClassDescriptorAddress =
					extendedFlatAPI.getReferencedAddress(pointerAddress, true);
				if (baseClassArrayAddress == null) {
					continue;
				}
				Symbol baseClassDescSymbol =
					symbolTable.getPrimarySymbol(baseClassDescriptorAddress);
				if (baseClassDescSymbol == null) {
					continue;
				}
				Namespace namespace = baseClassDescSymbol.getParentNamespace();
				if (namespace.equals(globalNamespace)) {
					continue;
				}
				RecoveredClass baseClass = getClass(namespace);

				// update parent map based on pdisp (-1 means not virtual base, otherwise it is a 
				// virtual base
				// set the has vbtable if any of them are a virtual base
				// update the vbstruct if any of them are a virtual base
				int pdisp = api.getInt(baseClassDescriptorAddress.add(12));
				int vdisp = api.getInt(baseClassDescriptorAddress.add(16));

				if (vbaseStructure.getComponentAt(vdisp) == null) {
					String classFieldName = new String();
					if (USE_SHORT_TEMPLATE_NAMES_IN_STRUCTURE_FIELDS &&
						!baseClass.getShortenedTemplateName().isEmpty()) {
						classFieldName = baseClass.getShortenedTemplateName();
					}
					else {
						classFieldName = baseClass.getName();
					}
					vbaseStructure.insertAtOffset(vdisp, integerDataType,
						integerDataType.getLength(), classFieldName + "_offset", null);
				}

				// skip the rest for the given class
				if (baseClass == recoveredClass) {
					continue;
				}

				if (pdisp == -1) {
					recoveredClass.addParentToBaseTypeMapping(baseClass, false);
				}
				else {
					if (vbaseOffset == NONE) {
						vbaseOffset = pdisp;
					}
					else if (vbaseOffset != pdisp) {
						throw new Exception(
							recoveredClass.getName() + " vbaseOffset values do not match");
					}

					hasVirtualAncestor = true;
					recoveredClass.addParentToBaseTypeMapping(baseClass, true);
				}

				// after the loop check if vbstruct/flag and if so figure out the vbaseTable address 
				if (hasVirtualAncestor) {
					if (vbaseOffset != UNKNOWN) {
						Address vbtableAddress = getVbaseTableAddress(recoveredClass, vbaseOffset);
						if (vbtableAddress != null) {
							recoveredClass.setVbtableAddress(vbtableAddress);
						}
					}
					recoveredClass.setVbtableStructure(vbaseStructure);
					recoveredClass.setInheritsVirtualAncestor(true);
					recoveredClass.setVbtableOffset(vbaseOffset);
				}
			}
		}
	}
Method to recover parent information, including class offsets, vbase structure and its offset and address if applicable, and whether
the parent is regularly or virtually inherited
@param recoveredClasses List of classes to process
@throws Exception when cancelled
Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RTTIWindowsClassRecoverer.java