forked from EpicGamesExt/WineResources
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathntquerydirectoryfile-reset-mask.patch
More file actions
95 lines (87 loc) · 3.82 KB
/
ntquerydirectoryfile-reset-mask.patch
File metadata and controls
95 lines (87 loc) · 3.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index ee68e4dee9b6ead57333096775edd191ebc8fe22..b4c5e21e12f99f491d86b457b16c6fd6c846687a 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -228,6 +228,7 @@ struct dir_data
struct file_identity id; /* directory file identity */
struct dir_data_names *names; /* directory file names */
struct dir_data_buffer *buffer; /* head of data buffers list */
+ UNICODE_STRING mask; /* the mask used when creating the cache entry */
};
static const unsigned int dir_data_buffer_initial_size = 4096;
@@ -523,6 +524,7 @@ static void free_dir_data( struct dir_data *data )
free( buffer );
}
free( data->names );
+ if (data->mask.Buffer) free( data->mask.Buffer );
free( data );
}
@@ -2526,6 +2528,14 @@ static NTSTATUS init_cached_dir_data( struct dir_data **data_ret, int fd, const
return status;
}
+ /* if a mask was specified then copy it into the cache entry */
+ if (mask && mask->Length)
+ {
+ data->mask.Length = data->mask.MaximumLength = mask->Length;
+ if (!(data->mask.Buffer = calloc( 1, mask->Length ))) return STATUS_NO_MEMORY;
+ memcpy(data->mask.Buffer, mask->Buffer, mask->Length);
+ }
+
/* sort filenames, but not "." and ".." */
i = 0;
if (i < data->count && !strcmp( data->names[i].unix_name, "." )) i++;
@@ -2548,13 +2558,29 @@ static NTSTATUS init_cached_dir_data( struct dir_data **data_ret, int fd, const
}
+/***********************************************************************
+ * ustring_equal
+ *
+ * Simplified version of RtlEqualUnicodeString that performs only case-sensitive comparisons.
+ */
+static BOOLEAN ustring_equal( const UNICODE_STRING *a, const UNICODE_STRING *b )
+{
+ USHORT length_a = (a ? a->Length : 0);
+ USHORT length_b = (b ? b->Length : 0);
+ if (length_a != length_b) return FALSE;
+
+ if (length_a == 0 && length_b == 0) return TRUE;
+ return (!memcmp(a->Buffer, b->Buffer, a->Length));
+}
+
+
/***********************************************************************
* get_cached_dir_data
*
* Retrieve the cached directory data, or initialize it if necessary.
*/
static unsigned int get_cached_dir_data( HANDLE handle, struct dir_data **data_ret, int fd,
- const UNICODE_STRING *mask )
+ const UNICODE_STRING *mask, BOOLEAN restart_scan )
{
unsigned int i;
int entry = -1, free_entries[16];
@@ -2595,6 +2621,19 @@ static unsigned int get_cached_dir_data( HANDLE handle, struct dir_data **data_r
dir_data_cache_size = size;
}
+ /*
+ If we have an existing cache entry, but restart_scan is true and a new non-empty mask
+ was specified then we need to invalidate the existing cache entry and create a new one
+ */
+ if (dir_data_cache[entry] && restart_scan && mask &&
+ !ustring_equal(&dir_data_cache[entry]->mask, mask))
+ {
+ TRACE( "invalidating existing cache entry for handle %p, old mask: \"%s\", new mask: \"%s\"\n",
+ handle, debugstr_us(&(dir_data_cache[entry]->mask)), debugstr_us(mask));
+ free_dir_data( dir_data_cache[entry] );
+ dir_data_cache[entry] = NULL;
+ }
+
if (!dir_data_cache[entry]) status = init_cached_dir_data( &dir_data_cache[entry], fd, mask );
*data_ret = dir_data_cache[entry];
@@ -2666,7 +2705,7 @@ NTSTATUS WINAPI NtQueryDirectoryFile( HANDLE handle, HANDLE event, PIO_APC_ROUTI
cwd = open( ".", O_RDONLY );
if (fchdir( fd ) != -1)
{
- if (!(status = get_cached_dir_data( handle, &data, fd, mask )))
+ if (!(status = get_cached_dir_data( handle, &data, fd, mask, restart_scan )))
{
union file_directory_info *last_info = NULL;