advapi32/tests: Statically link to ConvertSidToStringSidA().
[wine.git] / dlls / kernel32 / change.c
blob781ccfede9922e9e021280a3fe84afcb974f489b
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 #include "windef.h"
31 #include "winbase.h"
32 #include "winerror.h"
33 #include "winternl.h"
34 #include "kernel_private.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(file);
39 /****************************************************************************
40 * FindFirstChangeNotificationA (KERNEL32.@)
42 HANDLE WINAPI FindFirstChangeNotificationA( LPCSTR lpPathName, BOOL bWatchSubtree,
43 DWORD dwNotifyFilter )
45 WCHAR *pathW;
47 if (!(pathW = FILE_name_AtoW( lpPathName, FALSE ))) return INVALID_HANDLE_VALUE;
48 return FindFirstChangeNotificationW( pathW, bWatchSubtree, dwNotifyFilter );
52 * NtNotifyChangeDirectoryFile may write back to the IO_STATUS_BLOCK
53 * asynchronously. We don't care about the contents, but it can't
54 * be placed on the stack since it will go out of scope when we return.
56 static IO_STATUS_BLOCK FindFirstChange_iosb;
58 /****************************************************************************
59 * FindFirstChangeNotificationW (KERNEL32.@)
61 HANDLE WINAPI FindFirstChangeNotificationW( LPCWSTR lpPathName, BOOL bWatchSubtree,
62 DWORD dwNotifyFilter)
64 UNICODE_STRING nt_name;
65 OBJECT_ATTRIBUTES attr;
66 NTSTATUS status;
67 HANDLE handle = INVALID_HANDLE_VALUE;
69 TRACE( "%s %d %x\n", debugstr_w(lpPathName), bWatchSubtree, dwNotifyFilter );
71 if (!RtlDosPathNameToNtPathName_U( lpPathName, &nt_name, NULL, NULL ))
73 SetLastError( ERROR_PATH_NOT_FOUND );
74 return handle;
77 attr.Length = sizeof(attr);
78 attr.RootDirectory = 0;
79 attr.Attributes = OBJ_CASE_INSENSITIVE;
80 attr.ObjectName = &nt_name;
81 attr.SecurityDescriptor = NULL;
82 attr.SecurityQualityOfService = NULL;
84 status = NtOpenFile( &handle, FILE_LIST_DIRECTORY | SYNCHRONIZE,
85 &attr, &FindFirstChange_iosb,
86 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
87 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT );
88 RtlFreeUnicodeString( &nt_name );
90 if (status != STATUS_SUCCESS)
92 SetLastError( RtlNtStatusToDosError(status) );
93 return INVALID_HANDLE_VALUE;
96 status = NtNotifyChangeDirectoryFile( handle, NULL, NULL, NULL,
97 &FindFirstChange_iosb,
98 NULL, 0, dwNotifyFilter, bWatchSubtree );
99 if (status != STATUS_PENDING)
101 NtClose( handle );
102 SetLastError( RtlNtStatusToDosError(status) );
103 return INVALID_HANDLE_VALUE;
105 return handle;
108 /****************************************************************************
109 * FindNextChangeNotification (KERNEL32.@)
111 BOOL WINAPI FindNextChangeNotification( HANDLE handle )
113 NTSTATUS status;
115 TRACE("%p\n",handle);
117 status = NtNotifyChangeDirectoryFile( handle, NULL, NULL, NULL,
118 &FindFirstChange_iosb,
119 NULL, 0, FILE_NOTIFY_CHANGE_SIZE, 0 );
120 if (status != STATUS_PENDING)
122 SetLastError( RtlNtStatusToDosError(status) );
123 return FALSE;
125 return TRUE;
128 /****************************************************************************
129 * FindCloseChangeNotification (KERNEL32.@)
131 BOOL WINAPI FindCloseChangeNotification( HANDLE handle )
133 return CloseHandle( handle );
136 static void WINAPI invoke_completion(LPVOID ctx, IO_STATUS_BLOCK *ios, ULONG res)
138 LPOVERLAPPED_COMPLETION_ROUTINE completion = ctx;
139 completion(ios->u.Status, ios->Information, (LPOVERLAPPED)ios);
142 /****************************************************************************
143 * ReadDirectoryChangesW (KERNEL32.@)
145 * NOTES
147 * The filter is remember from the first run and ignored on successive runs.
149 * If there's no output buffer on the first run, it's ignored successive runs
150 * and STATUS_NOTIFY_ENUM_DIRECTORY is returned with an empty buffer.
152 * If a NULL overlapped->hEvent is passed, the directory handle is used
153 * for signalling.
155 BOOL WINAPI ReadDirectoryChangesW( HANDLE handle, LPVOID buffer, DWORD len, BOOL subtree,
156 DWORD filter, LPDWORD returned, LPOVERLAPPED overlapped,
157 LPOVERLAPPED_COMPLETION_ROUTINE completion )
159 OVERLAPPED ov, *pov;
160 IO_STATUS_BLOCK *ios;
161 NTSTATUS status;
162 BOOL ret = TRUE;
163 LPVOID cvalue = NULL;
165 TRACE("%p %p %08x %d %08x %p %p %p\n", handle, buffer, len, subtree, filter,
166 returned, overlapped, completion );
168 if (!overlapped)
170 memset( &ov, 0, sizeof ov );
171 ov.hEvent = CreateEventW( NULL, 0, 0, NULL );
172 pov = &ov;
174 else
176 pov = overlapped;
177 if(completion) cvalue = completion;
178 else if (((ULONG_PTR)overlapped->hEvent & 1) == 0) cvalue = overlapped;
181 ios = (PIO_STATUS_BLOCK) pov;
182 ios->u.Status = STATUS_PENDING;
184 status = NtNotifyChangeDirectoryFile( handle, completion && overlapped ? NULL : pov->hEvent,
185 completion && overlapped ? invoke_completion : NULL,
186 cvalue, ios, buffer, len, filter, subtree );
187 if (status == STATUS_PENDING)
189 if (overlapped)
190 return TRUE;
192 WaitForSingleObjectEx( ov.hEvent, INFINITE, TRUE );
193 if (returned)
194 *returned = ios->Information;
195 status = ios->u.Status;
198 if (!overlapped)
199 CloseHandle( ov.hEvent );
201 if (status != STATUS_SUCCESS)
203 SetLastError( RtlNtStatusToDosError(status) );
204 ret = FALSE;
207 return ret;