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