problem reading dir's with fix

Rein Klazes wijn at wanadoo.nl
Thu Dec 9 07:38:37 CST 2004


hi,

Since the change from readdir to getdents64 I cannot access certain
files and dir's (including the one used for saving wine patches) with
the common file dialog's. 

| 0009:Call ntdll.NtQueryDirectoryFile(00000010,00000000,00000000,00000000,77a6a070,77cc6b24,00002000,00000003,00000000,77cc6b10,00000000) ret=77b26174
| trace:file:NtQueryDirectoryFile (0x10 (nil) (nil) (nil) 0x77a6a070 0x77cc6b24 0x00002000 0x00000003 0x00000000 L"diffs" 0x00000000
| trace:file:append_entry long L"."... short L""... mask L"diffs"
| trace:file:match_filename (L"."..., L"diffs")
| trace:file:append_entry long L".."... short L""... mask L"diffs"
| trace:file:match_filename (L".."..., L"diffs")

[some 200 entries snipped]

| trace:file:append_entry long L"freecell.ICO"... short L""... mask L"diffs"
| trace:file:match_filename (L"freecell.ICO"..., L"diffs")
| trace:file:NtQueryDirectoryFile => 80000006 (0)
| 0009:Ret  ntdll.NtQueryDirectoryFile() retval=80000006 ret=77b26174
| 0009:Call ntdll.RtlNtStatusToDosError(80000006) ret=77b261e1
| 0009:Ret  ntdll.RtlNtStatusToDosError() retval=00000012 ret=77b261e1
| trace:file:FindFirstFileExW L"H:\\diffs" not found

H:\ contains almost 400 entries, so it is clear not all are read.

Looking through the code I notice that getdents64 is called only once,
where readdir was called several times.

Here is my solution that fixes the problem for me.

Changelog:
	dlls/ntdll	: directory.c
	If needed, keep calling getdents64() until no more entries are
	returned.

Rein.
-------------- next part --------------
--- wine/dlls/ntdll/directory.c	2004-12-08 08:50:24.000000000 +0100
+++ mywine/dlls/ntdll/directory.c	2004-12-09 14:21:15.000000000 +0100
@@ -753,54 +753,57 @@ static int read_directory_getdents( int 
         {
             io->u.Status = STATUS_NO_MORE_FILES;
             res = 0;
-            goto done;
+            goto done_2;
         }
     }
 
     io->u.Status = STATUS_SUCCESS;
-
-    res = getdents64( fd, data, size );
-    if (res == -1)
-    {
-        if (errno != ENOSYS)
+    while(1) {
+        res = getdents64( fd, data, size );
+        if (res == -1)
         {
-            io->u.Status = FILE_GetNtStatus();
-            res = 0;
+            if (errno != ENOSYS)
+            {
+                io->u.Status = FILE_GetNtStatus();
+                res = 0;
+            }
+            goto done_2;
         }
-        goto done;
-    }
+        if( !res) break;
 
-    de = data;
+        de = data;
 
-    while (res > 0)
-    {
-        res -= de->d_reclen;
-        info = append_entry( buffer, &io->Information, length, de->d_name, NULL, mask );
-        if (info)
+        while (res > 0)
         {
-            last_info = info;
-            if ((char *)info->FileName + info->FileNameLength > (char *)buffer + length)
-            {
-                io->u.Status = STATUS_BUFFER_OVERFLOW;
-                lseek( fd, old_pos, SEEK_SET );  /* restore pos to previous entry */
-                break;
-            }
-            /* check if we still have enough space for the largest possible entry */
-            if (single_entry || io->Information + max_dir_info_size > length)
+            res -= de->d_reclen;
+            info = append_entry( buffer, &io->Information, length, de->d_name, NULL, mask );
+            if (info)
             {
-                if (res > 0) lseek( fd, de->d_off, SEEK_SET );  /* set pos to next entry */
-                break;
+                last_info = info;
+                if ((char *)info->FileName + info->FileNameLength > (char *)buffer + length)
+                {
+                    io->u.Status = STATUS_BUFFER_OVERFLOW;
+                    lseek( fd, old_pos, SEEK_SET );  /* restore pos to previous entry */
+                    goto done_1;
+                }
+                /* check if we still have enough space for the largest possible entry */
+                if (single_entry || io->Information + max_dir_info_size > length)
+                {
+                    if (res > 0) lseek( fd, de->d_off, SEEK_SET );  /* set pos to next entry */
+                    goto done_1;
+                }
             }
+            old_pos = de->d_off;
+            /* move on to the next entry */
+            de = (KERNEL_DIRENT64 *)((char *)de + de->d_reclen);
         }
-        old_pos = de->d_off;
-        /* move on to the next entry */
-        de = (KERNEL_DIRENT64 *)((char *)de + de->d_reclen);
     }
 
+done_1:
     if (last_info) last_info->NextEntryOffset = 0;
     else io->u.Status = restart_scan ? STATUS_NO_SUCH_FILE : STATUS_NO_MORE_FILES;
     res = 0;
-done:
+done_2:
     if ((char *)data != local_buffer) RtlFreeHeap( GetProcessHeap(), 0, data );
     return res;
 }


More information about the wine-devel mailing list