struct r_bin_pe_addr_t *PE_(check_msvcseh) (struct PE_(r_bin_pe_obj_t) *bin) {
	struct r_bin_pe_addr_t* entry;
	ut8 b[512];
	int n = 0;
	if (!bin || !bin->b) {
		return 0LL;
	}
	entry = PE_(r_bin_pe_get_entrypoint) (bin);
	ZERO_FILL (b);
	if (r_buf_read_at (bin->b, entry->paddr, b, sizeof (b)) < 0) {
		bprintf ("Warning: Cannot read entry at 0x%08"PFMT64x "\n", entry->paddr);
		free (entry);
		return NULL;
	}
	// MSVC SEH
	// E8 13 09 00 00  call    0x44C388
	// E9 05 00 00 00  jmp     0x44BA7F
	if (b[0] == 0xe8 && b[5] == 0xe9) {
		const st32 jmp_dst = r_read_ble32 (b + 6, bin->big_endian);
		entry->paddr += (5 + 5 + jmp_dst);
		entry->vaddr += (5 + 5 + jmp_dst);
		if (r_buf_read_at (bin->b, entry->paddr, b, sizeof (b)) > 0) {
			// case1:
			// from des address of jmp search for 68 xx xx xx xx e8 and test xx xx xx xx = imagebase
			// 68 00 00 40 00  push    0x400000
			// E8 3E F9 FF FF  call    0x44B4FF
			ut32 imageBase = bin->nt_headers->optional_header.ImageBase;
			for (n = 0; n < sizeof (b) - 6; n++) {
				const ut32 tmp_imgbase = r_read_ble32 (b + n + 1, bin->big_endian);
				if (b[n] == 0x68 && tmp_imgbase == imageBase && b[n + 5] == 0xe8) {
					const st32 call_dst = r_read_ble32 (b + n + 6, bin->big_endian);
					entry->paddr += (n + 5 + 5 + call_dst);
					entry->vaddr += (n + 5 + 5 + call_dst);
					return entry;
				}
			}
			//case2:
			// from des address of jmp search for 50 FF xx FF xx E8
			//50			 push    eax
			//FF 37			 push    dword ptr[edi]
			//FF 36          push    dword ptr[esi]
			//E8 6F FC FF FF call    _main
			for (n = 0; n < sizeof (b) - 6; n++) {
				if (b[n] == 0x50 && b[n+1] == 0xff && b[n + 3] == 0xff && b[n + 5] == 0xe8) {
					const st32 call_dst = r_read_ble32 (b + n + 6, bin->big_endian);
					entry->paddr += (n + 5 + 5 + call_dst);
					entry->vaddr += (n + 5 + 5 + call_dst);
					return entry;
				}
			}
			//case3:
			//50                                         push    eax
			//FF 35 0C E2 40 00                          push    xxxxxxxx
			//FF 35 08 E2 40 00                          push    xxxxxxxx
			//E8 2B FD FF FF                             call    _main
			for (n = 0; n < sizeof (b) - 20; n++) {
				if (b[n] == 0x50 && b[n + 1] == 0xff && b[n + 7] == 0xff && b[n + 13] == 0xe8) {
					const st32 call_dst = r_read_ble32 (b + n + 14, bin->big_endian);
					entry->paddr += (n + 5 + 13 + call_dst);
					entry->vaddr += (n + 5 + 13 + call_dst);
					return entry;
				}
			}
			//case4:
			//50                                        push    eax
			//57                                        push    edi
			//FF 36                                     push    dword ptr[esi]
			//E8 D9 FD FF FF                            call    _main
			for (n = 0; n < sizeof (b) - 5; n++) {
				if (b[n] == 0x50 && b[n + 1] == 0x57 && b[n + 2] == 0xff && b[n + 4] == 0xe8) {
					const st32 call_dst = r_read_ble32 (b + n + 5, bin->big_endian);
					entry->paddr += (n + 5 + 4 + call_dst);
					entry->vaddr += (n + 5 + 4 + call_dst);
					return entry;
				}
			}

		}
	}
	// MSVC AMD64
	// 48 83 EC 28       sub     rsp, 0x28
	// E8 xx xx xx xx    call    xxxxxxxx
	// 48 83 C4 28       add     rsp, 0x28
	// E9 xx xx xx xx    jmp     xxxxxxxx
	if (b[4] == 0xe8 && b[13] == 0xe9) {
		//const st32 jmp_dst = b[14] | (b[15] << 8) | (b[16] << 16) | (b[17] << 24);
		const st32 jmp_dst = r_read_ble32 (b + 14, bin->big_endian);
		entry->paddr += (5 + 13 + jmp_dst);
		entry->vaddr += (5 + 13 + jmp_dst);
		if (r_buf_read_at (bin->b, entry->paddr, b, sizeof (b)) > 0) {
			// from des address of jmp, search for 4C ... 48 ... 8B ... E8
			// 4C 8B C0                    mov     r8, rax
			// 48 8B 17                    mov     rdx, qword [rdi]
			// 8B 0B                       mov     ecx, dword [rbx]
			// E8 xx xx xx xx              call    main
			for (n = 0; n < sizeof (b) - 13; n++) {
				if (b[n] == 0x4c && b[n + 3] == 0x48 && b[n + 6] == 0x8b && b[n + 8] == 0xe8) {
					const st32 call_dst = r_read_ble32 (b + n + 9, bin->big_endian);
					entry->paddr += (n + 5 + 8 + call_dst);
					entry->vaddr += (n + 5 + 8 + call_dst);
					return entry;
				}
			}
		}
	}
	//Microsoft Visual-C
	// 50                  push eax
	// FF 75 9C            push dword [ebp - local_64h]
	// 56                  push    esi
	// 56                  push    esi
	// FF 15 CC C0  44 00  call dword [sym.imp.KERNEL32.dll_GetModuleHandleA]
	// 50                  push    eax
	// E8 DB DA 00 00      call    main
	// 89 45 A0            mov dword [ebp - local_60h], eax
	// 50                  push    eax
	// E8 2D 00 00  00     call 0x4015a6
	if (b[188] == 0x50 && b[201] == 0xe8) {
		const st32 call_dst = r_read_ble32 (b + 202, bin->big_endian);
		entry->paddr += (201 + 5 + call_dst);
		entry->vaddr += (201 + 5 + call_dst);
		return entry;
	}

	if (b[292] == 0x50 && b[303] == 0xe8) {
		const st32 call_dst = r_read_ble32 (b + 304, bin->big_endian);
		entry->paddr += (303 + 5 + call_dst);
		entry->vaddr += (303 + 5 + call_dst);
		return entry;
	}

	free (entry);
	return NULL;
}