summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2020-08-31 11:55:09 +0000
committerStefan Schmidt <stefan@datenfreihafen.org>2020-08-31 14:08:21 +0200
commit45cabae42b766a9c5df1f577ca251d04f90bbdff (patch)
treeef69a07fae2995a73457579f0dbe2e71bda024fa
parentabc308accb39dc6f7e946108da1b5a65489bc051 (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
-rw-r--r--src/lib/ecore_file/ecore_file.c88
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)
622EAPI Eina_Bool 622EAPI Eina_Bool
623ecore_file_can_exec(const char *file) 623ecore_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