struct r_bin_pe_import_t* PE_(r_bin_pe_get_imports)(struct PE_(r_bin_pe_obj_t)* bin) {
	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 = NULL;
	PE_(image_delay_import_directory) * curr_delay_import_dir = 0;

	if (!bin) {
		return NULL;
	}
	if (bin->import_directory_offset >= bin->size) {
		return NULL;
	}
	if (bin->import_directory_offset + 32 >= bin->size) {
		return NULL;
	}

	off = bin->import_directory_offset;
	if (off < bin->size && off > 0) {
		void* last;
		if (off + sizeof(PE_(image_import_directory)) > bin->size) {
			return NULL;
		}
		curr_import_dir = (PE_(image_import_directory)*)(bin->b->buf + bin->import_directory_offset);
		dll_name_offset = curr_import_dir->Name;

		if (bin->import_directory_size < 1) {
			return NULL;
		}
		if (off + bin->import_directory_size > bin->size) {
			//why chopping instead of returning and cleaning?
			bprintf ("Warning: read (import directory too big)\n");
			bin->import_directory_size = bin->size - bin->import_directory_offset;
		}
		last = (char*) curr_import_dir + bin->import_directory_size;
		while ((void*) (curr_import_dir + 1) <= 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 = bin_pe_rva_to_paddr (bin, dll_name_offset);
			if (paddr > bin->size) {
				goto beach;
			}
			if (paddr + PE_NAME_LENGTH > bin->size) {
				rr = r_buf_read_at (bin->b, paddr, (ut8*) dll_name, bin->size - paddr);
				if (rr != bin->size - paddr) {
					goto beach;
				}
				dll_name[bin->size - paddr] = '\0';
			}else {
				rr = r_buf_read_at (bin->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 (bin, &imports, &nimp, dll_name,
				curr_import_dir->Characteristics,
				curr_import_dir->FirstThunk)) {
				break;
			}
			curr_import_dir++;
		}
	}
	off = bin->delay_import_directory_offset;
	if (off < bin->size && off > 0) {
		if (off + sizeof(PE_(image_delay_import_directory)) > bin->size) {
			goto beach;
		}
		curr_delay_import_dir = (PE_(image_delay_import_directory)*)(bin->b->buf + off);
		if (!curr_delay_import_dir->Attributes) {
			dll_name_offset = bin_pe_rva_to_paddr (bin,
				curr_delay_import_dir->Name - PE_(r_bin_pe_get_image_base)(bin));
			import_func_name_offset = curr_delay_import_dir->DelayImportNameTable -
			PE_(r_bin_pe_get_image_base)(bin);
		} else {
			dll_name_offset = bin_pe_rva_to_paddr (bin, curr_delay_import_dir->Name);
			import_func_name_offset = curr_delay_import_dir->DelayImportNameTable;
		}
		while ((curr_delay_import_dir->Name != 0) && (curr_delay_import_dir->DelayImportAddressTable !=0)) {
			if (dll_name_offset > bin->size || dll_name_offset + PE_NAME_LENGTH > bin->size) {
				goto beach;
			}
			int rr = r_buf_read_at (bin->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 (bin, &imports, &nimp, dll_name, import_func_name_offset,
				curr_delay_import_dir->DelayImportAddressTable)) {
				break;
			}
			if ((char*) (curr_delay_import_dir + 2) > (char*) (bin->b->buf + bin->size)) {
				goto beach;
			}
			curr_delay_import_dir++;
		}
	}
beach:
	if (nimp) {
		imps = realloc (imports, (nimp + 1) * sizeof(struct r_bin_pe_import_t));
		if (!imps) {
			r_sys_perror ("realloc (import)");
			return NULL;
		}
		imports = imps;
		imports[nimp].last = 1;
	}
	return imports;
}