How to traverse linkedItems from markups/PMIs

The code sample below will dump in the console geometry indexes of all linkedItems associated to root product occurrence markups/PMIs:

/***********************************************************************************************************************
*
* Copyright (c) 2021 by Tech Soft 3D, LLC.
* The information contained herein is confidential and proprietary to Tech Soft 3D, LLC., and considered a trade secret
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
* employees of Tech Soft 3D, LLC. is granted only under a written non-disclosure agreement, expressly prescribing the
* scope and manner of such use.
*
***********************************************************************************************************************/

#define INITIALIZE_A3D_API
#include <A3DSDKIncludes.h>

#include "../common.hpp"

static MY_CHAR acSrcFileName[_MAX_PATH * 2];
static MY_CHAR acDstFileName[_MAX_PATH * 2];
static MY_CHAR acLogFileName[_MAX_PATH * 2];


void browseRefOnTopo(A3DEntity * pRefOnTopo)
{
	A3DMiscReferenceOnTopologyData miscRefOnTopoData;
	A3D_INITIALIZE_DATA(A3DMiscReferenceOnTopologyData, miscRefOnTopoData);
	A3DMiscReferenceOnTopologyGet(pRefOnTopo, &miscRefOnTopoData);

	A3DTopoBrepDataData brepData;
	A3D_INITIALIZE_DATA(A3DTopoBrepDataData, brepData);
	A3DTopoBrepDataGet(miscRefOnTopoData.m_pBrepData, &brepData);

	printf("face: %d", miscRefOnTopoData.m_puiAdditionalIndexes[0]);

	if(miscRefOnTopoData.m_uiSize > 1)
		printf(" loop: %d", miscRefOnTopoData.m_puiAdditionalIndexes[1]);

	if(miscRefOnTopoData.m_uiSize > 2)
		printf(" edge: %d", miscRefOnTopoData.m_puiAdditionalIndexes[2]);

	if (miscRefOnTopoData.m_uiSize > 3)
		printf(" vertex: %d", miscRefOnTopoData.m_puiAdditionalIndexes[3]);

	printf("\n");
}

void browseLinkedItem(A3DMiscMarkupLinkedItem * pLinkedItem)
{
	A3DMiscMarkupLinkedItemData miscLinkedItemData;
	A3D_INITIALIZE_DATA(A3DMiscMarkupLinkedItemData, miscLinkedItemData);
	A3DMiscMarkupLinkedItemGet(pLinkedItem, &miscLinkedItemData);

	A3DEEntityType eType = kA3DTypeUnknown;
	A3DEntityGetType(miscLinkedItemData.m_pReference, &eType);

	if (eType == kA3DTypeMiscReferenceOnTopology)
	{
		browseRefOnTopo(miscLinkedItemData.m_pReference);
	}
}

void browseMarkup(A3DMkpAnnotationEntity * pMarkup)
{
	A3DEEntityType eType = kA3DTypeUnknown;
	A3DEntityGetType(pMarkup, &eType);

	switch (eType)
	{
		case kA3DTypeMkpAnnotationSet:
		{
			A3DMkpAnnotationSetData annotationSetData;
			A3D_INITIALIZE_DATA(A3DMkpAnnotationSetData, annotationSetData);
			A3DMkpAnnotationSetGet(pMarkup, &annotationSetData);

			for (int i = 0; i < annotationSetData.m_uiAnnotationsSize; i++)
			{
				browseMarkup(annotationSetData.m_ppAnnotations[i]);
			}

			break;
		}

		case kA3DTypeMkpAnnotationReference:
		{
			A3DMkpAnnotationReferenceData annotationRefData;
			A3D_INITIALIZE_DATA(A3DMkpAnnotationReferenceData, annotationRefData);
			A3DMkpAnnotationReferenceGet(pMarkup, &annotationRefData);

			for (int i = 0; i < annotationRefData.m_uiLinkedItemsSize; i++)
			{
				browseLinkedItem(annotationRefData.m_ppLinkedItems[i]);
			}

			break;
		}

		case kA3DTypeMkpAnnotationItem:
		{
			A3DMkpAnnotationItemData annotationItemData;
			A3D_INITIALIZE_DATA(A3DMkpAnnotationItemData, annotationItemData);
			A3DMkpAnnotationItemGet(pMarkup, &annotationItemData);

			A3DMkpMarkupData mkpData;
			A3D_INITIALIZE_DATA(A3DMkpMarkupData, mkpData);
			A3DMkpMarkupGet(annotationItemData.m_pMarkup, &mkpData);

			A3DRootBaseData rbData;
			A3D_INITIALIZE_DATA(A3DRootBaseData, rbData);
			A3DRootBaseGet(annotationItemData.m_pMarkup, &rbData);

			if (rbData.m_pcName != NULL)
			{
				printf("%s (%d linkedItems):\n", rbData.m_pcName, mkpData.m_uiLinkedItemsSize);
			}

			for (int i = 0; i < mkpData.m_uiLinkedItemsSize; i++)
			{
				browseLinkedItem(mkpData.m_ppLinkedItems[i]);
			}

			printf("\n");

			break;
		}
	}
}


//######################################################################################################################
#ifdef _MSC_VER
int wmain(A3DInt32 iArgc, A3DUniChar** ppcArgv)
#else
int main(A3DInt32 iArgc, A3DUTF8Char** ppcArgv)
#endif
{
	//
	// ### COMMAND LINE ARGUMENTS
	//

	if (iArgc < 2)
	{
		MY_PRINTF2("Usage:\n %s [input CAD file] [output CAD file] [output LOG file]\n", ppcArgv[0]);
		MY_PRINTF("  Default output CAD file is [input CAD file].prc\n");
		MY_PRINTF("  Default output LOG file is [output CAD file]_Log.txt\n\n");
		return A3D_ERROR;
	}

	if (iArgc > 1) MY_STRCPY(acSrcFileName, ppcArgv[1]);
	else           MY_STRCPY(acSrcFileName, DEFAULT_INPUT_CAD);
	if (iArgc > 2) MY_STRCPY(acDstFileName, ppcArgv[2]);
	else           MY_SPRINTF(acDstFileName, "%s.prc", acSrcFileName);
	if (iArgc > 3) MY_STRCPY(acLogFileName, ppcArgv[3]);
	else           MY_SPRINTF(acLogFileName, "%s_Log.txt", acDstFileName);
	GetLogFile(acLogFileName); // Initialize log file

	//
	// ### INITIALIZE HOOPS EXCHANGE
	//

	A3DSDKHOOPSExchangeLoader sHoopsExchangeLoader(_T(HOOPS_BINARY_DIRECTORY));
	CHECK_RET(sHoopsExchangeLoader.m_eSDKStatus);
	CHECK_RET(A3DDllSetCallbacksReport(PrintLogMessage, PrintLogWarning, PrintLogError));

	//
	// ### PROCESS SAMPLE CODE
	//

	// specify input file
	A3DImport sImport(acSrcFileName); // see A3DSDKInternalConvert.hxx for import and export detailed parametersc

	A3DStatus importStatus = sHoopsExchangeLoader.Import(sImport);

	A3DAsmModelFileData modelData;
	A3D_INITIALIZE_DATA(A3DAsmModelFileData, modelData);
	A3DAsmModelFileGet(sHoopsExchangeLoader.m_psModelFile, &modelData);

	A3DAsmProductOccurrenceData poData;
	A3D_INITIALIZE_DATA(A3DAsmProductOccurrenceData, poData);
	A3DAsmProductOccurrenceGet(modelData.m_ppPOccurrences[0], &poData);

        // We only browse trough markups located on the root PO level !

	for (int i = 0; i < poData.m_uiAnnotationsSize; i++)
	{
		browseMarkup(poData.m_ppAnnotations[i]);
	}

	A3DAsmPartDefinitionData partDefData;
	A3D_INITIALIZE_DATA(A3DAsmPartDefinitionData, partDefData);
	A3DAsmPartDefinitionGet(poData.m_pPart, &partDefData);

	for (int i = 0; i < partDefData.m_uiAnnotationsSize; i++)
	{
		browseMarkup(partDefData.m_ppAnnotations[i]);
	}

	//
	// ### TERMINATE HOOPS EXCHANGE
	//

	return A3D_SUCCESS;
}