sync with trunk r46493
[reactos.git] / dll / win32 / kernel32 / file / cnotify.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/file/find.c
6 * PURPOSE: Find functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
8 * UPDATE HISTORY:
9 * Created 01/11/98
10 */
11
12 #include <k32.h>
13 #include <wine/debug.h>
14
15 WINE_DEFAULT_DEBUG_CHANNEL(kernel32file);
16
17 /*
18 * @implemented
19 */
20 BOOL WINAPI
21 FindCloseChangeNotification (HANDLE hChangeHandle)
22 {
23 NTSTATUS Status = NtClose(hChangeHandle);
24 if(!NT_SUCCESS(Status))
25 {
26 SetLastErrorByStatus(Status);
27 return FALSE;
28 }
29
30 return TRUE;
31 }
32
33
34 /*
35 * @implemented
36 */
37 HANDLE
38 WINAPI
39 FindFirstChangeNotificationA (
40 LPCSTR lpPathName,
41 BOOL bWatchSubtree,
42 DWORD dwNotifyFilter
43 )
44 {
45 PWCHAR PathNameW;
46
47 if (!(PathNameW = FilenameA2W(lpPathName, FALSE)))
48 return INVALID_HANDLE_VALUE;
49
50 return FindFirstChangeNotificationW (PathNameW ,
51 bWatchSubtree,
52 dwNotifyFilter);
53 }
54
55
56 /*
57 * @implemented
58 */
59 HANDLE
60 WINAPI
61 FindFirstChangeNotificationW (
62 LPCWSTR lpPathName,
63 BOOL bWatchSubtree,
64 DWORD dwNotifyFilter
65 )
66 {
67 NTSTATUS Status;
68 UNICODE_STRING NtPathU;
69 IO_STATUS_BLOCK IoStatus;
70 OBJECT_ATTRIBUTES ObjectAttributes;
71 HANDLE hDir;
72
73 if (!RtlDosPathNameToNtPathName_U (lpPathName,
74 &NtPathU,
75 NULL,
76 NULL))
77 {
78 SetLastErrorByStatus(STATUS_OBJECT_PATH_SYNTAX_BAD);
79 return INVALID_HANDLE_VALUE;
80 }
81
82
83
84 InitializeObjectAttributes (&ObjectAttributes,
85 &NtPathU,
86 OBJ_CASE_INSENSITIVE,
87 NULL,
88 NULL);
89
90 Status = NtOpenFile (&hDir,
91 SYNCHRONIZE|FILE_LIST_DIRECTORY,
92 &ObjectAttributes,
93 &IoStatus,
94 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
95 FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT);
96
97 RtlFreeHeap(RtlGetProcessHeap(),
98 0,
99 NtPathU.Buffer);
100
101
102
103 if (!NT_SUCCESS(Status))
104 {
105 SetLastErrorByStatus(Status);
106 return INVALID_HANDLE_VALUE;
107 }
108
109 Status = NtNotifyChangeDirectoryFile(hDir,
110 NULL,
111 NULL,
112 NULL,
113 &IoStatus,
114 NULL,//Buffer,
115 0,//BufferLength,
116 dwNotifyFilter,
117 (BOOLEAN)bWatchSubtree);
118 if (!NT_SUCCESS(Status))
119 {
120 NtClose(hDir);
121 SetLastErrorByStatus(Status);
122 return INVALID_HANDLE_VALUE;
123 }
124
125 return hDir;
126 }
127
128
129 /*
130 * @implemented
131 */
132 BOOL
133 WINAPI
134 FindNextChangeNotification (
135 HANDLE hChangeHandle
136 )
137 {
138 IO_STATUS_BLOCK IoStatus;
139 NTSTATUS Status;
140
141 Status = NtNotifyChangeDirectoryFile(hChangeHandle,
142 NULL,
143 NULL,
144 NULL,
145 &IoStatus,
146 NULL,//Buffer,
147 0,//BufferLength,
148 FILE_NOTIFY_CHANGE_SECURITY,//meaningless/ignored for subsequent calls, but must contain a valid flag
149 0 //meaningless/ignored for subsequent calls
150 );
151
152 if (!NT_SUCCESS(Status))
153 {
154 SetLastErrorByStatus(Status);
155 return FALSE;
156 }
157
158 return TRUE;
159 }
160
161
162 extern VOID
163 (WINAPI ApcRoutine)(PVOID ApcContext,
164 struct _IO_STATUS_BLOCK* IoStatusBlock,
165 ULONG Reserved);
166
167
168 /*
169 * @implemented
170 */
171 BOOL
172 WINAPI
173 ReadDirectoryChangesW(
174 HANDLE hDirectory,
175 LPVOID lpBuffer OPTIONAL,
176 DWORD nBufferLength,
177 BOOL bWatchSubtree,
178 DWORD dwNotifyFilter,
179 LPDWORD lpBytesReturned, /* undefined for asych. operations */
180 LPOVERLAPPED lpOverlapped OPTIONAL,
181 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine /* OPTIONAL???????? */
182 )
183 {
184 PVOID CompletionRoutine;
185 NTSTATUS Status;
186 IO_STATUS_BLOCK IoStatus;
187 HANDLE EventHandle;
188 PIO_APC_ROUTINE IoApcRoutine;
189
190 if (lpOverlapped )
191 {
192 if (lpCompletionRoutine)
193 {
194 CompletionRoutine = (PVOID) lpCompletionRoutine;
195 EventHandle = NULL;
196 IoApcRoutine = ApcRoutine;
197 }
198 else
199 {
200 if (((ULONG_PTR) lpOverlapped->hEvent & 1) == 0)
201 CompletionRoutine = (PVOID) lpOverlapped;
202 else
203 CompletionRoutine = NULL;
204
205 EventHandle = lpOverlapped->hEvent;
206 IoApcRoutine = NULL;
207 }
208
209 lpOverlapped->Internal = STATUS_PENDING;
210 }
211 else
212 {
213 EventHandle = NULL;
214 IoApcRoutine = NULL;
215 CompletionRoutine = NULL;
216 }
217
218 Status = NtNotifyChangeDirectoryFile(
219 hDirectory,
220 EventHandle,
221 IoApcRoutine,
222 CompletionRoutine, /* ApcContext */
223 lpOverlapped ? (PIO_STATUS_BLOCK)lpOverlapped->Internal : &IoStatus,
224 lpBuffer,
225 nBufferLength,
226 dwNotifyFilter,
227 (BOOLEAN)bWatchSubtree
228 );
229
230 if ((Status == STATUS_PENDING) && (!lpOverlapped))
231 {
232 Status = NtWaitForSingleObject(hDirectory, FALSE, NULL);
233
234 if (NT_SUCCESS(Status))
235 {
236 Status = IoStatus.Status;
237 }
238 }
239
240 if (!NT_SUCCESS(Status))
241 {
242 SetLastErrorByStatus(Status);
243 return FALSE;
244 }
245
246
247 /* NOTE: lpBytesReturned is undefined for asynch. operations */
248 *lpBytesReturned = IoStatus.Information;
249
250 return TRUE;
251 }
252
253
254
255
256
257 /* EOF */