Make FindFirstFileExW and FindFirstChangeNotificationW use NtOpenFile
directly so that they can take advantage of the FILE_DIRECTORY_FILE option.
This commit is contained in:
parent
2a6e89ca64
commit
a9832be1a7
|
@ -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 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue