private Structure createClassStructureUsingRTTI(RecoveredClass recoveredClass,
			Map<Address, DataType> vfPointerDataTypes) throws Exception {

		String className = recoveredClass.getName();

		CategoryPath classPath = recoveredClass.getClassPath();

		// get either existing structure if prog has a structure created by pdb or computed structure
		// from decompiled construtor(s) info
		Structure classStructure;
		if (recoveredClass.hasExistingClassStructure()) {
			classStructure = recoveredClass.getExistingClassStructure();
		}
		else {
			classStructure = recoveredClass.getComputedClassStructure();
		}

		int structLen = 0;
		if (classStructure != null) {
			structLen = addAlignment(classStructure.getLength());
		}

		Structure classStructureDataType =
			new StructureDataType(classPath, className, structLen, dataTypeManager);

		Data baseClassArrayData = getBaseClassArray(recoveredClass);

		// if cannot recover the base class array return the existing or computed one instead
		// so user will at least have some information like correct size and some members
		if (baseClassArrayData == null) {
			classStructureDataType.replaceWith(classStructure);

			classStructureDataType = (Structure) dataTypeManager.addDataType(classStructureDataType,
				DataTypeConflictHandler.DEFAULT_HANDLER);
			return classStructureDataType;
		}

		// if lowest level multi-v (not just inherits a multi-v), need to add this first so it isn't overwritten by base class structures
		// at same offset
		if (recoveredClass.getClassHierarchyMap().size() > 1 &&
			recoveredClass.hasMultipleVirtualInheritance()) {
			classStructureDataType =
				addVbtableToClassStructure(recoveredClass, classStructureDataType, false);
		}

		int baseClassOffset = 0;
		int numPointers = baseClassArrayData.getNumComponents();

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

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

			Address baseClassDescriptorAddress =
				extendedFlatAPI.getReferencedAddress(pointerAddress, true);
			if (baseClassDescriptorAddress == null) {
				continue;
			}

			RecoveredClass baseClass = getClassFromBaseClassDescriptor(baseClassDescriptorAddress);
			if (i > 0 && baseClass == null) {
				continue;
			}

			int mdisp = api.getInt(baseClassDescriptorAddress.add(8));
			int pdisp = api.getInt(baseClassDescriptorAddress.add(12));
			int vdisp = api.getInt(baseClassDescriptorAddress.add(16));

			// skip main class - will fill in its vftable ptr later
			if (pdisp == -1 && i == 0) {
				continue;
			}

			// get the baseClassStructure (ie self or ancestor class) and its displacement values
			Structure baseClassStructure = getClassStructureFromDataTypeManager(baseClass);
			if (baseClassStructure == null) {
				Msg.debug(this, "****recovered Class = " + recoveredClass.getName() +
					"'s base Class " + baseClass.getName() + " class struct is null");
				continue;
			}

			// Continue if the class has mult inh but base class is not on the parent list
			if (recoveredClass.hasMultipleInheritance() &&
				!recoveredClass.getParentList().contains(baseClass)) {
				continue;
			}

			// process the non-virtually inherited ones 
			if (pdisp == -1) {

				baseClassOffset = mdisp;

				if (recoveredClass.hasMultipleInheritance() &&
					!recoveredClass.getParentList().contains(baseClass)) {
					continue;
				}

				// if it is a direct parent and the structure exists add it to the structure in the mdisp offset					
				// if class has virtual inheritance then copy individual members from the non-virtual parent struct
				// into the struct 	
				if (recoveredClass.hasSingleInheritance() &&
					recoveredClass.getVftableAddresses().size() > 1 &&
					recoveredClass.inheritsVirtualAncestor()) {

					Integer virtParentOffset = getSingleVirtualParentOffset(baseClass);

					int dataLength;
					if (virtParentOffset == null || virtParentOffset == NONE) {
						dataLength = baseClassStructure.getLength();
					}
					else {
						int virtParentLength = baseClassStructure.getLength() - virtParentOffset;
						dataLength = baseClassStructure.getLength() - virtParentLength;
					}

					// if there is room add the individual parts of the base class from the top of the 
					// structure up to but not including the single virtual parent offset within 
					// the class structure
					addIndividualComponentsToStructure(classStructureDataType, baseClassStructure,
						baseClassOffset, dataLength);
					continue;
				}

				// if it fits at offset or is at the end and class structure can be grown, 
				// copy the whole baseClass structure to the class Structure at the given offset
				EditStructureUtils.addDataTypeToStructure(classStructureDataType, baseClassOffset,
					baseClassStructure, baseClassStructure.getName(), monitor);

			}
			else {
				// else need to fill in the virtually inherited ones 
				// get the offset of this base class in the class using the vbtable				
				Address vbtableAddress = recoveredClass.getVbtableAddress();
				if (vbtableAddress == null) {
					continue;
				}

				baseClassOffset = api.getInt(recoveredClass.getVbtableAddress().add(vdisp)) + pdisp;

				// if it fits at offset or is at the end and class structure can be grown, 
				// copy the whole baseClass structure to the class Structure at the given offset
				EditStructureUtils.addDataTypeToStructure(classStructureDataType, baseClassOffset,
					baseClassStructure, baseClassStructure.getName(), monitor);

			}

		}// end of base class array

		if (vfPointerDataTypes != null) {
			if (!isClassOffsetToVftableMapComplete(recoveredClass)) {
				Msg.debug(this, "class vftable offset map for " + recoveredClass.getName() +
					" is not complete");
			}

			// iterate over the set of offsets to vftables for the class and if nothing
			// is already at the offset, add the vftables
			Map<Integer, Address> classOffsetToVftableMap =
				recoveredClass.getClassOffsetToVftableMap();
			Set<Integer> classVftableOffsets = classOffsetToVftableMap.keySet();
			List<Integer> sortedOffsets = new ArrayList<Integer>(classVftableOffsets);
			Collections.sort(sortedOffsets);

			Integer offset = sortedOffsets.get(0);

			Address vftableAddress = classOffsetToVftableMap.get(offset);

			DataType classVftablePointer = vfPointerDataTypes.get(vftableAddress);

			// if it fits at offset or is at the end and class structure can be grown, 
			// copy the whole baseClass structure to the class Structure at the given offset
			EditStructureUtils.addDataTypeToStructure(classStructureDataType, offset.intValue(),
				classVftablePointer, CLASS_VTABLE_PTR_FIELD_EXT, monitor);
		}

		// add the vbtable structure for single inheritance/virt parent case
		if (recoveredClass.hasSingleInheritance() && recoveredClass.inheritsVirtualAncestor()) {
			classStructureDataType =
				addVbtableToClassStructure(recoveredClass, classStructureDataType, false);
		}

		int dataOffset = getDataOffset(recoveredClass, classStructureDataType);
		int dataLen = UNKNOWN;
		if (dataOffset != NONE) {
			dataLen = EditStructureUtils.getNumberOfUndefinedsStartingAtOffset(
				classStructureDataType, dataOffset, monitor);
		}

		if (dataLen != UNKNOWN && dataLen > 0) {

			Structure recoveredClassDataStruct = createClassMemberDataStructure(recoveredClass,
				classStructureDataType, dataLen, dataOffset);

			if (recoveredClassDataStruct != null) {
				// if it fits at offset or is at the end and class structure can be grown, 
				// copy the whole baseClass structure to the class Structure at the given offset
				EditStructureUtils.addDataTypeToStructure(classStructureDataType, dataOffset,
					recoveredClassDataStruct, classStructureDataType.getName() + "_data", monitor);
			}

		}

		classStructureDataType =
			addClassVftables(classStructureDataType, recoveredClass, vfPointerDataTypes);

		classStructureDataType =
			addVbtableToClassStructure(recoveredClass, classStructureDataType, true);

		if (classStructureDataType.getNumComponents() == classStructureDataType
				.getNumDefinedComponents()) {
			classStructureDataType.setPackingEnabled(true);
		}

		classStructureDataType.setDescription(createParentStringBuffer(recoveredClass).toString());

		classStructureDataType = (Structure) dataTypeManager.addDataType(classStructureDataType,
			DataTypeConflictHandler.DEFAULT_HANDLER);

		return classStructureDataType;
	}
Method to create a class structure using information in program RTTI structures
@param recoveredClass the given class
@param vfPointerDataTypes map of address/vftable pointer structs
@return the created class structure data type
@throws Exception if invalid data creation
Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RTTIWindowsClassRecoverer.java