1 /*++ 2 3 Copyright (c) 1989-2000 Microsoft Corporation 4 5 Module Name: 6 7 ResrcSup.c 8 9 Abstract: 10 11 This module implements the Cdfs Resource acquisition routines 12 13 14 --*/ 15 16 #include "cdprocs.h" 17 18 // 19 // The Bug check file id for this module 20 // 21 22 #define BugCheckFileId (CDFS_BUG_CHECK_RESRCSUP) 23 24 #ifdef ALLOC_PRAGMA 25 #pragma alloc_text(PAGE, CdAcquireForCache) 26 #pragma alloc_text(PAGE, CdFilterCallbackAcquireForCreateSection) 27 #pragma alloc_text(PAGE, CdAcquireResource) 28 #pragma alloc_text(PAGE, CdNoopAcquire) 29 #pragma alloc_text(PAGE, CdNoopRelease) 30 #pragma alloc_text(PAGE, CdReleaseForCreateSection) 31 #pragma alloc_text(PAGE, CdReleaseFromCache) 32 #endif 33 34 35 36 _Requires_lock_held_(_Global_critical_region_) 37 _When_(Type == AcquireExclusive && return != FALSE, _Acquires_exclusive_lock_(*Resource)) 38 _When_(Type == AcquireShared && return != FALSE, _Acquires_shared_lock_(*Resource)) 39 _When_(Type == AcquireSharedStarveExclusive && return != FALSE, _Acquires_shared_lock_(*Resource)) 40 _When_(IgnoreWait == FALSE, _Post_satisfies_(return == TRUE)) 41 BOOLEAN 42 CdAcquireResource ( 43 _In_ PIRP_CONTEXT IrpContext, 44 _Inout_ PERESOURCE Resource, 45 _In_ BOOLEAN IgnoreWait, 46 _In_ TYPE_OF_ACQUIRE Type 47 ) 48 49 /*++ 50 51 Routine Description: 52 53 This is the single routine used to acquire file system resources. It 54 looks at the IgnoreWait flag to determine whether to try to acquire the 55 resource without waiting. Returning TRUE/FALSE to indicate success or 56 failure. Otherwise it is driven by the WAIT flag in the IrpContext and 57 will raise CANT_WAIT on a failure. 58 59 Arguments: 60 61 Resource - This is the resource to try and acquire. 62 63 IgnoreWait - If TRUE then this routine will not wait to acquire the 64 resource and will return a boolean indicating whether the resource was 65 acquired. Otherwise we use the flag in the IrpContext and raise 66 if the resource is not acquired. 67 68 Type - Indicates how we should try to get the resource. 69 70 Return Value: 71 72 BOOLEAN - TRUE if the resource is acquired. FALSE if not acquired and 73 IgnoreWait is specified. Otherwise we raise CANT_WAIT. 74 75 --*/ 76 77 { 78 BOOLEAN Wait = FALSE; 79 BOOLEAN Acquired; 80 PAGED_CODE(); 81 82 // 83 // We look first at the IgnoreWait flag, next at the flag in the Irp 84 // Context to decide how to acquire this resource. 85 // 86 87 if (!IgnoreWait && FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) { 88 89 Wait = TRUE; 90 } 91 92 // 93 // Attempt to acquire the resource either shared or exclusively. 94 // 95 96 switch (Type) { 97 case AcquireExclusive: 98 99 #ifdef _MSC_VER 100 #pragma prefast( suppress:28137, "prefast believes Wait should be a constant, but this is ok for CDFS" ) 101 #endif 102 Acquired = ExAcquireResourceExclusiveLite( Resource, Wait ); 103 break; 104 105 case AcquireShared: 106 107 Acquired = ExAcquireResourceSharedLite( Resource, Wait ); 108 break; 109 110 case AcquireSharedStarveExclusive: 111 112 Acquired = ExAcquireSharedStarveExclusive( Resource, Wait ); 113 break; 114 115 default: 116 Acquired = FALSE; 117 NT_ASSERT( FALSE ); 118 } 119 120 // 121 // If not acquired and the user didn't specifiy IgnoreWait then 122 // raise CANT_WAIT. 123 // 124 125 if (!Acquired && !IgnoreWait) { 126 127 CdRaiseStatus( IrpContext, STATUS_CANT_WAIT ); 128 } 129 130 return Acquired; 131 } 132 133 134 135 _Requires_lock_held_(_Global_critical_region_) 136 _When_(return!=0, _Acquires_shared_lock_(*Fcb->Resource)) 137 BOOLEAN 138 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 139 CdAcquireForCache ( 140 _Inout_ PFCB Fcb, 141 _In_ BOOLEAN Wait 142 ) 143 144 /*++ 145 146 Routine Description: 147 148 The address of this routine is specified when creating a CacheMap for 149 a file. It is subsequently called by the Lazy Writer for synchronization. 150 151 Arguments: 152 153 Fcb - The pointer supplied as context to the cache initialization 154 routine. 155 156 Wait - TRUE if the caller is willing to block. 157 158 Return Value: 159 160 None 161 162 --*/ 163 164 { 165 PAGED_CODE(); 166 167 if (!ExAcquireResourceSharedLite( Fcb->Resource, Wait )) { 168 169 return FALSE; 170 } 171 172 NT_ASSERT(IoGetTopLevelIrp() == NULL); 173 IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); 174 175 return TRUE; 176 } 177 178 179 _Requires_lock_held_(_Global_critical_region_) 180 _Releases_lock_(*Fcb->Resource) 181 VOID 182 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 183 CdReleaseFromCache ( 184 _Inout_ PFCB Fcb 185 ) 186 187 /*++ 188 189 Routine Description: 190 191 The address of this routine is specified when creating a CacheMap for 192 a virtual file. It is subsequently called by the Lazy Writer to release 193 a resource acquired above. 194 195 Arguments: 196 197 Fcb - The pointer supplied as context to the cache initialization 198 routine. 199 200 Return Value: 201 202 None 203 204 --*/ 205 206 { 207 PAGED_CODE(); 208 209 NT_ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); 210 IoSetTopLevelIrp( NULL ); 211 212 ExReleaseResourceLite( Fcb->Resource ); 213 } 214 215 216 BOOLEAN 217 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 218 CdNoopAcquire ( 219 _In_ PVOID Fcb, 220 _In_ BOOLEAN Wait 221 ) 222 223 /*++ 224 225 Routine Description: 226 227 This routine does nothing. 228 229 Arguments: 230 231 Fcb - The Fcb/Vcb which was specified as a context parameter for this 232 routine. 233 234 Wait - TRUE if the caller is willing to block. 235 236 Return Value: 237 238 TRUE 239 240 --*/ 241 242 { 243 PAGED_CODE(); 244 245 UNREFERENCED_PARAMETER( Fcb ); 246 UNREFERENCED_PARAMETER( Wait ); 247 248 return TRUE; 249 } 250 251 252 VOID 253 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 254 CdNoopRelease ( 255 _In_ PVOID Fcb 256 ) 257 258 /*++ 259 260 Routine Description: 261 262 This routine does nothing. 263 264 Arguments: 265 266 Fcb - The Fcb/Vcb which was specified as a context parameter for this 267 routine. 268 269 Return Value: 270 271 None 272 273 --*/ 274 275 { 276 PAGED_CODE(); 277 278 UNREFERENCED_PARAMETER( Fcb ); 279 } 280 281 282 _Requires_lock_held_(_Global_critical_region_) 283 NTSTATUS 284 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 285 CdFilterCallbackAcquireForCreateSection ( 286 _In_ PFS_FILTER_CALLBACK_DATA CallbackData, 287 _Unreferenced_parameter_ PVOID *CompletionContext 288 ) 289 290 /*++ 291 292 Routine Description: 293 294 This is the callback routine for MM to use to acquire the file exclusively. 295 296 Arguments: 297 298 FS_FILTER_CALLBACK_DATA - Filter based callback data that provides the file object we 299 want to acquire. 300 301 CompletionContext - Ignored. 302 303 Return Value: 304 305 On success we return STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY. 306 307 If SyncType is SyncTypeCreateSection, we return a status that indicates there are no 308 writers to this file. 309 310 --*/ 311 312 { 313 PFILE_OBJECT FileObject; 314 315 316 PAGED_CODE(); 317 318 NT_ASSERT( CallbackData->Operation == FS_FILTER_ACQUIRE_FOR_SECTION_SYNCHRONIZATION ); 319 NT_ASSERT( CallbackData->SizeOfFsFilterCallbackData == sizeof(FS_FILTER_CALLBACK_DATA) ); 320 321 // 322 // Get the file object from the callback data. 323 // 324 325 FileObject = CallbackData->FileObject; 326 327 // 328 // Get the Fcb resource exclusively. 329 // 330 331 ExAcquireResourceExclusiveLite( &((PFCB) FileObject->FsContext)->FcbNonpaged->FcbResource, 332 TRUE ); 333 334 // 335 // Take the File resource shared. We need this later on when MM calls 336 // QueryStandardInfo to get the file size. 337 // 338 // If we don't use StarveExclusive, then we can get wedged behind an 339 // exclusive waiter who is waiting on someone else holding it shared in the 340 // read->initializecachemap path (which calls createsection) who is in turn 341 // waiting on us to finish the create section. 342 // 343 344 ExAcquireSharedStarveExclusive( ((PFCB) FileObject->FsContext)->Resource, 345 TRUE ); 346 347 // 348 // CDFS is a read-only file system, so we can always indicate no writers. 349 // We only do this for create section synchronization. For others we 350 // return the generic success STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY. 351 // 352 353 if (CallbackData->Parameters.AcquireForSectionSynchronization.SyncType == SyncTypeCreateSection) { 354 355 return STATUS_FILE_LOCKED_WITH_ONLY_READERS; 356 357 } else { 358 359 return STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY; 360 } 361 362 UNREFERENCED_PARAMETER( CompletionContext ); 363 } 364 365 366 _Function_class_(FAST_IO_RELEASE_FILE) 367 _Requires_lock_held_(_Global_critical_region_) 368 VOID 369 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 370 CdReleaseForCreateSection ( 371 _In_ PFILE_OBJECT FileObject 372 ) 373 374 /*++ 375 376 Routine Description: 377 378 This is the callback routine for MM to use to release a file acquired with 379 the AcquireForCreateSection call above. 380 381 Arguments: 382 383 FileObject - File object for a Cdfs stream. 384 385 Return Value: 386 387 None 388 389 --*/ 390 391 { 392 PAGED_CODE(); 393 394 // 395 // Release the resources. 396 // 397 398 ExReleaseResourceLite( &((PFCB) FileObject->FsContext)->FcbNonpaged->FcbResource ); 399 ExReleaseResourceLite( ((PFCB) FileObject->FsContext)->Resource); 400 } 401 402