Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfilelock.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/filelock.c 00005 * PURPOSE: File Locking implementation for File System Drivers 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 00011 #include <ntoskrnl.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* GLOBALS *******************************************************************/ 00016 00017 PAGED_LOOKASIDE_LIST FsRtlFileLockLookasideList; 00018 00019 /* Note: this aligns the two types of lock entry structs so we can access the 00020 FILE_LOCK_INFO part in common. Add elements after Shared if new stuff is needed. 00021 */ 00022 typedef union _COMBINED_LOCK_ELEMENT 00023 { 00024 struct 00025 { 00026 LIST_ENTRY dummy; 00027 FILE_SHARED_LOCK_ENTRY Shared; 00028 }; 00029 FILE_EXCLUSIVE_LOCK_ENTRY Exclusive; 00030 } 00031 COMBINED_LOCK_ELEMENT, *PCOMBINED_LOCK_ELEMENT; 00032 00033 typedef struct _LOCK_INFORMATION 00034 { 00035 RTL_GENERIC_TABLE RangeTable; 00036 IO_CSQ Csq; 00037 KSPIN_LOCK CsqLock; 00038 LIST_ENTRY CsqList; 00039 PFILE_LOCK BelongsTo; 00040 LIST_ENTRY SharedLocks; 00041 } 00042 LOCK_INFORMATION, *PLOCK_INFORMATION; 00043 00044 typedef struct _LOCK_SHARED_RANGE 00045 { 00046 LIST_ENTRY Entry; 00047 LARGE_INTEGER Start, End; 00048 ULONG Key; 00049 PVOID ProcessId; 00050 } 00051 LOCK_SHARED_RANGE, *PLOCK_SHARED_RANGE; 00052 00053 /* PRIVATE FUNCTIONS *********************************************************/ 00054 00055 VOID 00056 NTAPI 00057 FsRtlCompleteLockIrpReal(IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteRoutine, 00058 IN PVOID Context, 00059 IN PIRP Irp, 00060 IN NTSTATUS Status, 00061 OUT PNTSTATUS NewStatus, 00062 IN PFILE_OBJECT FileObject OPTIONAL); 00063 00064 /* Generic table methods */ 00065 00066 static PVOID NTAPI LockAllocate(PRTL_GENERIC_TABLE Table, CLONG Bytes) 00067 { 00068 PVOID Result; 00069 Result = ExAllocatePoolWithTag(NonPagedPool, Bytes, 'LTAB'); 00070 DPRINT("LockAllocate(%d) => %p\n", Bytes, Result); 00071 return Result; 00072 } 00073 00074 static VOID NTAPI LockFree(PRTL_GENERIC_TABLE Table, PVOID Buffer) 00075 { 00076 DPRINT("LockFree(%p)\n", Buffer); 00077 ExFreePoolWithTag(Buffer, 'LTAB'); 00078 } 00079 00080 static RTL_GENERIC_COMPARE_RESULTS NTAPI LockCompare 00081 (PRTL_GENERIC_TABLE Table, PVOID PtrA, PVOID PtrB) 00082 { 00083 PCOMBINED_LOCK_ELEMENT A = PtrA, B = PtrB; 00084 RTL_GENERIC_COMPARE_RESULTS Result; 00085 #if 0 00086 DPRINT("Starting to compare element %x to element %x\n", PtrA, PtrB); 00087 #endif 00088 /* Match if we overlap */ 00089 if (((A->Exclusive.FileLock.StartingByte.QuadPart < 00090 B->Exclusive.FileLock.EndingByte.QuadPart) && 00091 (A->Exclusive.FileLock.StartingByte.QuadPart >= 00092 B->Exclusive.FileLock.StartingByte.QuadPart)) || 00093 ((B->Exclusive.FileLock.StartingByte.QuadPart < 00094 A->Exclusive.FileLock.EndingByte.QuadPart) && 00095 (B->Exclusive.FileLock.StartingByte.QuadPart >= 00096 A->Exclusive.FileLock.StartingByte.QuadPart))) 00097 return GenericEqual; 00098 /* Otherwise, key on the starting byte */ 00099 Result = 00100 (A->Exclusive.FileLock.StartingByte.QuadPart < 00101 B->Exclusive.FileLock.StartingByte.QuadPart) ? GenericLessThan : 00102 (A->Exclusive.FileLock.StartingByte.QuadPart > 00103 B->Exclusive.FileLock.StartingByte.QuadPart) ? GenericGreaterThan : 00104 GenericEqual; 00105 #if 0 00106 DPRINT("Compare(%x:%x) %x-%x to %x-%x => %d\n", 00107 A,B, 00108 A->Exclusive.FileLock.StartingByte.LowPart, 00109 A->Exclusive.FileLock.EndingByte.LowPart, 00110 B->Exclusive.FileLock.StartingByte.LowPart, 00111 B->Exclusive.FileLock.EndingByte.LowPart, 00112 Result); 00113 #endif 00114 return Result; 00115 } 00116 00117 /* CSQ methods */ 00118 00119 static NTSTATUS NTAPI LockInsertIrpEx 00120 (PIO_CSQ Csq, 00121 PIRP Irp, 00122 PVOID InsertContext) 00123 { 00124 PLOCK_INFORMATION LockInfo = CONTAINING_RECORD(Csq, LOCK_INFORMATION, Csq); 00125 InsertTailList(&LockInfo->CsqList, &Irp->Tail.Overlay.ListEntry); 00126 return STATUS_SUCCESS; 00127 } 00128 00129 static VOID NTAPI LockRemoveIrp(PIO_CSQ Csq, PIRP Irp) 00130 { 00131 RemoveEntryList(&Irp->Tail.Overlay.ListEntry); 00132 } 00133 00134 static PIRP NTAPI LockPeekNextIrp(PIO_CSQ Csq, PIRP Irp, PVOID PeekContext) 00135 { 00136 // Context will be a COMBINED_LOCK_ELEMENT. We're looking for a 00137 // lock that can be acquired, now that the lock matching PeekContext 00138 // has been removed. 00139 COMBINED_LOCK_ELEMENT LockElement; 00140 PCOMBINED_LOCK_ELEMENT WhereUnlock = PeekContext; 00141 PLOCK_INFORMATION LockInfo = CONTAINING_RECORD(Csq, LOCK_INFORMATION, Csq); 00142 PLIST_ENTRY Following; 00143 DPRINT("PeekNextIrp(IRP %p, Context %p)\n", Irp, PeekContext); 00144 if (!Irp) 00145 { 00146 Following = LockInfo->CsqList.Flink; 00147 } 00148 else 00149 Following = Irp->Tail.Overlay.ListEntry.Flink; 00150 00151 DPRINT("ListEntry %p Head %p\n", Following, &LockInfo->CsqList); 00152 for (; 00153 Following != &LockInfo->CsqList; 00154 Following = Following->Flink) 00155 { 00156 PIO_STACK_LOCATION IoStack; 00157 BOOLEAN Matching; 00158 Irp = CONTAINING_RECORD(Following, IRP, Tail.Overlay.ListEntry); 00159 DPRINT("Irp %p\n", Irp); 00160 IoStack = IoGetCurrentIrpStackLocation(Irp); 00161 LockElement.Exclusive.FileLock.StartingByte = 00162 IoStack->Parameters.LockControl.ByteOffset; 00163 LockElement.Exclusive.FileLock.EndingByte.QuadPart = 00164 LockElement.Exclusive.FileLock.StartingByte.QuadPart + 00165 IoStack->Parameters.LockControl.Length->QuadPart; 00166 /* If a context was specified, it's a range to check to unlock */ 00167 if (WhereUnlock) 00168 { 00169 Matching = LockCompare 00170 (&LockInfo->RangeTable, &LockElement, WhereUnlock) != GenericEqual; 00171 } 00172 /* Else get any completable IRP */ 00173 else 00174 { 00175 Matching = FALSE; 00176 } 00177 if (!Matching) 00178 { 00179 // This IRP is fine... 00180 DPRINT("Returning the IRP %p\n", Irp); 00181 return Irp; 00182 } 00183 } 00184 DPRINT("Return NULL\n"); 00185 return NULL; 00186 } 00187 00188 static VOID NTAPI 00189 LockAcquireQueueLock(PIO_CSQ Csq, PKIRQL Irql) 00190 { 00191 PLOCK_INFORMATION LockInfo = CONTAINING_RECORD(Csq, LOCK_INFORMATION, Csq); 00192 KeAcquireSpinLock(&LockInfo->CsqLock, Irql); 00193 } 00194 00195 static VOID NTAPI 00196 LockReleaseQueueLock(PIO_CSQ Csq, KIRQL Irql) 00197 { 00198 PLOCK_INFORMATION LockInfo = CONTAINING_RECORD(Csq, LOCK_INFORMATION, Csq); 00199 KeReleaseSpinLock(&LockInfo->CsqLock, Irql); 00200 } 00201 00202 static VOID NTAPI 00203 LockCompleteCanceledIrp(PIO_CSQ Csq, PIRP Irp) 00204 { 00205 NTSTATUS Status; 00206 PLOCK_INFORMATION LockInfo = CONTAINING_RECORD(Csq, LOCK_INFORMATION, Csq); 00207 DPRINT("Complete cancelled IRP %p Status %x\n", Irp, STATUS_CANCELLED); 00208 FsRtlCompleteLockIrpReal 00209 (LockInfo->BelongsTo->CompleteLockIrpRoutine, 00210 NULL, 00211 Irp, 00212 STATUS_CANCELLED, 00213 &Status, 00214 NULL); 00215 } 00216 00217 VOID 00218 NTAPI 00219 FsRtlCompleteLockIrpReal(IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteRoutine, 00220 IN PVOID Context, 00221 IN PIRP Irp, 00222 IN NTSTATUS Status, 00223 OUT PNTSTATUS NewStatus, 00224 IN PFILE_OBJECT FileObject OPTIONAL) 00225 { 00226 /* Check if we have a complete routine */ 00227 if (CompleteRoutine) 00228 { 00229 /* Check if we have a file object */ 00230 if (FileObject) FileObject->LastLock = NULL; 00231 00232 /* Set the I/O Status and do completion */ 00233 Irp->IoStatus.Status = Status; 00234 DPRINT("Calling completion routine %p Status %x\n", Irp, Status); 00235 *NewStatus = CompleteRoutine(Context, Irp); 00236 } 00237 else 00238 { 00239 /* Otherwise do a normal I/O complete request */ 00240 DPRINT("Completing IRP %p Status %x\n", Irp, Status); 00241 FsRtlCompleteRequest(Irp, Status); 00242 *NewStatus = Status; 00243 } 00244 } 00245 00246 /* PUBLIC FUNCTIONS **********************************************************/ 00247 00248 /* 00249 * @implemented 00250 */ 00251 PFILE_LOCK_INFO 00252 NTAPI 00253 FsRtlGetNextFileLock(IN PFILE_LOCK FileLock, 00254 IN BOOLEAN Restart) 00255 { 00256 PCOMBINED_LOCK_ELEMENT Entry; 00257 if (!FileLock->LockInformation) return NULL; 00258 Entry = RtlEnumerateGenericTable(FileLock->LockInformation, Restart); 00259 if (!Entry) return NULL; 00260 else return &Entry->Exclusive.FileLock; 00261 } 00262 00263 /* This function expands the conflicting range Conflict by removing and reinserting it, 00264 then adds a shared range of the same size */ 00265 PCOMBINED_LOCK_ELEMENT 00266 NTAPI 00267 FsRtlpSubsumeSharedLock 00268 (PFILE_LOCK FileLock, 00269 PLOCK_INFORMATION LockInfo, 00270 PCOMBINED_LOCK_ELEMENT ToInsert, 00271 PCOMBINED_LOCK_ELEMENT Conflict) 00272 { 00273 BOOLEAN InsertedNew = FALSE, RemovedOld; 00274 COMBINED_LOCK_ELEMENT NewElement; 00275 PLOCK_SHARED_RANGE SharedRange = 00276 ExAllocatePoolWithTag(NonPagedPool, sizeof(*SharedRange), 'FSRA'); 00277 00278 if (!SharedRange) 00279 return NULL; 00280 00281 ASSERT(!Conflict->Exclusive.FileLock.ExclusiveLock); 00282 ASSERT(!ToInsert->Exclusive.FileLock.ExclusiveLock); 00283 SharedRange->Start = ToInsert->Exclusive.FileLock.StartingByte; 00284 SharedRange->End = ToInsert->Exclusive.FileLock.EndingByte; 00285 SharedRange->Key = ToInsert->Exclusive.FileLock.Key; 00286 SharedRange->ProcessId = ToInsert->Exclusive.FileLock.ProcessId; 00287 InsertTailList(&LockInfo->SharedLocks, &SharedRange->Entry); 00288 00289 NewElement = *Conflict; 00290 if (ToInsert->Exclusive.FileLock.StartingByte.QuadPart > 00291 Conflict->Exclusive.FileLock.StartingByte.QuadPart) 00292 { 00293 NewElement.Exclusive.FileLock.StartingByte = 00294 Conflict->Exclusive.FileLock.StartingByte; 00295 } 00296 if (ToInsert->Exclusive.FileLock.EndingByte.QuadPart < 00297 Conflict->Exclusive.FileLock.EndingByte.QuadPart) 00298 { 00299 NewElement.Exclusive.FileLock.EndingByte = 00300 Conflict->Exclusive.FileLock.EndingByte; 00301 } 00302 RemovedOld = RtlDeleteElementGenericTable 00303 (&LockInfo->RangeTable, 00304 Conflict); 00305 ASSERT(RemovedOld); 00306 Conflict = RtlInsertElementGenericTable 00307 (&LockInfo->RangeTable, 00308 ToInsert, 00309 sizeof(*ToInsert), 00310 &InsertedNew); 00311 ASSERT(InsertedNew && Conflict); 00312 return Conflict; 00313 } 00314 00315 /* 00316 * @implemented 00317 */ 00318 BOOLEAN 00319 NTAPI 00320 FsRtlPrivateLock(IN PFILE_LOCK FileLock, 00321 IN PFILE_OBJECT FileObject, 00322 IN PLARGE_INTEGER FileOffset, 00323 IN PLARGE_INTEGER Length, 00324 IN PEPROCESS Process, 00325 IN ULONG Key, 00326 IN BOOLEAN FailImmediately, 00327 IN BOOLEAN ExclusiveLock, 00328 OUT PIO_STATUS_BLOCK IoStatus, 00329 IN PIRP Irp OPTIONAL, 00330 IN PVOID Context OPTIONAL, 00331 IN BOOLEAN AlreadySynchronized) 00332 { 00333 NTSTATUS Status; 00334 COMBINED_LOCK_ELEMENT ToInsert; 00335 PCOMBINED_LOCK_ELEMENT Conflict; 00336 PLOCK_INFORMATION LockInfo; 00337 BOOLEAN InsertedNew; 00338 00339 DPRINT("FsRtlPrivateLock(%wZ, Offset %08x%08x, Length %08x%08x, Key %x, FailImmediately %d, Exclusive %d)\n", 00340 &FileObject->FileName, 00341 FileOffset->HighPart, 00342 FileOffset->LowPart, 00343 Length->HighPart, 00344 Length->LowPart, 00345 Key, 00346 FailImmediately, 00347 ExclusiveLock); 00348 00349 if (FileOffset->QuadPart < 0ll || 00350 FileOffset->QuadPart + Length->QuadPart < FileOffset->QuadPart) 00351 { 00352 DPRINT("File offset out of range\n"); 00353 IoStatus->Status = STATUS_INVALID_PARAMETER; 00354 if (Irp) 00355 { 00356 DPRINT("Complete lock %p Status %x\n", Irp, IoStatus->Status); 00357 FsRtlCompleteLockIrpReal 00358 (FileLock->CompleteLockIrpRoutine, 00359 Context, 00360 Irp, 00361 IoStatus->Status, 00362 &Status, 00363 FileObject); 00364 } 00365 return FALSE; 00366 } 00367 00368 /* Initialize the lock, if necessary */ 00369 if (!FileLock->LockInformation) 00370 { 00371 LockInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(LOCK_INFORMATION), 'FLCK'); 00372 FileLock->LockInformation = LockInfo; 00373 if (!FileLock) { 00374 IoStatus->Status = STATUS_NO_MEMORY; 00375 return FALSE; 00376 } 00377 00378 LockInfo->BelongsTo = FileLock; 00379 InitializeListHead(&LockInfo->SharedLocks); 00380 00381 RtlInitializeGenericTable 00382 (&LockInfo->RangeTable, 00383 LockCompare, 00384 LockAllocate, 00385 LockFree, 00386 NULL); 00387 00388 KeInitializeSpinLock(&LockInfo->CsqLock); 00389 InitializeListHead(&LockInfo->CsqList); 00390 00391 IoCsqInitializeEx 00392 (&LockInfo->Csq, 00393 LockInsertIrpEx, 00394 LockRemoveIrp, 00395 LockPeekNextIrp, 00396 LockAcquireQueueLock, 00397 LockReleaseQueueLock, 00398 LockCompleteCanceledIrp); 00399 } 00400 00401 LockInfo = FileLock->LockInformation; 00402 ToInsert.Exclusive.FileLock.FileObject = FileObject; 00403 ToInsert.Exclusive.FileLock.StartingByte = *FileOffset; 00404 ToInsert.Exclusive.FileLock.EndingByte.QuadPart = FileOffset->QuadPart + Length->QuadPart; 00405 ToInsert.Exclusive.FileLock.ProcessId = Process->UniqueProcessId; 00406 ToInsert.Exclusive.FileLock.Key = Key; 00407 ToInsert.Exclusive.FileLock.ExclusiveLock = ExclusiveLock; 00408 00409 Conflict = RtlInsertElementGenericTable 00410 (FileLock->LockInformation, 00411 &ToInsert, 00412 sizeof(ToInsert), 00413 &InsertedNew); 00414 00415 if (Conflict && !InsertedNew) 00416 { 00417 if (Conflict->Exclusive.FileLock.ExclusiveLock || ExclusiveLock) 00418 { 00419 if (FailImmediately) 00420 { 00421 IoStatus->Status = STATUS_FILE_LOCK_CONFLICT; 00422 if (Irp) 00423 { 00424 FsRtlCompleteLockIrpReal 00425 (FileLock->CompleteLockIrpRoutine, 00426 Context, 00427 Irp, 00428 IoStatus->Status, 00429 &Status, 00430 FileObject); 00431 } 00432 return FALSE; 00433 } 00434 else 00435 { 00436 IoStatus->Status = STATUS_PENDING; 00437 if (Irp) 00438 { 00439 IoMarkIrpPending(Irp); 00440 IoCsqInsertIrpEx 00441 (&LockInfo->Csq, 00442 Irp, 00443 NULL, 00444 NULL); 00445 } 00446 } 00447 return FALSE; 00448 } 00449 else 00450 { 00451 ULONG i; 00452 /* We know of at least one lock in range that's shared. We need to 00453 * find out if any more exist and any are exclusive. */ 00454 for (i = 0; i < RtlNumberGenericTableElements(&LockInfo->RangeTable); i++) 00455 { 00456 Conflict = RtlGetElementGenericTable(&LockInfo->RangeTable, i); 00457 /* The first argument will be inserted as a shared range */ 00458 if (LockCompare(&LockInfo->RangeTable, Conflict, &ToInsert) == GenericEqual) 00459 { 00460 if (Conflict->Exclusive.FileLock.ExclusiveLock) 00461 { 00462 /* Found an exclusive match */ 00463 if (FailImmediately) 00464 { 00465 IoStatus->Status = STATUS_FILE_LOCK_CONFLICT; 00466 if (Irp) 00467 { 00468 FsRtlCompleteLockIrpReal 00469 (FileLock->CompleteLockIrpRoutine, 00470 Context, 00471 Irp, 00472 IoStatus->Status, 00473 &Status, 00474 FileObject); 00475 } 00476 } 00477 else 00478 { 00479 IoStatus->Status = STATUS_PENDING; 00480 if (Irp) 00481 { 00482 IoMarkIrpPending(Irp); 00483 IoCsqInsertIrpEx 00484 (&LockInfo->Csq, 00485 Irp, 00486 NULL, 00487 NULL); 00488 } 00489 } 00490 return FALSE; 00491 } 00492 else 00493 { 00494 /* We've made all overlapping shared ranges into one big range 00495 * now we need to add a range entry for the new range */ 00496 DPRINT("Overlapping shared lock %wZ %08x%08x %08x%08x\n", 00497 &FileObject->FileName, 00498 Conflict->Exclusive.FileLock.StartingByte.HighPart, 00499 Conflict->Exclusive.FileLock.StartingByte.LowPart, 00500 Conflict->Exclusive.FileLock.EndingByte.HighPart, 00501 Conflict->Exclusive.FileLock.EndingByte.LowPart); 00502 Conflict = FsRtlpSubsumeSharedLock 00503 (FileLock, LockInfo, &ToInsert, Conflict); 00504 if (!Conflict) 00505 { 00506 IoStatus->Status = STATUS_NO_MEMORY; 00507 if (Irp) 00508 { 00509 FsRtlCompleteLockIrpReal 00510 (FileLock->CompleteLockIrpRoutine, 00511 Context, 00512 Irp, 00513 IoStatus->Status, 00514 &Status, 00515 FileObject); 00516 } 00517 return FALSE; 00518 } 00519 } 00520 } 00521 } 00522 00523 /* We got here because there were only overlapping shared locks */ 00524 DPRINT("Acquired shared lock %wZ %08x%08x %08x%08x\n", 00525 &FileObject->FileName, 00526 Conflict->Exclusive.FileLock.StartingByte.HighPart, 00527 Conflict->Exclusive.FileLock.StartingByte.LowPart, 00528 Conflict->Exclusive.FileLock.EndingByte.HighPart, 00529 Conflict->Exclusive.FileLock.EndingByte.LowPart); 00530 if (!FsRtlpSubsumeSharedLock(FileLock, LockInfo, &ToInsert, Conflict)) 00531 { 00532 IoStatus->Status = STATUS_NO_MEMORY; 00533 if (Irp) 00534 { 00535 FsRtlCompleteLockIrpReal 00536 (FileLock->CompleteLockIrpRoutine, 00537 Context, 00538 Irp, 00539 IoStatus->Status, 00540 &Status, 00541 FileObject); 00542 } 00543 return FALSE; 00544 } 00545 IoStatus->Status = STATUS_SUCCESS; 00546 if (Irp) 00547 { 00548 FsRtlCompleteLockIrpReal 00549 (FileLock->CompleteLockIrpRoutine, 00550 Context, 00551 Irp, 00552 IoStatus->Status, 00553 &Status, 00554 FileObject); 00555 } 00556 return TRUE; 00557 } 00558 } 00559 else if (!Conflict) 00560 { 00561 /* Conflict here is (or would be) the newly inserted element, but we ran 00562 * out of space probably. */ 00563 IoStatus->Status = STATUS_NO_MEMORY; 00564 if (Irp) 00565 { 00566 FsRtlCompleteLockIrpReal 00567 (FileLock->CompleteLockIrpRoutine, 00568 Context, 00569 Irp, 00570 IoStatus->Status, 00571 &Status, 00572 FileObject); 00573 } 00574 return FALSE; 00575 } 00576 else 00577 { 00578 DPRINT("Inserted new lock %wZ %08x%08x %08x%08x exclusive %d\n", 00579 &FileObject->FileName, 00580 Conflict->Exclusive.FileLock.StartingByte.HighPart, 00581 Conflict->Exclusive.FileLock.StartingByte.LowPart, 00582 Conflict->Exclusive.FileLock.StartingByte.HighPart, 00583 Conflict->Exclusive.FileLock.StartingByte.LowPart, 00584 Conflict->Exclusive.FileLock.ExclusiveLock); 00585 if (!ExclusiveLock) 00586 { 00587 PLOCK_SHARED_RANGE NewSharedRange; 00588 NewSharedRange = 00589 ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewSharedRange), 'FSRA'); 00590 if (!NewSharedRange) 00591 { 00592 IoStatus->Status = STATUS_NO_MEMORY; 00593 if (Irp) 00594 { 00595 FsRtlCompleteLockIrpReal 00596 (FileLock->CompleteLockIrpRoutine, 00597 Context, 00598 Irp, 00599 IoStatus->Status, 00600 &Status, 00601 FileObject); 00602 } 00603 return FALSE; 00604 } 00605 DPRINT("Adding shared lock %wZ\n", &FileObject->FileName); 00606 NewSharedRange->Start = ToInsert.Exclusive.FileLock.StartingByte; 00607 NewSharedRange->End = ToInsert.Exclusive.FileLock.EndingByte; 00608 NewSharedRange->Key = Key; 00609 NewSharedRange->ProcessId = ToInsert.Exclusive.FileLock.ProcessId; 00610 InsertTailList(&LockInfo->SharedLocks, &NewSharedRange->Entry); 00611 } 00612 00613 /* Assume all is cool, and lock is set */ 00614 IoStatus->Status = STATUS_SUCCESS; 00615 00616 if (Irp) 00617 { 00618 /* Complete the request */ 00619 FsRtlCompleteLockIrpReal(FileLock->CompleteLockIrpRoutine, 00620 Context, 00621 Irp, 00622 IoStatus->Status, 00623 &Status, 00624 FileObject); 00625 00626 /* Update the status */ 00627 IoStatus->Status = Status; 00628 } 00629 } 00630 00631 return TRUE; 00632 } 00633 00634 /* 00635 * @implemented 00636 */ 00637 BOOLEAN 00638 NTAPI 00639 FsRtlCheckLockForReadAccess(IN PFILE_LOCK FileLock, 00640 IN PIRP Irp) 00641 { 00642 BOOLEAN Result; 00643 PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp); 00644 COMBINED_LOCK_ELEMENT ToFind; 00645 PCOMBINED_LOCK_ELEMENT Found; 00646 DPRINT("CheckLockForReadAccess(%wZ, Offset %08x%08x, Length %x)\n", 00647 &IoStack->FileObject->FileName, 00648 IoStack->Parameters.Read.ByteOffset.HighPart, 00649 IoStack->Parameters.Read.ByteOffset.LowPart, 00650 IoStack->Parameters.Read.Length); 00651 if (!FileLock->LockInformation) { 00652 DPRINT("CheckLockForReadAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName); 00653 return TRUE; 00654 } 00655 ToFind.Exclusive.FileLock.StartingByte = IoStack->Parameters.Read.ByteOffset; 00656 ToFind.Exclusive.FileLock.EndingByte.QuadPart = 00657 ToFind.Exclusive.FileLock.StartingByte.QuadPart + 00658 IoStack->Parameters.Read.Length; 00659 Found = RtlLookupElementGenericTable 00660 (FileLock->LockInformation, 00661 &ToFind); 00662 if (!Found) { 00663 DPRINT("CheckLockForReadAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName); 00664 return TRUE; 00665 } 00666 Result = !Found->Exclusive.FileLock.ExclusiveLock || 00667 IoStack->Parameters.Read.Key == Found->Exclusive.FileLock.Key; 00668 DPRINT("CheckLockForReadAccess(%wZ) => %s\n", &IoStack->FileObject->FileName, Result ? "TRUE" : "FALSE"); 00669 return Result; 00670 } 00671 00672 /* 00673 * @implemented 00674 */ 00675 BOOLEAN 00676 NTAPI 00677 FsRtlCheckLockForWriteAccess(IN PFILE_LOCK FileLock, 00678 IN PIRP Irp) 00679 { 00680 BOOLEAN Result; 00681 PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp); 00682 COMBINED_LOCK_ELEMENT ToFind; 00683 PCOMBINED_LOCK_ELEMENT Found; 00684 PEPROCESS Process = Irp->Tail.Overlay.Thread->ThreadsProcess; 00685 DPRINT("CheckLockForWriteAccess(%wZ, Offset %08x%08x, Length %x)\n", 00686 &IoStack->FileObject->FileName, 00687 IoStack->Parameters.Write.ByteOffset.HighPart, 00688 IoStack->Parameters.Write.ByteOffset.LowPart, 00689 IoStack->Parameters.Write.Length); 00690 if (!FileLock->LockInformation) { 00691 DPRINT("CheckLockForWriteAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName); 00692 return TRUE; 00693 } 00694 ToFind.Exclusive.FileLock.StartingByte = IoStack->Parameters.Write.ByteOffset; 00695 ToFind.Exclusive.FileLock.EndingByte.QuadPart = 00696 ToFind.Exclusive.FileLock.StartingByte.QuadPart + 00697 IoStack->Parameters.Write.Length; 00698 Found = RtlLookupElementGenericTable 00699 (FileLock->LockInformation, 00700 &ToFind); 00701 if (!Found) { 00702 DPRINT("CheckLockForWriteAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName); 00703 return TRUE; 00704 } 00705 Result = Process->UniqueProcessId == Found->Exclusive.FileLock.ProcessId; 00706 DPRINT("CheckLockForWriteAccess(%wZ) => %s\n", &IoStack->FileObject->FileName, Result ? "TRUE" : "FALSE"); 00707 return Result; 00708 } 00709 00710 /* 00711 * @implemented 00712 */ 00713 BOOLEAN 00714 NTAPI 00715 FsRtlFastCheckLockForRead(IN PFILE_LOCK FileLock, 00716 IN PLARGE_INTEGER FileOffset, 00717 IN PLARGE_INTEGER Length, 00718 IN ULONG Key, 00719 IN PFILE_OBJECT FileObject, 00720 IN PVOID Process) 00721 { 00722 PEPROCESS EProcess = Process; 00723 COMBINED_LOCK_ELEMENT ToFind; 00724 PCOMBINED_LOCK_ELEMENT Found; 00725 DPRINT("FsRtlFastCheckLockForRead(%wZ, Offset %08x%08x, Length %08x%08x, Key %x)\n", 00726 &FileObject->FileName, 00727 FileOffset->HighPart, 00728 FileOffset->LowPart, 00729 Length->HighPart, 00730 Length->LowPart, 00731 Key); 00732 ToFind.Exclusive.FileLock.StartingByte = *FileOffset; 00733 ToFind.Exclusive.FileLock.EndingByte.QuadPart = 00734 FileOffset->QuadPart + Length->QuadPart; 00735 if (!FileLock->LockInformation) return TRUE; 00736 Found = RtlLookupElementGenericTable 00737 (FileLock->LockInformation, 00738 &ToFind); 00739 if (!Found || !Found->Exclusive.FileLock.ExclusiveLock) return TRUE; 00740 return Found->Exclusive.FileLock.Key == Key && 00741 Found->Exclusive.FileLock.ProcessId == EProcess->UniqueProcessId; 00742 } 00743 00744 /* 00745 * @implemented 00746 */ 00747 BOOLEAN 00748 NTAPI 00749 FsRtlFastCheckLockForWrite(IN PFILE_LOCK FileLock, 00750 IN PLARGE_INTEGER FileOffset, 00751 IN PLARGE_INTEGER Length, 00752 IN ULONG Key, 00753 IN PFILE_OBJECT FileObject, 00754 IN PVOID Process) 00755 { 00756 BOOLEAN Result; 00757 PEPROCESS EProcess = Process; 00758 COMBINED_LOCK_ELEMENT ToFind; 00759 PCOMBINED_LOCK_ELEMENT Found; 00760 DPRINT("FsRtlFastCheckLockForWrite(%wZ, Offset %08x%08x, Length %08x%08x, Key %x)\n", 00761 &FileObject->FileName, 00762 FileOffset->HighPart, 00763 FileOffset->LowPart, 00764 Length->HighPart, 00765 Length->LowPart, 00766 Key); 00767 ToFind.Exclusive.FileLock.StartingByte = *FileOffset; 00768 ToFind.Exclusive.FileLock.EndingByte.QuadPart = 00769 FileOffset->QuadPart + Length->QuadPart; 00770 if (!FileLock->LockInformation) { 00771 DPRINT("CheckForWrite(%wZ) => TRUE\n", &FileObject->FileName); 00772 return TRUE; 00773 } 00774 Found = RtlLookupElementGenericTable 00775 (FileLock->LockInformation, 00776 &ToFind); 00777 if (!Found) { 00778 DPRINT("CheckForWrite(%wZ) => TRUE\n", &FileObject->FileName); 00779 return TRUE; 00780 } 00781 Result = Found->Exclusive.FileLock.Key == Key && 00782 Found->Exclusive.FileLock.ProcessId == EProcess->UniqueProcessId; 00783 DPRINT("CheckForWrite(%wZ) => %s\n", &FileObject->FileName, Result ? "TRUE" : "FALSE"); 00784 return Result; 00785 } 00786 00787 /* 00788 * @implemented 00789 */ 00790 NTSTATUS 00791 NTAPI 00792 FsRtlFastUnlockSingle(IN PFILE_LOCK FileLock, 00793 IN PFILE_OBJECT FileObject, 00794 IN PLARGE_INTEGER FileOffset, 00795 IN PLARGE_INTEGER Length, 00796 IN PEPROCESS Process, 00797 IN ULONG Key, 00798 IN PVOID Context OPTIONAL, 00799 IN BOOLEAN AlreadySynchronized) 00800 { 00801 BOOLEAN FoundShared = FALSE; 00802 PLIST_ENTRY SharedEntry; 00803 PLOCK_SHARED_RANGE SharedRange = NULL; 00804 COMBINED_LOCK_ELEMENT Find; 00805 PCOMBINED_LOCK_ELEMENT Entry; 00806 PIRP NextMatchingLockIrp; 00807 PLOCK_INFORMATION InternalInfo = FileLock->LockInformation; 00808 DPRINT("FsRtlFastUnlockSingle(%wZ, Offset %08x%08x, Length %08x%08x, Key %x)\n", 00809 &FileObject->FileName, 00810 FileOffset->HighPart, 00811 FileOffset->LowPart, 00812 Length->HighPart, 00813 Length->LowPart, 00814 Key); 00815 // The region to unlock must correspond exactly to a previously locked region 00816 // -- msdn 00817 // But Windows 2003 doesn't assert on it and simply ignores that parameter 00818 // ASSERT(AlreadySynchronized); 00819 Find.Exclusive.FileLock.StartingByte = *FileOffset; 00820 Find.Exclusive.FileLock.EndingByte.QuadPart = 00821 FileOffset->QuadPart + Length->QuadPart; 00822 Entry = RtlLookupElementGenericTable(&InternalInfo->RangeTable, &Find); 00823 if (!Entry) { 00824 DPRINT("Range not locked %wZ\n", &FileObject->FileName); 00825 return STATUS_RANGE_NOT_LOCKED; 00826 } 00827 00828 if (Entry->Exclusive.FileLock.ExclusiveLock) 00829 { 00830 if (Entry->Exclusive.FileLock.Key != Key || 00831 Entry->Exclusive.FileLock.ProcessId != Process->UniqueProcessId || 00832 Entry->Exclusive.FileLock.StartingByte.QuadPart != FileOffset->QuadPart || 00833 Entry->Exclusive.FileLock.EndingByte.QuadPart != 00834 FileOffset->QuadPart + Length->QuadPart) 00835 { 00836 DPRINT("Range not locked %wZ\n", &FileObject->FileName); 00837 return STATUS_RANGE_NOT_LOCKED; 00838 } 00839 RtlCopyMemory(&Find, Entry, sizeof(Find)); 00840 } 00841 else 00842 { 00843 DPRINT("Shared lock %wZ Start %08x%08x End %08x%08x\n", 00844 &FileObject->FileName, 00845 Entry->Exclusive.FileLock.StartingByte.HighPart, 00846 Entry->Exclusive.FileLock.StartingByte.LowPart, 00847 Entry->Exclusive.FileLock.EndingByte.HighPart, 00848 Entry->Exclusive.FileLock.EndingByte.LowPart); 00849 for (SharedEntry = InternalInfo->SharedLocks.Flink; 00850 SharedEntry != &InternalInfo->SharedLocks; 00851 SharedEntry = SharedEntry->Flink) 00852 { 00853 SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry); 00854 if (SharedRange->Start.QuadPart == FileOffset->QuadPart && 00855 SharedRange->End.QuadPart == FileOffset->QuadPart + Length->QuadPart && 00856 SharedRange->Key == Key && 00857 SharedRange->ProcessId == Process->UniqueProcessId) 00858 { 00859 FoundShared = TRUE; 00860 DPRINT("Found shared element to delete %wZ Start %08x%08x End %08x%08x Key %x\n", 00861 &FileObject->FileName, 00862 SharedRange->Start.HighPart, 00863 SharedRange->Start.LowPart, 00864 SharedRange->End.HighPart, 00865 SharedRange->End.LowPart, 00866 SharedRange->Key); 00867 break; 00868 } 00869 } 00870 if (FoundShared) 00871 { 00872 Find.Exclusive.FileLock.StartingByte = SharedRange->Start; 00873 Find.Exclusive.FileLock.EndingByte = SharedRange->End; 00874 SharedEntry = SharedRange->Entry.Flink; 00875 RemoveEntryList(&SharedRange->Entry); 00876 ExFreePool(SharedRange); 00877 } 00878 else 00879 { 00880 return STATUS_RANGE_NOT_LOCKED; 00881 } 00882 } 00883 00884 if (IsListEmpty(&InternalInfo->SharedLocks)) { 00885 DPRINT("Removing the lock entry %wZ\n", &FileObject->FileName); 00886 RtlDeleteElementGenericTable(&InternalInfo->RangeTable, Entry); 00887 } else { 00888 DPRINT("Lock still has:\n"); 00889 for (SharedEntry = InternalInfo->SharedLocks.Flink; 00890 SharedEntry != &InternalInfo->SharedLocks; 00891 SharedEntry = SharedEntry->Flink) 00892 { 00893 SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry); 00894 DPRINT("Shared element %wZ Offset %08x%08x Length %08x%08x Key %x\n", 00895 &FileObject->FileName, 00896 SharedRange->Start.HighPart, 00897 SharedRange->Start.LowPart, 00898 SharedRange->End.HighPart, 00899 SharedRange->End.LowPart, 00900 SharedRange->Key); 00901 } 00902 } 00903 00904 // this is definitely the thing we want 00905 NextMatchingLockIrp = IoCsqRemoveNextIrp(&InternalInfo->Csq, &Find); 00906 while (NextMatchingLockIrp) 00907 { 00908 // Got a new lock irp... try to do the new lock operation 00909 // Note that we pick an operation that would succeed at the time 00910 // we looked, but can't guarantee that it won't just be re-queued 00911 // because somebody else snatched part of the range in a new thread. 00912 DPRINT("Locking another IRP %p for %p %wZ\n", 00913 &FileObject->FileName, FileLock, NextMatchingLockIrp); 00914 FsRtlProcessFileLock(InternalInfo->BelongsTo, NextMatchingLockIrp, NULL); 00915 } 00916 00917 DPRINT("Success %wZ\n", &FileObject->FileName); 00918 return STATUS_SUCCESS; 00919 } 00920 00921 /* 00922 * @implemented 00923 */ 00924 NTSTATUS 00925 NTAPI 00926 FsRtlFastUnlockAll(IN PFILE_LOCK FileLock, 00927 IN PFILE_OBJECT FileObject, 00928 IN PEPROCESS Process, 00929 IN PVOID Context OPTIONAL) 00930 { 00931 PCOMBINED_LOCK_ELEMENT Entry; 00932 PRTL_GENERIC_TABLE InternalInfo = FileLock->LockInformation; 00933 DPRINT("FsRtlFastUnlockAll(%wZ)\n", &FileObject->FileName); 00934 // XXX Synchronize somehow 00935 if (!FileLock->LockInformation) { 00936 DPRINT("Not locked %wZ\n", &FileObject->FileName); 00937 return STATUS_RANGE_NOT_LOCKED; // no locks 00938 } 00939 for (Entry = RtlEnumerateGenericTable(InternalInfo, TRUE); 00940 Entry; 00941 Entry = RtlEnumerateGenericTable(InternalInfo, FALSE)) 00942 { 00943 LARGE_INTEGER Length; 00944 // We'll take the first one to be the list head, and free the others first... 00945 Length.QuadPart = 00946 Entry->Exclusive.FileLock.EndingByte.QuadPart - 00947 Entry->Exclusive.FileLock.StartingByte.QuadPart; 00948 FsRtlFastUnlockSingle 00949 (FileLock, 00950 Entry->Exclusive.FileLock.FileObject, 00951 &Entry->Exclusive.FileLock.StartingByte, 00952 &Length, 00953 Entry->Exclusive.FileLock.ProcessId, 00954 Entry->Exclusive.FileLock.Key, 00955 Context, 00956 TRUE); 00957 } 00958 DPRINT("Done %wZ\n", &FileObject->FileName); 00959 return STATUS_SUCCESS; 00960 } 00961 00962 /* 00963 * @implemented 00964 */ 00965 NTSTATUS 00966 NTAPI 00967 FsRtlFastUnlockAllByKey(IN PFILE_LOCK FileLock, 00968 IN PFILE_OBJECT FileObject, 00969 IN PEPROCESS Process, 00970 IN ULONG Key, 00971 IN PVOID Context OPTIONAL) 00972 { 00973 PCOMBINED_LOCK_ELEMENT Entry; 00974 PLOCK_INFORMATION InternalInfo = FileLock->LockInformation; 00975 00976 DPRINT("FsRtlFastUnlockAllByKey(%wZ,Key %x)\n", &FileObject->FileName, Key); 00977 00978 // XXX Synchronize somehow 00979 if (!FileLock->LockInformation) return STATUS_RANGE_NOT_LOCKED; // no locks 00980 for (Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, TRUE); 00981 Entry; 00982 Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, FALSE)) 00983 { 00984 LARGE_INTEGER Length; 00985 // We'll take the first one to be the list head, and free the others first... 00986 Length.QuadPart = 00987 Entry->Exclusive.FileLock.EndingByte.QuadPart - 00988 Entry->Exclusive.FileLock.StartingByte.QuadPart; 00989 if (Entry->Exclusive.FileLock.Key == Key && 00990 Entry->Exclusive.FileLock.ProcessId == Process->UniqueProcessId) 00991 { 00992 FsRtlFastUnlockSingle 00993 (FileLock, 00994 Entry->Exclusive.FileLock.FileObject, 00995 &Entry->Exclusive.FileLock.StartingByte, 00996 &Length, 00997 Entry->Exclusive.FileLock.ProcessId, 00998 Entry->Exclusive.FileLock.Key, 00999 Context, 01000 TRUE); 01001 } 01002 } 01003 01004 return STATUS_SUCCESS; 01005 } 01006 01007 /* 01008 * @implemented 01009 */ 01010 NTSTATUS 01011 NTAPI 01012 FsRtlProcessFileLock(IN PFILE_LOCK FileLock, 01013 IN PIRP Irp, 01014 IN PVOID Context OPTIONAL) 01015 { 01016 PIO_STACK_LOCATION IoStackLocation; 01017 NTSTATUS Status; 01018 IO_STATUS_BLOCK IoStatusBlock; 01019 01020 /* Get the I/O Stack location */ 01021 IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 01022 ASSERT(IoStackLocation->MajorFunction == IRP_MJ_LOCK_CONTROL); 01023 01024 /* Clear the I/O status block and check what function this is */ 01025 IoStatusBlock.Information = 0; 01026 01027 DPRINT("FsRtlProcessFileLock(%wZ, MinorFunction %x)\n", 01028 &IoStackLocation->FileObject->FileName, 01029 IoStackLocation->MinorFunction); 01030 01031 switch(IoStackLocation->MinorFunction) 01032 { 01033 /* A lock */ 01034 case IRP_MN_LOCK: 01035 01036 /* Call the private lock routine */ 01037 FsRtlPrivateLock(FileLock, 01038 IoStackLocation->FileObject, 01039 &IoStackLocation-> 01040 Parameters.LockControl.ByteOffset, 01041 IoStackLocation->Parameters.LockControl.Length, 01042 IoGetRequestorProcess(Irp), 01043 IoStackLocation->Parameters.LockControl.Key, 01044 IoStackLocation->Flags & SL_FAIL_IMMEDIATELY, 01045 IoStackLocation->Flags & SL_EXCLUSIVE_LOCK, 01046 &IoStatusBlock, 01047 Irp, 01048 Context, 01049 FALSE); 01050 return IoStatusBlock.Status; 01051 01052 /* A single unlock */ 01053 case IRP_MN_UNLOCK_SINGLE: 01054 01055 /* Call fast unlock */ 01056 IoStatusBlock.Status = 01057 FsRtlFastUnlockSingle(FileLock, 01058 IoStackLocation->FileObject, 01059 &IoStackLocation->Parameters.LockControl. 01060 ByteOffset, 01061 IoStackLocation->Parameters.LockControl. 01062 Length, 01063 IoGetRequestorProcess(Irp), 01064 IoStackLocation->Parameters.LockControl. 01065 Key, 01066 Context, 01067 FALSE); 01068 break; 01069 01070 /* Total unlock */ 01071 case IRP_MN_UNLOCK_ALL: 01072 01073 /* Do a fast unlock */ 01074 IoStatusBlock.Status = FsRtlFastUnlockAll(FileLock, 01075 IoStackLocation-> 01076 FileObject, 01077 IoGetRequestorProcess(Irp), 01078 Context); 01079 break; 01080 01081 /* Unlock by key */ 01082 case IRP_MN_UNLOCK_ALL_BY_KEY: 01083 01084 /* Do it */ 01085 IoStatusBlock.Status = 01086 FsRtlFastUnlockAllByKey(FileLock, 01087 IoStackLocation->FileObject, 01088 IoGetRequestorProcess(Irp), 01089 IoStackLocation->Parameters. 01090 LockControl.Key, 01091 Context); 01092 break; 01093 01094 /* Invalid request */ 01095 default: 01096 01097 /* Complete it */ 01098 FsRtlCompleteRequest(Irp, STATUS_INVALID_DEVICE_REQUEST); 01099 IoStatusBlock.Status = STATUS_INVALID_DEVICE_REQUEST; 01100 return STATUS_INVALID_DEVICE_REQUEST; 01101 } 01102 01103 /* Return the status */ 01104 DPRINT("Lock IRP %p %x\n", Irp, IoStatusBlock.Status); 01105 FsRtlCompleteLockIrpReal 01106 (FileLock->CompleteLockIrpRoutine, 01107 Context, 01108 Irp, 01109 IoStatusBlock.Status, 01110 &Status, 01111 NULL); 01112 return IoStatusBlock.Status; 01113 } 01114 01115 /* 01116 * @implemented 01117 */ 01118 VOID 01119 NTAPI 01120 FsRtlInitializeFileLock (IN PFILE_LOCK FileLock, 01121 IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, 01122 IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL) 01123 { 01124 /* Setup the lock */ 01125 RtlZeroMemory(FileLock, sizeof(*FileLock)); 01126 FileLock->FastIoIsQuestionable = FALSE; 01127 FileLock->CompleteLockIrpRoutine = CompleteLockIrpRoutine; 01128 FileLock->UnlockRoutine = UnlockRoutine; 01129 FileLock->LockInformation = NULL; 01130 } 01131 01132 /* 01133 * @implemented 01134 */ 01135 VOID 01136 NTAPI 01137 FsRtlUninitializeFileLock(IN PFILE_LOCK FileLock) 01138 { 01139 if (FileLock->LockInformation) 01140 { 01141 PIRP Irp; 01142 PLOCK_INFORMATION InternalInfo = FileLock->LockInformation; 01143 PCOMBINED_LOCK_ELEMENT Entry; 01144 PLIST_ENTRY SharedEntry; 01145 PLOCK_SHARED_RANGE SharedRange; 01146 // MSDN: this completes any remaining lock IRPs 01147 for (SharedEntry = InternalInfo->SharedLocks.Flink; 01148 SharedEntry != &InternalInfo->SharedLocks;) 01149 { 01150 SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry); 01151 SharedEntry = SharedEntry->Flink; 01152 RemoveEntryList(SharedEntry); 01153 ExFreePool(SharedRange); 01154 } 01155 while ((Entry = RtlGetElementGenericTable(&InternalInfo->RangeTable, 0)) != NULL) 01156 { 01157 RtlDeleteElementGenericTable(&InternalInfo->RangeTable, Entry); 01158 } 01159 while ((Irp = IoCsqRemoveNextIrp(&InternalInfo->Csq, NULL)) != NULL) 01160 { 01161 FsRtlProcessFileLock(FileLock, Irp, NULL); 01162 } 01163 ExFreePoolWithTag(InternalInfo, 'FLCK'); 01164 FileLock->LockInformation = NULL; 01165 } 01166 } 01167 01168 /* 01169 * @implemented 01170 */ 01171 PFILE_LOCK 01172 NTAPI 01173 FsRtlAllocateFileLock(IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, 01174 IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL) 01175 { 01176 PFILE_LOCK FileLock; 01177 01178 /* Try to allocate it */ 01179 FileLock = ExAllocateFromPagedLookasideList(&FsRtlFileLockLookasideList); 01180 if (FileLock) 01181 { 01182 /* Initialize it */ 01183 FsRtlInitializeFileLock(FileLock, 01184 CompleteLockIrpRoutine, 01185 UnlockRoutine); 01186 } 01187 01188 /* Return the lock */ 01189 return FileLock; 01190 } 01191 01192 /* 01193 * @implemented 01194 */ 01195 VOID 01196 NTAPI 01197 FsRtlFreeFileLock(IN PFILE_LOCK FileLock) 01198 { 01199 /* Uninitialize and free the lock */ 01200 FsRtlUninitializeFileLock(FileLock); 01201 ExFreeToPagedLookasideList(&FsRtlFileLockLookasideList, FileLock); 01202 } Generated on Sat May 26 2012 04:36:04 for ReactOS by
1.7.6.1
|