Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenobref.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
1.7.6.1
|