include: Move struct WSABUF and WSAMSG to ws2def.h.
[wine.git] / dlls / kernel32 / change.c
blobab9432fac3dd1f10be876acc66ce9d42ee2e32a6
1 /*
2 * Win32 file change notification functions
4 * Copyright 1998 Ulrich Weigand
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.
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.
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
21 #include "config.h"
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <string.h>
27 #include "ntstatus.h"
28 #define WIN32_NO_STATUS
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winerror.h"
34 #include "winternl.h"
35 #include "kernel_private.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(file);
40 /****************************************************************************
41 * FindFirstChangeNotificationA (KERNEL32.@)
43 HANDLE WINAPI FindFirstChangeNotificationA( LPCSTR lpPathName, BOOL bWatchSubtree,
44 DWORD dwNotifyFilter )
46 WCHAR *pathW;
48 if (!(pathW = FILE_name_AtoW( lpPathName, FALSE ))) return INVALID_HANDLE_VALUE;
49 return FindFirstChangeNotificationW( pathW, bWatchSubtree, dwNotifyFilter );
53 * NtNotifyChangeDirectoryFile may write back to the IO_STATUS_BLOCK
54 * asynchronously. We don't care about the contents, but it can't
55 * be placed on the stack since it will go out of scope when we return.
57 static IO_STATUS_BLOCK FindFirstChange_iosb;
59 /****************************************************************************
60 * FindFirstChangeNotificationW (KERNEL32.@)
62 HANDLE WINAPI FindFirstChangeNotificationW( LPCWSTR lpPathName, BOOL bWatchSubtree,
63 DWORD dwNotifyFilter)
65 UNICODE_STRING nt_name;
66 OBJECT_ATTRIBUTES attr;
67 NTSTATUS status;
68 HANDLE handle = INVALID_HANDLE_VALUE;
70 TRACE( "%s %d %x\n", debugstr_w(lpPathName), bWatchSubtree, dwNotifyFilter );
72 if (!RtlDosPathNameToNtPathName_U( lpPathName, &nt_name, NULL, NULL ))
74 SetLastError( ERROR_PATH_NOT_FOUND );
75 return handle;
78 attr.Length = sizeof(attr);
79 attr.RootDirectory = 0;
80 attr.Attributes = OBJ_CASE_INSENSITIVE;
81 attr.ObjectName = &nt_name;
82 attr.SecurityDescriptor = NULL;
83 attr.SecurityQualityOfService = NULL;
85 status = NtOpenFile( &handle, FILE_LIST_DIRECTORY | SYNCHRONIZE,
86 &attr, &FindFirstChange_iosb,
87 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
88 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT );
89 RtlFreeUnicodeString( &nt_name );
91 if (status != STATUS_SUCCESS)
93 SetLastError( RtlNtStatusToDosError(status) );
94 return INVALID_HANDLE_VALUE;
97 status = NtNotifyChangeDirectoryFile( handle, NULL, NULL, NULL,
98 &FindFirstChange_iosb,
99 NULL, 0, dwNotifyFilter, bWatchSubtree );
100 if (status != STATUS_PENDING)
102 NtClose( handle );
103 SetLastError( RtlNtStatusToDosError(status) );
104 return INVALID_HANDLE_VALUE;
106 return handle;
109 /****************************************************************************
110 * FindNextChangeNotification (KERNEL32.@)
112 BOOL WINAPI FindNextChangeNotification( HANDLE handle )
114 NTSTATUS status;
116 TRACE("%p\n",handle);
118 status = NtNotifyChangeDirectoryFile( handle, NULL, NULL, NULL,
119 &FindFirstChange_iosb,
120 NULL, 0, FILE_NOTIFY_CHANGE_SIZE, 0 );
121 if (status != STATUS_PENDING)
123 SetLastError( RtlNtStatusToDosError(status) );
124 return FALSE;
126 return TRUE;
129 /****************************************************************************
130 * FindCloseChangeNotification (KERNEL32.@)
132 BOOL WINAPI FindCloseChangeNotification( HANDLE handle )
134 return CloseHandle( handle );
137 static void WINAPI invoke_completion(LPVOID ctx, IO_STATUS_BLOCK *ios, ULONG res)
139 LPOVERLAPPED_COMPLETION_ROUTINE completion = ctx;
140 completion(ios->u.Status, ios->Information, (LPOVERLAPPED)ios);
143 /****************************************************************************
144 * ReadDirectoryChangesW (KERNEL32.@)
146 * NOTES
148 * The filter is remember from the first run and ignored on successive runs.
150 * If there's no output buffer on the first run, it's ignored successive runs
151 * and STATUS_NOTIFY_ENUM_DIRECTORY is returned with an empty buffer.
153 * If a NULL overlapped->hEvent is passed, the directory handle is used
154 * for signalling.
156 BOOL WINAPI ReadDirectoryChangesW( HANDLE handle, LPVOID buffer, DWORD len, BOOL subtree,
157 DWORD filter, LPDWORD returned, LPOVERLAPPED overlapped,
158 LPOVERLAPPED_COMPLETION_ROUTINE completion )
160 OVERLAPPED ov, *pov;
161 IO_STATUS_BLOCK *ios;
162 NTSTATUS status;
163 BOOL ret = TRUE;
164 LPVOID cvalue = NULL;
166 TRACE("%p %p %08x %d %08x %p %p %p\n", handle, buffer, len, subtree, filter,
167 returned, overlapped, completion );
169 if (!overlapped)
171 memset( &ov, 0, sizeof ov );
172 ov.hEvent = CreateEventW( NULL, 0, 0, NULL );
173 pov = &ov;
175 else
177 pov = overlapped;
178 if(completion) cvalue = completion;
179 else if (((ULONG_PTR)overlapped->hEvent & 1) == 0) cvalue = overlapped;
182 ios = (PIO_STATUS_BLOCK) pov;
183 ios->u.Status = STATUS_PENDING;
185 status = NtNotifyChangeDirectoryFile( handle, completion && overlapped ? NULL : pov->hEvent,
186 completion && overlapped ? invoke_completion : NULL,
187 cvalue, ios, buffer, len, filter, subtree );
188 if (status == STATUS_PENDING)
190 if (overlapped)
191 return TRUE;
193 WaitForSingleObjectEx( ov.hEvent, INFINITE, TRUE );
194 CloseHandle( ov.hEvent );
195 if (returned)
196 *returned = ios->Information;
197 status = ios->u.Status;
200 if (status != STATUS_SUCCESS)
202 SetLastError( RtlNtStatusToDosError(status) );
203 ret = FALSE;
206 return ret;