Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencnotify.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
1.7.6.1
|