ReactOS  r76032
cnotify.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS system libraries
4  * FILE: dll/win32/kernel32/client/file/cnotify.c
5  * PURPOSE: Find functions
6  * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
7  * UPDATE HISTORY:
8  * Created 01/11/98
9  */
10 
11 /* INCLUDES *******************************************************************/
12 
13 #include <k32.h>
14 #define NDEBUG
15 #include <debug.h>
16 
17 /* GLOBALS ********************************************************************/
18 
21 
22 /* PRIVATE FUNCTIONS **********************************************************/
23 
24 VOID
25 WINAPI
29 {
30  PBASEP_ACTCTX_BLOCK ActivationBlock = ApcContext;
32  DWORD BytesTransfered, Result;
33  RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActCtx;
34  PVOID ActivationContext = NULL;
35 
36  /* Setup the activation frame */
37  RtlZeroMemory(&ActCtx, sizeof(ActCtx));
38  ActCtx.Size = sizeof(ActCtx);
40 
41  /* Check if the routine returned an error */
42  if (NT_ERROR(IoStatusBlock->Status))
43  {
44  /* Convert the error code and don't copy anything */
45  Result = RtlNtStatusToDosError(IoStatusBlock->Status);
46  BytesTransfered = 0;
47  }
48  else
49  {
50  /* Set success code and copy the bytes transferred */
51  Result = ERROR_SUCCESS;
52  BytesTransfered = IoStatusBlock->Information;
53  }
54 
55  /* Read context and routine out from the activation block */
56  ActivationContext = ActivationBlock->ActivationContext;
57  CompletionRoutine = ActivationBlock->CompletionRoutine;
58 
59  /* Check if the block should be freed */
60  if (!(ActivationBlock->Flags & 1))
61  {
62  /* Free it */
64  }
65 
66  /* Activate the context, call the routine, and then deactivate the context */
67  RtlActivateActivationContextUnsafeFast(&ActCtx, ActivationContext);
68  CompletionRoutine(Result, BytesTransfered, (LPOVERLAPPED)IoStatusBlock);
70 }
71 
72 VOID
73 WINAPI
77 {
79  DWORD Result, BytesTransfered;
80 
81  /* Check if the routine returned an error */
82  if (NT_ERROR(IoStatusBlock->Status))
83  {
84  /* Convert the error code and don't copy anything */
85  Result = RtlNtStatusToDosError(IoStatusBlock->Status);
86  BytesTransfered = 0;
87  }
88  else
89  {
90  /* Set success code and copy the bytes transferred */
91  Result = ERROR_SUCCESS;
92  BytesTransfered = IoStatusBlock->Information;
93  }
94 
95  /* Call the callback routine */
96  CompletionRoutine(Result, BytesTransfered, (LPOVERLAPPED)IoStatusBlock);
97 }
98 
99 /* PUBLIC FUNCTIONS ***********************************************************/
100 
101 /*
102  * @implemented
103  */
104 BOOL
105 WINAPI
107 {
108  /* Just close the handle */
109  return CloseHandle(hChangeHandle);
110 }
111 
112 /*
113  * @implemented
114  */
115 HANDLE
116 WINAPI
118  IN BOOL bWatchSubtree,
119  IN DWORD dwNotifyFilter)
120 {
121  /* Call the W(ide) function */
123  lpPathName,
124  bWatchSubtree,
125  dwNotifyFilter);
126 }
127 
128 /*
129  * @implemented
130  */
131 HANDLE
132 WINAPI
134  IN BOOL bWatchSubtree,
135  IN DWORD dwNotifyFilter)
136 {
138  UNICODE_STRING NtPathU;
140  HANDLE hDir;
141  RTL_RELATIVE_NAME_U RelativeName;
142  PWCHAR PathBuffer;
144 
145  /* Convert to NT path and get the relative name too */
146  if (!RtlDosPathNameToNtPathName_U(lpPathName,
147  &NtPathU,
148  NULL,
149  &RelativeName))
150  {
151  /* Bail out if the path name makes no sense */
153  return INVALID_HANDLE_VALUE;
154  }
155 
156  /* Save the path buffer in case we free it later */
157  PathBuffer = NtPathU.Buffer;
158 
159  /* If we have a relative name... */
160  if (RelativeName.RelativeName.Length)
161  {
162  /* Do a relative open with only the relative path set */
163  NtPathU = RelativeName.RelativeName;
164  }
165  else
166  {
167  /* Do a full path open with no containing directory */
168  RelativeName.ContainingDirectory = NULL;
169  }
170 
171  /* Now open the directory name that was passed in */
172  InitializeObjectAttributes(&ObjectAttributes,
173  &NtPathU,
175  RelativeName.ContainingDirectory,
176  NULL);
177  Status = NtOpenFile(&hDir,
179  &ObjectAttributes,
180  &IoStatusBlock,
183 
184  /* Release our buffer and relative name structure */
185  RtlReleaseRelativeName(&RelativeName);
186  RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
187 
188  /* Check if the open failed */
189  if (!NT_SUCCESS(Status))
190  {
191  /* Bail out in that case */
192  BaseSetLastNTError(Status);
193  return INVALID_HANDLE_VALUE;
194  }
195 
196  /* Now setup the notification on the directory as requested */
197  Status = NtNotifyChangeDirectoryFile(hDir,
198  NULL,
199  NULL,
200  NULL,
201  &staticIoStatusBlock,
203  sizeof(staticchangebuff),
204  dwNotifyFilter,
205  (BOOLEAN)bWatchSubtree);
206  if (!NT_SUCCESS(Status))
207  {
208  /* We failed, close the handle and convert the error */
209  NtClose(hDir);
210  BaseSetLastNTError(Status);
211  hDir = INVALID_HANDLE_VALUE;
212  }
213 
214  /* Return the directory handle on success, or invalid handle otherwise */
215  return hDir;
216 }
217 
218 /*
219  * @implemented
220  */
221 BOOL
222 WINAPI
224 {
226 
227  /* Just call the native API directly, dealing with the non-optional parameters */
228  Status = NtNotifyChangeDirectoryFile(hChangeHandle,
229  NULL,
230  NULL,
231  NULL,
232  &staticIoStatusBlock,
234  sizeof(staticchangebuff),
236  TRUE);
237  if (!NT_SUCCESS(Status))
238  {
239  /* Convert the error code and fail */
240  BaseSetLastNTError(Status);
241  return FALSE;
242  }
243 
244  /* All went well */
245  return TRUE;
246 }
247 
248 /*
249  * @implemented
250  */
251 BOOL
252 WINAPI
256  IN BOOL bWatchSubtree,
257  IN DWORD dwNotifyFilter,
259  IN LPOVERLAPPED lpOverlapped OPTIONAL,
260  IN LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
261 {
262 
267  PBASEP_ACTCTX_BLOCK ActivationContext = NULL;
268  BOOL Result = TRUE;
270 
271  /* Is the caller doing this synchronously? */
272  if (!lpOverlapped)
273  {
274  /* Great, just pass in the parameters */
275  Status = NtNotifyChangeDirectoryFile(hDirectory,
276  NULL,
277  NULL,
278  NULL,
279  &IoStatusBlock,
280  lpBuffer,
281  nBufferLength,
282  dwNotifyFilter,
283  bWatchSubtree);
284  if (Status == STATUS_PENDING)
285  {
286  /* Wait for completion since we are synchronous */
287  Status = NtWaitForSingleObject(hDirectory, FALSE, NULL);
288  if (!NT_SUCCESS(Status))
289  {
290  /* The wait failed, bail out */
291  BaseSetLastNTError(Status);
292  return FALSE;
293  }
294 
295  /* Retrieve the final status code */
296  Status = IoStatusBlock.Status;
297  }
298 
299  /* Did the operation succeed? */
300  if (NT_SUCCESS(Status))
301  {
302  /* Return the bytes transferd and success */
303  *lpBytesReturned = IoStatusBlock.Information;
304  return Result;
305  }
306 
307  /* Convert error code and return failure */
308  BaseSetLastNTError(Status);
309  return FALSE;
310  }
311 
312  /* Does the caller want an APC callback? */
313  if (lpCompletionRoutine)
314  {
315  /* Don't use an event in this case */
316  EventHandle = NULL;
317 
318  /* Allocate a Fusion/SxS activation context for the callback routine */
320  lpCompletionRoutine,
321  lpOverlapped,
322  &ActivationContext);
323  if (!NT_SUCCESS(Status))
324  {
325  /* This failed, so abandon the call */
326  BaseSetLastNTError(Status);
327  return FALSE;
328  }
329 
330  /* Use the SxS context as the APC context */
331  ApcContext = ActivationContext;
332  if (ActivationContext)
333  {
334  /* And use a special stub routine that deals with activation */
335  ApcRoutine = BasepIoCompletion;
336  }
337  else
338  {
339  /* If there was no context, however, use the simple stub routine */
340  ApcContext = lpCompletionRoutine;
341  ApcRoutine = BasepIoCompletionSimple;
342  }
343  }
344  else
345  {
346  /* Use the even with no APC routine */
347  EventHandle = lpOverlapped->hEvent;
348  ApcRoutine = 0;
349 
350  /* LPOVERLAPPED should be ignored if event is ORed with 1 */
351  ApcContext = (ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped;
352  }
353 
354  /* Set the initial status to pending and call the native API */
355  lpOverlapped->Internal = STATUS_PENDING;
356  Status = NtNotifyChangeDirectoryFile(hDirectory,
357  EventHandle,
358  ApcRoutine,
359  ApcContext,
361  lpBuffer,
362  nBufferLength,
363  dwNotifyFilter,
364  (BOOLEAN)bWatchSubtree);
365  if (NT_ERROR(Status))
366  {
367  /* Normally we cleanup the context in the completion routine, but we failed */
368  if (ActivationContext) BasepFreeActivationContextActivationBlock(ActivationContext);
369 
370  /* Convert the error and fail */
371  BaseSetLastNTError(Status);
372  return FALSE;
373  }
374 
375  /* Return success */
376  return Result;
377 }
378 
379 /* EOF */
NTSTATUS NTAPI BasepAllocateActivationContextActivationBlock(IN DWORD Flags, IN PVOID CompletionRoutine, IN PVOID CompletionContext, OUT PBASEP_ACTCTX_BLOCK *ActivationBlock)
Definition: actctx.c:45
DWORD *typedef PVOID
Definition: winlogon.h:52
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define IN
Definition: typedefs.h:38
_In_opt_ HANDLE _In_opt_ PIO_APC_ROUTINE _In_opt_ PVOID ApcContext
Definition: iofuncs.h:719
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
VOID(* PIO_APC_ROUTINE)(IN PVOID ApcContext, IN PIO_STATUS_BLOCK IoStatusBlock, IN ULONG Reserved)
Definition: nt_native.h:877
#define ERROR_SUCCESS
Definition: deptool.c:10
struct _FILE_NOTIFY_INFORMATION FILE_NOTIFY_INFORMATION
HANDLE WINAPI FindFirstChangeNotificationW(IN LPCWSTR lpPathName, IN BOOL bWatchSubtree, IN DWORD dwNotifyFilter)
Definition: cnotify.c:133
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
char CHAR
Definition: xmlstorage.h:175
ULONG NTAPI RtlNtStatusToDosError(IN NTSTATUS Status)
Definition: error.c:96
HANDLE ContainingDirectory
Definition: rtltypes.h:1260
VOID NTAPI RtlReleaseRelativeName(_In_ PRTL_RELATIVE_NAME_U RelativeName)
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:603
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
uint16_t * PWCHAR
Definition: typedefs.h:54
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
*nSize LPSTR lpBuffer
Definition: winbase.h:1973
DWORD DWORD
Definition: winlogon.h:75
#define FILE_SHARE_READ
Definition: compat.h:125
#define FALSE
Definition: types.h:117
CHAR staticchangebuff[sizeof(FILE_NOTIFY_INFORMATION)+16]
Definition: cnotify.c:19
PVOID ActivationContext
Definition: kernel32.h:100
smooth NULL
Definition: ftsmooth.c:557
#define RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER
Definition: rtltypes.h:101
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:166
const char * LPCSTR
Definition: xmlstorage.h:183
IO_STATUS_BLOCK staticIoStatusBlock
Definition: cnotify.c:20
_In_ LPCSTR _In_opt_ LPCSTR _In_ DWORD nBufferLength
Definition: winbase.h:2959
VOID WINAPI BasepIoCompletionSimple(IN PVOID ApcContext, IN PIO_STATUS_BLOCK IoStatusBlock, IN DWORD Reserved)
Definition: cnotify.c:74
NTSYSAPI NTSTATUS NTAPI NtOpenFile(OUT PHANDLE phFile, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG ShareMode, IN ULONG OpenMode)
Definition: file.c:3508
unsigned char BOOLEAN
#define FILE_LIST_DIRECTORY
Definition: nt_native.h:629
unsigned int BOOL
Definition: ntddk_ex.h:94
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
#define STATUS_PENDING
Definition: ntstatus.h:82
BOOL WINAPI FindNextChangeNotification(IN HANDLE hChangeHandle)
Definition: cnotify.c:223
PRTL_ACTIVATION_CONTEXT_STACK_FRAME FASTCALL RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame)
Definition: actctx.c:5501
#define SetLastError(x)
Definition: compat.h:409
BOOL WINAPI FindCloseChangeNotification(IN HANDLE hChangeHandle)
Definition: cnotify.c:106
#define NT_ERROR(Status)
Definition: umtypes.h:94
_In_ PCWSTR _Out_ PVOID * ActCtx
Definition: ldrtypes.h:245
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3392
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
_In_opt_ HANDLE _In_opt_ PIO_APC_ROUTINE ApcRoutine
Definition: iofuncs.h:719
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
void(CALLBACK * LPOVERLAPPED_COMPLETION_ROUTINE)(DWORD, DWORD, LPOVERLAPPED)
Definition: winbase.h:1390
#define ConvertWin32AnsiChangeApiToUnicodeApi(obj, name,...)
Definition: base_x.h:76
#define SYNCHRONIZE
Definition: nt_native.h:61
VOID NTAPI BasepFreeActivationContextActivationBlock(IN PBASEP_ACTCTX_BLOCK ActivationBlock)
Definition: actctx.c:26
#define WINAPI
Definition: msvc.h:20
ULONG PVOID Reserved
Definition: ntimage.h:533
LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
Definition: kernel32.h:102
Status
Definition: gdiplustypes.h:24
DWORD *typedef HANDLE
Definition: winlogon.h:52
LONG NTSTATUS
Definition: DriverTester.h:11
_In_ HANDLE _In_ DWORD _In_ DWORD _Inout_opt_ LPOVERLAPPED lpOverlapped
Definition: mswsock.h:90
#define FILE_NOTIFY_CHANGE_SECURITY
#define FILE_OPEN_FOR_BACKUP_INTENT
Definition: from_kernel.h:42
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
_In_ DWORD _In_ DWORD _In_ DWORD _Out_ LPDWORD lpBytesReturned
Definition: winddi.h:1704
NTSTATUS NTAPI NtNotifyChangeDirectoryFile(IN HANDLE FileHandle, IN HANDLE EventHandle OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID Buffer, IN ULONG BufferSize, IN ULONG CompletionFilter, IN BOOLEAN WatchTree)
Definition: iofunc.c:1467
PRTL_ACTIVATION_CONTEXT_STACK_FRAME FASTCALL RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame, IN PVOID Context)
Definition: actctx.c:5424
#define OUT
Definition: typedefs.h:39
uint32_t * LPDWORD
Definition: typedefs.h:57
_In_ PIRP _In_opt_ PVOID _In_opt_ POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine
Definition: fsrtlfuncs.h:673
BOOL WINAPI ReadDirectoryChangesW(IN HANDLE hDirectory, IN LPVOID lpBuffer OPTIONAL, IN DWORD nBufferLength, IN BOOL bWatchSubtree, IN DWORD dwNotifyFilter, OUT LPDWORD lpBytesReturned, IN LPOVERLAPPED lpOverlapped OPTIONAL, IN LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
Definition: cnotify.c:253
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define ULONG_PTR
Definition: config.h:101
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
UNICODE_STRING RelativeName
Definition: rtltypes.h:1259
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
IN HDEVINFO IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
Definition: devinst.c:44
VOID WINAPI BasepIoCompletion(IN PVOID ApcContext, IN PIO_STATUS_BLOCK IoStatusBlock, IN DWORD Reserved)
Definition: cnotify.c:26
#define FindFirstChangeNotification
Definition: winbase.h:3543
NTSYSAPI BOOLEAN NTAPI RtlDosPathNameToNtPathName_U(_In_opt_z_ PCWSTR DosPathName, _Out_ PUNICODE_STRING NtPathName, _Out_opt_ PCWSTR *NtFileNamePart, _Out_opt_ PRTL_RELATIVE_NAME_U DirectoryInfo)
HANDLE WINAPI FindFirstChangeNotificationA(IN LPCSTR lpPathName, IN BOOL bWatchSubtree, IN DWORD dwNotifyFilter)
Definition: cnotify.c:117
_Out_ PHANDLE EventHandle
Definition: iofuncs.h:855
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)