struct r_bin_pe_import_t* PE_(r_bin_pe_get_imports)(RBinPEObj* pe) {
	struct r_bin_pe_import_t* imps, * imports = NULL;
	char dll_name[PE_NAME_LENGTH + 1];
	int nimp = 0;
	ut64 off; //used to cache value
	PE_DWord dll_name_offset = 0;
	PE_DWord paddr = 0;
	PE_DWord import_func_name_offset;
	PE_(image_import_directory) curr_import_dir;
	PE_(image_delay_import_directory) curr_delay_import_dir;

	if (!pe) {
		return NULL;
	}
	if (pe->import_directory_offset >= pe->size) {
		return NULL;
	}
	if (pe->import_directory_offset + 20 > pe->size) {
		return NULL;
	}

	off = pe->import_directory_offset;
	if (off < pe->size && off > 0) {
		ut64 last;
		int idi = 0;
		if (off + sizeof (PE_(image_import_directory)) > pe->size) {
			return NULL;
		}
		int r = read_image_import_directory (pe->b, pe->import_directory_offset +
			idi * sizeof (curr_import_dir), &curr_import_dir);
		if (r < 0) {
			return NULL;
		}

		if (pe->import_directory_size < 1) {
			return NULL;
		}
		if (off + pe->import_directory_size > pe->size) {
			//why chopping instead of returning and cleaning?
			pe_printf ("Warning: read (import directory too big)\n");
			pe->import_directory_size = pe->size - pe->import_directory_offset;
		}
		last = pe->import_directory_offset + pe->import_directory_size;
		while (r == sizeof (curr_import_dir) && pe->import_directory_offset + (idi + 1) * sizeof (curr_import_dir) <= last && (
			curr_import_dir.FirstThunk != 0 || curr_import_dir.Name != 0 ||
			curr_import_dir.TimeDateStamp != 0 || curr_import_dir.Characteristics != 0 ||
			curr_import_dir.ForwarderChain != 0)) {
			int rr;
			dll_name_offset = curr_import_dir.Name;
			paddr = PE_(va2pa) (pe, dll_name_offset);
			if (paddr > pe->size) {
				goto beach;
			}
			if (paddr + PE_NAME_LENGTH > pe->size) {
				rr = r_buf_read_at (pe->b, paddr, (ut8*) dll_name, pe->size - paddr);
				if (rr != pe->size - paddr) {
					goto beach;
				}
				dll_name[pe->size - paddr] = '\0';
			} else {
				rr = r_buf_read_at (pe->b, paddr, (ut8*) dll_name, PE_NAME_LENGTH);
				if (rr != PE_NAME_LENGTH) {
					goto beach;
				}
				dll_name[PE_NAME_LENGTH] = '\0';
			}
			if (!bin_pe_parse_imports (pe, &imports, &nimp, dll_name,
				curr_import_dir.Characteristics,
				curr_import_dir.FirstThunk)) {
				break;
			}
			idi++;
			r = read_image_import_directory (pe->b, pe->import_directory_offset +
				idi * sizeof (curr_import_dir), &curr_import_dir);
			if (r < 0) {
				free (imports);
				return NULL;
			}
		}
	}
	off = pe->delay_import_directory_offset;
	if (off < pe->size && off > 0) {
		if (off + sizeof (PE_(image_delay_import_directory)) > pe->size) {
			goto beach;
		}
		int didi;
		for (didi = 0;; didi++) {
			int r = read_image_delay_import_directory (pe->b, off + didi * sizeof (curr_delay_import_dir),
					&curr_delay_import_dir);
			if (r != sizeof (curr_delay_import_dir)) {
				goto beach;
			}
			if ((curr_delay_import_dir.Name == 0) || (curr_delay_import_dir.DelayImportAddressTable == 0)) {
				break;
			}
			if (!curr_delay_import_dir.Attributes) {
				dll_name_offset = PE_(va2pa) (pe, curr_delay_import_dir.Name - PE_(r_bin_pe_get_image_base)(pe));
				import_func_name_offset = curr_delay_import_dir.DelayImportNameTable - PE_(r_bin_pe_get_image_base)(pe);
			} else {
				dll_name_offset = PE_(va2pa) (pe, curr_delay_import_dir.Name);
				import_func_name_offset = curr_delay_import_dir.DelayImportNameTable;
			}
			if (dll_name_offset > pe->size || dll_name_offset + PE_NAME_LENGTH > pe->size) {
				goto beach;
			}
			int rr = r_buf_read_at (pe->b, dll_name_offset, (ut8*) dll_name, PE_NAME_LENGTH);
			if (rr < 5) {
				goto beach;
			}
			dll_name[PE_NAME_LENGTH] = '\0';
			if (!bin_pe_parse_imports (pe, &imports, &nimp, dll_name, import_func_name_offset,
				curr_delay_import_dir.DelayImportAddressTable)) {
				break;
			}
		}
	}
beach:
	if (nimp) {
		imps = realloc (imports, (nimp + 1) * sizeof (struct r_bin_pe_import_t));
		if (!imps) {
			r_sys_perror ("realloc (import)");
			free (imports);
			return NULL;
		}
		imports = imps;
		imports[nimp].last = 1;
	}
	return imports;
}
struct r_bin_pe_import_t* PE_(r_bin_pe_get_imports)(RBinPEObj* pe) {
	struct r_bin_pe_import_t* imps, * imports = NULL;
	char dll_name[PE_NAME_LENGTH + 1];
	int nimp = 0;
	ut64 off;  
	PE_DWord dll_name_offset = 0;
	PE_DWord paddr = 0;
	PE_DWord import_func_name_offset;
	PE_(image_import_directory) curr_import_dir;
	PE_(image_delay_import_directory) curr_delay_import_dir;

	if (!pe) {
		return NULL;
	}
	if (pe->import_directory_offset >= pe->size) {
		return NULL;
	}
	if (pe->import_directory_offset + 20 > pe->size) {
		return NULL;
	}

	off = pe->import_directory_offset;
	if (off < pe->size && off > 0) {
		ut64 last;
		int idi = 0;
		if (off + sizeof (PE_(image_import_directory)) > pe->size) {
			return NULL;
		}
		int r = read_image_import_directory (pe->b, pe->import_directory_offset +
			idi * sizeof (curr_import_dir), &curr_import_dir);
		if (r < 0) {
			return NULL;
		}

		if (pe->import_directory_size < 1) {
			return NULL;
		}
		if (off + pe->import_directory_size > pe->size) {
			 
			pe_printf ("Warning: read (import directory too big)\n");
			pe->import_directory_size = pe->size - pe->import_directory_offset;
		}
		last = pe->import_directory_offset + pe->import_directory_size;
		while (r == sizeof (curr_import_dir) && pe->import_directory_offset + (idi + 1) * sizeof (curr_import_dir) <= last && (
			curr_import_dir.FirstThunk != 0 || curr_import_dir.Name != 0 ||
			curr_import_dir.TimeDateStamp != 0 || curr_import_dir.Characteristics != 0 ||
			curr_import_dir.ForwarderChain != 0)) {
			int rr;
			dll_name_offset = curr_import_dir.Name;
			paddr = PE_(va2pa) (pe, dll_name_offset);
			if (paddr > pe->size) {
				goto beach;
			}
			if (paddr + PE_NAME_LENGTH > pe->size) {
				rr = r_buf_read_at (pe->b, paddr, (ut8*) dll_name, pe->size - paddr);
				if (rr != pe->size - paddr) {
					goto beach;
				}
				dll_name[pe->size - paddr] = '\0';
			} else {
				rr = r_buf_read_at (pe->b, paddr, (ut8*) dll_name, PE_NAME_LENGTH);
				if (rr != PE_NAME_LENGTH) {
					goto beach;
				}
				dll_name[PE_NAME_LENGTH] = '\0';
			}
			if (!bin_pe_parse_imports (pe, &imports, &nimp, dll_name,
				curr_import_dir.Characteristics,
				curr_import_dir.FirstThunk)) {
				break;
			}
			idi++;
			r = read_image_import_directory (pe->b, pe->import_directory_offset +
				idi * sizeof (curr_import_dir), &curr_import_dir);
			if (r < 0) {
				free (imports);
				return NULL;
			}
		}
	}
	off = pe->delay_import_directory_offset;
	if (off < pe->size && off > 0) {
		if (off + sizeof (PE_(image_delay_import_directory)) > pe->size) {
			goto beach;
		}
		int didi;
		for (didi = 0;; didi++) {
			int r = read_image_delay_import_directory (pe->b, off + didi * sizeof (curr_delay_import_dir),
					&curr_delay_import_dir);
			if (r != sizeof (curr_delay_import_dir)) {
				goto beach;
			}
			if ((curr_delay_import_dir.Name == 0) || (curr_delay_import_dir.DelayImportAddressTable == 0)) {
				break;
			}
			if (!curr_delay_import_dir.Attributes) {
				dll_name_offset = PE_(va2pa) (pe, curr_delay_import_dir.Name - PE_(r_bin_pe_get_image_base)(pe));
				import_func_name_offset = curr_delay_import_dir.DelayImportNameTable - PE_(r_bin_pe_get_image_base)(pe);
			} else {
				dll_name_offset = PE_(va2pa) (pe, curr_delay_import_dir.Name);
				import_func_name_offset = curr_delay_import_dir.DelayImportNameTable;
			}
			if (dll_name_offset > pe->size || dll_name_offset + PE_NAME_LENGTH > pe->size) {
				goto beach;
			}
			int rr = r_buf_read_at (pe->b, dll_name_offset, (ut8*) dll_name, PE_NAME_LENGTH);
			if (rr < 5) {
				goto beach;
			}
			dll_name[PE_NAME_LENGTH] = '\0';
			if (!bin_pe_parse_imports (pe, &imports, &nimp, dll_name, import_func_name_offset,
				curr_delay_import_dir.DelayImportAddressTable)) {
				break;
			}
		}
	}
beach:
	if (nimp) {
		imps = realloc (imports, (nimp + 1) * sizeof (struct r_bin_pe_import_t));
		if (!imps) {
			r_sys_perror ("realloc (import)");
			free (imports);
			return NULL;
		}
		imports = imps;
		imports[nimp].last = 1;
	}
	return imports;
}