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

filelock.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 doxygen 1.7.6.1

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