kernel32: ReadDirectoryChangesW fixes.
[wine/hacks.git] / dlls / kernel / change.c
blob7c5eb92474bbf4a76f77b2c2f116ec0b9063dd1b
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 #include "windef.h"
30 #include "winbase.h"
31 #include "winerror.h"
32 #include "winternl.h"
33 #include "kernel_private.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(file);
38 /****************************************************************************
39 * FindFirstChangeNotificationA (KERNEL32.@)
41 HANDLE WINAPI FindFirstChangeNotificationA( LPCSTR lpPathName, BOOL bWatchSubtree,
42 DWORD dwNotifyFilter )
44 WCHAR *pathW;
46 if (!(pathW = FILE_name_AtoW( lpPathName, FALSE ))) return INVALID_HANDLE_VALUE;
47 return FindFirstChangeNotificationW( pathW, bWatchSubtree, dwNotifyFilter );
51 * NtNotifyChangeDirectoryFile may write back to the IO_STATUS_BLOCK
52 * asynchronously. We don't care about the contents, but it can't
53 * be placed on the stack since it will go out of scope when we return.
55 static IO_STATUS_BLOCK FindFirstChange_iosb;
57 /****************************************************************************
58 * FindFirstChangeNotificationW (KERNEL32.@)
60 HANDLE WINAPI FindFirstChangeNotificationW( LPCWSTR lpPathName, BOOL bWatchSubtree,
61 DWORD dwNotifyFilter)
63 UNICODE_STRING nt_name;
64 OBJECT_ATTRIBUTES attr;
65 NTSTATUS status;
66 HANDLE handle = INVALID_HANDLE_VALUE;
68 TRACE( "%s %d %lx\n", debugstr_w(lpPathName), bWatchSubtree, dwNotifyFilter );
70 if (!RtlDosPathNameToNtPathName_U( lpPathName, &nt_name, NULL, NULL ))
72 SetLastError( ERROR_PATH_NOT_FOUND );
73 return handle;
76 attr.Length = sizeof(attr);
77 attr.RootDirectory = 0;
78 attr.Attributes = OBJ_CASE_INSENSITIVE;
79 attr.ObjectName = &nt_name;
80 attr.SecurityDescriptor = NULL;
81 attr.SecurityQualityOfService = NULL;
83 status = NtOpenFile( &handle, FILE_LIST_DIRECTORY | SYNCHRONIZE,
84 &attr, &FindFirstChange_iosb,
85 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
86 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT );
87 RtlFreeUnicodeString( &nt_name );
89 if (status != STATUS_SUCCESS)
91 SetLastError( RtlNtStatusToDosError(status) );
92 return INVALID_HANDLE_VALUE;
95 status = NtNotifyChangeDirectoryFile( handle, NULL, NULL, NULL,
96 &FindFirstChange_iosb,
97 NULL, 0, dwNotifyFilter, bWatchSubtree );
98 if (status != STATUS_PENDING)
100 NtClose( handle );
101 SetLastError( RtlNtStatusToDosError(status) );
102 return INVALID_HANDLE_VALUE;
104 return handle;
107 /****************************************************************************
108 * FindNextChangeNotification (KERNEL32.@)
110 BOOL WINAPI FindNextChangeNotification( HANDLE handle )
112 NTSTATUS status;
114 TRACE("%p\n",handle);
116 status = NtNotifyChangeDirectoryFile( handle, NULL, NULL, NULL,
117 &FindFirstChange_iosb,
118 NULL, 0, FILE_NOTIFY_CHANGE_SIZE, 0 );
119 if (status != STATUS_PENDING)
121 SetLastError( RtlNtStatusToDosError(status) );
122 return FALSE;
124 return TRUE;
127 /****************************************************************************
128 * FindCloseChangeNotification (KERNEL32.@)
130 BOOL WINAPI FindCloseChangeNotification( HANDLE handle )
132 return CloseHandle( handle );
135 /****************************************************************************
136 * ReadDirectoryChangesW (KERNEL32.@)
138 * NOTES
140 * The filter is remember from the first run and ignored on successive runs.
142 * If there's no output buffer on the first run, it's ignored successive runs
143 * and STATUS_NOTIFY_ENUM_DIRECTORY is returned with an empty buffer.
145 * If a NULL overlapped->hEvent is passed, the directory handle is used
146 * for signalling.
148 BOOL WINAPI ReadDirectoryChangesW( HANDLE handle, LPVOID buffer, DWORD len, BOOL subtree,
149 DWORD filter, LPDWORD returned, LPOVERLAPPED overlapped,
150 LPOVERLAPPED_COMPLETION_ROUTINE completion )
152 OVERLAPPED ov, *pov;
153 IO_STATUS_BLOCK *ios;
154 NTSTATUS status;
155 BOOL ret = TRUE;
157 TRACE("%p %p %08lx %d %08lx %p %p %p\n", handle, buffer, len, subtree, filter,
158 returned, overlapped, completion );
160 if (!overlapped)
162 memset( &ov, 0, sizeof ov );
163 ov.hEvent = CreateEventW( NULL, 0, 0, NULL );
164 pov = &ov;
166 else
167 pov = overlapped;
169 ios = (PIO_STATUS_BLOCK) pov;
170 ios->Status = STATUS_PENDING;
172 status = NtNotifyChangeDirectoryFile( handle, pov->hEvent, NULL, NULL,
173 ios, buffer, len, filter, subtree );
174 if (status == STATUS_PENDING)
176 if (overlapped)
177 return TRUE;
179 WaitForSingleObjectEx( ov.hEvent, INFINITE, TRUE );
180 CloseHandle( ov.hEvent );
181 if (returned)
182 *returned = ios->Information;
183 status = ios->Status;
186 if (status != STATUS_SUCCESS)
188 SetLastError( RtlNtStatusToDosError(status) );
189 ret = FALSE;
192 return ret;