[NTDLL_WINETEST] Add a PCH.
[reactos.git] / modules / rostests / winetests / ntdll / change.c
1 /*
2 * File change notification tests
3 *
4 * Copyright 2006 Mike McCormack for CodeWeavers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "ntdll_test.h"
22
23 static NTSTATUS (WINAPI *pNtNotifyChangeDirectoryFile)(
24 HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,
25 PIO_STATUS_BLOCK,PVOID,ULONG,ULONG,BOOLEAN);
26
27 static NTSTATUS (WINAPI *pNtCancelIoFile)(HANDLE,PIO_STATUS_BLOCK);
28
29
30 static void test_ntncdf(void)
31 {
32 NTSTATUS r;
33 HANDLE hdir, hEvent;
34 char buffer[0x1000];
35 DWORD fflags, filter = 0;
36 IO_STATUS_BLOCK iosb;
37 WCHAR path[MAX_PATH], subdir[MAX_PATH];
38 static const WCHAR szBoo[] = { '\\','b','o','o',0 };
39 static const WCHAR szHoo[] = { '\\','h','o','o',0 };
40 PFILE_NOTIFY_INFORMATION pfni;
41
42 r = GetTempPathW( MAX_PATH, path );
43 ok( r != 0, "temp path failed\n");
44 if (!r)
45 return;
46
47 lstrcatW( path, szBoo );
48 lstrcpyW( subdir, path );
49 lstrcatW( subdir, szHoo );
50
51 RemoveDirectoryW( subdir );
52 RemoveDirectoryW( path );
53
54 r = CreateDirectoryW(path, NULL);
55 ok( r == TRUE, "failed to create directory\n");
56
57 r = pNtNotifyChangeDirectoryFile(NULL,NULL,NULL,NULL,NULL,NULL,0,0,0);
58 ok(r==STATUS_ACCESS_VIOLATION, "should return access violation\n");
59
60 fflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED;
61 hdir = CreateFileW(path, GENERIC_READ|SYNCHRONIZE, FILE_SHARE_READ, NULL,
62 OPEN_EXISTING, fflags, NULL);
63 ok( hdir != INVALID_HANDLE_VALUE, "failed to open directory\n");
64
65 hEvent = CreateEventA( NULL, 0, 0, NULL );
66
67 r = pNtNotifyChangeDirectoryFile(hdir,NULL,NULL,NULL,&iosb,NULL,0,0,0);
68 ok(r==STATUS_INVALID_PARAMETER, "should return invalid parameter\n");
69
70 r = pNtNotifyChangeDirectoryFile(hdir,hEvent,NULL,NULL,&iosb,NULL,0,0,0);
71 ok(r==STATUS_INVALID_PARAMETER, "should return invalid parameter\n");
72
73 filter = FILE_NOTIFY_CHANGE_FILE_NAME;
74 filter |= FILE_NOTIFY_CHANGE_DIR_NAME;
75 filter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
76 filter |= FILE_NOTIFY_CHANGE_SIZE;
77 filter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
78 filter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
79 filter |= FILE_NOTIFY_CHANGE_CREATION;
80 filter |= FILE_NOTIFY_CHANGE_SECURITY;
81
82 U(iosb).Status = 1;
83 iosb.Information = 1;
84 r = pNtNotifyChangeDirectoryFile(hdir,hEvent,NULL,NULL,&iosb,buffer,sizeof buffer,-1,0);
85 ok(r==STATUS_INVALID_PARAMETER, "should return invalid parameter\n");
86
87 ok( U(iosb).Status == 1, "information wrong\n");
88 ok( iosb.Information == 1, "information wrong\n");
89
90 U(iosb).Status = 1;
91 iosb.Information = 0;
92 r = pNtNotifyChangeDirectoryFile(hdir,hEvent,NULL,NULL,&iosb,buffer,sizeof buffer,filter,0);
93 ok(r==STATUS_PENDING, "should return status pending\n");
94
95 r = WaitForSingleObject( hEvent, 100 );
96 ok( r == STATUS_TIMEOUT, "should timeout\n" );
97
98 r = WaitForSingleObject( hdir, 100 );
99 ok( r == STATUS_TIMEOUT, "should timeout\n" );
100
101 r = CreateDirectoryW( subdir, NULL );
102 ok( r == TRUE, "failed to create directory\n");
103
104 r = WaitForSingleObject( hdir, 100 );
105 ok( r == STATUS_TIMEOUT, "should timeout\n" );
106
107 r = WaitForSingleObject( hEvent, 100 );
108 ok( r == WAIT_OBJECT_0, "event should be ready\n" );
109
110 ok( U(iosb).Status == STATUS_SUCCESS, "information wrong\n");
111 ok( iosb.Information == 0x12, "information wrong\n");
112
113 pfni = (PFILE_NOTIFY_INFORMATION) buffer;
114 ok( pfni->NextEntryOffset == 0, "offset wrong\n" );
115 ok( pfni->Action == FILE_ACTION_ADDED, "action wrong\n" );
116 ok( pfni->FileNameLength == 6, "len wrong\n" );
117 ok( !memcmp(pfni->FileName,&szHoo[1],6), "name wrong\n" );
118
119 r = pNtNotifyChangeDirectoryFile(hdir,0,NULL,NULL,&iosb,buffer,sizeof buffer,0,0);
120 ok(r==STATUS_INVALID_PARAMETER, "should return invalid parameter\n");
121
122 r = pNtNotifyChangeDirectoryFile(hdir,hEvent,NULL,NULL,&iosb,buffer,sizeof buffer,0,0);
123 ok(r==STATUS_INVALID_PARAMETER, "should return invalid parameter\n");
124
125 filter = FILE_NOTIFY_CHANGE_SIZE;
126
127 U(iosb).Status = 1;
128 iosb.Information = 1;
129 r = pNtNotifyChangeDirectoryFile(hdir,0,NULL,NULL,&iosb,NULL,0,filter,0);
130 ok(r==STATUS_PENDING, "should status pending\n");
131
132 ok( U(iosb).Status == 1, "information wrong\n");
133 ok( iosb.Information == 1, "information wrong\n");
134
135 r = WaitForSingleObject( hdir, 0 );
136 ok( r == STATUS_TIMEOUT, "should timeout\n" );
137
138 r = RemoveDirectoryW( subdir );
139 ok( r == TRUE, "failed to remove directory\n");
140
141 r = WaitForSingleObject( hdir, 100 );
142 ok( r == WAIT_OBJECT_0, "should be ready\n" );
143
144 r = WaitForSingleObject( hdir, 100 );
145 ok( r == WAIT_OBJECT_0, "should be ready\n" );
146
147 ok( U(iosb).Status == STATUS_NOTIFY_ENUM_DIR, "information wrong\n");
148 ok( iosb.Information == 0, "information wrong\n");
149
150 CloseHandle(hdir);
151 CloseHandle(hEvent);
152
153 r = RemoveDirectoryW( path );
154 ok( r == TRUE, "failed to remove directory\n");
155 }
156
157
158 static void test_ntncdf_async(void)
159 {
160 NTSTATUS r;
161 HANDLE hdir, hEvent;
162 char buffer[0x1000];
163 DWORD fflags, filter = 0;
164 IO_STATUS_BLOCK iosb, iosb2;
165 WCHAR path[MAX_PATH], subdir[MAX_PATH];
166 static const WCHAR szBoo[] = { '\\','b','o','o',0 };
167 static const WCHAR szHoo[] = { '\\','h','o','o',0 };
168 PFILE_NOTIFY_INFORMATION pfni;
169
170 r = GetTempPathW( MAX_PATH, path );
171 ok( r != 0, "temp path failed\n");
172 if (!r)
173 return;
174
175 lstrcatW( path, szBoo );
176 lstrcpyW( subdir, path );
177 lstrcatW( subdir, szHoo );
178
179 RemoveDirectoryW( subdir );
180 RemoveDirectoryW( path );
181
182 r = CreateDirectoryW(path, NULL);
183 ok( r == TRUE, "failed to create directory\n");
184
185 r = pNtNotifyChangeDirectoryFile(NULL,NULL,NULL,NULL,NULL,NULL,0,0,0);
186 ok(r==STATUS_ACCESS_VIOLATION, "should return access violation\n");
187
188 fflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED;
189 hdir = CreateFileW(path, GENERIC_READ|SYNCHRONIZE, FILE_SHARE_READ, NULL,
190 OPEN_EXISTING, fflags, NULL);
191 ok( hdir != INVALID_HANDLE_VALUE, "failed to open directory\n");
192
193 hEvent = CreateEventA( NULL, 0, 0, NULL );
194
195 filter = FILE_NOTIFY_CHANGE_FILE_NAME;
196 filter |= FILE_NOTIFY_CHANGE_DIR_NAME;
197 filter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
198 filter |= FILE_NOTIFY_CHANGE_SIZE;
199 filter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
200 filter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
201 filter |= FILE_NOTIFY_CHANGE_CREATION;
202 filter |= FILE_NOTIFY_CHANGE_SECURITY;
203
204
205 U(iosb).Status = 0x01234567;
206 iosb.Information = 0x12345678;
207 r = pNtNotifyChangeDirectoryFile(hdir,0,NULL,NULL,&iosb,buffer,sizeof buffer,filter,0);
208 ok(r==STATUS_PENDING, "should status pending\n");
209 ok(U(iosb).Status == 0x01234567, "status set too soon\n");
210 ok(iosb.Information == 0x12345678, "info set too soon\n");
211
212 r = CreateDirectoryW( subdir, NULL );
213 ok( r == TRUE, "failed to create directory\n");
214
215 r = WaitForSingleObject( hdir, 100 );
216 ok( r == WAIT_OBJECT_0, "should be ready\n" );
217
218 ok(U(iosb).Status == STATUS_SUCCESS, "status not successful\n");
219 ok(iosb.Information == 0x12, "info not set\n");
220
221 pfni = (PFILE_NOTIFY_INFORMATION) buffer;
222 ok( pfni->NextEntryOffset == 0, "offset wrong\n" );
223 ok( pfni->Action == FILE_ACTION_ADDED, "action wrong\n" );
224 ok( pfni->FileNameLength == 6, "len wrong\n" );
225 ok( !memcmp(pfni->FileName,&szHoo[1],6), "name wrong\n" );
226
227 r = pNtNotifyChangeDirectoryFile(hdir,0,NULL,NULL,&iosb,buffer,sizeof buffer,filter,0);
228 ok(r==STATUS_PENDING, "should status pending\n");
229
230 r = RemoveDirectoryW( subdir );
231 ok( r == TRUE, "failed to remove directory\n");
232
233 r = WaitForSingleObject( hdir, 0 );
234 ok( r == WAIT_OBJECT_0, "should be ready\n" );
235
236 ok(U(iosb).Status == STATUS_SUCCESS, "status not successful\n");
237 ok(iosb.Information == 0x12, "info not set\n");
238
239 ok( pfni->NextEntryOffset == 0, "offset wrong\n" );
240 ok( pfni->Action == FILE_ACTION_REMOVED, "action wrong\n" );
241 ok( pfni->FileNameLength == 6, "len wrong\n" );
242 ok( !memcmp(pfni->FileName,&szHoo[1],6), "name wrong\n" );
243
244 /* check APCs */
245 U(iosb).Status = 0;
246 iosb.Information = 0;
247
248 r = pNtNotifyChangeDirectoryFile(hdir,0,NULL,NULL,&iosb,NULL,0,filter,0);
249 ok(r==STATUS_PENDING, "should status pending\n");
250
251 r = CreateDirectoryW( subdir, NULL );
252 ok( r == TRUE, "failed to create directory\n");
253
254 r = WaitForSingleObject( hdir, 0 );
255 ok( r == WAIT_OBJECT_0, "should be ready\n" );
256
257 ok(U(iosb).Status == STATUS_NOTIFY_ENUM_DIR, "status not successful\n");
258 ok(iosb.Information == 0, "info not set\n");
259
260 U(iosb).Status = 0;
261 iosb.Information = 0;
262
263 r = pNtNotifyChangeDirectoryFile(hdir,hEvent,NULL,NULL,&iosb,buffer,sizeof buffer,filter,0);
264 ok(r==STATUS_PENDING, "should status pending\n");
265
266 r = RemoveDirectoryW( subdir );
267 ok( r == TRUE, "failed to remove directory\n");
268
269 r = WaitForSingleObject( hEvent, 0 );
270 ok( r == WAIT_OBJECT_0, "should be ready\n" );
271
272 ok(U(iosb).Status == STATUS_SUCCESS, "status not successful\n");
273 ok(iosb.Information == 0x12, "info not set\n");
274
275
276 U(iosb).Status = 0x01234567;
277 iosb.Information = 0x12345678;
278 r = pNtNotifyChangeDirectoryFile(hdir,0,NULL,NULL,&iosb,buffer,sizeof buffer,filter,0);
279 ok(r==STATUS_PENDING, "should status pending\n");
280
281 U(iosb2).Status = 0x01234567;
282 iosb2.Information = 0x12345678;
283 r = pNtNotifyChangeDirectoryFile(hdir,0,NULL,NULL,&iosb2,buffer,sizeof buffer,filter,0);
284 ok(r==STATUS_PENDING, "should status pending\n");
285
286 ok(U(iosb).Status == 0x01234567, "status set too soon\n");
287 ok(iosb.Information == 0x12345678, "info set too soon\n");
288
289 r = pNtCancelIoFile(hdir, &iosb);
290 ok( r == STATUS_SUCCESS, "cancel failed\n");
291
292 CloseHandle(hdir);
293
294 ok(U(iosb).Status == STATUS_SUCCESS, "status wrong\n");
295 ok(U(iosb2).Status == STATUS_CANCELLED, "status wrong %x\n",U(iosb2).Status);
296
297 ok(iosb.Information == 0, "info wrong\n");
298 ok(iosb2.Information == 0, "info wrong\n");
299
300 r = RemoveDirectoryW( path );
301 ok( r == TRUE, "failed to remove directory\n");
302
303 CloseHandle(hEvent);
304 }
305
306 START_TEST(change)
307 {
308 HMODULE hntdll = GetModuleHandleA("ntdll");
309 if (!hntdll)
310 {
311 win_skip("not running on NT, skipping test\n");
312 return;
313 }
314
315 pNtNotifyChangeDirectoryFile = (void *)GetProcAddress(hntdll, "NtNotifyChangeDirectoryFile");
316 pNtCancelIoFile = (void *)GetProcAddress(hntdll, "NtCancelIoFile");
317
318 if (!pNtNotifyChangeDirectoryFile || !pNtCancelIoFile)
319 {
320 win_skip("missing functions, skipping test\n");
321 return;
322 }
323
324 test_ntncdf();
325 test_ntncdf_async();
326 }