PATCH: FindNextFile error code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Greetings all,
As discussed on wine-devel a couple weeks ago, this is a patch that changes FindNextFile and friends to use HeapAlloc and a critical section instead of GlobalAlloc. The reason is that GlobalUnlock was setting the last error to 0, and that was breaking some programs.


I also merged the test program I used into the existing file tests.

Alex


ChangeLog: - Use HeapAlloc instead of GlobalAlloc in FindNextFile - Add test for FindNextFile that checks last error value

Index: files/dos_fs.c
===================================================================
RCS file: /home/wine/wine/files/dos_fs.c,v
retrieving revision 1.136
diff -u -r1.136 dos_fs.c
--- files/dos_fs.c	5 Sep 2003 23:15:45 -0000	1.136
+++ files/dos_fs.c	12 Sep 2003 01:13:57 -0000
@@ -147,6 +147,7 @@
     BYTE  attr;
     int   drive;
     int   cur_pos;
+    CRITICAL_SECTION cs;
     union
     {
         DOS_DIR *dos_dir;
@@ -1995,7 +1996,6 @@
 	LPVOID lpSearchFilter,
 	DWORD dwAdditionalFlags)
 {
-    HGLOBAL handle;
     FIND_FIRST_INFO *info;
 
     if (!lpFileName)
@@ -2023,20 +2023,22 @@
           if (lpFileName[0] == '\\' && lpFileName[1] == '\\')
           {
               ERR("UNC path name\n");
-              if (!(handle = GlobalAlloc(GMEM_MOVEABLE, sizeof(FIND_FIRST_INFO)))) break;
+	      if (!(info = HeapAlloc( GetProcessHeap(), 0, sizeof(FIND_FIRST_INFO)))) break;
 
-              info = (FIND_FIRST_INFO *)GlobalLock( handle );
+	      RtlInitializeCriticalSection( &info->cs );
+	      RtlEnterCriticalSection( &info->cs );
               info->u.smb_dir = SMB_FindFirst(lpFileName);
               if(!info->u.smb_dir)
               {
-                 GlobalUnlock( handle );
-                 GlobalFree(handle);
+                 RtlLeaveCriticalSection( &info->cs );
+                 RtlDeleteCriticalSection( &info->cs );
+                 HeapFree(GetProcessHeap(), 0, info);
                  break;
               }
 
               info->drive = -1;
 
-              GlobalUnlock( handle );
+              RtlLeaveCriticalSection( &info->cs );
           }
           else
           {
@@ -2053,8 +2055,9 @@
                 }
             }
             if (!DOSFS_GetFullName( lpFileName, FALSE, &full_name )) break;
-            if (!(handle = GlobalAlloc(GMEM_MOVEABLE, sizeof(FIND_FIRST_INFO)))) break;
-            info = (FIND_FIRST_INFO *)GlobalLock( handle );
+            if (!(info = HeapAlloc( GetProcessHeap(), 0, sizeof(FIND_FIRST_INFO)))) break;
+            RtlInitializeCriticalSection( &info->cs );
+            RtlEnterCriticalSection( &info->cs );
             info->path = HeapAlloc( GetProcessHeap(), 0, strlen(full_name.long_name)+1 );
             strcpy( info->path, full_name.long_name );
 
@@ -2071,15 +2074,15 @@
             info->cur_pos = 0;
 
             info->u.dos_dir = DOSFS_OpenDir( codepage, info->path );
-            GlobalUnlock( handle );
+            RtlLeaveCriticalSection( &info->cs );
           }
-          if (!FindNextFileW( handle, data ))
+          if (!FindNextFileW( (HANDLE) info, data ))
           {
-              FindClose( handle );
+              FindClose( (HANDLE) info );
               SetLastError( ERROR_FILE_NOT_FOUND );
               break;
           }
-          return handle;
+          return (HANDLE) info;
         }
         break;
       default:
@@ -2163,12 +2166,13 @@
     BOOL ret = FALSE;
     DWORD gle = ERROR_NO_MORE_FILES;
 
-    if ((handle == INVALID_HANDLE_VALUE) ||
-       !(info = (FIND_FIRST_INFO *)GlobalLock( handle )))
+    if (handle == INVALID_HANDLE_VALUE)
     {
         SetLastError( ERROR_INVALID_HANDLE );
         return ret;
     }
+    info = (FIND_FIRST_INFO*) handle;
+    RtlEnterCriticalSection( &info->cs );
     if (info->drive == -1)
     {
         ret = SMB_FindNext( info->u.smb_dir, data );
@@ -2194,7 +2198,7 @@
     }
     ret = TRUE;
 done:
-    GlobalUnlock( handle );
+    RtlLeaveCriticalSection( &info->cs );
     if( !ret ) SetLastError( gle );
     return ret;
 }
@@ -2226,13 +2230,14 @@
  */
 BOOL WINAPI FindClose( HANDLE handle )
 {
-    FIND_FIRST_INFO *info;
+    FIND_FIRST_INFO *info = (FIND_FIRST_INFO*) handle;
 
     if (handle == INVALID_HANDLE_VALUE) goto error;
 
     __TRY
     {
-        if ((info = (FIND_FIRST_INFO *)GlobalLock( handle )))
+        RtlEnterCriticalSection( &info->cs );
+        if (info)
         {
             if (info->u.dos_dir) DOSFS_CloseDir( info->u.dos_dir );
             if (info->path) HeapFree( GetProcessHeap(), 0, info->path );
@@ -2247,8 +2252,9 @@
     }
     __ENDTRY
     if (!info) goto error;
-    GlobalUnlock( handle );
-    GlobalFree( handle );
+    RtlLeaveCriticalSection( &info->cs );
+    RtlDeleteCriticalSection( &info->cs );
+    HeapFree(GetProcessHeap(), 0, info);
     return TRUE;
 
  error:
Index: dlls/kernel/tests/file.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/tests/file.c,v
retrieving revision 1.19
diff -u -r1.19 file.c
--- dlls/kernel/tests/file.c	5 Sep 2003 23:08:36 -0000	1.19
+++ dlls/kernel/tests/file.c	12 Sep 2003 01:12:30 -0000
@@ -813,6 +813,23 @@
     ok ( FindClose(handle) == TRUE, "Failed to close handle");
 }
 
+void test_FindNextFileA()
+{
+    HANDLE handle;
+    WIN32_FIND_DATAA search_results;
+    int err;
+
+    handle = FindFirstFileA("C:\\*",&search_results);
+    ok ( handle != INVALID_HANDLE_VALUE, "FindFirstFile on C:\\* should succeed" );
+    while (FindNextFile(handle, &search_results))
+    {
+        /* get to the end of the files */
+    }
+    ok ( FindClose(handle) == TRUE, "Failed to close handle");
+    err = GetLastError();
+    ok ( err == ERROR_NO_MORE_FILES, "GetLastError should return ERROR_NO_MORE_FILES");
+}
+
 START_TEST(file)
 {
     test__hread(  );
@@ -830,6 +847,7 @@
     test_DeleteFileA();
     test_DeleteFileW();
     test_FindFirstFileA();
+    test_FindNextFileA();
     test_LockFile();
     test_offset_in_overlapped_structure();
 }

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux