From 220312e993bb7000569ca6df7fdd32cc21b2ba00 Mon Sep 17 00:00:00 2001
From: Andreas Mohr <amohr@codeweavers.com>
Date: Thu, 19 Oct 2000 20:38:38 +0000
Subject: [PATCH] Skip directory symlinks in DOSFS_FindNextEx.

---
 files/dos_fs.c  | 11 ++++++++++-
 files/file.c    | 18 ++++++++++++++----
 include/winnt.h |  1 +
 3 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/files/dos_fs.c b/files/dos_fs.c
index d4dd2c3ffd2..5c1da9a8f34 100644
--- a/files/dos_fs.c
+++ b/files/dos_fs.c
@@ -1362,7 +1362,7 @@ DWORD WINAPI GetFullPathNameW( LPCWSTR name, DWORD len, LPWSTR buffer,
  */
 static int DOSFS_FindNextEx( FIND_FIRST_INFO *info, WIN32_FIND_DATAA *entry )
 {
-    BYTE attr = info->attr | FA_UNUSED | FA_ARCHIVE | FA_RDONLY;
+    DWORD attr = info->attr | FA_UNUSED | FA_ARCHIVE | FA_RDONLY | FILE_ATTRIBUTE_SYMLINK;
     UINT flags = DRIVE_GetFlags( info->drive );
     char *p, buffer[MAX_PATHNAME_LEN];
     const char *drive_path;
@@ -1436,6 +1436,15 @@ static int DOSFS_FindNextEx( FIND_FIRST_INFO *info, WIN32_FIND_DATAA *entry )
             WARN("can't stat %s\n", buffer);
             continue;
         }
+        if ((fileinfo.dwFileAttributes & FILE_ATTRIBUTE_SYMLINK) &&
+            (fileinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+        {
+            static int show_dir_symlinks = -1;
+            if (show_dir_symlinks == -1)
+                show_dir_symlinks = PROFILE_GetWineIniBool("wine", "ShowDirSymlinks", 0);
+            if (!show_dir_symlinks) continue;
+        }
+
         if (fileinfo.dwFileAttributes & ~attr) continue;
 
         /* We now have a matching entry; fill the result and return */
diff --git a/files/file.c b/files/file.c
index 15201c30f76..2f9bc307f9e 100644
--- a/files/file.c
+++ b/files/file.c
@@ -617,14 +617,24 @@ BOOL FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info )
 {
     struct stat st;
 
-    if (!unixName || !info) return FALSE;
-
-    if (stat( unixName, &st ) == -1)
+    if (lstat( unixName, &st ) == -1)
     {
         FILE_SetDosError();
         return FALSE;
     }
-    FILE_FillInfo( &st, info );
+    if (!S_ISLNK(st.st_mode)) FILE_FillInfo( &st, info );
+    else
+    {
+        /* do a "real" stat to find out
+	   about the type of the symlink destination */
+        if (stat( unixName, &st ) == -1)
+        {
+            FILE_SetDosError();
+            return FALSE;
+        }
+        FILE_FillInfo( &st, info );
+        info->dwFileAttributes |= FILE_ATTRIBUTE_SYMLINK;
+    }
     return TRUE;
 }
 
diff --git a/include/winnt.h b/include/winnt.h
index 67b50d6ccce..60afdc4add2 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -2891,6 +2891,7 @@ typedef enum tagSID_NAME_USE {
 #define FILE_ATTRIBUTE_XACTION_WRITE    0x00000400L
 #define FILE_ATTRIBUTE_COMPRESSED       0x00000800L
 #define FILE_ATTRIBUTE_OFFLINE		0x00001000L
+#define FILE_ATTRIBUTE_SYMLINK		0x80000000L  /* Not in Windows API */
 
 /* File notification flags */
 #define FILE_NOTIFY_CHANGE_FILE_NAME    0x00000001
-- 
GitLab