diff options
author | Vincent Torri <vincent.torri@gmail.com> | 2020-08-31 11:55:09 +0000 |
---|---|---|
committer | Stefan Schmidt <stefan@datenfreihafen.org> | 2020-08-31 14:08:21 +0200 |
commit | 45cabae42b766a9c5df1f577ca251d04f90bbdff (patch) | |
tree | ef69a07fae2995a73457579f0dbe2e71bda024fa /src/lib/ecore_file/ecore_file.c | |
parent | abc308accb39dc6f7e946108da1b5a65489bc051 (diff) |
ecore-file: fix ecore_file_can_exec() on Windows
on Windows access() has no support of X_OK (see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/access-waccess?view=vs-2019), use SHGetFileInfo() instead
Reviewed-by: João Paulo Taylor Ienczak Zanette <joao.tiz@expertisesolutions.com.br>
Reviewed-by: Stefan Schmidt <stefan@datenfreihafen.org>
Differential Revision: https://phab.enlightenment.org/D12118
Diffstat (limited to '')
-rw-r--r-- | src/lib/ecore_file/ecore_file.c | 88 |
1 files changed, 87 insertions, 1 deletions
diff --git a/src/lib/ecore_file/ecore_file.c b/src/lib/ecore_file/ecore_file.c index ab8b07f1ce..528de6a97a 100644 --- a/src/lib/ecore_file/ecore_file.c +++ b/src/lib/ecore_file/ecore_file.c | |||
@@ -622,8 +622,94 @@ ecore_file_can_write(const char *file) | |||
622 | EAPI Eina_Bool | 622 | EAPI Eina_Bool |
623 | ecore_file_can_exec(const char *file) | 623 | ecore_file_can_exec(const char *file) |
624 | { | 624 | { |
625 | if (!file) return EINA_FALSE; | 625 | #ifdef _WIN32 |
626 | HANDLE h; | ||
627 | HANDLE fm; | ||
628 | char *base; | ||
629 | char *base_nt; | ||
630 | LARGE_INTEGER sz; | ||
631 | WORD characteristics; | ||
632 | #endif | ||
633 | |||
634 | if (!file || !*file) return EINA_FALSE; | ||
635 | |||
636 | #ifdef _WIN32 | ||
637 | /* | ||
638 | * we parse the file to check if it is a PE file (EXE or DLL) | ||
639 | * and we finally check whether it's a DLL or not. | ||
640 | * Reference : | ||
641 | * https://docs.microsoft.com/en-us/windows/win32/debug/pe-format | ||
642 | */ | ||
643 | h = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, | ||
644 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); | ||
645 | if (h == INVALID_HANDLE_VALUE) | ||
646 | return EINA_FALSE; | ||
647 | |||
648 | if (!GetFileSizeEx(h, &sz)) | ||
649 | goto close_h; | ||
650 | |||
651 | /* a PE file must have at least the DOS and NT headers */ | ||
652 | if (sz.QuadPart < (LONGLONG)(sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS))) | ||
653 | goto close_h; | ||
654 | |||
655 | fm = CreateFileMapping(h, NULL, PAGE_READONLY, 0, 0, NULL); | ||
656 | if (fm == NULL) | ||
657 | goto close_h; | ||
658 | |||
659 | base = (char *)MapViewOfFile(fm, FILE_MAP_READ, 0, 0, 0); | ||
660 | CloseHandle(fm); | ||
661 | if (base == NULL) | ||
662 | goto close_h; | ||
663 | |||
664 | /* | ||
665 | * the PE file begins with the DOS header. | ||
666 | * First magic number : the DOS header must begin with a DOS magic number, | ||
667 | * that is "MZ", that is 0x5a4d, stored in a WORD. | ||
668 | */ | ||
669 | if (*((WORD *)base) != 0x5a4d) | ||
670 | goto unmap_view; | ||
671 | |||
672 | /* | ||
673 | * The position of the NT header is located at the offset 0x3c. | ||
674 | */ | ||
675 | base_nt = base + *((DWORD *)(base + 0x3c)); | ||
676 | /* | ||
677 | * The NT header begins with the magic number "PE\0\0", that is | ||
678 | * 0x00004550, stored in a DWORD. | ||
679 | */ | ||
680 | if (*((DWORD *)base_nt) != 0x00004550) | ||
681 | goto unmap_view; | ||
682 | |||
683 | /* | ||
684 | * to get informations about executable (EXE or DLL), we look at | ||
685 | * the 'Characteristics' member of the NT header, located at the offset | ||
686 | * 22 (4 for the magic number, 18 for the offset) from base_nt. | ||
687 | * https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#characteristics | ||
688 | */ | ||
689 | characteristics = *((WORD *)(base_nt + 4 + 18)); | ||
690 | |||
691 | UnmapViewOfFile(base); | ||
692 | CloseHandle(h); | ||
693 | |||
694 | /* | ||
695 | * 0x0002 : if set, EXE or DLL | ||
696 | * 0x2000 : if set, DLL | ||
697 | */ | ||
698 | if ((characteristics & 0x0002) && !(characteristics & 0x2000)) | ||
699 | return EINA_TRUE; | ||
700 | |||
701 | /* | ||
702 | * a .bat file, considered as an executable, is only a text file, | ||
703 | * so we rely on the extension. Not the best but we cannot do more. | ||
704 | */ | ||
705 | return eina_str_has_extension(file, ".bat"); | ||
706 | unmap_view: | ||
707 | UnmapViewOfFile(base); | ||
708 | close_h: | ||
709 | CloseHandle(h); | ||
710 | #else | ||
626 | if (!access(file, X_OK)) return EINA_TRUE; | 711 | if (!access(file, X_OK)) return EINA_TRUE; |
712 | #endif | ||
627 | return EINA_FALSE; | 713 | return EINA_FALSE; |
628 | } | 714 | } |
629 | 715 | ||