Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfiltrctx.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/fsrtl/filtrctx.c 00005 * PURPOSE: File Stream Filter Context support for File System Drivers 00006 * PROGRAMMERS: Pierre Schweitzer (pierre.schweitzer@reactos.org) 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 00011 #include <ntoskrnl.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* PRIVATE FUNCTIONS *********************************************************/ 00016 00017 typedef struct _FILE_OBJECT_FILTER_CONTEXTS 00018 { 00019 FAST_MUTEX FilterContextsMutex; 00020 LIST_ENTRY FilterContexts; 00021 } FILE_OBJECT_FILTER_CONTEXTS, *PFILE_OBJECT_FILTER_CONTEXTS; 00022 00023 /* 00024 * @implemented 00025 */ 00026 VOID 00027 NTAPI 00028 FsRtlPTeardownPerFileObjectContexts(IN PFILE_OBJECT FileObject) 00029 { 00030 PFILE_OBJECT_FILTER_CONTEXTS FOContext = NULL; 00031 00032 ASSERT(FileObject); 00033 00034 if (!(FOContext = IoGetFileObjectFilterContext(FileObject))) 00035 { 00036 return; 00037 } 00038 00039 ASSERT(IoChangeFileObjectFilterContext(FileObject, FOContext, FALSE) == STATUS_SUCCESS); 00040 ASSERT(IsListEmpty(&(FOContext->FilterContexts))); 00041 00042 ExFreePoolWithTag(FOContext, 'FOCX'); 00043 } 00044 00045 00046 /* PUBLIC FUNCTIONS **********************************************************/ 00047 00048 /*++ 00049 * @name FsRtlIsPagingFile 00050 * @implemented NT 5.2 00051 * 00052 * The FsRtlIsPagingFile routine checks if the FileObject is a Paging File. 00053 * 00054 * @param FileObject 00055 * A pointer to the File Object to be tested. 00056 * 00057 * @return TRUE if the File is a Paging File, FALSE otherwise. 00058 * 00059 * @remarks None. 00060 * 00061 *--*/ 00062 LOGICAL 00063 NTAPI 00064 FsRtlIsPagingFile(IN PFILE_OBJECT FileObject) 00065 { 00066 return MmIsFileObjectAPagingFile(FileObject); 00067 } 00068 00069 /* 00070 * @implemented 00071 */ 00072 PFSRTL_PER_FILEOBJECT_CONTEXT 00073 NTAPI 00074 FsRtlLookupPerFileObjectContext(IN PFILE_OBJECT FileObject, 00075 IN PVOID OwnerId OPTIONAL, 00076 IN PVOID InstanceId OPTIONAL) 00077 { 00078 PLIST_ENTRY NextEntry; 00079 PFILE_OBJECT_FILTER_CONTEXTS FOContext = NULL; 00080 PFSRTL_PER_FILEOBJECT_CONTEXT TmpPerFOContext, PerFOContext = NULL; 00081 00082 if (!FileObject || !(FOContext = IoGetFileObjectFilterContext(FileObject))) 00083 { 00084 return NULL; 00085 } 00086 00087 ExAcquireFastMutex(&(FOContext->FilterContextsMutex)); 00088 00089 /* If list is empty, no need to browse it */ 00090 if (!IsListEmpty(&(FOContext->FilterContexts))) 00091 { 00092 for (NextEntry = FOContext->FilterContexts.Flink; 00093 NextEntry != &(FOContext->FilterContexts); 00094 NextEntry = NextEntry->Flink) 00095 { 00096 /* If we don't have any criteria for search, first entry will be enough */ 00097 if (!OwnerId && !InstanceId) 00098 { 00099 PerFOContext = (PFSRTL_PER_FILEOBJECT_CONTEXT)NextEntry; 00100 break; 00101 } 00102 /* Else, we've to find something that matches with the parameters. */ 00103 else 00104 { 00105 TmpPerFOContext = CONTAINING_RECORD(NextEntry, FSRTL_PER_FILEOBJECT_CONTEXT, Links); 00106 if ((InstanceId && TmpPerFOContext->InstanceId == InstanceId && TmpPerFOContext->OwnerId == OwnerId) || 00107 (OwnerId && TmpPerFOContext->OwnerId == OwnerId)) 00108 { 00109 PerFOContext = TmpPerFOContext; 00110 break; 00111 } 00112 } 00113 } 00114 } 00115 00116 ExReleaseFastMutex(&(FOContext->FilterContextsMutex)); 00117 00118 return PerFOContext; 00119 } 00120 00121 /* 00122 * @implemented 00123 */ 00124 PFSRTL_PER_STREAM_CONTEXT 00125 NTAPI 00126 FsRtlLookupPerStreamContextInternal(IN PFSRTL_ADVANCED_FCB_HEADER AdvFcbHeader, 00127 IN PVOID OwnerId OPTIONAL, 00128 IN PVOID InstanceId OPTIONAL) 00129 { 00130 PLIST_ENTRY NextEntry; 00131 PFSRTL_PER_STREAM_CONTEXT TmpPerStreamContext, PerStreamContext = NULL; 00132 00133 ASSERT(AdvFcbHeader); 00134 ASSERT(FlagOn(AdvFcbHeader->Flags2, FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS)); 00135 00136 ExAcquireFastMutex(AdvFcbHeader->FastMutex); 00137 00138 /* If list is empty, no need to browse it */ 00139 if (!IsListEmpty(&(AdvFcbHeader->FilterContexts))) 00140 { 00141 for (NextEntry = AdvFcbHeader->FilterContexts.Flink; 00142 NextEntry != &(AdvFcbHeader->FilterContexts); 00143 NextEntry = NextEntry->Flink) 00144 { 00145 /* If we don't have any criteria for search, first entry will be enough */ 00146 if (!OwnerId && !InstanceId) 00147 { 00148 PerStreamContext = (PFSRTL_PER_STREAM_CONTEXT)NextEntry; 00149 break; 00150 } 00151 /* Else, we've to find something that matches with the parameters. */ 00152 else 00153 { 00154 TmpPerStreamContext = CONTAINING_RECORD(NextEntry, FSRTL_PER_STREAM_CONTEXT, Links); 00155 if ((InstanceId && TmpPerStreamContext->InstanceId == InstanceId && TmpPerStreamContext->OwnerId == OwnerId) || 00156 (OwnerId && TmpPerStreamContext->OwnerId == OwnerId)) 00157 { 00158 PerStreamContext = TmpPerStreamContext; 00159 break; 00160 } 00161 } 00162 } 00163 } 00164 00165 ExReleaseFastMutex(AdvFcbHeader->FastMutex); 00166 00167 return PerStreamContext; 00168 } 00169 00170 /* 00171 * @implemented 00172 */ 00173 NTSTATUS 00174 NTAPI 00175 FsRtlInsertPerFileObjectContext(IN PFILE_OBJECT FileObject, 00176 IN PFSRTL_PER_FILEOBJECT_CONTEXT Ptr) 00177 { 00178 PFILE_OBJECT_FILTER_CONTEXTS FOContext = NULL; 00179 00180 if (!FileObject) 00181 { 00182 return STATUS_INVALID_PARAMETER; 00183 } 00184 00185 if (!(FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION)) 00186 { 00187 return STATUS_INVALID_DEVICE_REQUEST; 00188 } 00189 00190 /* Get filter contexts */ 00191 FOContext = IoGetFileObjectFilterContext(FileObject); 00192 if (!FOContext) 00193 { 00194 /* If there's none, allocate new structure */ 00195 FOContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(FILE_OBJECT_FILTER_CONTEXTS), 'FOCX'); 00196 if (!FOContext) 00197 { 00198 return STATUS_INSUFFICIENT_RESOURCES; 00199 } 00200 00201 /* Initialize it */ 00202 ExInitializeFastMutex(&(FOContext->FilterContextsMutex)); 00203 InitializeListHead(&(FOContext->FilterContexts)); 00204 00205 /* Set it */ 00206 if (!IoChangeFileObjectFilterContext(FileObject, FOContext, TRUE)) 00207 { 00208 /* If it fails, it means that someone else has set it in the meanwhile */ 00209 ExFreePoolWithTag(FOContext, 'FOCX'); 00210 00211 /* So, we can get it */ 00212 FOContext = IoGetFileObjectFilterContext(FileObject); 00213 if (!FOContext) 00214 { 00215 /* If we fall down here, something went very bad. This shouldn't happen */ 00216 ASSERT(FALSE); 00217 return STATUS_UNSUCCESSFUL; 00218 } 00219 } 00220 } 00221 00222 /* Finally, insert */ 00223 ExAcquireFastMutex(&(FOContext->FilterContextsMutex)); 00224 InsertHeadList(&(FOContext->FilterContexts), &(Ptr->Links)); 00225 ExReleaseFastMutex(&(FOContext->FilterContextsMutex)); 00226 00227 return STATUS_SUCCESS; 00228 } 00229 00230 /* 00231 * @implemented 00232 */ 00233 NTSTATUS 00234 NTAPI 00235 FsRtlInsertPerStreamContext(IN PFSRTL_ADVANCED_FCB_HEADER AdvFcbHeader, 00236 IN PFSRTL_PER_STREAM_CONTEXT PerStreamContext) 00237 { 00238 if (!(AdvFcbHeader) || !(AdvFcbHeader->Flags2 & FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS)) 00239 { 00240 return STATUS_INVALID_DEVICE_REQUEST; 00241 } 00242 00243 ExAcquireFastMutex(AdvFcbHeader->FastMutex); 00244 InsertHeadList(&(AdvFcbHeader->FilterContexts), &(PerStreamContext->Links)); 00245 ExReleaseFastMutex(AdvFcbHeader->FastMutex); 00246 return STATUS_SUCCESS; 00247 } 00248 00249 /* 00250 * @implemented 00251 */ 00252 PFSRTL_PER_FILEOBJECT_CONTEXT 00253 NTAPI 00254 FsRtlRemovePerFileObjectContext(IN PFILE_OBJECT FileObject, 00255 IN PVOID OwnerId OPTIONAL, 00256 IN PVOID InstanceId OPTIONAL) 00257 { 00258 PLIST_ENTRY NextEntry; 00259 PFILE_OBJECT_FILTER_CONTEXTS FOContext = NULL; 00260 PFSRTL_PER_FILEOBJECT_CONTEXT TmpPerFOContext, PerFOContext = NULL; 00261 00262 if (!FileObject || !(FOContext = IoGetFileObjectFilterContext(FileObject))) 00263 { 00264 return NULL; 00265 } 00266 00267 ExAcquireFastMutex(&(FOContext->FilterContextsMutex)); 00268 00269 /* If list is empty, no need to browse it */ 00270 if (!IsListEmpty(&(FOContext->FilterContexts))) 00271 { 00272 for (NextEntry = FOContext->FilterContexts.Flink; 00273 NextEntry != &(FOContext->FilterContexts); 00274 NextEntry = NextEntry->Flink) 00275 { 00276 /* If we don't have any criteria for search, first entry will be enough */ 00277 if (!OwnerId && !InstanceId) 00278 { 00279 PerFOContext = (PFSRTL_PER_FILEOBJECT_CONTEXT)NextEntry; 00280 break; 00281 } 00282 /* Else, we've to find something that matches with the parameters. */ 00283 else 00284 { 00285 TmpPerFOContext = CONTAINING_RECORD(NextEntry, FSRTL_PER_FILEOBJECT_CONTEXT, Links); 00286 if ((InstanceId && TmpPerFOContext->InstanceId == InstanceId && TmpPerFOContext->OwnerId == OwnerId) || 00287 (OwnerId && TmpPerFOContext->OwnerId == OwnerId)) 00288 { 00289 PerFOContext = TmpPerFOContext; 00290 break; 00291 } 00292 } 00293 } 00294 00295 /* Finally remove entry from list */ 00296 if (PerFOContext) 00297 { 00298 RemoveEntryList(&(PerFOContext->Links)); 00299 } 00300 } 00301 00302 ExReleaseFastMutex(&(FOContext->FilterContextsMutex)); 00303 00304 return PerFOContext; 00305 } 00306 00307 /* 00308 * @implemented 00309 */ 00310 PFSRTL_PER_STREAM_CONTEXT 00311 NTAPI 00312 FsRtlRemovePerStreamContext(IN PFSRTL_ADVANCED_FCB_HEADER AdvFcbHeader, 00313 IN PVOID OwnerId OPTIONAL, 00314 IN PVOID InstanceId OPTIONAL) 00315 { 00316 PLIST_ENTRY NextEntry; 00317 PFSRTL_PER_STREAM_CONTEXT TmpPerStreamContext, PerStreamContext = NULL; 00318 00319 if (!(AdvFcbHeader) || !(AdvFcbHeader->Flags2 & FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS)) 00320 { 00321 return NULL; 00322 } 00323 00324 ExAcquireFastMutex(AdvFcbHeader->FastMutex); 00325 /* If list is empty, no need to browse it */ 00326 if (!IsListEmpty(&(AdvFcbHeader->FilterContexts))) 00327 { 00328 for (NextEntry = AdvFcbHeader->FilterContexts.Flink; 00329 NextEntry != &(AdvFcbHeader->FilterContexts); 00330 NextEntry = NextEntry->Flink) 00331 { 00332 /* If we don't have any criteria for search, first entry will be enough */ 00333 if (!OwnerId && !InstanceId) 00334 { 00335 PerStreamContext = (PFSRTL_PER_STREAM_CONTEXT)NextEntry; 00336 break; 00337 } 00338 /* Else, we've to find something that matches with the parameters. */ 00339 else 00340 { 00341 TmpPerStreamContext = CONTAINING_RECORD(NextEntry, FSRTL_PER_STREAM_CONTEXT, Links); 00342 if ((InstanceId && TmpPerStreamContext->InstanceId == InstanceId && TmpPerStreamContext->OwnerId == OwnerId) || 00343 (OwnerId && TmpPerStreamContext->OwnerId == OwnerId)) 00344 { 00345 PerStreamContext = TmpPerStreamContext; 00346 break; 00347 } 00348 } 00349 } 00350 00351 /* Finally remove entry from list */ 00352 if (PerStreamContext) 00353 { 00354 RemoveEntryList(&(PerStreamContext->Links)); 00355 } 00356 } 00357 ExReleaseFastMutex(AdvFcbHeader->FastMutex); 00358 00359 return PerStreamContext; 00360 00361 } 00362 00363 /* 00364 * @implemented 00365 */ 00366 VOID 00367 NTAPI 00368 FsRtlTeardownPerStreamContexts(IN PFSRTL_ADVANCED_FCB_HEADER AdvFcbHeader) 00369 { 00370 PLIST_ENTRY NextEntry; 00371 BOOLEAN IsMutexLocked = FALSE; 00372 PFSRTL_PER_STREAM_CONTEXT PerStreamContext; 00373 00374 _SEH2_TRY 00375 { 00376 /* Acquire mutex to deal with the list */ 00377 ExAcquireFastMutex(AdvFcbHeader->FastMutex); 00378 IsMutexLocked = TRUE; 00379 00380 /* While there are items... */ 00381 while (!IsListEmpty(&(AdvFcbHeader->FilterContexts))) 00382 { 00383 /* ...remove one */ 00384 NextEntry = RemoveHeadList(&(AdvFcbHeader->FilterContexts)); 00385 PerStreamContext = CONTAINING_RECORD(NextEntry, FSRTL_PER_STREAM_CONTEXT, Links); 00386 00387 /* Release mutex before calling callback */ 00388 ExReleaseFastMutex(AdvFcbHeader->FastMutex); 00389 IsMutexLocked = FALSE; 00390 00391 /* Call the callback */ 00392 ASSERT(PerStreamContext->FreeCallback); 00393 (*PerStreamContext->FreeCallback)(PerStreamContext); 00394 00395 /* Relock the list to continue */ 00396 ExAcquireFastMutex(AdvFcbHeader->FastMutex); 00397 IsMutexLocked = TRUE; 00398 } 00399 } 00400 _SEH2_FINALLY 00401 { 00402 /* If mutex was locked, release */ 00403 if (IsMutexLocked) 00404 { 00405 ExReleaseFastMutex(AdvFcbHeader->FastMutex); 00406 } 00407 } 00408 _SEH2_END; 00409 } Generated on Sun May 27 2012 04:37:11 for ReactOS by
1.7.6.1
|