def parse_imports(
        self,
        original_first_thunk,
        first_thunk,
        forwarder_chain,
        max_length=None,
        contains_addresses=False,
    ):
        """Parse the imported symbols.

        It will fill a list, which will be available as the dictionary
        attribute "imports". Its keys will be the DLL names and the values
        of all the symbols imported from that object.
        """

        imported_symbols = []

        # Import Lookup Table. Contains ordinals or pointers to strings.
        ilt = self.get_import_table(
            original_first_thunk, max_length, contains_addresses
        )
        # Import Address Table. May have identical content to ILT if
        # PE file is not bound. It will contain the address of the
        # imported symbols once the binary is loaded or if it is already
        # bound.
        iat = self.get_import_table(first_thunk, max_length, contains_addresses)

        # Would crash if IAT or ILT had None type
        if (not iat or len(iat) == 0) and (not ilt or len(ilt) == 0):
            self.__warnings.append(
                "Damaged Import Table information. "
                "ILT and/or IAT appear to be broken. "
                f"OriginalFirstThunk: 0x{original_first_thunk:x} "
                f"FirstThunk: 0x{first_thunk:x}"
            )
            return []

        table = None
        if ilt:
            table = ilt
        elif iat:
            table = iat
        else:
            return None

        imp_offset = 4
        address_mask = 0x7FFFFFFF
        if self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE:
            ordinal_flag = IMAGE_ORDINAL_FLAG
        elif self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS:
            ordinal_flag = IMAGE_ORDINAL_FLAG64
            imp_offset = 8
            address_mask = 0x7FFFFFFFFFFFFFFF
        else:
            # Some PEs may have an invalid value in the Magic field of the
            # Optional Header. Just in case the remaining file is parseable
            # let's pretend it's a 32bit PE32 by default.
            ordinal_flag = IMAGE_ORDINAL_FLAG

        num_invalid = 0
        for idx, tbl_entry in enumerate(table):
            imp_ord = None
            imp_hint = None
            imp_name = None
            name_offset = None
            hint_name_table_rva = None
            import_by_ordinal = False  # declare it here first

            if tbl_entry.AddressOfData:
                # If imported by ordinal, we will append the ordinal number
                #
                if tbl_entry.AddressOfData & ordinal_flag:
                    import_by_ordinal = True
                    imp_ord = tbl_entry.AddressOfData & 0xFFFF
                    imp_name = None
                    name_offset = None
                else:
                    import_by_ordinal = False
                    try:
                        hint_name_table_rva = tbl_entry.AddressOfData & address_mask
                        data = self.get_data(hint_name_table_rva, 2)
                        # Get the Hint
                        imp_hint = self.get_word_from_data(data, 0)
                        imp_name = self.get_string_at_rva(
                            tbl_entry.AddressOfData + 2, MAX_IMPORT_NAME_LENGTH
                        )
                        if not is_valid_function_name(imp_name):
                            imp_name = b"*invalid*"

                        name_offset = self.get_offset_from_rva(
                            tbl_entry.AddressOfData + 2
                        )
                    except PEFormatError:
                        pass

                # by nriva: we want the ThunkRVA and ThunkOffset
                thunk_offset = tbl_entry.get_file_offset()
                thunk_rva = self.get_rva_from_offset(thunk_offset)

            imp_address = (
                first_thunk + self.OPTIONAL_HEADER.ImageBase + idx * imp_offset
            )

            struct_iat = None
            try:
                if iat and ilt and ilt[idx].AddressOfData != iat[idx].AddressOfData:
                    imp_bound = iat[idx].AddressOfData
                    struct_iat = iat[idx]
                else:
                    imp_bound = None
            except IndexError:
                imp_bound = None

            # The file with hashes:
            #
            # MD5: bfe97192e8107d52dd7b4010d12b2924
            # SHA256: 3d22f8b001423cb460811ab4f4789f277b35838d45c62ec0454c877e7c82c7f5
            #
            # has an invalid table built in a way that it's parseable but contains
            # invalid entries that lead pefile to take extremely long amounts of time to
            # parse. It also leads to extreme memory consumption.
            # To prevent similar cases, if invalid entries are found in the middle of a
            # table the parsing will be aborted
            #
            if imp_ord is None and imp_name is None:
                raise PEFormatError("Invalid entries, aborting parsing.")

            # Some PEs appear to interleave valid and invalid imports. Instead of
            # aborting the parsing altogether we will simply skip the invalid entries.
            # Although if we see 1000 invalid entries and no legit ones, we abort.
            if imp_name == b"*invalid*":
                if num_invalid > 1000 and num_invalid == idx:
                    raise PEFormatError("Too many invalid names, aborting parsing.")
                num_invalid += 1
                continue

            if imp_ord or imp_name:
                imported_symbols.append(
                    ImportData(
                        pe=self,
                        struct_table=tbl_entry,
                        struct_iat=struct_iat,  # for bound imports if any
                        import_by_ordinal=import_by_ordinal,
                        ordinal=imp_ord,
                        ordinal_offset=tbl_entry.get_file_offset(),
                        hint=imp_hint,
                        name=imp_name,
                        name_offset=name_offset,
                        bound=imp_bound,
                        address=imp_address,
                        hint_name_table_rva=hint_name_table_rva,
                        thunk_offset=thunk_offset,
                        thunk_rva=thunk_rva,
                    )
                )

        return imported_symbols
Parse the imported symbols.

        It will fill a list, which will be available as the dictionary
        attribute "imports". Its keys will be the DLL names and the values
        of all the symbols imported from that object.
        
pefile.py