mshtml: COM cleanup for the IOleInPlaceObjectWindowless iface.
[wine] / dlls / ntdll / tests / 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 <ntstatus.h>
22 #define WIN32_NO_STATUS
23 #include <windows.h>
24 #include <winnt.h>
25 #include <winternl.h>
26 #include <winerror.h>
27 #include <stdio.h>
28 #include "wine/test.h"
29
30 static NTSTATUS (WINAPI *pNtNotifyChangeDirectoryFile)(
31                           HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,
32                           PIO_STATUS_BLOCK,PVOID,ULONG,ULONG,BOOLEAN);
33
34 static NTSTATUS (WINAPI *pNtCancelIoFile)(HANDLE,PIO_STATUS_BLOCK);
35
36
37 static void test_ntncdf(void)
38 {
39     NTSTATUS r;
40     HANDLE hdir, hEvent;
41     char buffer[0x1000];
42     DWORD fflags, filter = 0;
43     IO_STATUS_BLOCK iosb;
44     WCHAR path[MAX_PATH], subdir[MAX_PATH];
45     static const WCHAR szBoo[] = { '\\','b','o','o',0 };
46     static const WCHAR szHoo[] = { '\\','h','o','o',0 };
47     PFILE_NOTIFY_INFORMATION pfni;
48
49     r = GetTempPathW( MAX_PATH, path );
50     ok( r != 0, "temp path failed\n");
51     if (!r)
52         return;
53
54     lstrcatW( path, szBoo );
55     lstrcpyW( subdir, path );
56     lstrcatW( subdir, szHoo );
57
58     RemoveDirectoryW( subdir );
59     RemoveDirectoryW( path );
60     
61     r = CreateDirectoryW(path, NULL);
62     ok( r == TRUE, "failed to create directory\n");
63
64     r = pNtNotifyChangeDirectoryFile(NULL,NULL,NULL,NULL,NULL,NULL,0,0,0);
65     ok(r==STATUS_ACCESS_VIOLATION, "should return access violation\n");
66
67     fflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED;
68     hdir = CreateFileW(path, GENERIC_READ|SYNCHRONIZE, FILE_SHARE_READ, NULL, 
69                         OPEN_EXISTING, fflags, NULL);
70     ok( hdir != INVALID_HANDLE_VALUE, "failed to open directory\n");
71
72     hEvent = CreateEvent( NULL, 0, 0, NULL );
73
74     r = pNtNotifyChangeDirectoryFile(hdir,NULL,NULL,NULL,&iosb,NULL,0,0,0);
75     ok(r==STATUS_INVALID_PARAMETER, "should return invalid parameter\n");
76
77     r = pNtNotifyChangeDirectoryFile(hdir,hEvent,NULL,NULL,&iosb,NULL,0,0,0);
78     ok(r==STATUS_INVALID_PARAMETER, "should return invalid parameter\n");
79
80     filter = FILE_NOTIFY_CHANGE_FILE_NAME;
81     filter |= FILE_NOTIFY_CHANGE_DIR_NAME;
82     filter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
83     filter |= FILE_NOTIFY_CHANGE_SIZE;
84     filter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
85     filter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
86     filter |= FILE_NOTIFY_CHANGE_CREATION;
87     filter |= FILE_NOTIFY_CHANGE_SECURITY;
88
89     U(iosb).Status = 1;
90     iosb.Information = 1;
91     r = pNtNotifyChangeDirectoryFile(hdir,hEvent,NULL,NULL,&iosb,buffer,sizeof buffer,-1,0);
92     ok(r==STATUS_INVALID_PARAMETER, "should return invalid parameter\n");
93
94     ok( U(iosb).Status == 1, "information wrong\n");
95     ok( iosb.Information == 1, "information wrong\n");
96
97     U(iosb).Status = 1;
98     iosb.Information = 0;
99     r = pNtNotifyChangeDirectoryFile(hdir,hEvent,NULL,NULL,&iosb,buffer,sizeof buffer,filter,0);
100     ok(r==STATUS_PENDING, "should return status pending\n");
101
102     r = WaitForSingleObject( hEvent, 0 );
103     ok( r == STATUS_TIMEOUT, "should timeout\n" );
104
105     r = WaitForSingleObject( hdir, 0 );
106     ok( r == STATUS_TIMEOUT, "should timeout\n" );
107
108     r = CreateDirectoryW( subdir, NULL );
109     ok( r == TRUE, "failed to create directory\n");
110
111     r = WaitForSingleObject( hdir, 0 );
112     ok( r == STATUS_TIMEOUT, "should timeout\n" );
113
114     r = WaitForSingleObject( hEvent, 0 );
115     ok( r == WAIT_OBJECT_0, "event should be ready\n" );
116
117     ok( U(iosb).Status == STATUS_SUCCESS, "information wrong\n");
118     ok( iosb.Information == 0x12, "information wrong\n");
119
120     pfni = (PFILE_NOTIFY_INFORMATION) buffer;
121     ok( pfni->NextEntryOffset == 0, "offset wrong\n" );
122     ok( pfni->Action == FILE_ACTION_ADDED, "action wrong\n" );
123     ok( pfni->FileNameLength == 6, "len wrong\n" );
124     ok( !memcmp(pfni->FileName,&szHoo[1],6), "name wrong\n" );
125
126     r = pNtNotifyChangeDirectoryFile(hdir,0,NULL,NULL,&iosb,buffer,sizeof buffer,0,0);
127     ok(r==STATUS_INVALID_PARAMETER, "should return invalid parameter\n");
128
129     r = pNtNotifyChangeDirectoryFile(hdir,hEvent,NULL,NULL,&iosb,buffer,sizeof buffer,0,0);
130     ok(r==STATUS_INVALID_PARAMETER, "should return invalid parameter\n");
131
132     filter = FILE_NOTIFY_CHANGE_SIZE;
133
134     U(iosb).Status = 1;
135     iosb.Information = 1;
136     r = pNtNotifyChangeDirectoryFile(hdir,0,NULL,NULL,&iosb,NULL,0,filter,0);
137     ok(r==STATUS_PENDING, "should status pending\n");
138
139     ok( U(iosb).Status == 1, "information wrong\n");
140     ok( iosb.Information == 1, "information wrong\n");
141
142     r = WaitForSingleObject( hdir, 0 );
143     ok( r == STATUS_TIMEOUT, "should timeout\n" );
144
145     r = RemoveDirectoryW( subdir );
146     ok( r == TRUE, "failed to remove directory\n");
147
148     r = WaitForSingleObject( hdir, 100 );
149     ok( r == WAIT_OBJECT_0, "should be ready\n" );
150
151     r = WaitForSingleObject( hdir, 100 );
152     ok( r == WAIT_OBJECT_0, "should be ready\n" );
153
154     ok( U(iosb).Status == STATUS_NOTIFY_ENUM_DIR, "information wrong\n");
155     ok( iosb.Information == 0, "information wrong\n");
156
157     CloseHandle(hdir);
158     CloseHandle(hEvent);
159
160     r = RemoveDirectoryW( path );
161     ok( r == TRUE, "failed to remove directory\n");
162 }
163
164
165 static void test_ntncdf_async(void)
166 {
167     NTSTATUS r;
168     HANDLE hdir, hEvent;
169     char buffer[0x1000];
170     DWORD fflags, filter = 0;
171     IO_STATUS_BLOCK iosb, iosb2;
172     WCHAR path[MAX_PATH], subdir[MAX_PATH];
173     static const WCHAR szBoo[] = { '\\','b','o','o',0 };
174     static const WCHAR szHoo[] = { '\\','h','o','o',0 };
175     PFILE_NOTIFY_INFORMATION pfni;
176
177     r = GetTempPathW( MAX_PATH, path );
178     ok( r != 0, "temp path failed\n");
179     if (!r)
180         return;
181
182     lstrcatW( path, szBoo );
183     lstrcpyW( subdir, path );
184     lstrcatW( subdir, szHoo );
185
186     RemoveDirectoryW( subdir );
187     RemoveDirectoryW( path );
188     
189     r = CreateDirectoryW(path, NULL);
190     ok( r == TRUE, "failed to create directory\n");
191
192     r = pNtNotifyChangeDirectoryFile(NULL,NULL,NULL,NULL,NULL,NULL,0,0,0);
193     ok(r==STATUS_ACCESS_VIOLATION, "should return access violation\n");
194
195     fflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED;
196     hdir = CreateFileW(path, GENERIC_READ|SYNCHRONIZE, FILE_SHARE_READ, NULL, 
197                         OPEN_EXISTING, fflags, NULL);
198     ok( hdir != INVALID_HANDLE_VALUE, "failed to open directory\n");
199
200     hEvent = CreateEvent( NULL, 0, 0, NULL );
201
202     filter = FILE_NOTIFY_CHANGE_FILE_NAME;
203     filter |= FILE_NOTIFY_CHANGE_DIR_NAME;
204     filter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
205     filter |= FILE_NOTIFY_CHANGE_SIZE;
206     filter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
207     filter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
208     filter |= FILE_NOTIFY_CHANGE_CREATION;
209     filter |= FILE_NOTIFY_CHANGE_SECURITY;
210
211
212     U(iosb).Status   = 0x01234567;
213     iosb.Information = 0x12345678;
214     r = pNtNotifyChangeDirectoryFile(hdir,0,NULL,NULL,&iosb,buffer,sizeof buffer,filter,0);
215     ok(r==STATUS_PENDING, "should status pending\n");
216     ok(U(iosb).Status == 0x01234567, "status set too soon\n");
217     ok(iosb.Information == 0x12345678, "info set too soon\n");
218
219     r = CreateDirectoryW( subdir, NULL );
220     ok( r == TRUE, "failed to create directory\n");
221
222     r = WaitForSingleObject( hdir, 100 );
223     ok( r == WAIT_OBJECT_0, "should be ready\n" );
224
225     ok(U(iosb).Status == STATUS_SUCCESS, "status not successful\n");
226     ok(iosb.Information == 0x12, "info not set\n");
227
228     pfni = (PFILE_NOTIFY_INFORMATION) buffer;
229     ok( pfni->NextEntryOffset == 0, "offset wrong\n" );
230     ok( pfni->Action == FILE_ACTION_ADDED, "action wrong\n" );
231     ok( pfni->FileNameLength == 6, "len wrong\n" );
232     ok( !memcmp(pfni->FileName,&szHoo[1],6), "name wrong\n" );
233
234     r = pNtNotifyChangeDirectoryFile(hdir,0,NULL,NULL,&iosb,buffer,sizeof buffer,filter,0);
235     ok(r==STATUS_PENDING, "should status pending\n");
236
237     r = RemoveDirectoryW( subdir );
238     ok( r == TRUE, "failed to remove directory\n");
239
240     r = WaitForSingleObject( hdir, 0 );
241     ok( r == WAIT_OBJECT_0, "should be ready\n" );
242
243     ok(U(iosb).Status == STATUS_SUCCESS, "status not successful\n");
244     ok(iosb.Information == 0x12, "info not set\n");
245
246     ok( pfni->NextEntryOffset == 0, "offset wrong\n" );
247     ok( pfni->Action == FILE_ACTION_REMOVED, "action wrong\n" );
248     ok( pfni->FileNameLength == 6, "len wrong\n" );
249     ok( !memcmp(pfni->FileName,&szHoo[1],6), "name wrong\n" );
250
251     /* check APCs */
252     U(iosb).Status = 0;
253     iosb.Information = 0;
254
255     r = pNtNotifyChangeDirectoryFile(hdir,0,NULL,NULL,&iosb,NULL,0,filter,0);
256     ok(r==STATUS_PENDING, "should status pending\n");
257
258     r = CreateDirectoryW( subdir, NULL );
259     ok( r == TRUE, "failed to create directory\n");
260
261     r = WaitForSingleObject( hdir, 0 );
262     ok( r == WAIT_OBJECT_0, "should be ready\n" );
263
264     ok(U(iosb).Status == STATUS_NOTIFY_ENUM_DIR, "status not successful\n");
265     ok(iosb.Information == 0, "info not set\n");
266
267     U(iosb).Status = 0;
268     iosb.Information = 0;
269
270     r = pNtNotifyChangeDirectoryFile(hdir,hEvent,NULL,NULL,&iosb,buffer,sizeof buffer,filter,0);
271     ok(r==STATUS_PENDING, "should status pending\n");
272
273     r = RemoveDirectoryW( subdir );
274     ok( r == TRUE, "failed to remove directory\n");
275
276     r = WaitForSingleObject( hEvent, 0 );
277     ok( r == WAIT_OBJECT_0, "should be ready\n" );
278
279     ok(U(iosb).Status == STATUS_SUCCESS, "status not successful\n");
280     ok(iosb.Information == 0x12, "info not set\n");
281
282
283     U(iosb).Status   = 0x01234567;
284     iosb.Information = 0x12345678;
285     r = pNtNotifyChangeDirectoryFile(hdir,0,NULL,NULL,&iosb,buffer,sizeof buffer,filter,0);
286     ok(r==STATUS_PENDING, "should status pending\n");
287
288     U(iosb2).Status   = 0x01234567;
289     iosb2.Information = 0x12345678;
290     r = pNtNotifyChangeDirectoryFile(hdir,0,NULL,NULL,&iosb2,buffer,sizeof buffer,filter,0);
291     ok(r==STATUS_PENDING, "should status pending\n");
292
293     ok(U(iosb).Status == 0x01234567, "status set too soon\n");
294     ok(iosb.Information == 0x12345678, "info set too soon\n");
295
296     r = pNtCancelIoFile(hdir, &iosb);
297     ok( r == STATUS_SUCCESS, "cancel failed\n");
298
299     CloseHandle(hdir);
300
301     ok(U(iosb).Status == STATUS_SUCCESS, "status wrong\n");
302     todo_wine ok(U(iosb2).Status == STATUS_CANCELLED, "status wrong\n");
303
304     ok(iosb.Information == 0, "info wrong\n");
305     ok(iosb2.Information == 0, "info wrong\n");
306
307     r = RemoveDirectoryW( path );
308     ok( r == TRUE, "failed to remove directory\n");
309
310     CloseHandle(hEvent);
311 }
312
313 START_TEST(change)
314 {
315     HMODULE hntdll = GetModuleHandle("ntdll");
316     if (!hntdll)
317     {
318         win_skip("not running on NT, skipping test\n");
319         return;
320     }
321
322     pNtNotifyChangeDirectoryFile = (void *)GetProcAddress(hntdll, "NtNotifyChangeDirectoryFile");
323     pNtCancelIoFile = (void *)GetProcAddress(hntdll, "NtCancelIoFile");
324
325     if (!pNtNotifyChangeDirectoryFile || !pNtCancelIoFile)
326     {
327         win_skip("missing functions, skipping test\n");
328         return;
329     }
330
331     test_ntncdf();
332     test_ntncdf_async();
333 }