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

obref.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/ob/obref.c
00005  * PURPOSE:         Manages the referencing and de-referencing of all Objects,
00006  *                  as well as the Object Fast Reference implementation.
00007  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
00008  *                  Eric Kohl
00009  *                  Thomas Weidenmueller (w3seek@reactos.org)
00010  */
00011 
00012 /* INCLUDES ******************************************************************/
00013 
00014 #include <ntoskrnl.h>
00015 #define NDEBUG
00016 #include <debug.h>
00017 
00018 /* PRIVATE FUNCTIONS *********************************************************/
00019 
00020 BOOLEAN
00021 FASTCALL
00022 ObReferenceObjectSafe(IN PVOID Object)
00023 {
00024     POBJECT_HEADER ObjectHeader;
00025     LONG OldValue, NewValue;
00026 
00027     /* Get the object header */
00028     ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
00029 
00030     /* Get the current reference count and fail if it's zero */
00031     OldValue = ObjectHeader->PointerCount;
00032     if (!OldValue) return FALSE;
00033 
00034     /* Start reference loop */
00035     do
00036     {
00037         /* Increase the reference count */
00038         NewValue = InterlockedCompareExchange(&ObjectHeader->PointerCount,
00039                                               OldValue + 1,
00040                                               OldValue);
00041         if (OldValue == NewValue) return TRUE;
00042 
00043         /* Keep looping */
00044         OldValue = NewValue;
00045     } while (OldValue);
00046 
00047     /* If we got here, then the reference count is now 0 */
00048     return FALSE;
00049 }
00050 
00051 VOID
00052 NTAPI
00053 ObpDeferObjectDeletion(IN POBJECT_HEADER Header)
00054 {
00055     PVOID Entry;
00056 
00057     /* Loop while trying to update the list */
00058     do
00059     {
00060         /* Get the current entry */
00061         Entry = ObpReaperList;
00062 
00063         /* Link our object to the list */
00064         Header->NextToFree = Entry;
00065 
00066         /* Update the list */
00067     } while (InterlockedCompareExchangePointer(&ObpReaperList,
00068                                                Header,
00069                                                Entry) != Entry);
00070 
00071     /* Queue the work item if needed */
00072     if (!Entry) ExQueueWorkItem(&ObpReaperWorkItem, CriticalWorkQueue);
00073 }
00074 
00075 LONG
00076 FASTCALL
00077 ObReferenceObjectEx(IN PVOID Object,
00078                     IN LONG Count)
00079 {
00080     /* Increment the reference count and return the count now */
00081     return InterlockedExchangeAdd(&OBJECT_TO_OBJECT_HEADER(Object)->
00082                                   PointerCount,
00083                                   Count) + Count;
00084 }
00085 
00086 LONG
00087 FASTCALL
00088 ObDereferenceObjectEx(IN PVOID Object,
00089                       IN LONG Count)
00090 {
00091     POBJECT_HEADER Header;
00092     LONG NewCount;
00093 
00094     /* Extract the object header */
00095     Header = OBJECT_TO_OBJECT_HEADER(Object);
00096 
00097     /* Check whether the object can now be deleted. */
00098     NewCount = InterlockedExchangeAdd(&Header->PointerCount, -Count) - Count;
00099     if (!NewCount) ObpDeferObjectDeletion(Header);
00100 
00101     /* Return the current count */
00102     return NewCount;
00103 }
00104 
00105 VOID
00106 FASTCALL
00107 ObInitializeFastReference(IN PEX_FAST_REF FastRef,
00108                           IN PVOID Object OPTIONAL)
00109 {
00110     /* Check if we were given an object and reference it 7 times */
00111     if (Object) ObReferenceObjectEx(Object, MAX_FAST_REFS);
00112     
00113     /* Setup the fast reference */
00114     ExInitializeFastReference(FastRef, Object);
00115 }
00116 
00117 PVOID
00118 FASTCALL
00119 ObFastReferenceObjectLocked(IN PEX_FAST_REF FastRef)
00120 {
00121     PVOID Object;
00122     EX_FAST_REF OldValue = *FastRef;
00123 
00124     /* Get the object and reference it slowly */
00125     Object = ExGetObjectFastReference(OldValue);
00126     if (Object) ObReferenceObject(Object);
00127     return Object;
00128 }
00129 
00130 PVOID
00131 FASTCALL
00132 ObFastReferenceObject(IN PEX_FAST_REF FastRef)
00133 {
00134     EX_FAST_REF OldValue;
00135     ULONG_PTR Count;
00136     PVOID Object;
00137 
00138     /* Reference the object and get it pointer */
00139     OldValue = ExAcquireFastReference(FastRef);
00140     Object = ExGetObjectFastReference(OldValue);
00141 
00142     /* Check how many references are left */
00143     Count = ExGetCountFastReference(OldValue);
00144 
00145     /* Check if the reference count is over 1 */
00146     if (Count > 1) return Object;
00147 
00148     /* Check if the reference count has reached 0 */
00149     if (!Count) return NULL;
00150 
00151     /* Otherwise, reference the object 7 times */
00152     ObReferenceObjectEx(Object, MAX_FAST_REFS);
00153     
00154     /* Now update the reference count */
00155     if (!ExInsertFastReference(FastRef, Object))
00156     {
00157         /* We failed: completely dereference the object */
00158         ObDereferenceObjectEx(Object, MAX_FAST_REFS);
00159     }
00160 
00161     /* Return the Object */
00162     return Object;
00163 }
00164 
00165 VOID
00166 FASTCALL
00167 ObFastDereferenceObject(IN PEX_FAST_REF FastRef,
00168                         IN PVOID Object)
00169 {
00170     /* Release a fast reference. If this failed, use the slow path */
00171     if (!ExReleaseFastReference(FastRef, Object)) ObDereferenceObject(Object);
00172 }
00173 
00174 PVOID
00175 FASTCALL
00176 ObFastReplaceObject(IN PEX_FAST_REF FastRef,
00177                     PVOID Object)
00178 {
00179     EX_FAST_REF OldValue;
00180     PVOID OldObject;
00181     ULONG Count;
00182 
00183     /* Check if we were given an object and reference it 7 times */
00184     if (Object) ObReferenceObjectEx(Object, MAX_FAST_REFS);
00185     
00186     /* Do the swap */
00187     OldValue = ExSwapFastReference(FastRef, Object);
00188     OldObject = ExGetObjectFastReference(OldValue);
00189     
00190     /* Check if we had an active object and dereference it */
00191     Count = ExGetCountFastReference(OldValue);
00192     if ((OldObject) && (Count)) ObDereferenceObjectEx(OldObject, Count);
00193 
00194     /* Return the old object */
00195     return OldObject;
00196 }
00197 
00198 /* PUBLIC FUNCTIONS *********************************************************/
00199 
00200 LONG_PTR
00201 FASTCALL
00202 ObfReferenceObject(IN PVOID Object)
00203 {
00204     ASSERT(Object);
00205 
00206     /* Get the header and increment the reference count */
00207     return InterlockedIncrement(&OBJECT_TO_OBJECT_HEADER(Object)->PointerCount);
00208 }
00209 
00210 LONG_PTR
00211 FASTCALL
00212 ObfDereferenceObject(IN PVOID Object)
00213 {
00214     POBJECT_HEADER Header;
00215     LONG_PTR OldCount;
00216 
00217     /* Extract the object header */
00218     Header = OBJECT_TO_OBJECT_HEADER(Object);
00219 
00220     if (Header->PointerCount < Header->HandleCount)
00221     {
00222         DPRINT1("Misbehaving object: %wZ\n", &Header->Type->Name);
00223         return Header->PointerCount;
00224     }
00225 
00226     /* Check whether the object can now be deleted. */
00227     OldCount = InterlockedDecrement(&Header->PointerCount);
00228     if (!OldCount)
00229     {
00230         /* Sanity check */
00231         ASSERT(Header->HandleCount == 0);
00232 
00233         /* Check if APCs are still active */
00234         if (!KeAreAllApcsDisabled())
00235         {
00236             /* Remove the object */
00237             ObpDeleteObject(Object, FALSE);
00238         }
00239         else
00240         {
00241             /* Add us to the deferred deletion list */
00242             ObpDeferObjectDeletion(Header);
00243         }
00244     }
00245 
00246     /* Return the old count */
00247     return OldCount;
00248 }
00249 
00250 VOID
00251 NTAPI
00252 ObDereferenceObjectDeferDelete(IN PVOID Object)
00253 {
00254     POBJECT_HEADER Header = OBJECT_TO_OBJECT_HEADER(Object);
00255 
00256     /* Check whether the object can now be deleted. */
00257     if (!InterlockedDecrement(&Header->PointerCount))
00258     {
00259         /* Add us to the deferred deletion list */
00260         ObpDeferObjectDeletion(Header);
00261     }
00262 }
00263 
00264 #undef ObDereferenceObject
00265 VOID
00266 NTAPI
00267 ObDereferenceObject(IN PVOID Object)
00268 {
00269     /* Call the fastcall function */
00270     ObfDereferenceObject(Object);
00271 }
00272 
00273 NTSTATUS
00274 NTAPI
00275 ObReferenceObjectByPointer(IN PVOID Object,
00276                            IN ACCESS_MASK DesiredAccess,
00277                            IN POBJECT_TYPE ObjectType,
00278                            IN KPROCESSOR_MODE AccessMode)
00279 {
00280     POBJECT_HEADER Header;
00281 
00282     /* Get the header */
00283     Header = OBJECT_TO_OBJECT_HEADER(Object);
00284 
00285     /*
00286      * Validate object type if the call is for UserMode.
00287      * NOTE: Unless it's a symbolic link (Caz Yokoyama [MSFT])
00288      */
00289     if ((Header->Type != ObjectType) && ((AccessMode != KernelMode) ||
00290         (ObjectType == ObSymbolicLinkType)))
00291     {
00292         /* Invalid type */
00293         return STATUS_OBJECT_TYPE_MISMATCH;
00294     }
00295 
00296     /* Increment the reference count and return success */
00297     InterlockedIncrement(&Header->PointerCount);
00298     return STATUS_SUCCESS;
00299 }
00300 
00301 NTSTATUS
00302 NTAPI
00303 ObReferenceObjectByName(IN PUNICODE_STRING ObjectPath,
00304                         IN ULONG Attributes,
00305                         IN PACCESS_STATE PassedAccessState,
00306                         IN ACCESS_MASK DesiredAccess,
00307                         IN POBJECT_TYPE ObjectType,
00308                         IN KPROCESSOR_MODE AccessMode,
00309                         IN OUT PVOID ParseContext,
00310                         OUT PVOID* ObjectPtr)
00311 {
00312     PVOID Object = NULL;
00313     UNICODE_STRING ObjectName;
00314     NTSTATUS Status;
00315     OBP_LOOKUP_CONTEXT Context;
00316     AUX_ACCESS_DATA AuxData;
00317     ACCESS_STATE AccessState;
00318     PAGED_CODE();
00319 
00320     /* Fail quickly */
00321     if (!ObjectPath) return STATUS_OBJECT_NAME_INVALID;
00322 
00323     /* Capture the name */
00324     Status = ObpCaptureObjectName(&ObjectName, ObjectPath, AccessMode, TRUE);
00325     if (!NT_SUCCESS(Status)) return Status;
00326 
00327     /* We also need a valid name after capture */
00328     if (!ObjectName.Length) return STATUS_OBJECT_NAME_INVALID;
00329 
00330     /* Check if we didn't get an access state */
00331     if (!PassedAccessState)
00332     {
00333         /* Use our built-in access state */
00334         PassedAccessState = &AccessState;
00335         Status = SeCreateAccessState(&AccessState,
00336                                      &AuxData,
00337                                      DesiredAccess,
00338                                      &ObjectType->TypeInfo.GenericMapping);
00339         if (!NT_SUCCESS(Status)) goto Quickie;
00340     }
00341 
00342     /* Find the object */
00343     *ObjectPtr = NULL;
00344     Status = ObpLookupObjectName(NULL,
00345                                  &ObjectName,
00346                                  Attributes,
00347                                  ObjectType,
00348                                  AccessMode,
00349                                  ParseContext,
00350                                  NULL,
00351                                  NULL,
00352                                  PassedAccessState,
00353                                  &Context,
00354                                  &Object);
00355 
00356     /* Cleanup after lookup */
00357     ObpReleaseLookupContext(&Context);
00358 
00359     /* Check if the lookup succeeded */
00360     if (NT_SUCCESS(Status))
00361     {
00362         /* Check if access is allowed */
00363         if (ObpCheckObjectReference(Object,
00364                                     PassedAccessState,
00365                                     FALSE,
00366                                     AccessMode,
00367                                     &Status))
00368         {
00369             /* Return the object */
00370             *ObjectPtr = Object;
00371         }
00372     }
00373 
00374     /* Free the access state */
00375     if (PassedAccessState == &AccessState)
00376     {
00377         SeDeleteAccessState(PassedAccessState);
00378     }
00379 
00380 Quickie:
00381     /* Free the captured name if we had one, and return status */
00382     ObpFreeObjectNameBuffer(&ObjectName);
00383     return Status;
00384 }
00385 
00386 NTSTATUS
00387 NTAPI
00388 ObReferenceObjectByHandle(IN HANDLE Handle,
00389                           IN ACCESS_MASK DesiredAccess,
00390                           IN POBJECT_TYPE ObjectType,
00391                           IN KPROCESSOR_MODE AccessMode,
00392                           OUT PVOID* Object,
00393                           OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
00394 {
00395     PHANDLE_TABLE_ENTRY HandleEntry;
00396     POBJECT_HEADER ObjectHeader;
00397     ACCESS_MASK GrantedAccess;
00398     ULONG Attributes;
00399     PEPROCESS CurrentProcess;
00400     PVOID HandleTable;
00401     PETHREAD CurrentThread;
00402     NTSTATUS Status;
00403     PAGED_CODE();
00404 
00405     /* Assume failure */
00406     *Object = NULL;
00407 
00408     /* Check if this is a special handle */
00409     if (HandleToLong(Handle) < 0)
00410     {
00411         /* Check if this is the current process */
00412         if (Handle == NtCurrentProcess())
00413         {
00414             /* Check if this is the right object type */
00415             if ((ObjectType == PsProcessType) || !(ObjectType))
00416             {
00417                 /* Get the current process and granted access */
00418                 CurrentProcess = PsGetCurrentProcess();
00419                 GrantedAccess = CurrentProcess->GrantedAccess;
00420 
00421                 /* Validate access */
00422                 /* ~GrantedAccess = RefusedAccess.*/
00423                 /* ~GrantedAccess & DesiredAccess = list of refused bits. */
00424                 /* !(~GrantedAccess & DesiredAccess) == TRUE means ALL requested rights are granted */
00425                 if ((AccessMode == KernelMode) ||
00426                     !(~GrantedAccess & DesiredAccess))
00427                 {
00428                     /* Check if the caller wanted handle information */
00429                     if (HandleInformation)
00430                     {
00431                         /* Return it */
00432                         HandleInformation->HandleAttributes = 0;
00433                         HandleInformation->GrantedAccess = GrantedAccess;
00434                     }
00435 
00436                     /* Reference ourselves */
00437                     ObjectHeader = OBJECT_TO_OBJECT_HEADER(CurrentProcess);
00438                     InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1);
00439 
00440                     /* Return the pointer */
00441                     *Object = CurrentProcess;
00442                     ASSERT(*Object != NULL);
00443                     Status = STATUS_SUCCESS;
00444                 }
00445                 else
00446                 {
00447                     /* Access denied */
00448                     Status = STATUS_ACCESS_DENIED;
00449                 }
00450             }
00451             else
00452             {
00453                 /* The caller used this special handle value with a non-process type */
00454                 Status = STATUS_OBJECT_TYPE_MISMATCH;
00455             }
00456 
00457             /* Return the status */
00458             return Status;
00459         }
00460         else if (Handle == NtCurrentThread())
00461         {
00462             /* Check if this is the right object type */
00463             if ((ObjectType == PsThreadType) || !(ObjectType))
00464             {
00465                 /* Get the current process and granted access */
00466                 CurrentThread = PsGetCurrentThread();
00467                 GrantedAccess = CurrentThread->GrantedAccess;
00468 
00469                 /* Validate access */
00470                 /* ~GrantedAccess = RefusedAccess.*/
00471                 /* ~GrantedAccess & DesiredAccess = list of refused bits. */
00472                 /* !(~GrantedAccess & DesiredAccess) == TRUE means ALL requested rights are granted */
00473                 if ((AccessMode == KernelMode) ||
00474                     !(~GrantedAccess & DesiredAccess))
00475                 {
00476                     /* Check if the caller wanted handle information */
00477                     if (HandleInformation)
00478                     {
00479                         /* Return it */
00480                         HandleInformation->HandleAttributes = 0;
00481                         HandleInformation->GrantedAccess = GrantedAccess;
00482                     }
00483 
00484                     /* Reference ourselves */
00485                     ObjectHeader = OBJECT_TO_OBJECT_HEADER(CurrentThread);
00486                     InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1);
00487 
00488                     /* Return the pointer */
00489                     *Object = CurrentThread;
00490                     ASSERT(*Object != NULL);
00491                     Status = STATUS_SUCCESS;
00492                 }
00493                 else
00494                 {
00495                     /* Access denied */
00496                     Status = STATUS_ACCESS_DENIED;
00497                 }
00498             }
00499             else
00500             {
00501                 /* The caller used this special handle value with a non-process type */
00502                 Status = STATUS_OBJECT_TYPE_MISMATCH;
00503             }
00504 
00505             /* Return the status */
00506             return Status;
00507         }
00508         else if (AccessMode == KernelMode)
00509         {
00510             /* Use the kernel handle table and get the actual handle value */
00511             Handle = ObKernelHandleToHandle(Handle);
00512             HandleTable = ObpKernelHandleTable;
00513         }
00514         else
00515         {
00516             /* Invalid access, fail */
00517             return STATUS_INVALID_HANDLE;
00518         }
00519     }
00520     else
00521     {
00522         /* Otherwise use this process's handle table */
00523         HandleTable = PsGetCurrentProcess()->ObjectTable;
00524     }
00525 
00526     /* Enter a critical region while we touch the handle table */
00527     ASSERT(HandleTable != NULL);
00528     KeEnterCriticalRegion();
00529 
00530     /* Get the handle entry */
00531     HandleEntry = ExMapHandleToPointer(HandleTable, Handle);
00532     if (HandleEntry)
00533     {
00534         /* Get the object header and validate the type*/
00535         ObjectHeader = ObpGetHandleObject(HandleEntry);
00536         if (!(ObjectType) || (ObjectType == ObjectHeader->Type))
00537         {
00538             /* Get the granted access and validate it */
00539             GrantedAccess = HandleEntry->GrantedAccess;
00540 
00541             /* Validate access */
00542             /* ~GrantedAccess = RefusedAccess.*/
00543             /* ~GrantedAccess & DesiredAccess = list of refused bits. */
00544             /* !(~GrantedAccess & DesiredAccess) == TRUE means ALL requested rights are granted */
00545             if ((AccessMode == KernelMode) ||
00546                 !(~GrantedAccess & DesiredAccess))
00547             {
00548                 /* Reference the object directly since we have its header */
00549                 InterlockedIncrement(&ObjectHeader->PointerCount);
00550 
00551                 /* Mask out the internal attributes */
00552                 Attributes = HandleEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES;
00553 
00554                 /* Check if the caller wants handle information */
00555                 if (HandleInformation)
00556                 {
00557                     /* Fill out the information */
00558                     HandleInformation->HandleAttributes = Attributes;
00559                     HandleInformation->GrantedAccess = GrantedAccess;
00560                 }
00561 
00562                 /* Return the pointer */
00563                 *Object = &ObjectHeader->Body;
00564 
00565                 /* Unlock the handle */
00566                 ExUnlockHandleTableEntry(HandleTable, HandleEntry);
00567                 KeLeaveCriticalRegion();
00568 
00569                 /* Return success */
00570                 ASSERT(*Object != NULL);
00571                 return STATUS_SUCCESS;
00572             }
00573             else
00574             {
00575                 /* Requested access failed */
00576                 DPRINT("Rights not granted: %x\n", ~GrantedAccess & DesiredAccess);
00577                 Status = STATUS_ACCESS_DENIED;
00578             }
00579         }
00580         else
00581         {
00582             /* Invalid object type */
00583             Status = STATUS_OBJECT_TYPE_MISMATCH;
00584         }
00585 
00586         /* Unlock the entry */
00587         ExUnlockHandleTableEntry(HandleTable, HandleEntry);
00588     }
00589     else
00590     {
00591         /* Invalid handle */
00592         Status = STATUS_INVALID_HANDLE;
00593     }
00594 
00595     /* Return failure status */
00596     KeLeaveCriticalRegion();
00597     *Object = NULL;
00598     return Status;
00599 }
00600 
00601 /* EOF */

Generated on Sun May 27 2012 04:37:40 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.