Commit 98a3912e authored by Alexandre Julliard's avatar Alexandre Julliard

kernel32: Fixed behavior of FindFirstFile for DOS devices.

parent d65e80c8
...@@ -1553,6 +1553,7 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level, ...@@ -1553,6 +1553,7 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
OBJECT_ATTRIBUTES attr; OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io; IO_STATUS_BLOCK io;
NTSTATUS status; NTSTATUS status;
DWORD device = 0;
TRACE("%s %d %p %d %p %x\n", debugstr_w(filename), level, data, search_op, filter, flags); TRACE("%s %d %p %d %p %x\n", debugstr_w(filename), level, data, search_op, filter, flags);
...@@ -1574,27 +1575,56 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level, ...@@ -1574,27 +1575,56 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
} }
if (!mask || !*mask)
{
SetLastError( ERROR_FILE_NOT_FOUND );
goto error;
}
if (!(info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info)))) if (!(info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info))))
{ {
SetLastError( ERROR_NOT_ENOUGH_MEMORY ); SetLastError( ERROR_NOT_ENOUGH_MEMORY );
goto error; goto error;
} }
if (!RtlCreateUnicodeString( &info->mask, mask )) if (!mask && (device = RtlIsDosDeviceName_U( filename )))
{ {
SetLastError( ERROR_NOT_ENOUGH_MEMORY ); static const WCHAR dotW[] = {'.',0};
WCHAR *dir = NULL;
/* we still need to check that the directory can be opened */
if (HIWORD(device))
{
if (!(dir = HeapAlloc( GetProcessHeap(), 0, HIWORD(device) + sizeof(WCHAR) )))
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
goto error;
}
memcpy( dir, filename, HIWORD(device) );
dir[HIWORD(device)/sizeof(WCHAR)] = 0;
}
RtlFreeUnicodeString( &nt_name );
if (!RtlDosPathNameToNtPathName_U( dir ? dir : dotW, &nt_name, &mask, NULL ))
{
HeapFree( GetProcessHeap(), 0, dir );
SetLastError( ERROR_PATH_NOT_FOUND );
goto error;
}
HeapFree( GetProcessHeap(), 0, dir );
RtlInitUnicodeString( &info->mask, NULL );
}
else if (!mask || !*mask)
{
SetLastError( ERROR_FILE_NOT_FOUND );
goto error; goto error;
} }
else
{
if (!RtlCreateUnicodeString( &info->mask, mask ))
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
goto error;
}
/* truncate dir name before mask */ /* truncate dir name before mask */
*mask = 0; *mask = 0;
nt_name.Length = (mask - nt_name.Buffer) * sizeof(WCHAR); nt_name.Length = (mask - nt_name.Buffer) * sizeof(WCHAR);
}
/* check if path is the root of the drive */ /* check if path is the root of the drive */
info->is_root = FALSE; info->is_root = FALSE;
...@@ -1620,7 +1650,10 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level, ...@@ -1620,7 +1650,10 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
if (status != STATUS_SUCCESS) if (status != STATUS_SUCCESS)
{ {
RtlFreeUnicodeString( &info->mask ); RtlFreeUnicodeString( &info->mask );
SetLastError( RtlNtStatusToDosError(status) ); if (status == STATUS_OBJECT_NAME_NOT_FOUND)
SetLastError( ERROR_PATH_NOT_FOUND );
else
SetLastError( RtlNtStatusToDosError(status) );
goto error; goto error;
} }
...@@ -1631,14 +1664,24 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level, ...@@ -1631,14 +1664,24 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
info->data_len = 0; info->data_len = 0;
info->search_op = search_op; info->search_op = search_op;
if (!FindNextFileW( (HANDLE)info, data )) if (device)
{
WIN32_FIND_DATAW *wfd = data;
memset( wfd, 0, sizeof(*wfd) );
memcpy( wfd->cFileName, filename + HIWORD(device)/sizeof(WCHAR), LOWORD(device) );
wfd->dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE;
CloseHandle( info->handle );
info->handle = 0;
}
else if (!FindNextFileW( (HANDLE)info, data ))
{ {
TRACE( "%s not found\n", debugstr_w(filename) ); TRACE( "%s not found\n", debugstr_w(filename) );
FindClose( (HANDLE)info ); FindClose( (HANDLE)info );
SetLastError( ERROR_FILE_NOT_FOUND ); SetLastError( ERROR_FILE_NOT_FOUND );
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
} }
if (!strpbrkW( info->mask.Buffer, wildcardsW )) else if (!strpbrkW( info->mask.Buffer, wildcardsW ))
{ {
/* we can't find two files with the same name */ /* we can't find two files with the same name */
CloseHandle( info->handle ); CloseHandle( info->handle );
......
...@@ -1186,7 +1186,7 @@ static char get_windows_drive(void) ...@@ -1186,7 +1186,7 @@ static char get_windows_drive(void)
static void test_FindFirstFileA(void) static void test_FindFirstFileA(void)
{ {
HANDLE handle; HANDLE handle;
WIN32_FIND_DATAA search_results; WIN32_FIND_DATAA data;
int err; int err;
char buffer[5] = "C:\\"; char buffer[5] = "C:\\";
char buffer2[100]; char buffer2[100];
...@@ -1195,7 +1195,7 @@ static void test_FindFirstFileA(void) ...@@ -1195,7 +1195,7 @@ static void test_FindFirstFileA(void)
buffer[0] = get_windows_drive(); buffer[0] = get_windows_drive();
SetLastError( 0xdeadbeaf ); SetLastError( 0xdeadbeaf );
handle = FindFirstFileA(buffer, &search_results); handle = FindFirstFileA(buffer, &data);
err = GetLastError(); err = GetLastError();
ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on root directory should fail\n" ); ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on root directory should fail\n" );
ok ( err == ERROR_FILE_NOT_FOUND, "Bad Error number %d\n", err ); ok ( err == ERROR_FILE_NOT_FOUND, "Bad Error number %d\n", err );
...@@ -1203,7 +1203,7 @@ static void test_FindFirstFileA(void) ...@@ -1203,7 +1203,7 @@ static void test_FindFirstFileA(void)
/* try FindFirstFileA on "C:\*" */ /* try FindFirstFileA on "C:\*" */
strcpy(buffer2, buffer); strcpy(buffer2, buffer);
strcat(buffer2, "*"); strcat(buffer2, "*");
handle = FindFirstFileA(buffer2, &search_results); handle = FindFirstFileA(buffer2, &data);
ok ( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s should succeed\n", buffer2 ); ok ( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s should succeed\n", buffer2 );
ok ( FindClose(handle) == TRUE, "Failed to close handle %s\n", buffer2 ); ok ( FindClose(handle) == TRUE, "Failed to close handle %s\n", buffer2 );
...@@ -1211,7 +1211,7 @@ static void test_FindFirstFileA(void) ...@@ -1211,7 +1211,7 @@ static void test_FindFirstFileA(void)
SetLastError( 0xdeadbeaf ); SetLastError( 0xdeadbeaf );
strcpy(buffer2, buffer); strcpy(buffer2, buffer);
strcat(buffer2, "foo\\"); strcat(buffer2, "foo\\");
handle = FindFirstFileA(buffer2, &search_results); handle = FindFirstFileA(buffer2, &data);
err = GetLastError(); err = GetLastError();
ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 ); ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
todo_wine { todo_wine {
...@@ -1222,33 +1222,94 @@ static void test_FindFirstFileA(void) ...@@ -1222,33 +1222,94 @@ static void test_FindFirstFileA(void)
SetLastError( 0xdeadbeaf ); SetLastError( 0xdeadbeaf );
strcpy(buffer2, buffer); strcpy(buffer2, buffer);
strcat(buffer2, "foo\\bar.txt"); strcat(buffer2, "foo\\bar.txt");
handle = FindFirstFileA(buffer2, &search_results); handle = FindFirstFileA(buffer2, &data);
err = GetLastError(); err = GetLastError();
ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 ); ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
todo_wine { ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
}
/* try FindFirstFileA on "C:\foo\*.*" */ /* try FindFirstFileA on "C:\foo\*.*" */
SetLastError( 0xdeadbeaf ); SetLastError( 0xdeadbeaf );
strcpy(buffer2, buffer); strcpy(buffer2, buffer);
strcat(buffer2, "foo\\*.*"); strcat(buffer2, "foo\\*.*");
handle = FindFirstFileA(buffer2, &search_results); handle = FindFirstFileA(buffer2, &data);
err = GetLastError(); err = GetLastError();
ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 ); ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
todo_wine { ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
}
/* try FindFirstFileA on "foo\bar.txt" */ /* try FindFirstFileA on "foo\bar.txt" */
SetLastError( 0xdeadbeaf ); SetLastError( 0xdeadbeaf );
strcpy(buffer2, "foo\\bar.txt"); strcpy(buffer2, "foo\\bar.txt");
handle = FindFirstFileA(buffer2, &search_results); handle = FindFirstFileA(buffer2, &data);
err = GetLastError(); err = GetLastError();
ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 ); ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
todo_wine { ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
} /* try FindFirstFileA on "c:\nul" */
SetLastError( 0xdeadbeaf );
strcpy(buffer2, buffer);
strcat(buffer2, "nul");
handle = FindFirstFileA(buffer2, &data);
err = GetLastError();
ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed\n", buffer2 );
ok( 0 == lstrcmpiA(data.cFileName, "nul"), "wrong name %s\n", data.cFileName );
ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh );
ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow );
ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes, "wrong attributes %x\n", data.dwFileAttributes );
SetLastError( 0xdeadbeaf );
ok( !FindNextFileA( handle, &data ), "FindNextFileA succeeded\n" );
ok( GetLastError() == ERROR_NO_MORE_FILES, "bad error %d\n", GetLastError() );
ok( FindClose( handle ), "failed to close handle\n" );
/* try FindFirstFileA on "lpt1" */
SetLastError( 0xdeadbeaf );
strcpy(buffer2, "lpt1");
handle = FindFirstFileA(buffer2, &data);
err = GetLastError();
ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed\n", buffer2 );
ok( 0 == lstrcmpiA(data.cFileName, "lpt1"), "wrong name %s\n", data.cFileName );
ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh );
ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow );
ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes, "wrong attributes %x\n", data.dwFileAttributes );
SetLastError( 0xdeadbeaf );
ok( !FindNextFileA( handle, &data ), "FindNextFileA succeeded\n" );
ok( GetLastError() == ERROR_NO_MORE_FILES, "bad error %d\n", GetLastError() );
ok( FindClose( handle ), "failed to close handle\n" );
/* try FindFirstFileA on "c:\nul\*" */
SetLastError( 0xdeadbeaf );
strcpy(buffer2, buffer);
strcat(buffer2, "nul\\*");
handle = FindFirstFileA(buffer2, &data);
err = GetLastError();
ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
/* try FindFirstFileA on "c:\nul*" */
SetLastError( 0xdeadbeaf );
strcpy(buffer2, buffer);
strcat(buffer2, "nul*");
handle = FindFirstFileA(buffer2, &data);
err = GetLastError();
ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
ok ( err == ERROR_FILE_NOT_FOUND, "Bad Error number %d\n", err );
/* try FindFirstFileA on "c:\foo\bar\nul" */
SetLastError( 0xdeadbeaf );
strcpy(buffer2, buffer);
strcat(buffer2, "foo\\bar\\nul");
handle = FindFirstFileA(buffer2, &data);
err = GetLastError();
ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
/* try FindFirstFileA on "c:\foo\nul\bar" */
SetLastError( 0xdeadbeaf );
strcpy(buffer2, buffer);
strcat(buffer2, "foo\\nul\\bar");
handle = FindFirstFileA(buffer2, &data);
err = GetLastError();
ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
} }
static void test_FindNextFileA(void) static void test_FindNextFileA(void)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment