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(); }