ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

cnotify.c
Go to the documentation of this file.
00001 /* $Id: cnotify.c 55801 2012-02-21 23:27:45Z ion $
00002  *
00003  * COPYRIGHT:       See COPYING in the top level directory
00004  * PROJECT:         ReactOS system libraries
00005  * FILE:            lib/kernel32/file/find.c
00006  * PURPOSE:         Find functions
00007  * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
00008  * UPDATE HISTORY:
00009  *                  Created 01/11/98
00010  */
00011 
00012 /* INCLUDES *******************************************************************/
00013 
00014 #include <k32.h>
00015 #define NDEBUG
00016 #include <debug.h>
00017 
00018 /* GLOBALS ********************************************************************/
00019 
00020 CHAR staticchangebuff[sizeof(FILE_NOTIFY_INFORMATION) + 16];
00021 IO_STATUS_BLOCK staticIoStatusBlock;
00022 
00023 /* PRIVATE FUNCTIONS **********************************************************/
00024 
00025 VOID
00026 WINAPI
00027 BasepIoCompletion(IN PVOID ApcContext,
00028                   IN PIO_STATUS_BLOCK IoStatusBlock,
00029                   IN DWORD Reserved)
00030 {
00031     PBASEP_ACTCTX_BLOCK ActivationBlock = ApcContext;
00032     LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine;
00033     DWORD BytesTransfered, Result;
00034     RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActCtx;
00035     PVOID ActivationContext = NULL;
00036 
00037     /* Setup the activation frame */
00038     RtlZeroMemory(&ActCtx, sizeof(ActCtx));
00039     ActCtx.Size = sizeof(ActCtx);
00040     ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER;
00041 
00042     /* Check if the routine returned an error */
00043     if (NT_ERROR(IoStatusBlock->Status))
00044     {
00045         /* Convert the error code and don't copy anything */
00046         Result = RtlNtStatusToDosError(IoStatusBlock->Status);
00047         BytesTransfered = 0;
00048     }
00049     else
00050     {
00051         /* Set success code and copy the bytes transferred */
00052         Result = ERROR_SUCCESS;
00053         BytesTransfered = IoStatusBlock->Information;
00054     }
00055 
00056     /* Read context and routine out from the activation block */
00057     ActivationContext = ActivationBlock->ActivationContext;
00058     CompletionRoutine = ActivationBlock->CompletionRoutine;
00059 
00060     /* Check if the block should be freed */
00061     if (!(ActivationBlock->Flags & 1))
00062     {
00063         /* Free it */
00064         BasepFreeActivationContextActivationBlock(ActivationBlock);
00065     }
00066 
00067     /* Activate the context, call the routine, and then deactivate the context */
00068     RtlActivateActivationContextUnsafeFast(&ActCtx, ActivationContext);
00069     CompletionRoutine(Result, BytesTransfered, (LPOVERLAPPED)IoStatusBlock);
00070     RtlDeactivateActivationContextUnsafeFast(&ActCtx);
00071 }
00072 
00073 VOID
00074 WINAPI
00075 BasepIoCompletionSimple(IN PVOID ApcContext,
00076                         IN PIO_STATUS_BLOCK IoStatusBlock,
00077                         IN DWORD Reserved)
00078 {
00079     LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine = ApcContext;
00080     DWORD Result, BytesTransfered;
00081 
00082     /* Check if the routine returned an error */
00083     if (NT_ERROR(IoStatusBlock->Status))
00084     {
00085         /* Convert the error code and don't copy anything */
00086         Result = RtlNtStatusToDosError(IoStatusBlock->Status);
00087         BytesTransfered = 0;
00088     }
00089     else
00090     {
00091         /* Set success code and copy the bytes transferred */
00092         Result = ERROR_SUCCESS;
00093         BytesTransfered = IoStatusBlock->Information;
00094     }
00095 
00096     /* Call the callback routine */
00097     CompletionRoutine(Result, BytesTransfered, (LPOVERLAPPED)IoStatusBlock);
00098 }
00099 
00100 /* PUBLIC FUNCTIONS ***********************************************************/
00101 
00102 /*
00103  * @implemented
00104  */
00105 BOOL
00106 WINAPI
00107 FindCloseChangeNotification(IN HANDLE hChangeHandle)
00108 {
00109     /* Just close the handle */
00110     return CloseHandle(hChangeHandle);
00111 }
00112 
00113 /*
00114  * @implemented
00115  */
00116 HANDLE
00117 WINAPI
00118 FindFirstChangeNotificationA(IN LPCSTR lpPathName,
00119                              IN BOOL bWatchSubtree,
00120                              IN DWORD dwNotifyFilter)
00121 {
00122     /* Call the W(ide) function */
00123     ConvertWin32AnsiChangeApiToUnicodeApi(FindFirstChangeNotification,
00124                                           lpPathName,
00125                                           bWatchSubtree,
00126                                           dwNotifyFilter);
00127 }
00128 
00129 /*
00130  * @implemented
00131  */
00132 HANDLE
00133 WINAPI
00134 FindFirstChangeNotificationW(IN LPCWSTR lpPathName,
00135                              IN BOOL bWatchSubtree,
00136                              IN DWORD dwNotifyFilter)
00137 {
00138     NTSTATUS Status;
00139     UNICODE_STRING NtPathU;
00140     OBJECT_ATTRIBUTES ObjectAttributes;
00141     HANDLE hDir;
00142     RTL_RELATIVE_NAME_U RelativeName;
00143     PWCHAR PathBuffer;
00144     IO_STATUS_BLOCK IoStatusBlock;
00145 
00146     /* Convert to NT path and get the relative name too */
00147     if (!RtlDosPathNameToNtPathName_U(lpPathName,
00148                                       &NtPathU,
00149                                       NULL,
00150                                       &RelativeName))
00151     {
00152         /* Bail out if the path name makes no sense */
00153         SetLastError(ERROR_PATH_NOT_FOUND);
00154         return INVALID_HANDLE_VALUE;
00155     }
00156 
00157     /* Save the path buffer in case we free it later */
00158     PathBuffer = NtPathU.Buffer;
00159 
00160     /* If we have a relative name... */
00161     if (RelativeName.RelativeName.Length)
00162     {
00163         /* Do a relative open with only the relative path set */
00164         NtPathU = RelativeName.RelativeName;
00165     }
00166     else
00167     {
00168         /* Do a full path open with no containing directory */
00169         RelativeName.ContainingDirectory = NULL;
00170     }
00171 
00172     /* Now open the directory name that was passed in */
00173     InitializeObjectAttributes(&ObjectAttributes,
00174                                &NtPathU,
00175                                OBJ_CASE_INSENSITIVE,
00176                                RelativeName.ContainingDirectory,
00177                                NULL);
00178     Status = NtOpenFile(&hDir,
00179                         SYNCHRONIZE | FILE_LIST_DIRECTORY,
00180                         &ObjectAttributes,
00181                         &IoStatusBlock,
00182                         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
00183                         FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT);
00184 
00185     /* Release our buffer and relative name structure */
00186     RtlReleaseRelativeName(&RelativeName);
00187     RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
00188 
00189     /* Check if the open failed */
00190     if (!NT_SUCCESS(Status))
00191     {
00192         /* Bail out in that case */
00193         BaseSetLastNTError(Status);
00194         return INVALID_HANDLE_VALUE;
00195     }
00196 
00197     /* Now setup the notification on the directory as requested */
00198     Status = NtNotifyChangeDirectoryFile(hDir,
00199                                          NULL,
00200                                          NULL,
00201                                          NULL,
00202                                          &staticIoStatusBlock,
00203                                          staticchangebuff,
00204                                          sizeof(staticchangebuff),
00205                                          dwNotifyFilter,
00206                                          (BOOLEAN)bWatchSubtree);
00207     if (!NT_SUCCESS(Status))
00208     {
00209         /* We failed, close the handle and convert the error */
00210         NtClose(hDir);
00211         BaseSetLastNTError(Status);
00212         hDir = INVALID_HANDLE_VALUE;
00213     }
00214 
00215     /* Return the directory handle on success, or invalid handle otherwise */
00216     return hDir;
00217 }
00218 
00219 /*
00220  * @implemented
00221  */
00222 BOOL
00223 WINAPI
00224 FindNextChangeNotification(IN HANDLE hChangeHandle)
00225 {
00226     NTSTATUS Status;
00227 
00228     /* Just call the native API directly, dealing with the non-optional parameters */
00229     Status = NtNotifyChangeDirectoryFile(hChangeHandle,
00230                                          NULL,
00231                                          NULL,
00232                                          NULL,
00233                                          &staticIoStatusBlock,
00234                                          staticchangebuff,
00235                                          sizeof(staticchangebuff),
00236                                          FILE_NOTIFY_CHANGE_SECURITY,
00237                                          TRUE);
00238     if (!NT_SUCCESS(Status))
00239     {
00240         /* Convert the error code and fail */
00241         BaseSetLastNTError(Status);
00242         return FALSE;
00243     }
00244 
00245     /* All went well */
00246     return TRUE;
00247 }
00248 
00249 /*
00250  * @implemented
00251  */
00252 BOOL
00253 WINAPI
00254 ReadDirectoryChangesW(IN HANDLE hDirectory,
00255                       IN LPVOID lpBuffer OPTIONAL,
00256                       IN DWORD nBufferLength,
00257                       IN BOOL bWatchSubtree,
00258                       IN DWORD dwNotifyFilter,
00259                       OUT LPDWORD lpBytesReturned,
00260                       IN LPOVERLAPPED lpOverlapped OPTIONAL,
00261                       IN LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
00262 {
00263 
00264     NTSTATUS Status;
00265     HANDLE EventHandle;
00266     PVOID ApcContext;
00267     PIO_APC_ROUTINE ApcRoutine;
00268     PBASEP_ACTCTX_BLOCK ActivationContext = NULL;
00269     BOOL Result = TRUE;
00270     IO_STATUS_BLOCK IoStatusBlock;
00271 
00272     /* Is the caller doing this synchronously? */
00273     if (!lpOverlapped)
00274     {
00275         /* Great, just pass in the parameters */
00276         Status = NtNotifyChangeDirectoryFile(hDirectory,
00277                                              NULL,
00278                                              NULL,
00279                                              NULL,
00280                                              &IoStatusBlock,
00281                                              lpBuffer,
00282                                              nBufferLength,
00283                                              dwNotifyFilter,
00284                                              bWatchSubtree);
00285         if (Status == STATUS_PENDING)
00286         {
00287             /* Wait for completion since we are synchronous */
00288             Status = NtWaitForSingleObject(hDirectory, FALSE, NULL);
00289             if (!NT_SUCCESS(Status))
00290             {
00291                 /* The wait failed, bail out */
00292                 BaseSetLastNTError(Status);
00293                 return FALSE;
00294             }
00295             
00296             /* Retrieve the final status code */
00297             Status = IoStatusBlock.Status;
00298         }
00299 
00300         /* Did the operation succeed? */
00301         if (NT_SUCCESS(Status))
00302         {
00303             /* Return the bytes transferd and success */
00304             *lpBytesReturned = IoStatusBlock.Information;
00305             return Result;
00306         }
00307 
00308         /* Convert error code and return failure */
00309         BaseSetLastNTError(Status);
00310         return FALSE;
00311     }
00312 
00313     /* Does the caller want an APC callbac? */
00314     if (lpCompletionRoutine)
00315     {
00316         /* Don't use an event in this case */
00317         EventHandle = NULL;
00318 
00319         /* Allocate a Fusion/SxS activation context for the callback routine */
00320         Status = BasepAllocateActivationContextActivationBlock(1 | 2,
00321                                                                lpCompletionRoutine,
00322                                                                lpOverlapped,
00323                                                                &ActivationContext);
00324         if (!NT_SUCCESS(Status))
00325         {
00326             /* This failed, so abandon the call */
00327             BaseSetLastNTError(Status);
00328             return FALSE;
00329         }
00330 
00331         /* Use the SxS context as the APC context */
00332         ApcContext = ActivationContext;
00333         if (ActivationContext)
00334         {
00335             /* And use a special stub routine that deals with activation */
00336             ApcRoutine = BasepIoCompletion;
00337         }
00338         else
00339         {
00340             /* If there was no context, however, use the simple stub routine */
00341             ApcContext = lpCompletionRoutine;
00342             ApcRoutine = BasepIoCompletionSimple;
00343         }
00344     }
00345     else
00346     {
00347         /* Use the even with no APC routine */
00348         EventHandle = lpOverlapped->hEvent;
00349         ApcRoutine = 0;
00350 
00351         /* LPOVERLAPPED should be ignored if event is ORed with 1 */
00352         ApcContext = (ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped;
00353     }
00354 
00355     /* Set the initial status to pending and call the native API */
00356     lpOverlapped->Internal = STATUS_PENDING;
00357     Status = NtNotifyChangeDirectoryFile(hDirectory,
00358                                          EventHandle,
00359                                          ApcRoutine,
00360                                          ApcContext,
00361                                          (PIO_STATUS_BLOCK)lpOverlapped,
00362                                          lpBuffer,
00363                                          nBufferLength,
00364                                          dwNotifyFilter,
00365                                          (BOOLEAN)bWatchSubtree);
00366     if (NT_ERROR(Status))
00367     {
00368         /* Normally we cleanup the context in the completon routine, but we failed */
00369         if (ActivationContext) BasepFreeActivationContextActivationBlock(ActivationContext);
00370 
00371         /* Convert the error and fail */
00372         BaseSetLastNTError(Status);
00373         return FALSE;
00374     }
00375 
00376     /* Return success */
00377     return Result;
00378 }
00379 
00380 /* EOF */

Generated on Sun May 27 2012 04:24:25 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.