@Override
	public void markup(Program program, boolean isBinary, TaskMonitor monitor, MessageLog log,
			NTHeader ntHeader) throws DuplicateNameException, IOException {

		monitor.setMessage("[" + program.getName() + "]: CLI stream...");
		Address addr = PeUtils.getMarkupAddress(program, isBinary, ntHeader, rva);

		program.getBookmarkManager().setBookmark(addr, BookmarkType.INFO, "CLI Stream",
			header.getName());

		try {
			program.getSymbolTable().createLabel(addr, "CLI_Stream_" + header.getName(),
				SourceType.ANALYSIS);
		}
		catch (InvalidInputException e) {
			Msg.error(this, "Error marking up CLI stream \"" + header.getName() + "\"", e);
			return;
		}

		if (!program.getMemory().contains(addr)) {
			return;
		}

		DataType dt = this.toDataType();
		dt.setCategoryPath(new CategoryPath(PATH));
		PeUtils.createData(program, addr, dt, log);
	}
Does basic markup that all streams will want:
<ul>
  <li>Set monitor message</li>
  <li>Validate addresses</li>
  <li>Add bookmark</li>
  <li>Add symbol</li>
  <li>Create data type</li>
</ul>
Subclass should first call this and then provide any custom markup they need.
Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/streams/CliAbstractStream.java