Make FindFirstFileExW and FindFirstChangeNotificationW use NtOpenFile

directly so that they can take advantage of the FILE_DIRECTORY_FILE
option.
This commit is contained in:
Alexandre Julliard 2004-04-17 00:26:54 +00:00
parent 2a6e89ca64
commit a9832be1a7
2 changed files with 60 additions and 38 deletions

View File

@ -27,6 +27,7 @@
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "winerror.h" #include "winerror.h"
#include "ntstatus.h"
#include "wine/windef16.h" #include "wine/windef16.h"
#include "wine/server.h" #include "wine/server.h"
#include "wine/debug.h" #include "wine/debug.h"
@ -39,23 +40,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(file);
HANDLE WINAPI FindFirstChangeNotificationA( LPCSTR lpPathName, BOOL bWatchSubtree, HANDLE WINAPI FindFirstChangeNotificationA( LPCSTR lpPathName, BOOL bWatchSubtree,
DWORD dwNotifyFilter ) DWORD dwNotifyFilter )
{ {
HANDLE file, ret = INVALID_HANDLE_VALUE; UNICODE_STRING pathW;
HANDLE ret = INVALID_HANDLE_VALUE;
TRACE( "%s %d %lx\n", debugstr_a(lpPathName), bWatchSubtree, dwNotifyFilter ); if (RtlCreateUnicodeStringFromAsciiz( &pathW, lpPathName ))
if ((file = CreateFileA( lpPathName, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 )) == INVALID_HANDLE_VALUE)
return INVALID_HANDLE_VALUE;
SERVER_START_REQ( create_change_notification )
{ {
req->handle = file; ret = FindFirstChangeNotificationW( pathW.Buffer, bWatchSubtree, dwNotifyFilter );
req->subtree = bWatchSubtree; RtlFreeUnicodeString( &pathW );
req->filter = dwNotifyFilter;
if (!wine_server_call_err( req )) ret = reply->handle;
} }
SERVER_END_REQ; else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
CloseHandle( file );
return ret; return ret;
} }
@ -65,13 +58,36 @@ HANDLE WINAPI FindFirstChangeNotificationA( LPCSTR lpPathName, BOOL bWatchSubtre
HANDLE WINAPI FindFirstChangeNotificationW( LPCWSTR lpPathName, BOOL bWatchSubtree, HANDLE WINAPI FindFirstChangeNotificationW( LPCWSTR lpPathName, BOOL bWatchSubtree,
DWORD dwNotifyFilter) DWORD dwNotifyFilter)
{ {
UNICODE_STRING nt_name;
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
NTSTATUS status;
HANDLE file, ret = INVALID_HANDLE_VALUE; HANDLE file, ret = INVALID_HANDLE_VALUE;
TRACE( "%s %d %lx\n", debugstr_w(lpPathName), bWatchSubtree, dwNotifyFilter ); TRACE( "%s %d %lx\n", debugstr_w(lpPathName), bWatchSubtree, dwNotifyFilter );
if ((file = CreateFileW( lpPathName, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, if (!RtlDosPathNameToNtPathName_U( lpPathName, &nt_name, NULL, NULL ))
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 )) == INVALID_HANDLE_VALUE) {
SetLastError( ERROR_PATH_NOT_FOUND );
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
}
attr.Length = sizeof(attr);
attr.RootDirectory = 0;
attr.Attributes = OBJ_CASE_INSENSITIVE;
attr.ObjectName = &nt_name;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
status = NtOpenFile( &file, 0, &attr, &io, 0,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT );
RtlFreeUnicodeString( &nt_name );
if (status != STATUS_SUCCESS)
{
SetLastError( RtlNtStatusToDosError(status) );
return INVALID_HANDLE_VALUE;
}
SERVER_START_REQ( create_change_notification ) SERVER_START_REQ( create_change_notification )
{ {

View File

@ -626,10 +626,12 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
LPVOID data, FINDEX_SEARCH_OPS search_op, LPVOID data, FINDEX_SEARCH_OPS search_op,
LPVOID filter, DWORD flags) LPVOID filter, DWORD flags)
{ {
WCHAR buffer[MAX_PATH]; WCHAR *mask, *p;
WCHAR *mask, *tmp = buffer;
FIND_FIRST_INFO *info = NULL; FIND_FIRST_INFO *info = NULL;
DWORD size; UNICODE_STRING nt_name;
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
NTSTATUS status;
if ((search_op != FindExSearchNameMatch) || (flags != 0)) if ((search_op != FindExSearchNameMatch) || (flags != 0))
{ {
@ -641,22 +643,12 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
FIXME("info level %d not implemented\n", level ); FIXME("info level %d not implemented\n", level );
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
} }
size = RtlGetFullPathName_U( filename, sizeof(buffer), buffer, &mask );
if (!size) if (!RtlDosPathNameToNtPathName_U( filename, &nt_name, &mask, NULL ))
{ {
SetLastError( ERROR_PATH_NOT_FOUND ); SetLastError( ERROR_PATH_NOT_FOUND );
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
} }
if (size > sizeof(buffer))
{
tmp = HeapAlloc( GetProcessHeap(), 0, size );
if (!tmp)
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return INVALID_HANDLE_VALUE;
}
size = RtlGetFullPathName_U( filename, size, tmp, &mask );
}
if (!mask || !*mask) if (!mask || !*mask)
{ {
@ -675,29 +667,43 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
SetLastError( ERROR_NOT_ENOUGH_MEMORY ); SetLastError( ERROR_NOT_ENOUGH_MEMORY );
goto error; goto error;
} }
/* truncate dir name before mask */
*mask = 0; *mask = 0;
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;
if (tmp[0] && tmp[1] == ':') p = nt_name.Buffer + 4; /* skip \??\ prefix */
if (p[0] && p[1] == ':')
{ {
WCHAR *p = tmp + 2; p += 2;
while (*p == '\\') p++; while (*p == '\\') p++;
info->is_root = (*p == 0); info->is_root = (*p == 0);
} }
info->handle = CreateFileW( tmp, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, attr.Length = sizeof(attr);
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 ); attr.RootDirectory = 0;
if (info->handle == INVALID_HANDLE_VALUE) attr.Attributes = OBJ_CASE_INSENSITIVE;
attr.ObjectName = &nt_name;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
status = NtOpenFile( &info->handle, GENERIC_READ, &attr, &io,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT );
if (status != STATUS_SUCCESS)
{ {
RtlFreeUnicodeString( &info->mask ); RtlFreeUnicodeString( &info->mask );
SetLastError( RtlNtStatusToDosError(status) );
goto error; goto error;
} }
RtlFreeUnicodeString( &nt_name );
RtlInitializeCriticalSection( &info->cs ); RtlInitializeCriticalSection( &info->cs );
info->data_pos = 0; info->data_pos = 0;
info->data_len = 0; info->data_len = 0;
if (tmp != buffer) HeapFree( GetProcessHeap(), 0, tmp );
if (!FindNextFileW( (HANDLE)info, data )) if (!FindNextFileW( (HANDLE)info, data ))
{ {
@ -709,8 +715,8 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
return (HANDLE)info; return (HANDLE)info;
error: error:
if (tmp != buffer) HeapFree( GetProcessHeap(), 0, tmp );
if (info) HeapFree( GetProcessHeap(), 0, info ); if (info) HeapFree( GetProcessHeap(), 0, info );
RtlFreeUnicodeString( &nt_name );
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
} }