Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

obhandle.c File Reference

#include "obp.h"

Go to the source code of this file.

Defines

#define GENERIC_ACCESS   (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL)

Functions

NTSTATUS ObpIncrementHandleDataBase (IN POBJECT_HEADER ObjectHeader, IN PEPROCESS Process, OUT PULONG NewProcessHandleCount)
NTSTATUS ObpCaptureHandleInformation (IN OUT PSYSTEM_HANDLE_TABLE_ENTRY_INFO *HandleEntryInfo, IN HANDLE UniqueProcessId, IN PVOID HandleTableEntry, IN HANDLE HandleIndex, IN ULONG Length, IN OUT PULONG RequiredLength)
NTSTATUS NtDuplicateObject (IN HANDLE SourceProcessHandle, IN HANDLE SourceHandle, IN HANDLE TargetProcessHandle OPTIONAL, OUT PHANDLE TargetHandle OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG HandleAttributes, IN ULONG Options)
NTSTATUS ObGetHandleInformation (OUT PSYSTEM_HANDLE_INFORMATION HandleInformation, IN ULONG Length, OUT PULONG ReturnLength OPTIONAL)
NTSTATUS ObpCaptureHandleInformation (IN OUT PSYSTEM_HANDLE_TABLE_ENTRY_INFO *HandleEntryInfo, IN HANDLE UniqueProcessId, IN PHANDLE_TABLE_ENTRY ObjectTableEntry, IN HANDLE HandleIndex, IN ULONG Length, IN OUT PULONG RequiredLength)
POBJECT_HANDLE_COUNT_ENTRY ObpInsertHandleCount (POBJECT_HEADER ObjectHeader)
NTSTATUS ObpIncrementHandleCount (OB_OPEN_REASON OpenReason, PEPROCESS Process, PVOID Object, POBJECT_TYPE ObjectType, PACCESS_STATE AccessState OPTIONAL, KPROCESSOR_MODE AccessMode, ULONG Attributes)
NTSTATUS ObpIncrementUnnamedHandleCount (PACCESS_MASK DesiredAccess, PEPROCESS Process, PVOID Object, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, ULONG Attributes)
NTSTATUS ObpChargeQuotaForObject (IN POBJECT_HEADER ObjectHeader, IN POBJECT_TYPE ObjectType, OUT PBOOLEAN NewObject)
VOID ObpDecrementHandleCount (PEPROCESS Process, POBJECT_HEADER ObjectHeader, POBJECT_TYPE ObjectType, ACCESS_MASK GrantedAccess)
NTSTATUS ObpCreateHandle (IN OB_OPEN_REASON OpenReason, IN PVOID Object, IN POBJECT_TYPE ExpectedObjectType OPTIONAL, IN PACCESS_STATE AccessState, IN ULONG ObjectPointerBias OPTIONAL, IN ULONG Attributes, IN BOOLEAN DirectoryLocked, IN KPROCESSOR_MODE AccessMode, OUT PVOID *ReferencedNewObject OPTIONAL, OUT PHANDLE Handle)
NTSTATUS ObpCreateUnnamedHandle (IN PVOID Object, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias OPTIONAL, IN ULONG Attributes, IN KPROCESSOR_MODE AccessMode, OUT PVOID *ReferencedNewObject OPTIONAL, OUT PHANDLE Handle)
NTSTATUS ObpValidateDesiredAccess (IN ACCESS_MASK DesiredAccess)

Variables

KMUTANT ObpInitKillMutant


Define Documentation

#define GENERIC_ACCESS   (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL)
 

Definition at line 27 of file obhandle.c.

Referenced by NtDuplicateObject(), ObpIncrementHandleCount(), ObpIncrementUnnamedHandleCount(), and SeCreateAccessState().


Function Documentation

NTSTATUS NtDuplicateObject IN HANDLE  SourceProcessHandle,
IN HANDLE  SourceHandle,
IN HANDLE TargetProcessHandle  OPTIONAL,
OUT PHANDLE TargetHandle  OPTIONAL,
IN ACCESS_MASK  DesiredAccess,
IN ULONG  HandleAttributes,
IN ULONG  Options
 

Definition at line 163 of file obhandle.c.

References ASSERT, AUX_ACCESS_DATA, _HANDLE_TABLE_ENTRY::CreatorBackTraceIndex, EXCEPTION_EXECUTE_HANDLER, ExCreateHandle(), Executive, FALSE, _ACCESS_STATE::GenerateOnClose, GENERIC_ACCESS, _OBJECT_TYPE_INITIALIZER::GenericMapping, _HANDLE_TABLE_ENTRY::GrantedAccess, _OBJECT_HANDLE_INFORMATION::GrantedAccess, _HANDLE_TABLE_ENTRY::GrantedAccessIndex, _OBJECT_HANDLE_INFORMATION::HandleAttributes, KeAttachProcess(), KeDetachProcess(), KeEnterCriticalRegion, KeLeaveCriticalRegion, KeReleaseMutant(), KernelMode, KeWaitForSingleObject(), KPROCESSOR_MODE, NT_SUCCESS, NtClose(), NtGlobalFlag, NTSTATUS(), NULL, _HANDLE_TABLE_ENTRY::ObAttributes, ObDereferenceObject, ObDuplicateHandle, OBJ_AUDIT_OBJECT_CLOSE, OBJ_HANDLE_ATTRIBUTES, _HANDLE_TABLE_ENTRY::Object, OBJECT_TO_OBJECT_HEADER, ObpDecrementHandleCount(), ObpGetObjectTable, ObpIncrementHandleCount(), ObpInitKillMutant, ObpValidateDesiredAccess(), ObReferenceObjectByHandle(), ProbeForWriteHandle, PsGetCurrentProcess, PsProcessType, RtlMapGenericMask(), SeAuditHandleCreation(), SeAuditHandleDuplication(), SeCreateAccessState(), _OBJECT_TYPE_INITIALIZER::SecurityProcedure, SeDefaultObjectMethod(), SeDeleteAccessState(), SeDetailedAuditing, Status, TRUE, _OBJECT_HEADER::Type, _OBJECT_TYPE::TypeInfo, and _OBJECT_TYPE_INITIALIZER::ValidAccessMask.

Referenced by AllocateConsole(), ConsoleClientShutdown(), InitWindowsStuff(), PropertiesDlgShow(), PropertiesUpdate(), RtlpChangeQueryDebugBufferTarget(), RtlpIOWorkerThread(), RtlpWaitThread(), RtlpWorkerThread(), SepServerWaitForNextConnect(), SrvConsoleNotifyLastClose(), SrvRegisterConsoleVDM(), SrvSetConsoleCP(), SrvSetConsoleDisplayMode(), and TestTokenCreate().

00175 : 00176 00177 This function creates a handle that is a duplicate of the specified 00178 source handle. The source handle is evaluated in the context of the 00179 specified source process. The calling process must have 00180 PROCESS_DUP_HANDLE access to the source process. The duplicate 00181 handle is created with the specified attributes and desired access. 00182 The duplicate handle is created in the handle table of the specified 00183 target process. The calling process must have PROCESS_DUP_HANDLE 00184 access to the target process. 00185 00186 Arguments: 00187 00188 SourceProcessHandle - Supplies a handle to the source process for the 00189 handle being duplicated 00190 00191 SourceHandle - Supplies the handle being duplicated 00192 00193 TargetProcessHandle - Optionally supplies a handle to the target process 00194 that is to receive the new handle 00195 00196 TargetHandle - Optionally returns a the new duplicated handle 00197 00198 DesiredAccess - Desired access for the new handle 00199 00200 HandleAttributes - Desired attributes for the new handle 00201 00202 Options - Duplication options that control things like close source, 00203 same access, and same attributes. 00204 00205 Return Value: 00206 00207 TBS 00208 00209 --*/ 00210 00211 { 00212 KPROCESSOR_MODE PreviousMode; 00213 NTSTATUS Status; 00214 PVOID SourceObject; 00215 POBJECT_HEADER ObjectHeader; 00216 POBJECT_TYPE ObjectType; 00217 PEPROCESS SourceProcess; 00218 PEPROCESS TargetProcess; 00219 BOOLEAN Attached; 00220 PVOID ObjectTable; 00221 HANDLE_TABLE_ENTRY ObjectTableEntry; 00222 OBJECT_HANDLE_INFORMATION HandleInformation; 00223 HANDLE NewHandle; 00224 ACCESS_STATE AccessState; 00225 AUX_ACCESS_DATA AuxData; 00226 ACCESS_MASK SourceAccess; 00227 ACCESS_MASK TargetAccess; 00228 PACCESS_STATE PassedAccessState = NULL; 00229 00230 // 00231 // Get previous processor mode and probe output arguments if necessary. 00232 // 00233 00234 PreviousMode = KeGetPreviousMode(); 00235 00236 if (ARGUMENT_PRESENT( TargetHandle ) && (PreviousMode != KernelMode)) { 00237 00238 try { 00239 00240 ProbeForWriteHandle( TargetHandle ); 00241 00242 } except( EXCEPTION_EXECUTE_HANDLER ) { 00243 00244 return( GetExceptionCode() ); 00245 } 00246 } 00247 00248 // 00249 // If the caller is not asking for the same access then 00250 // validate the access they are requesting doesn't contain 00251 // any bad bits 00252 // 00253 00254 if (!(Options & DUPLICATE_SAME_ACCESS)) { 00255 00256 Status = ObpValidateDesiredAccess( DesiredAccess ); 00257 00258 if (!NT_SUCCESS( Status )) { 00259 00260 return( Status ); 00261 } 00262 } 00263 00264 // 00265 // The Attached variable indicates if we needed to 00266 // attach to the source process because it was not the 00267 // current process. 00268 // 00269 00270 Attached = FALSE; 00271 00272 // 00273 // Given the input source process handle get a pointer 00274 // to the source process object 00275 // 00276 00277 Status = ObReferenceObjectByHandle( SourceProcessHandle, 00278 PROCESS_DUP_HANDLE, 00279 PsProcessType, 00280 PreviousMode, 00281 (PVOID *)&SourceProcess, 00282 NULL ); 00283 00284 if (!NT_SUCCESS( Status )) { 00285 00286 return Status; 00287 } 00288 00289 // 00290 // Lock down access to the process object tables 00291 // 00292 00293 KeEnterCriticalRegion(); 00294 00295 KeWaitForSingleObject( &ObpInitKillMutant, 00296 Executive, 00297 KernelMode, 00298 FALSE, 00299 NULL ); 00300 00301 // 00302 // Make sure the source process has an object table still 00303 // 00304 00305 if ( SourceProcess->ObjectTable == NULL ) { 00306 00307 KeReleaseMutant( &ObpInitKillMutant, 0, FALSE, FALSE ); 00308 00309 KeLeaveCriticalRegion(); 00310 00311 ObDereferenceObject( SourceProcess ); 00312 00313 return STATUS_PROCESS_IS_TERMINATING; 00314 } 00315 00316 // 00317 // If the specified source process is not the current process, attach 00318 // to the specified source process. Then after we reference the object 00319 // we can detach from the process. 00320 // 00321 00322 if (PsGetCurrentProcess() != SourceProcess) { 00323 00324 KeAttachProcess( &SourceProcess->Pcb ); 00325 00326 Attached = TRUE; 00327 } 00328 00329 // 00330 // The the input source handle get a pointer to the 00331 // source object itself, then detach from the process 00332 // if necessary and check if we were given a good 00333 // source handle. 00334 // 00335 00336 Status = ObReferenceObjectByHandle( SourceHandle, 00337 0, 00338 (POBJECT_TYPE)NULL, 00339 PreviousMode, 00340 &SourceObject, 00341 &HandleInformation ); 00342 00343 if (Attached) { 00344 00345 KeDetachProcess(); 00346 00347 Attached = FALSE; 00348 } 00349 00350 if (!NT_SUCCESS( Status )) { 00351 00352 KeReleaseMutant( &ObpInitKillMutant, 0, FALSE, FALSE ); 00353 00354 KeLeaveCriticalRegion(); 00355 00356 ObDereferenceObject( SourceProcess ); 00357 00358 return( Status ); 00359 } 00360 00361 // 00362 // We are all done if no target process handle was specified. 00363 // This is practially a noop because the only really end result 00364 // could be that we've closed the source handle. 00365 // 00366 00367 if (!ARGUMENT_PRESENT( TargetProcessHandle )) { 00368 00369 // 00370 // If no TargetProcessHandle, then only possible option is to close 00371 // the source handle in the context of the source process. 00372 // 00373 00374 if (!(Options & DUPLICATE_CLOSE_SOURCE)) { 00375 00376 Status = STATUS_INVALID_PARAMETER; 00377 } 00378 00379 if (Options & DUPLICATE_CLOSE_SOURCE) { 00380 00381 KeAttachProcess( &SourceProcess->Pcb ); 00382 00383 NtClose( SourceHandle ); 00384 00385 KeDetachProcess(); 00386 } 00387 00388 KeReleaseMutant( &ObpInitKillMutant, 0, FALSE, FALSE ); 00389 00390 KeLeaveCriticalRegion(); 00391 00392 ObDereferenceObject( SourceObject ); 00393 ObDereferenceObject( SourceProcess ); 00394 00395 return( Status ); 00396 } 00397 00398 SourceAccess = HandleInformation.GrantedAccess; 00399 00400 // 00401 // At this point the caller did specify for a target process 00402 // So from the target process handle get a pointer to the 00403 // target process object. 00404 // 00405 00406 Status = ObReferenceObjectByHandle( TargetProcessHandle, 00407 PROCESS_DUP_HANDLE, 00408 PsProcessType, 00409 PreviousMode, 00410 (PVOID *)&TargetProcess, 00411 NULL ); 00412 00413 // 00414 // If we cannot get the traget process object then close the 00415 // source down if requsted, cleanup and return to our caller 00416 // 00417 00418 if (!NT_SUCCESS( Status )) { 00419 00420 if (Options & DUPLICATE_CLOSE_SOURCE) { 00421 00422 KeAttachProcess( &SourceProcess->Pcb ); 00423 00424 NtClose( SourceHandle ); 00425 00426 KeDetachProcess(); 00427 } 00428 00429 KeReleaseMutant( &ObpInitKillMutant, 0, FALSE, FALSE ); 00430 00431 KeLeaveCriticalRegion(); 00432 00433 ObDereferenceObject( SourceObject ); 00434 ObDereferenceObject( SourceProcess ); 00435 00436 return( Status ); 00437 } 00438 00439 // 00440 // Make sure the target process has not exited 00441 // 00442 00443 if ( TargetProcess->ObjectTable == NULL ) { 00444 00445 if (Options & DUPLICATE_CLOSE_SOURCE) { 00446 00447 KeAttachProcess( &SourceProcess->Pcb ); 00448 00449 NtClose( SourceHandle ); 00450 00451 KeDetachProcess(); 00452 } 00453 00454 KeReleaseMutant( &ObpInitKillMutant, 0, FALSE, FALSE ); 00455 00456 KeLeaveCriticalRegion(); 00457 00458 ObDereferenceObject( SourceObject ); 00459 ObDereferenceObject( SourceProcess ); 00460 ObDereferenceObject( TargetProcess ); 00461 00462 return STATUS_PROCESS_IS_TERMINATING; 00463 } 00464 00465 // 00466 // If the specified target process is not the current process, attach 00467 // to the specified target process. 00468 // 00469 00470 if (PsGetCurrentProcess() != TargetProcess) { 00471 00472 KeAttachProcess( &TargetProcess->Pcb ); 00473 00474 Attached = TRUE; 00475 } 00476 00477 // 00478 // Construct the proper desired access and attributes for the new handle 00479 // 00480 00481 if (Options & DUPLICATE_SAME_ACCESS) { 00482 00483 DesiredAccess = SourceAccess; 00484 } 00485 00486 if (Options & DUPLICATE_SAME_ATTRIBUTES) { 00487 00488 HandleAttributes = HandleInformation.HandleAttributes; 00489 00490 } else { 00491 00492 // 00493 // Always propogate auditing information. 00494 // 00495 00496 HandleAttributes |= HandleInformation.HandleAttributes & OBJ_AUDIT_OBJECT_CLOSE; 00497 } 00498 00499 // 00500 // Get the object header for the source object 00501 // 00502 00503 ObjectHeader = OBJECT_TO_OBJECT_HEADER( SourceObject ); 00504 ObjectType = ObjectHeader->Type; 00505 00506 ObjectTableEntry.Object = ObjectHeader; 00507 ObjectTableEntry.ObAttributes |= (HandleAttributes & OBJ_HANDLE_ATTRIBUTES); 00508 00509 // 00510 // If any of the generic access bits are specified then map those to more 00511 // specific access bits 00512 // 00513 00514 if ((DesiredAccess & GENERIC_ACCESS) != 0) { 00515 00516 RtlMapGenericMask( &DesiredAccess, 00517 &ObjectType->TypeInfo.GenericMapping ); 00518 } 00519 00520 // 00521 // Make sure to preserve ACCESS_SYSTEM_SECURITY, which most likely is not 00522 // found in the ValidAccessMask 00523 // 00524 00525 TargetAccess = DesiredAccess & 00526 (ObjectType->TypeInfo.ValidAccessMask | ACCESS_SYSTEM_SECURITY); 00527 00528 // 00529 // If the access requested for the target is a superset of the 00530 // access allowed in the source, perform full AVR. If it is a 00531 // subset or equal, do not perform any access validation. 00532 // 00533 // Do not allow superset access if object type has a private security 00534 // method, as there is no means to call them in this case to do the 00535 // access check. 00536 // 00537 // If the AccessState is not passed to ObpIncrementHandleCount 00538 // there will be no AVR. 00539 // 00540 00541 if (TargetAccess & ~SourceAccess) { 00542 00543 if (ObjectType->TypeInfo.SecurityProcedure == SeDefaultObjectMethod) { 00544 00545 Status = SeCreateAccessState( &AccessState, 00546 &AuxData, 00547 TargetAccess, // DesiredAccess 00548 &ObjectType->TypeInfo.GenericMapping ); 00549 00550 PassedAccessState = &AccessState; 00551 00552 } else { 00553 00554 Status = STATUS_ACCESS_DENIED; 00555 } 00556 00557 } else { 00558 00559 // 00560 // Do not perform AVR 00561 // 00562 00563 PassedAccessState = NULL; 00564 00565 Status = STATUS_SUCCESS; 00566 } 00567 00568 // 00569 // Increment the new handle count and get a pointer to 00570 // the target processes object table 00571 // 00572 00573 if ( NT_SUCCESS( Status )) { 00574 00575 Status = ObpIncrementHandleCount( ObDuplicateHandle, 00576 PsGetCurrentProcess(), // this is already the target process 00577 SourceObject, 00578 ObjectType, 00579 PassedAccessState, 00580 PreviousMode, 00581 HandleAttributes ); 00582 00583 ObjectTable = ObpGetObjectTable(); 00584 00585 ASSERT(ObjectTable); 00586 } 00587 00588 if (Attached) { 00589 00590 KeDetachProcess(); 00591 00592 Attached = FALSE; 00593 } 00594 00595 if (Options & DUPLICATE_CLOSE_SOURCE) { 00596 00597 KeAttachProcess( &SourceProcess->Pcb ); 00598 00599 NtClose( SourceHandle ); 00600 00601 KeDetachProcess(); 00602 } 00603 00604 if (!NT_SUCCESS( Status )) { 00605 00606 if (PassedAccessState != NULL) { 00607 00608 SeDeleteAccessState( PassedAccessState ); 00609 } 00610 00611 KeReleaseMutant( &ObpInitKillMutant, 0, FALSE, FALSE ); 00612 00613 KeLeaveCriticalRegion(); 00614 00615 ObDereferenceObject( SourceObject ); 00616 ObDereferenceObject( SourceProcess ); 00617 ObDereferenceObject( TargetProcess ); 00618 00619 return( Status ); 00620 } 00621 00622 if ((PassedAccessState != NULL) && (PassedAccessState->GenerateOnClose == TRUE)) { 00623 00624 // 00625 // If we performed AVR opening the handle, then mark the handle as needing 00626 // auditing when it's closed. 00627 // 00628 00629 ObjectTableEntry.ObAttributes |= OBJ_AUDIT_OBJECT_CLOSE; 00630 } 00631 00632 #if i386 && !FPO 00633 00634 if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) { 00635 00636 ObjectTableEntry.GrantedAccessIndex = ObpComputeGrantedAccessIndex( TargetAccess ); 00637 ObjectTableEntry.CreatorBackTraceIndex = RtlLogStackBackTrace(); 00638 00639 } else { 00640 00641 ObjectTableEntry.GrantedAccess = TargetAccess; 00642 } 00643 00644 #else 00645 00646 ObjectTableEntry.GrantedAccess = TargetAccess; 00647 00648 #endif // i386 && !FPO 00649 00650 // 00651 // Now that we've constructed a new object table entry for the duplicated handle 00652 // we need to add it to the object table of the target process 00653 00654 00655 NewHandle = ExCreateHandle( ObjectTable, &ObjectTableEntry ); 00656 00657 if (NewHandle) { 00658 00659 // 00660 // We have a new handle to audit the creation of the new handle if 00661 // AVR was done. And set the optional output handle variable. Note 00662 // that if we reach here the status variable is already a success 00663 // 00664 00665 if (PassedAccessState != NULL) { 00666 00667 SeAuditHandleCreation( PassedAccessState, NewHandle ); 00668 } 00669 00670 if (SeDetailedAuditing && (ObjectTableEntry.ObAttributes & OBJ_AUDIT_OBJECT_CLOSE)) { 00671 00672 SeAuditHandleDuplication( SourceHandle, 00673 NewHandle, 00674 SourceProcess, 00675 TargetProcess ); 00676 } 00677 00678 if (ARGUMENT_PRESENT( TargetHandle )) { 00679 00680 try { 00681 00682 *TargetHandle = NewHandle; 00683 00684 } except( EXCEPTION_EXECUTE_HANDLER ) { 00685 00686 // 00687 // Fall through, since we cannot undo what we have done. 00688 // 00689 } 00690 } 00691 00692 } else { 00693 00694 // 00695 // We didn't get a new handle to decrement the handle count dereference 00696 // the necessary objects, set the optional output variable and indicate 00697 // why we're failing 00698 // 00699 00700 ObpDecrementHandleCount( TargetProcess, 00701 ObjectHeader, 00702 ObjectType, 00703 TargetAccess ); 00704 00705 ObDereferenceObject( SourceObject ); 00706 00707 if (ARGUMENT_PRESENT( TargetHandle )) { 00708 00709 try { 00710 00711 *TargetHandle = (HANDLE)NULL; 00712 00713 } except( EXCEPTION_EXECUTE_HANDLER ) { 00714 00715 // 00716 // Fall through so we can return the correct status. 00717 // 00718 } 00719 } 00720 00721 Status = STATUS_INSUFFICIENT_RESOURCES; 00722 } 00723 00724 // 00725 // Cleanup from our selfs and then return to our caller 00726 // 00727 00728 if (PassedAccessState != NULL) { 00729 00730 SeDeleteAccessState( PassedAccessState ); 00731 } 00732 00733 KeReleaseMutant( &ObpInitKillMutant, 0, FALSE, FALSE ); 00734 00735 KeLeaveCriticalRegion(); 00736 00737 ObDereferenceObject( SourceProcess ); 00738 ObDereferenceObject( TargetProcess ); 00739 00740 return( Status ); 00741 }

NTSTATUS ObGetHandleInformation OUT PSYSTEM_HANDLE_INFORMATION  HandleInformation,
IN ULONG  Length,
OUT PULONG ReturnLength  OPTIONAL
 

Definition at line 745 of file obhandle.c.

References ExSnapShotHandleTables(), NTSTATUS(), ObpCaptureHandleInformation(), PAGED_CODE, and Status.

Referenced by ExpGetHandleInformation().

00753 : 00754 00755 This routine returns information about the specified handle. 00756 00757 Arguments: 00758 00759 HandleInformation - Supplies an array of handle information 00760 structures to fill in 00761 00762 Length - Supplies the length the handle information array in bytes 00763 00764 ReturnLength - Receives the number of bytes used by this call 00765 00766 Return Value: 00767 00768 An appropriate status value 00769 00770 --*/ 00771 00772 { 00773 NTSTATUS Status; 00774 ULONG RequiredLength; 00775 00776 PAGED_CODE(); 00777 00778 RequiredLength = FIELD_OFFSET( SYSTEM_HANDLE_INFORMATION, Handles ); 00779 00780 if (Length < RequiredLength) { 00781 00782 return( STATUS_INFO_LENGTH_MISMATCH ); 00783 } 00784 00785 HandleInformation->NumberOfHandles = 0; 00786 00787 // 00788 // For every handle in every handle table we'll be calling 00789 // our callback routine 00790 // 00791 00792 Status = ExSnapShotHandleTables( ObpCaptureHandleInformation, 00793 HandleInformation, 00794 Length, 00795 &RequiredLength ); 00796 00797 if (ARGUMENT_PRESENT( ReturnLength )) { 00798 00799 *ReturnLength = RequiredLength; 00800 } 00801 00802 return( Status ); 00803 }

NTSTATUS ObpCaptureHandleInformation IN OUT PSYSTEM_HANDLE_TABLE_ENTRY_INFO *  HandleEntryInfo,
IN HANDLE  UniqueProcessId,
IN PHANDLE_TABLE_ENTRY  ObjectTableEntry,
IN HANDLE  HandleIndex,
IN ULONG  Length,
IN OUT PULONG  RequiredLength
 

Definition at line 807 of file obhandle.c.

References _OBJECT_HEADER::Body, _OBJECT_TYPE::Index, NtGlobalFlag, NTSTATUS(), OBJ_HANDLE_ATTRIBUTES, Status, _OBJECT_HEADER::Type, and USHORT.

00818 : 00819 00820 This is the callback routine of ObGetHandleInformation 00821 00822 Arguments: 00823 00824 HandleEntryInfo - Supplies a pointer to the output buffer to receive 00825 the handle information 00826 00827 UniqueProcessId - Supplies the process id of the caller 00828 00829 ObjectTableEntry - Supplies the handle table entry that is being 00830 captured 00831 00832 HandleIndex - Supplies the index for the preceding handle table entry 00833 00834 Length - Specifies the length, in bytes, of the original user buffer 00835 00836 RequiredLength - Specifies the length, in bytes, that has already been 00837 used in the buffer to store information. On return this receives 00838 the updated number of bytes being used. 00839 00840 Note that the HandleEntryInfo does not necessarily point to the 00841 start of the original user buffer. It will have been offset by 00842 the feed-in RequiredLength value. 00843 00844 Return Value: 00845 00846 An appropriate status value 00847 00848 --*/ 00849 00850 { 00851 NTSTATUS Status; 00852 POBJECT_HEADER ObjectHeader; 00853 00854 // 00855 // Figure out who much size we really need to contain this extra record 00856 // and then check that it fits. 00857 // 00858 00859 *RequiredLength += sizeof( SYSTEM_HANDLE_TABLE_ENTRY_INFO ); 00860 00861 if (Length < *RequiredLength) { 00862 00863 Status = STATUS_INFO_LENGTH_MISMATCH; 00864 00865 } else { 00866 00867 // 00868 // Get the object header from the table entry and then copy over the information 00869 // 00870 00871 ObjectHeader = (POBJECT_HEADER)(((ULONG_PTR)(ObjectTableEntry->Object)) & ~OBJ_HANDLE_ATTRIBUTES); 00872 00873 (*HandleEntryInfo)->UniqueProcessId = (USHORT)((ULONG_PTR)UniqueProcessId); 00874 (*HandleEntryInfo)->HandleAttributes = (UCHAR)(ObjectTableEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES); 00875 (*HandleEntryInfo)->ObjectTypeIndex = (UCHAR)(ObjectHeader->Type->Index); 00876 (*HandleEntryInfo)->HandleValue = (USHORT)((ULONG_PTR)(HandleIndex)); 00877 (*HandleEntryInfo)->Object = &ObjectHeader->Body; 00878 (*HandleEntryInfo)->CreatorBackTraceIndex = 0; 00879 00880 #if i386 && !FPO 00881 00882 if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) { 00883 00884 (*HandleEntryInfo)->CreatorBackTraceIndex = ObjectTableEntry->CreatorBackTraceIndex; 00885 (*HandleEntryInfo)->GrantedAccess = ObpTranslateGrantedAccessIndex( ObjectTableEntry->GrantedAccessIndex ); 00886 00887 } else { 00888 00889 (*HandleEntryInfo)->GrantedAccess = ObjectTableEntry->GrantedAccess; 00890 } 00891 00892 #else 00893 00894 (*HandleEntryInfo)->GrantedAccess = ObjectTableEntry->GrantedAccess; 00895 00896 #endif // i386 && !FPO 00897 00898 (*HandleEntryInfo)++; 00899 00900 Status = STATUS_SUCCESS; 00901 } 00902 00903 return( Status ); 00904 }

NTSTATUS ObpCaptureHandleInformation IN OUT PSYSTEM_HANDLE_TABLE_ENTRY_INFO *  HandleEntryInfo,
IN HANDLE  UniqueProcessId,
IN PVOID  HandleTableEntry,
IN HANDLE  HandleIndex,
IN ULONG  Length,
IN OUT PULONG  RequiredLength
 

Referenced by ObGetHandleInformation().

NTSTATUS ObpChargeQuotaForObject IN POBJECT_HEADER  ObjectHeader,
IN POBJECT_TYPE  ObjectType,
OUT PBOOLEAN  NewObject
 

Definition at line 1861 of file obhandle.c.

References FALSE, _OBJECT_HEADER_QUOTA_INFO::NonPagedPoolCharge, NULL, OB_FLAG_DEFAULT_SECURITY_QUOTA, OB_FLAG_NEW_OBJECT, OBJECT_HEADER_TO_QUOTA_INFO, _OBJECT_HEADER_QUOTA_INFO::PagedPoolCharge, PsChargeSharedPoolQuota(), PsGetCurrentProcess, SE_DEFAULT_SECURITY_QUOTA, _OBJECT_HEADER_QUOTA_INFO::SecurityDescriptorCharge, and TRUE.

Referenced by ObpIncrementHandleCount(), and ObpIncrementUnnamedHandleCount().

01869 : 01870 01871 This routine charges quota against the current process for the new 01872 object 01873 01874 Arguments: 01875 01876 ObjectHeader - Supplies a pointer to the new object being charged for 01877 01878 ObjectType - Supplies the type of the new object 01879 01880 NewObject - Returns true if the object is really new and false otherwise 01881 01882 Return Value: 01883 01884 An appropriate status value 01885 01886 --*/ 01887 01888 { 01889 POBJECT_HEADER_QUOTA_INFO QuotaInfo; 01890 ULONG NonPagedPoolCharge; 01891 ULONG PagedPoolCharge; 01892 01893 // 01894 // Get a pointer to the quota block for this object 01895 // 01896 01897 QuotaInfo = OBJECT_HEADER_TO_QUOTA_INFO( ObjectHeader ); 01898 01899 *NewObject = FALSE; 01900 01901 // 01902 // If the object is new then we have work to do otherwise 01903 // we'll return with NewObject set to false 01904 // 01905 01906 if (ObjectHeader->Flags & OB_FLAG_NEW_OBJECT) { 01907 01908 // 01909 // Say the object now isn't new 01910 // 01911 01912 ObjectHeader->Flags &= ~OB_FLAG_NEW_OBJECT; 01913 01914 // 01915 // If there does exist a quota info structure for this 01916 // object then calculate what our charge should be from 01917 // the information stored in that structure 01918 // 01919 01920 if (QuotaInfo != NULL) { 01921 01922 PagedPoolCharge = QuotaInfo->PagedPoolCharge + 01923 QuotaInfo->SecurityDescriptorCharge; 01924 NonPagedPoolCharge = QuotaInfo->NonPagedPoolCharge; 01925 01926 } else { 01927 01928 // 01929 // There isn't any quota information so we're on our own 01930 // Paged pool charge is the default for the object plus 01931 // the security descriptor if present. Nonpaged pool charge 01932 // is the default for the object. 01933 // 01934 01935 PagedPoolCharge = ObjectType->TypeInfo.DefaultPagedPoolCharge; 01936 01937 if (ObjectHeader->SecurityDescriptor != NULL) { 01938 01939 ObjectHeader->Flags |= OB_FLAG_DEFAULT_SECURITY_QUOTA; 01940 PagedPoolCharge += SE_DEFAULT_SECURITY_QUOTA; 01941 } 01942 01943 NonPagedPoolCharge = ObjectType->TypeInfo.DefaultNonPagedPoolCharge; 01944 } 01945 01946 // 01947 // Now charge for the quota and make sure it succeeds 01948 // 01949 01950 ObjectHeader->QuotaBlockCharged = (PVOID)PsChargeSharedPoolQuota( PsGetCurrentProcess(), 01951 PagedPoolCharge, 01952 NonPagedPoolCharge ); 01953 01954 if (ObjectHeader->QuotaBlockCharged == NULL) { 01955 01956 return STATUS_QUOTA_EXCEEDED; 01957 } 01958 01959 *NewObject = TRUE; 01960 } 01961 01962 return STATUS_SUCCESS; 01963 }

NTSTATUS ObpCreateHandle IN OB_OPEN_REASON  OpenReason,
IN PVOID  Object,
IN POBJECT_TYPE ExpectedObjectType  OPTIONAL,
IN PACCESS_STATE  AccessState,
IN ULONG ObjectPointerBias  OPTIONAL,
IN ULONG  Attributes,
IN BOOLEAN  DirectoryLocked,
IN KPROCESSOR_MODE  AccessMode,
OUT PVOID *ReferencedNewObject  OPTIONAL,
OUT PHANDLE  Handle
 

Definition at line 2160 of file obhandle.c.

References _HANDLE_TABLE_ENTRY::CreatorBackTraceIndex, EncodeKernelHandle, ExCreateHandle(), FALSE, _HANDLE_TABLE_ENTRY::GrantedAccess, _HANDLE_TABLE_ENTRY::GrantedAccessIndex, Handle, KernelMode, KeStackAttachProcess(), KeUnstackDetachProcess(), NT_SUCCESS, NtGlobalFlag, NTSTATUS(), NULL, _HANDLE_TABLE_ENTRY::ObAttributes, ObCreateHandle, OBJ_AUDIT_OBJECT_CLOSE, OBJ_HANDLE_ATTRIBUTES, _HANDLE_TABLE_ENTRY::Object, OBJECT_TO_OBJECT_HEADER, ObpDecrementHandleCount(), ObpDecrPointerCount, ObpGetObjectTable, ObpIncrementHandleCount(), ObpIncrPointerCount, ObpKernelHandleTable, ObpLeaveRootDirectoryMutex, ObpValidateIrql, PAGED_CODE, PAUX_ACCESS_DATA, _EPROCESS::Pcb, _AUX_ACCESS_DATA::PrivilegesUsed, PsGetCurrentProcess, PsInitialSystemProcess, SeAuditHandleCreation(), SePrivilegeObjectAuditAlarm(), Status, TRUE, _OBJECT_HEADER::Type, _OBJECT_TYPE::TypeInfo, and _OBJECT_TYPE_INITIALIZER::ValidAccessMask.

Referenced by ObInsertObject(), ObOpenObjectByName(), and ObOpenObjectByPointer().

02175 : 02176 02177 This function creates a new handle to an existing object 02178 02179 Arguments: 02180 02181 OpenReason - The reason why we are doing this work 02182 02183 Object - A pointer to the body of the new object 02184 02185 ExpectedObjectType - Optionally Supplies the object type that 02186 the caller is expecting 02187 02188 AccessState - Supplies the access state for the handle requested 02189 by the caller 02190 02191 ObjectPointerBias - Optionally supplies a count of addition 02192 increments we do to the pointer count for the object 02193 02194 Attributes - Desired attributes for the handle 02195 02196 DirectoryLocked - Indicates if the root directory mutex is already held 02197 02198 AccessMode - Supplies the mode of the requestor. 02199 02200 ReferencedNewObject - Optionally receives a pointer to the body 02201 of the new object 02202 02203 Handle - Receives the new handle value 02204 02205 Return Value: 02206 02207 An appropriate status value 02208 02209 --*/ 02210 02211 { 02212 NTSTATUS Status; 02213 POBJECT_HEADER ObjectHeader; 02214 POBJECT_TYPE ObjectType; 02215 PVOID ObjectTable; 02216 HANDLE_TABLE_ENTRY ObjectTableEntry; 02217 HANDLE NewHandle; 02218 ACCESS_MASK DesiredAccess; 02219 ACCESS_MASK GrantedAccess; 02220 ULONG BiasCount; 02221 BOOLEAN AttachedToProcess = FALSE; 02222 BOOLEAN KernelHandle = FALSE; 02223 KAPC_STATE ApcState; 02224 02225 PAGED_CODE(); 02226 02227 ObpValidateIrql( "ObpCreateHandle" ); 02228 02229 // 02230 // Merge both the remaining desired access and the currently 02231 // granted access states into one mask 02232 // 02233 // **** why is this being done here and then later in the this 02234 // same routine. 02235 // 02236 02237 DesiredAccess = AccessState->RemainingDesiredAccess | 02238 AccessState->PreviouslyGrantedAccess; 02239 02240 // 02241 // Get a pointer to the object header and object type 02242 // 02243 02244 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 02245 ObjectType = ObjectHeader->Type; 02246 02247 // 02248 // If the object type isn't what was expected then 02249 // return an error to our caller, but first see if 02250 // we should release the directory mutex 02251 // 02252 02253 if ((ARGUMENT_PRESENT( ExpectedObjectType )) && 02254 (ObjectType != ExpectedObjectType )) { 02255 02256 if (DirectoryLocked) { 02257 02258 ObpLeaveRootDirectoryMutex(); 02259 } 02260 02261 return( STATUS_OBJECT_TYPE_MISMATCH ); 02262 } 02263 02264 // 02265 // Set the first ulong of the object table entry to point 02266 // back to the object header 02267 // 02268 02269 ObjectTableEntry.Object = ObjectHeader; 02270 02271 // 02272 // Now get a pointer to the object table for either the current process 02273 // of the kernel handle table 02274 // 02275 02276 if ((Attributes & OBJ_KERNEL_HANDLE) && (AccessMode == KernelMode)) { 02277 02278 ObjectTable = ObpKernelHandleTable; 02279 KernelHandle = TRUE; 02280 02281 // 02282 // Go to the system process if we have to 02283 // 02284 02285 if (PsGetCurrentProcess() != PsInitialSystemProcess) { 02286 KeStackAttachProcess (&PsInitialSystemProcess->Pcb, &ApcState); 02287 AttachedToProcess = TRUE; 02288 } 02289 02290 02291 } else { 02292 02293 ObjectTable = ObpGetObjectTable(); 02294 } 02295 02296 // 02297 // ObpIncrementHandleCount will perform access checking on the 02298 // object being opened as appropriate. 02299 // 02300 02301 Status = ObpIncrementHandleCount( OpenReason, 02302 PsGetCurrentProcess(), 02303 Object, 02304 ObjectType, 02305 AccessState, 02306 AccessMode, 02307 Attributes ); 02308 02309 if (AccessState->GenerateOnClose) { 02310 02311 Attributes |= OBJ_AUDIT_OBJECT_CLOSE; 02312 } 02313 02314 // 02315 // Or in some low order bits into the first ulong of the object 02316 // table entry 02317 // 02318 02319 ObjectTableEntry.ObAttributes |= (Attributes & OBJ_HANDLE_ATTRIBUTES); 02320 02321 // 02322 // Merge both the remaining desired access and the currently 02323 // granted access states into one mask and then compute 02324 // the granted access 02325 // 02326 02327 DesiredAccess = AccessState->RemainingDesiredAccess | 02328 AccessState->PreviouslyGrantedAccess; 02329 02330 GrantedAccess = DesiredAccess & 02331 (ObjectType->TypeInfo.ValidAccessMask | ACCESS_SYSTEM_SECURITY ); 02332 02333 // 02334 // Unlock the directory if it is locked and make sure 02335 // we've been successful so far 02336 // 02337 02338 if (DirectoryLocked) { 02339 02340 ObpLeaveRootDirectoryMutex(); 02341 } 02342 02343 if (!NT_SUCCESS( Status )) { 02344 02345 // 02346 // If we are attached to the system process then return 02347 // back to our caller 02348 // 02349 02350 if (AttachedToProcess) { 02351 KeUnstackDetachProcess(&ApcState); 02352 AttachedToProcess = FALSE; 02353 } 02354 02355 return( Status ); 02356 } 02357 02358 // 02359 // Bias the pointer count if that is what the caller wanted 02360 // 02361 02362 if (ARGUMENT_PRESENT( (PVOID)(ULONG_PTR)ObjectPointerBias )) { 02363 02364 BiasCount = ObjectPointerBias; 02365 02366 while (BiasCount--) { 02367 02368 ObpIncrPointerCount( ObjectHeader ); 02369 } 02370 } 02371 02372 // 02373 // Set the granted access mask in the object table entry (second ulong) 02374 // 02375 02376 #if i386 && !FPO 02377 02378 if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) { 02379 02380 ObjectTableEntry.GrantedAccessIndex = ObpComputeGrantedAccessIndex( GrantedAccess ); 02381 ObjectTableEntry.CreatorBackTraceIndex = RtlLogStackBackTrace(); 02382 02383 } else { 02384 02385 ObjectTableEntry.GrantedAccess = GrantedAccess; 02386 } 02387 02388 #else 02389 02390 ObjectTableEntry.GrantedAccess = GrantedAccess; 02391 02392 #endif // i386 && !FPO 02393 02394 // 02395 // Add this new object table entry to the object table for the process 02396 // 02397 02398 NewHandle = ExCreateHandle( ObjectTable, &ObjectTableEntry ); 02399 02400 // 02401 // If we didn't get a handle then cleanup after ourselves and return 02402 // the error to our caller 02403 // 02404 02405 if (NewHandle == NULL) { 02406 02407 if (ARGUMENT_PRESENT( (PVOID)(ULONG_PTR)ObjectPointerBias )) { 02408 02409 BiasCount = ObjectPointerBias; 02410 02411 while (BiasCount--) { 02412 02413 ObpDecrPointerCount( ObjectHeader ); 02414 } 02415 } 02416 02417 ObpDecrementHandleCount( PsGetCurrentProcess(), 02418 ObjectHeader, 02419 ObjectType, 02420 GrantedAccess ); 02421 02422 // 02423 // If we are attached to the system process then return 02424 // back to our caller 02425 // 02426 02427 if (AttachedToProcess) { 02428 KeUnstackDetachProcess(&ApcState); 02429 AttachedToProcess = FALSE; 02430 } 02431 02432 return( STATUS_INSUFFICIENT_RESOURCES ); 02433 } 02434 02435 // 02436 // We have a new Ex style handle now make it an ob style handle and also 02437 // adjust for the kernel handle by setting the sign bit in the handle 02438 // value 02439 // 02440 02441 if (KernelHandle) { 02442 02443 NewHandle = EncodeKernelHandle( NewHandle ); 02444 } 02445 02446 *Handle = NewHandle; 02447 02448 // 02449 // If requested, generate audit messages to indicate that a new handle 02450 // has been allocated. 02451 // 02452 // This is the final security operation in the creation/opening of the 02453 // object. 02454 // 02455 02456 if ( AccessState->GenerateAudit ) { 02457 02458 SeAuditHandleCreation( AccessState, 02459 *Handle ); 02460 } 02461 02462 if (OpenReason == ObCreateHandle) { 02463 02464 PAUX_ACCESS_DATA AuxData = AccessState->AuxData; 02465 02466 if ( ( AuxData->PrivilegesUsed != NULL) && (AuxData->PrivilegesUsed->PrivilegeCount > 0) ) { 02467 02468 SePrivilegeObjectAuditAlarm( *Handle, 02469 &AccessState->SubjectSecurityContext, 02470 GrantedAccess, 02471 AuxData->PrivilegesUsed, 02472 TRUE, 02473 KeGetPreviousMode() ); 02474 } 02475 } 02476 02477 // 02478 // If the caller had a pointer bias and wanted the new reference object 02479 // then return that value 02480 // 02481 02482 if ((ARGUMENT_PRESENT( (PVOID)(ULONG_PTR)ObjectPointerBias )) && 02483 (ARGUMENT_PRESENT( ReferencedNewObject ))) { 02484 02485 *ReferencedNewObject = Object; 02486 } 02487 02488 // 02489 // If we are attached to the system process then return 02490 // back to our caller 02491 // 02492 02493 if (AttachedToProcess) { 02494 KeUnstackDetachProcess(&ApcState); 02495 AttachedToProcess = FALSE; 02496 } 02497 02498 // 02499 // And return to our caller 02500 // 02501 02502 return( STATUS_SUCCESS ); 02503 }

NTSTATUS ObpCreateUnnamedHandle IN PVOID  Object,
IN ACCESS_MASK  DesiredAccess,
IN ULONG ObjectPointerBias  OPTIONAL,
IN ULONG  Attributes,
IN KPROCESSOR_MODE  AccessMode,
OUT PVOID *ReferencedNewObject  OPTIONAL,
OUT PHANDLE  Handle
 

Definition at line 2507 of file obhandle.c.

References _HANDLE_TABLE_ENTRY::CreatorBackTraceIndex, EncodeKernelHandle, ExCreateHandle(), FALSE, _HANDLE_TABLE_ENTRY::GrantedAccess, _HANDLE_TABLE_ENTRY::GrantedAccessIndex, Handle, KernelMode, KeStackAttachProcess(), KeUnstackDetachProcess(), NT_SUCCESS, NtGlobalFlag, NTSTATUS(), NULL, _HANDLE_TABLE_ENTRY::ObAttributes, OBJ_HANDLE_ATTRIBUTES, _HANDLE_TABLE_ENTRY::Object, OBJECT_TO_OBJECT_HEADER, ObpDecrementHandleCount(), ObpDecrPointerCount, ObpGetObjectTable, ObpIncrementUnnamedHandleCount(), ObpIncrPointerCount, ObpKernelHandleTable, ObpValidateIrql, PAGED_CODE, _EPROCESS::Pcb, PsGetCurrentProcess, PsInitialSystemProcess, Status, TRUE, _OBJECT_HEADER::Type, _OBJECT_TYPE::TypeInfo, and _OBJECT_TYPE_INITIALIZER::ValidAccessMask.

Referenced by ObInsertObject().

02519 : 02520 02521 This function creates a new unnamed handle for an existing object 02522 02523 Arguments: 02524 02525 Object - A pointer to the body of the new object 02526 02527 DesiredAccess - Supplies the access mask being requsted 02528 02529 ObjectPointerBias - Optionally supplies a count of addition 02530 increments we do to the pointer count for the object 02531 02532 Attributes - Desired attributes for the handle 02533 02534 AccessMode - Supplies the mode of the requestor. 02535 02536 ReferencedNewObject - Optionally receives a pointer to the body 02537 of the new object 02538 02539 Handle - Receives the new handle value 02540 02541 Return Value: 02542 02543 An appropriate status value 02544 02545 --*/ 02546 02547 { 02548 NTSTATUS Status; 02549 POBJECT_HEADER ObjectHeader; 02550 POBJECT_TYPE ObjectType; 02551 PVOID ObjectTable; 02552 HANDLE_TABLE_ENTRY ObjectTableEntry; 02553 HANDLE NewHandle; 02554 ULONG BiasCount; 02555 ACCESS_MASK GrantedAccess; 02556 BOOLEAN AttachedToProcess = FALSE; 02557 BOOLEAN KernelHandle = FALSE; 02558 KAPC_STATE ApcState; 02559 02560 PAGED_CODE(); 02561 02562 ObpValidateIrql( "ObpCreateUnnamedHandle" ); 02563 02564 // 02565 // Get the object header and type for the new object 02566 // 02567 02568 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 02569 ObjectType = ObjectHeader->Type; 02570 02571 // 02572 // Set the first ulong of the object table entry to point 02573 // to the object header and then or in the low order attribute 02574 // bits 02575 // 02576 02577 ObjectTableEntry.Object = ObjectHeader; 02578 02579 ObjectTableEntry.ObAttributes |= (Attributes & OBJ_HANDLE_ATTRIBUTES); 02580 02581 // 02582 // Now get a pointer to the object table for either the current process 02583 // of the kernel handle table 02584 // 02585 02586 if ((Attributes & OBJ_KERNEL_HANDLE) && (AccessMode == KernelMode)) { 02587 02588 ObjectTable = ObpKernelHandleTable; 02589 KernelHandle = TRUE; 02590 02591 // 02592 // Go to the system process if we have to 02593 // 02594 02595 if (PsGetCurrentProcess() != PsInitialSystemProcess) { 02596 KeStackAttachProcess (&PsInitialSystemProcess->Pcb, &ApcState); 02597 AttachedToProcess = TRUE; 02598 } 02599 02600 } else { 02601 02602 ObjectTable = ObpGetObjectTable(); 02603 } 02604 02605 // 02606 // Increment the handle count, this routine also does the access 02607 // check if necessary 02608 // 02609 02610 Status = ObpIncrementUnnamedHandleCount( &DesiredAccess, 02611 PsGetCurrentProcess(), 02612 Object, 02613 ObjectType, 02614 AccessMode, 02615 Attributes ); 02616 02617 02618 GrantedAccess = DesiredAccess & 02619 (ObjectType->TypeInfo.ValidAccessMask | ACCESS_SYSTEM_SECURITY ); 02620 02621 if (!NT_SUCCESS( Status )) { 02622 02623 // 02624 // If we are attached to the system process then return 02625 // back to our caller 02626 // 02627 02628 if (AttachedToProcess) { 02629 KeUnstackDetachProcess(&ApcState); 02630 AttachedToProcess = FALSE; 02631 } 02632 02633 return( Status ); 02634 } 02635 02636 // 02637 // Bias the pointer count if that is what the caller wanted 02638 // 02639 02640 if (ARGUMENT_PRESENT( (PVOID)(ULONG_PTR)ObjectPointerBias )) { 02641 02642 BiasCount = ObjectPointerBias; 02643 02644 while (BiasCount--) { 02645 02646 ObpIncrPointerCount( ObjectHeader ); 02647 } 02648 } 02649 02650 // 02651 // Set the granted access mask in the object table entry (second ulong) 02652 // 02653 02654 #if i386 && !FPO 02655 02656 if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) { 02657 02658 ObjectTableEntry.GrantedAccessIndex = ObpComputeGrantedAccessIndex( GrantedAccess ); 02659 ObjectTableEntry.CreatorBackTraceIndex = RtlLogStackBackTrace(); 02660 02661 } else { 02662 02663 ObjectTableEntry.GrantedAccess = GrantedAccess; 02664 } 02665 02666 #else 02667 02668 ObjectTableEntry.GrantedAccess = GrantedAccess; 02669 02670 #endif // i386 && !FPO 02671 02672 // 02673 // Add this new object table entry to the object table for the process 02674 // 02675 02676 NewHandle = ExCreateHandle( ObjectTable, &ObjectTableEntry ); 02677 02678 // 02679 // If we didn't get a handle then cleanup after ourselves and return 02680 // the error to our caller 02681 // 02682 02683 if (NewHandle == NULL) { 02684 02685 if (ARGUMENT_PRESENT( (PVOID)(ULONG_PTR)ObjectPointerBias )) { 02686 02687 BiasCount = ObjectPointerBias; 02688 02689 while (BiasCount--) { 02690 02691 ObpDecrPointerCount( ObjectHeader ); 02692 } 02693 } 02694 02695 ObpDecrementHandleCount( PsGetCurrentProcess(), 02696 ObjectHeader, 02697 ObjectType, 02698 GrantedAccess ); 02699 02700 // 02701 // If we are attached to the system process then return 02702 // back to our caller 02703 // 02704 02705 if (AttachedToProcess) { 02706 KeUnstackDetachProcess(&ApcState); 02707 AttachedToProcess = FALSE; 02708 } 02709 02710 return( STATUS_INSUFFICIENT_RESOURCES ); 02711 } 02712 02713 // 02714 // We have a new Ex style handle now make it an ob style handle and also 02715 // adjust for the kernel handle by setting the sign bit in the handle 02716 // value 02717 // 02718 02719 if (KernelHandle) { 02720 02721 NewHandle = EncodeKernelHandle( NewHandle ); 02722 } 02723 02724 *Handle = NewHandle; 02725 02726 // 02727 // If the caller had a pointer bias and wanted the new reference object 02728 // then return that value 02729 // 02730 02731 if ((ARGUMENT_PRESENT( (PVOID)(ULONG_PTR)ObjectPointerBias )) && 02732 (ARGUMENT_PRESENT( ReferencedNewObject ))) { 02733 02734 *ReferencedNewObject = Object; 02735 } 02736 02737 // 02738 // If we are attached to the system process then return 02739 // back to our caller 02740 // 02741 02742 if (AttachedToProcess) { 02743 KeUnstackDetachProcess(&ApcState); 02744 AttachedToProcess = FALSE; 02745 } 02746 02747 return( STATUS_SUCCESS ); 02748 }

VOID ObpDecrementHandleCount PEPROCESS  Process,
POBJECT_HEADER  ObjectHeader,
POBJECT_TYPE  ObjectType,
ACCESS_MASK  GrantedAccess
 

Definition at line 1967 of file obhandle.c.

References ASSERT, _OBJECT_HEADER::Body, _OBJECT_TYPE_INITIALIZER::CloseProcedure, _OBJECT_HANDLE_COUNT_DATABASE::CountEntries, FALSE, _OBJECT_HEADER::Flags, _OBJECT_HEADER::HandleCount, _OBJECT_HANDLE_COUNT_ENTRY::HandleCount, _OBJECT_HEADER_HANDLE_INFO::HandleCountDataBase, _OBJECT_HANDLE_COUNT_DATABASE::HandleCountEntries, _OBJECT_TYPE_INITIALIZER::MaintainHandleCount, NULL, OB_FLAG_EXCLUSIVE_OBJECT, OB_FLAG_SINGLE_HANDLE_ENTRY, OBJECT_HEADER_TO_CREATOR_INFO, OBJECT_HEADER_TO_HANDLE_INFO, OBJECT_HEADER_TO_QUOTA_INFO, ObpBeginTypeSpecificCallOut, ObpDecrHandleCount, ObpDeleteNameCheck(), ObpEndTypeSpecificCallOut, ObpEnterObjectTypeMutex, ObpLeaveObjectTypeMutex, PAGED_CODE, _OBJECT_HANDLE_COUNT_ENTRY::Process, _OBJECT_HEADER_HANDLE_INFO::SingleEntry, _OBJECT_TYPE::TotalNumberOfHandles, TRUE, _OBJECT_TYPE::TypeInfo, and _OBJECT_HEADER_CREATOR_INFO::TypeList.

Referenced by NtClose(), NtDuplicateObject(), ObpCreateHandle(), and ObpCreateUnnamedHandle().

01976 : 01977 01978 This procedure decrements the handle count for the specified object 01979 01980 Arguments: 01981 01982 Process - Supplies the process where the handle existed 01983 01984 ObjectHeader - Supplies a pointer to the object header for the object 01985 01986 ObjectType - Supplies a type of the object 01987 01988 GrantedAccess - Supplies the current access mask to the object 01989 01990 Return Value: 01991 01992 None. 01993 01994 --*/ 01995 01996 { 01997 POBJECT_HEADER_HANDLE_INFO HandleInfo; 01998 POBJECT_HANDLE_COUNT_DATABASE HandleCountDataBase; 01999 POBJECT_HANDLE_COUNT_ENTRY HandleCountEntry; 02000 POBJECT_HEADER_CREATOR_INFO CreatorInfo; 02001 PVOID Object; 02002 ULONG CountEntries; 02003 ULONG ProcessHandleCount; 02004 ULONG SystemHandleCount; 02005 BOOLEAN HandleCountIsZero; 02006 02007 PAGED_CODE(); 02008 02009 ObpEnterObjectTypeMutex( ObjectType ); 02010 02011 Object = (PVOID)&ObjectHeader->Body; 02012 02013 SystemHandleCount = ObjectHeader->HandleCount; 02014 ProcessHandleCount = 0; 02015 02016 // 02017 // Decrement the handle count and it was one and it 02018 // was an exclusive object then zero out the exclusive 02019 // process 02020 // 02021 02022 HandleCountIsZero = ObpDecrHandleCount( ObjectHeader ); 02023 02024 if ( HandleCountIsZero && 02025 (ObjectHeader->Flags & OB_FLAG_EXCLUSIVE_OBJECT)) { 02026 02027 OBJECT_HEADER_TO_QUOTA_INFO( ObjectHeader )->ExclusiveProcess = NULL; 02028 } 02029 02030 if ( HandleCountIsZero ) { 02031 02032 CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO( ObjectHeader ); 02033 02034 // 02035 // If there is a creator info record and we are on the list 02036 // for the object type then remove this object from the list 02037 // 02038 02039 if (CreatorInfo != NULL && !IsListEmpty( &CreatorInfo->TypeList )) { 02040 02041 RemoveEntryList( &CreatorInfo->TypeList ); 02042 02043 InitializeListHead( &CreatorInfo->TypeList ); 02044 } 02045 } 02046 02047 // 02048 // If the object maintains a handle count database then 02049 // search through the handle database and decrement 02050 // the necessary information 02051 // 02052 02053 if (ObjectType->TypeInfo.MaintainHandleCount) { 02054 02055 HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO( ObjectHeader ); 02056 02057 // 02058 // Check if there is a single handle entry, then it better 02059 // be ours 02060 // 02061 02062 if (ObjectHeader->Flags & OB_FLAG_SINGLE_HANDLE_ENTRY) { 02063 02064 ASSERT(HandleInfo->SingleEntry.Process == Process); 02065 ASSERT(HandleInfo->SingleEntry.HandleCount > 0); 02066 02067 ProcessHandleCount = HandleInfo->SingleEntry.HandleCount--; 02068 HandleCountEntry = &HandleInfo->SingleEntry; 02069 02070 } else { 02071 02072 // 02073 // Otherwise search the database for a process match 02074 // 02075 02076 HandleCountDataBase = HandleInfo->HandleCountDataBase; 02077 02078 if (HandleCountDataBase != NULL) { 02079 02080 CountEntries = HandleCountDataBase->CountEntries; 02081 HandleCountEntry = &HandleCountDataBase->HandleCountEntries[ 0 ]; 02082 02083 while (CountEntries) { 02084 02085 if ((HandleCountEntry->HandleCount != 0) && 02086 (HandleCountEntry->Process == Process)) { 02087 02088 ProcessHandleCount = HandleCountEntry->HandleCount--; 02089 02090 break; 02091 } 02092 02093 HandleCountEntry++; 02094 CountEntries--; 02095 } 02096 } 02097 } 02098 02099 // 02100 // Now if the process is giving up all handles to the object 02101 // then zero out the handle count entry. For a single handle 02102 // entry this is just the single entry in the header handle info 02103 // structure 02104 // 02105 02106 if (ProcessHandleCount == 1) { 02107 02108 HandleCountEntry->Process = NULL; 02109 HandleCountEntry->HandleCount = 0; 02110 } 02111 } 02112 02113 // 02114 // If the Object Type has a Close Procedure, then release the type 02115 // mutex before calling it, and then call ObpDeleteNameCheck without 02116 // the mutex held. 02117 // 02118 02119 if (ObjectType->TypeInfo.CloseProcedure) { 02120 02121 KIRQL SaveIrql; 02122 02123 ObpLeaveObjectTypeMutex( ObjectType ); 02124 02125 ObpBeginTypeSpecificCallOut( SaveIrql ); 02126 02127 (*ObjectType->TypeInfo.CloseProcedure)( Process, 02128 Object, 02129 GrantedAccess, 02130 ProcessHandleCount, 02131 SystemHandleCount ); 02132 02133 ObpEndTypeSpecificCallOut( SaveIrql, "Close", ObjectType, Object ); 02134 02135 ObpDeleteNameCheck( Object, FALSE ); 02136 02137 } else { 02138 02139 // 02140 // If there is no Close Procedure, then just call ObpDeleteNameCheck 02141 // with the mutex held. 02142 // 02143 // The following call will release the type mutex 02144 // 02145 02146 ObpDeleteNameCheck( Object, TRUE ); 02147 } 02148 02149 ObpEnterObjectTypeMutex( ObjectType ); 02150 02151 ObjectType->TotalNumberOfHandles -= 1; 02152 02153 ObpLeaveObjectTypeMutex( ObjectType ); 02154 02155 return; 02156 }

NTSTATUS ObpIncrementHandleCount OB_OPEN_REASON  OpenReason,
PEPROCESS  Process,
PVOID  Object,
POBJECT_TYPE  ObjectType,
PACCESS_STATE AccessState  OPTIONAL,
KPROCESSOR_MODE  AccessMode,
ULONG  Attributes
 

Definition at line 1232 of file obhandle.c.

References _OBJECT_TYPE_INITIALIZER::CloseProcedure, EXCEPTION_EXECUTE_HANDLER, FALSE, _OBJECT_HEADER::Flags, GENERIC_ACCESS, _OBJECT_TYPE_INITIALIZER::GenericMapping, _OBJECT_HEADER::HandleCount, _OBJECT_TYPE::HighWaterNumberOfHandles, _OBJECT_TYPE_INITIALIZER::MaintainHandleCount, NT_SUCCESS, NTSTATUS(), NULL, OB_FLAG_EXCLUSIVE_OBJECT, ObCheckObjectAccess(), ObCreateHandle, ObDuplicateHandle, OBJECT_HEADER_TO_CREATOR_INFO, OBJECT_HEADER_TO_EXCLUSIVE_PROCESS, OBJECT_HEADER_TO_QUOTA_INFO, OBJECT_TO_OBJECT_HEADER, ObOpenHandle, ObpBeginTypeSpecificCallOut, ObpChargeQuotaForObject(), ObpDecrHandleCount, ObpEndTypeSpecificCallOut, ObpEnterObjectTypeMutex, ObpIncrementHandleDataBase(), ObpIncrHandleCount, ObpLeaveObjectTypeMutex, ObpValidateIrql, _OBJECT_TYPE_INITIALIZER::OpenProcedure, PAGED_CODE, PsGetCurrentProcess, RtlMapGenericMask(), SeAppendPrivileges(), SePrivilegeCheck(), SePrivilegedServiceAuditAlarm(), SeSecurityPrivilege, Status, _OBJECT_TYPE::TotalNumberOfHandles, TRUE, _OBJECT_TYPE::TypeInfo, _OBJECT_TYPE::TypeList, _OBJECT_HEADER_CREATOR_INFO::TypeList, and VOID().

Referenced by NtDuplicateObject(), ObDupHandleProcedure(), and ObpCreateHandle().

01244 : 01245 01246 Increments the count of number of handles to the given object. 01247 01248 If the object is being opened or created, access validation and 01249 auditing will be performed as appropriate. 01250 01251 Arguments: 01252 01253 OpenReason - Supplies the reason the handle count is being incremented. 01254 01255 Process - Pointer to the process in which the new handle will reside. 01256 01257 Object - Supplies a pointer to the body of the object. 01258 01259 ObjectType - Supplies the type of the object. 01260 01261 AccessState - Optional parameter supplying the current accumulated 01262 security information describing the attempt to access the object. 01263 01264 AccessMode - Supplies the mode of the requestor. 01265 01266 Attributes - Desired attributes for the handle 01267 01268 Return Value: 01269 01270 An appropriate status value 01271 01272 --*/ 01273 01274 { 01275 NTSTATUS Status; 01276 ULONG ProcessHandleCount; 01277 BOOLEAN ExclusiveHandle; 01278 POBJECT_HEADER_CREATOR_INFO CreatorInfo; 01279 POBJECT_HEADER_QUOTA_INFO QuotaInfo; 01280 POBJECT_HEADER ObjectHeader; 01281 BOOLEAN HasPrivilege = FALSE; 01282 PRIVILEGE_SET Privileges; 01283 BOOLEAN NewObject; 01284 BOOLEAN HoldObjectTypeMutex = FALSE; 01285 01286 PAGED_CODE(); 01287 01288 ObpValidateIrql( "ObpIncrementHandleCount" ); 01289 01290 // 01291 // Get a pointer to the object header 01292 // 01293 01294 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 01295 01296 // 01297 // Charge the user quota for the object 01298 // 01299 01300 Status = ObpChargeQuotaForObject( ObjectHeader, ObjectType, &NewObject ); 01301 01302 if (!NT_SUCCESS( Status )) { 01303 01304 return Status; 01305 } 01306 01307 ObpEnterObjectTypeMutex( ObjectType ); 01308 HoldObjectTypeMutex = TRUE; 01309 01310 try { 01311 01312 ExclusiveHandle = FALSE; 01313 01314 // 01315 // Check if the caller wants exlusive access and if so then 01316 // make sure the attributes and header flags match up correctly 01317 // 01318 01319 if (Attributes & OBJ_EXCLUSIVE) { 01320 01321 if ((Attributes & OBJ_INHERIT) || 01322 ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE_OBJECT) == 0)) { 01323 01324 Status = STATUS_INVALID_PARAMETER; 01325 leave; 01326 } 01327 01328 if (((OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) == NULL) && 01329 (ObjectHeader->HandleCount != 0)) 01330 01331 || 01332 01333 ((OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) != NULL) && 01334 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) != PsGetCurrentProcess()))) { 01335 01336 Status = STATUS_ACCESS_DENIED; 01337 leave; 01338 } 01339 01340 ExclusiveHandle = TRUE; 01341 01342 // 01343 // The user doesn't want exclusive access so now check to make sure 01344 // the attriutes and header flags match up correctly 01345 // 01346 01347 } else if ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE_OBJECT) && 01348 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) != NULL)) { 01349 01350 Status = STATUS_ACCESS_DENIED; 01351 leave; 01352 } 01353 01354 // 01355 // If handle count going from zero to one for an existing object that 01356 // maintains a handle count database, but does not have an open procedure 01357 // just a close procedure, then fail the call as they are trying to 01358 // reopen an object by pointer and the close procedure will not know 01359 // that the object has been 'recreated' 01360 // 01361 01362 if ((ObjectHeader->HandleCount == 0) && 01363 (!NewObject) && 01364 (ObjectType->TypeInfo.MaintainHandleCount) && 01365 (ObjectType->TypeInfo.OpenProcedure == NULL) && 01366 (ObjectType->TypeInfo.CloseProcedure != NULL)) { 01367 01368 Status = STATUS_UNSUCCESSFUL; 01369 leave; 01370 } 01371 01372 if ((OpenReason == ObOpenHandle) || 01373 ((OpenReason == ObDuplicateHandle) && ARGUMENT_PRESENT(AccessState))) { 01374 01375 // 01376 // Perform Access Validation to see if we can open this 01377 // (already existing) object. 01378 // 01379 01380 if (!ObCheckObjectAccess( Object, 01381 AccessState, 01382 TRUE, 01383 AccessMode, 01384 &Status )) { 01385 01386 leave; 01387 } 01388 01389 } else if ((OpenReason == ObCreateHandle)) { 01390 01391 // 01392 // We are creating a new instance of this object type. 01393 // A total of three audit messages may be generated: 01394 // 01395 // 1 - Audit the attempt to create an instance of this 01396 // object type. 01397 // 01398 // 2 - Audit the successful creation. 01399 // 01400 // 3 - Audit the allocation of the handle. 01401 // 01402 01403 // 01404 // At this point, the RemainingDesiredAccess field in 01405 // the AccessState may still contain either Generic access 01406 // types, or MAXIMUM_ALLOWED. We will map the generics 01407 // and substitute GenericAll for MAXIMUM_ALLOWED. 01408 // 01409 01410 if ( AccessState->RemainingDesiredAccess & MAXIMUM_ALLOWED ) { 01411 01412 AccessState->RemainingDesiredAccess &= ~MAXIMUM_ALLOWED; 01413 AccessState->RemainingDesiredAccess |= GENERIC_ALL; 01414 } 01415 01416 if ((GENERIC_ACCESS & AccessState->RemainingDesiredAccess) != 0) { 01417 01418 RtlMapGenericMask( &AccessState->RemainingDesiredAccess, 01419 &ObjectType->TypeInfo.GenericMapping ); 01420 } 01421 01422 // 01423 // Since we are creating the object, we can give any access the caller 01424 // wants. The only exception is ACCESS_SYSTEM_SECURITY, which requires 01425 // a privilege. 01426 // 01427 01428 if ( AccessState->RemainingDesiredAccess & ACCESS_SYSTEM_SECURITY ) { 01429 01430 // 01431 // We could use SeSinglePrivilegeCheck here, but it 01432 // captures the subject context again, and we don't 01433 // want to do that in this path for performance reasons. 01434 // 01435 01436 Privileges.PrivilegeCount = 1; 01437 Privileges.Control = PRIVILEGE_SET_ALL_NECESSARY; 01438 Privileges.Privilege[0].Luid = SeSecurityPrivilege; 01439 Privileges.Privilege[0].Attributes = 0; 01440 01441 HasPrivilege = SePrivilegeCheck( &Privileges, 01442 &AccessState->SubjectSecurityContext, 01443 KeGetPreviousMode() ); 01444 01445 if (!HasPrivilege) { 01446 01447 SePrivilegedServiceAuditAlarm ( NULL, 01448 &AccessState->SubjectSecurityContext, 01449 &Privileges, 01450 FALSE ); 01451 01452 Status = STATUS_PRIVILEGE_NOT_HELD; 01453 leave; 01454 } 01455 01456 AccessState->RemainingDesiredAccess &= ~ACCESS_SYSTEM_SECURITY; 01457 AccessState->PreviouslyGrantedAccess |= ACCESS_SYSTEM_SECURITY; 01458 01459 (VOID) SeAppendPrivileges( AccessState, 01460 &Privileges ); 01461 } 01462 01463 // 01464 // Get the objects creator info block and insert it on the 01465 // global list of objects for that type 01466 // 01467 01468 CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO( ObjectHeader ); 01469 01470 if (CreatorInfo != NULL) { 01471 01472 InsertTailList( &ObjectType->TypeList, &CreatorInfo->TypeList ); 01473 } 01474 } 01475 01476 if (ExclusiveHandle) { 01477 01478 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader)->ExclusiveProcess = Process; 01479 } 01480 01481 ObpIncrHandleCount( ObjectHeader ); 01482 ProcessHandleCount = 0; 01483 01484 // 01485 // If the object type wants us to keep try of the handle counts 01486 // then call our routine to do the work 01487 // 01488 01489 if (ObjectType->TypeInfo.MaintainHandleCount) { 01490 01491 Status = ObpIncrementHandleDataBase( ObjectHeader, 01492 Process, 01493 &ProcessHandleCount ); 01494 01495 if (!NT_SUCCESS(Status)) { 01496 // BUG BUG, We probably need more backout than this, NeillC 01497 ObpDecrHandleCount( ObjectHeader ); 01498 01499 leave; 01500 } 01501 } 01502 01503 // 01504 // Set our preliminary status now to success because 01505 // the call to the open procedure might change this 01506 // 01507 01508 Status = STATUS_SUCCESS; 01509 01510 // 01511 // If the object type has an open procedure 01512 // then invoke that procedure 01513 // 01514 01515 if (ObjectType->TypeInfo.OpenProcedure != NULL) { 01516 01517 KIRQL SaveIrql; 01518 01519 // 01520 // Leave the object type mutex when call the OpenProcedure. If an exception 01521 // while OpenProcedure the HoldObjectTypeMutex disable leaving the mutex 01522 // on finally block 01523 // 01524 01525 ObpLeaveObjectTypeMutex( ObjectType ); 01526 HoldObjectTypeMutex = FALSE; 01527 01528 ObpBeginTypeSpecificCallOut( SaveIrql ); 01529 01530 try { 01531 01532 (*ObjectType->TypeInfo.OpenProcedure)( OpenReason, 01533 Process, 01534 Object, 01535 AccessState ? 01536 AccessState->PreviouslyGrantedAccess : 01537 0, 01538 ProcessHandleCount ); 01539 01540 } except( EXCEPTION_EXECUTE_HANDLER ) { 01541 01542 Status = GetExceptionCode(); 01543 } 01544 01545 ObpEndTypeSpecificCallOut( SaveIrql, "Open", ObjectType, Object ); 01546 01547 // 01548 // Hold back the object type mutex and set the HoldObjectTypeMutex variable 01549 // to allow releasing the mutex while leaving this procedure 01550 // 01551 01552 ObpEnterObjectTypeMutex( ObjectType ); 01553 HoldObjectTypeMutex = TRUE; 01554 01555 if (!NT_SUCCESS(Status)) { 01556 01557 (VOID)ObpDecrHandleCount( ObjectHeader ); 01558 leave; 01559 } 01560 } 01561 01562 // 01563 // Do some simple bookkeeping for the handle counts 01564 // and then return to our caller 01565 // 01566 01567 ObjectType->TotalNumberOfHandles += 1; 01568 01569 if (ObjectType->TotalNumberOfHandles > ObjectType->HighWaterNumberOfHandles) { 01570 01571 ObjectType->HighWaterNumberOfHandles = ObjectType->TotalNumberOfHandles; 01572 } 01573 01574 } finally { 01575 01576 if ( HoldObjectTypeMutex ) { 01577 01578 ObpLeaveObjectTypeMutex( ObjectType ); 01579 } 01580 } 01581 01582 return( Status ); 01583 }

NTSTATUS ObpIncrementHandleDataBase IN POBJECT_HEADER  ObjectHeader,
IN PEPROCESS  Process,
OUT PULONG  NewProcessHandleCount
 

Definition at line 1058 of file obhandle.c.

References _OBJECT_HANDLE_COUNT_DATABASE::CountEntries, _OBJECT_HANDLE_COUNT_ENTRY::HandleCount, _OBJECT_HEADER_HANDLE_INFO::HandleCountDataBase, _OBJECT_HANDLE_COUNT_DATABASE::HandleCountEntries, NULL, OB_FLAG_SINGLE_HANDLE_ENTRY, OBJECT_HEADER_TO_HANDLE_INFO, ObpInsertHandleCount(), PAGED_CODE, _OBJECT_HANDLE_COUNT_ENTRY::Process, and _OBJECT_HEADER_HANDLE_INFO::SingleEntry.

Referenced by ObpIncrementHandleCount(), and ObpIncrementUnnamedHandleCount().

01066 : 01067 01068 This function increments the handle count database associated with the 01069 specified object for a specified process. 01070 01071 Arguments: 01072 01073 ObjectHeader - Supplies a pointer to the object. 01074 01075 Process - Supplies a pointer to the process whose handle count is to be 01076 updated. 01077 01078 NewProcessHandleCount - Supplies a pointer to a variable that receives 01079 the new handle count for the process. 01080 01081 Return Value: 01082 01083 An appropriate status value 01084 01085 --*/ 01086 01087 { 01088 POBJECT_HEADER_HANDLE_INFO HandleInfo; 01089 POBJECT_HANDLE_COUNT_DATABASE HandleCountDataBase; 01090 POBJECT_HANDLE_COUNT_ENTRY HandleCountEntry; 01091 POBJECT_HANDLE_COUNT_ENTRY FreeHandleCountEntry; 01092 ULONG CountEntries; 01093 ULONG ProcessHandleCount; 01094 01095 PAGED_CODE(); 01096 01097 // 01098 // Translate the object header to the handle information. 01099 // 01100 01101 HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader); 01102 01103 // 01104 // Check if the object has space for only a single handle 01105 // 01106 01107 if (ObjectHeader->Flags & OB_FLAG_SINGLE_HANDLE_ENTRY) { 01108 01109 // 01110 // If the single handle isn't in use then set the entry 01111 // and tell the caller there is only one handle 01112 // 01113 01114 if (HandleInfo->SingleEntry.HandleCount == 0) { 01115 01116 *NewProcessHandleCount = 1; 01117 HandleInfo->SingleEntry.HandleCount = 1; 01118 HandleInfo->SingleEntry.Process = Process; 01119 01120 return STATUS_SUCCESS; 01121 01122 // 01123 // If the single entry is for the same process as specified 01124 // then increment the count and we're done 01125 // 01126 01127 } else if (HandleInfo->SingleEntry.Process == Process) { 01128 01129 *NewProcessHandleCount = ++HandleInfo->SingleEntry.HandleCount; 01130 01131 return STATUS_SUCCESS; 01132 01133 // 01134 // Finally we have a object with a single handle entry already 01135 // in use, so we need to grow the handle database before 01136 // we can set this new value 01137 // 01138 01139 } else { 01140 01141 FreeHandleCountEntry = ObpInsertHandleCount( ObjectHeader ); 01142 01143 if (FreeHandleCountEntry == NULL) { 01144 01145 return STATUS_INSUFFICIENT_RESOURCES; 01146 } 01147 01148 FreeHandleCountEntry->Process = Process; 01149 FreeHandleCountEntry->HandleCount = 1; 01150 *NewProcessHandleCount = 1; 01151 01152 return STATUS_SUCCESS; 01153 } 01154 } 01155 01156 // 01157 // The object does not contain a single entry, therefore we're 01158 // assuming it already has a handle count database 01159 // 01160 01161 // 01162 // **** HandleInfo should first be checked for null 01163 // 01164 01165 HandleCountDataBase = HandleInfo->HandleCountDataBase; 01166 01167 FreeHandleCountEntry = NULL; 01168 01169 // 01170 // **** can we with success if the database is null 01171 // 01172 01173 if (HandleCountDataBase != NULL) { 01174 01175 // 01176 // Get the number of entries and a pointer to the first one 01177 // in the handle database 01178 // 01179 01180 CountEntries = HandleCountDataBase->CountEntries; 01181 HandleCountEntry = &HandleCountDataBase->HandleCountEntries[ 0 ]; 01182 01183 // 01184 // For each entry in the handle database check for a process 01185 // match and if so then increment the handle count and return 01186 // to our caller. Otherwise if the entry is free then remember 01187 // it so we can store to it later 01188 // 01189 01190 while (CountEntries) { 01191 01192 if (HandleCountEntry->Process == Process) { 01193 01194 *NewProcessHandleCount = ++HandleCountEntry->HandleCount; 01195 01196 return STATUS_SUCCESS; 01197 01198 } else if (HandleCountEntry->HandleCount == 0) { 01199 01200 FreeHandleCountEntry = HandleCountEntry; 01201 } 01202 01203 ++HandleCountEntry; 01204 --CountEntries; 01205 } 01206 01207 // 01208 // If we did not find a free handle entry then we have to grow the 01209 // handle database before we can set this new value 01210 // 01211 01212 if (FreeHandleCountEntry == NULL) { 01213 01214 FreeHandleCountEntry = ObpInsertHandleCount( ObjectHeader ); 01215 01216 if (FreeHandleCountEntry == NULL) { 01217 01218 return(STATUS_INSUFFICIENT_RESOURCES); 01219 } 01220 } 01221 01222 FreeHandleCountEntry->Process = Process; 01223 FreeHandleCountEntry->HandleCount = 1; 01224 *NewProcessHandleCount = 1; 01225 } 01226 01227 return STATUS_SUCCESS; 01228 }

NTSTATUS ObpIncrementUnnamedHandleCount PACCESS_MASK  DesiredAccess,
PEPROCESS  Process,
PVOID  Object,
POBJECT_TYPE  ObjectType,
KPROCESSOR_MODE  AccessMode,
ULONG  Attributes
 

Definition at line 1587 of file obhandle.c.

References _OBJECT_TYPE_INITIALIZER::CloseProcedure, EXCEPTION_EXECUTE_HANDLER, FALSE, _OBJECT_HEADER::Flags, GENERIC_ACCESS, _OBJECT_TYPE_INITIALIZER::GenericMapping, _OBJECT_HEADER::HandleCount, _OBJECT_TYPE::HighWaterNumberOfHandles, _OBJECT_TYPE_INITIALIZER::MaintainHandleCount, NT_SUCCESS, NTSTATUS(), NULL, OB_FLAG_EXCLUSIVE_OBJECT, ObCreateHandle, OBJECT_HEADER_TO_CREATOR_INFO, OBJECT_HEADER_TO_EXCLUSIVE_PROCESS, OBJECT_HEADER_TO_QUOTA_INFO, OBJECT_TO_OBJECT_HEADER, ObpBeginTypeSpecificCallOut, ObpChargeQuotaForObject(), ObpDecrHandleCount, ObpEndTypeSpecificCallOut, ObpEnterObjectTypeMutex, ObpIncrementHandleDataBase(), ObpIncrHandleCount, ObpLeaveObjectTypeMutex, ObpValidateIrql, _OBJECT_TYPE_INITIALIZER::OpenProcedure, PAGED_CODE, PsGetCurrentProcess, RtlMapGenericMask(), Status, _OBJECT_TYPE::TotalNumberOfHandles, TRUE, _OBJECT_TYPE::TypeInfo, _OBJECT_TYPE::TypeList, _OBJECT_HEADER_CREATOR_INFO::TypeList, and VOID().

Referenced by ObpCreateUnnamedHandle().

01598 : 01599 01600 Increments the count of number of handles to the given object. 01601 01602 Arguments: 01603 01604 Desired Access - Supplies the desired access to the object and receives 01605 the assign access mask 01606 01607 Process - Pointer to the process in which the new handle will reside. 01608 01609 Object - Supplies a pointer to the body of the object. 01610 01611 ObjectType - Supplies the type of the object. 01612 01613 AccessMode - Supplies the mode of the requestor. 01614 01615 Attributes - Desired attributes for the handle 01616 01617 Return Value: 01618 01619 An appropriate status value 01620 01621 --*/ 01622 01623 { 01624 NTSTATUS Status; 01625 BOOLEAN ExclusiveHandle; 01626 POBJECT_HEADER_CREATOR_INFO CreatorInfo; 01627 POBJECT_HEADER_QUOTA_INFO QuotaInfo; 01628 POBJECT_HEADER ObjectHeader; 01629 BOOLEAN NewObject; 01630 ULONG ProcessHandleCount; 01631 BOOLEAN HoldObjectTypeMutex = FALSE; 01632 01633 PAGED_CODE(); 01634 01635 ObpValidateIrql( "ObpIncrementUnnamedHandleCount" ); 01636 01637 // 01638 // Get a pointer to the object header 01639 // 01640 01641 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 01642 01643 // 01644 // Charge the user quota for the object 01645 // 01646 01647 Status = ObpChargeQuotaForObject( ObjectHeader, ObjectType, &NewObject ); 01648 01649 if (!NT_SUCCESS( Status )) { 01650 01651 return Status; 01652 } 01653 01654 ObpEnterObjectTypeMutex( ObjectType ); 01655 HoldObjectTypeMutex = TRUE; 01656 01657 try { 01658 01659 ExclusiveHandle = FALSE; 01660 01661 // 01662 // Check if the caller wants exlusive access and if so then 01663 // make sure the attributes and header flags match up correctly 01664 // 01665 01666 if (Attributes & OBJ_EXCLUSIVE) { 01667 01668 if ((Attributes & OBJ_INHERIT) || 01669 ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE_OBJECT) == 0)) { 01670 01671 Status = STATUS_INVALID_PARAMETER; 01672 leave; 01673 } 01674 01675 if (((OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) == NULL) && 01676 (ObjectHeader->HandleCount != 0)) 01677 01678 || 01679 01680 ((OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) != NULL) && 01681 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) != PsGetCurrentProcess()))) { 01682 01683 Status = STATUS_ACCESS_DENIED; 01684 leave; 01685 } 01686 01687 ExclusiveHandle = TRUE; 01688 01689 // 01690 // The user doesn't want exclusive access so now check to make sure 01691 // the attriutes and header flags match up correctly 01692 // 01693 01694 } else if ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE_OBJECT) && 01695 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) != NULL)) { 01696 01697 Status = STATUS_ACCESS_DENIED; 01698 leave; 01699 } 01700 01701 // 01702 // If handle count going from zero to one for an existing object that 01703 // maintains a handle count database, but does not have an open procedure 01704 // just a close procedure, then fail the call as they are trying to 01705 // reopen an object by pointer and the close procedure will not know 01706 // that the object has been 'recreated' 01707 // 01708 01709 if ((ObjectHeader->HandleCount == 0) && 01710 (!NewObject) && 01711 (ObjectType->TypeInfo.MaintainHandleCount) && 01712 (ObjectType->TypeInfo.OpenProcedure == NULL) && 01713 (ObjectType->TypeInfo.CloseProcedure != NULL)) { 01714 01715 Status = STATUS_UNSUCCESSFUL; 01716 01717 leave; 01718 } 01719 01720 // 01721 // If the user asked for the maximum allowed then remove the bit and 01722 // or in generic all access 01723 // 01724 01725 if ( *DesiredAccess & MAXIMUM_ALLOWED ) { 01726 01727 *DesiredAccess &= ~MAXIMUM_ALLOWED; 01728 *DesiredAccess |= GENERIC_ALL; 01729 } 01730 01731 // If the user asked for any generic bit then translate it to 01732 // someone more appropriate for the object type 01733 // 01734 01735 if ((GENERIC_ACCESS & *DesiredAccess) != 0) { 01736 01737 RtlMapGenericMask( DesiredAccess, 01738 &ObjectType->TypeInfo.GenericMapping ); 01739 } 01740 01741 // 01742 // Get a pointer to the creator info block for the object and insert 01743 // it on the global list of object for that type 01744 // 01745 01746 CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO( ObjectHeader ); 01747 01748 if (CreatorInfo != NULL) { 01749 01750 InsertTailList( &ObjectType->TypeList, &CreatorInfo->TypeList ); 01751 } 01752 01753 if (ExclusiveHandle) { 01754 01755 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader)->ExclusiveProcess = Process; 01756 } 01757 01758 ObpIncrHandleCount( ObjectHeader ); 01759 ProcessHandleCount = 0; 01760 01761 // 01762 // If the object type wants us to keep try of the handle counts 01763 // then call our routine to do the work 01764 // 01765 01766 if (ObjectType->TypeInfo.MaintainHandleCount) { 01767 01768 Status = ObpIncrementHandleDataBase( ObjectHeader, 01769 Process, 01770 &ProcessHandleCount ); 01771 01772 if (!NT_SUCCESS(Status)) { 01773 // BUG BUG, We probably need more backout than this, NeillC 01774 ObpDecrHandleCount( ObjectHeader ); 01775 leave; 01776 } 01777 } 01778 01779 // 01780 // Set our preliminary status now to success because 01781 // the call to the open procedure might change this 01782 // 01783 01784 Status = STATUS_SUCCESS; 01785 01786 // 01787 // If the object type has an open procedure 01788 // then invoke that procedure 01789 // 01790 01791 if (ObjectType->TypeInfo.OpenProcedure != NULL) { 01792 01793 KIRQL SaveIrql; 01794 01795 // 01796 // Leave the object type mutex when call the OpenProcedure. If an exception 01797 // while OpenProcedure the HoldObjectTypeMutex disable leaving the mutex 01798 // on finally block 01799 // 01800 01801 ObpLeaveObjectTypeMutex( ObjectType ); 01802 HoldObjectTypeMutex = FALSE; 01803 01804 ObpBeginTypeSpecificCallOut( SaveIrql ); 01805 01806 try { 01807 01808 (*ObjectType->TypeInfo.OpenProcedure)( ObCreateHandle, 01809 Process, 01810 Object, 01811 *DesiredAccess, 01812 ProcessHandleCount ); 01813 01814 } except( EXCEPTION_EXECUTE_HANDLER ) { 01815 01816 Status = GetExceptionCode(); 01817 } 01818 01819 ObpEndTypeSpecificCallOut( SaveIrql, "Open", ObjectType, Object ); 01820 01821 // 01822 // Hold back the object type mutex and set the HoldObjectTypeMutex variable 01823 // to allow releasing the mutex while leaving this procedure 01824 // 01825 01826 ObpEnterObjectTypeMutex( ObjectType ); 01827 HoldObjectTypeMutex = TRUE; 01828 01829 if (!NT_SUCCESS(Status)) { 01830 01831 (VOID)ObpDecrHandleCount( ObjectHeader ); 01832 leave; 01833 } 01834 } 01835 01836 // 01837 // Do some simple bookkeeping for the handle counts 01838 // and then return to our caller 01839 // 01840 01841 ObjectType->TotalNumberOfHandles += 1; 01842 01843 if (ObjectType->TotalNumberOfHandles > ObjectType->HighWaterNumberOfHandles) { 01844 01845 ObjectType->HighWaterNumberOfHandles = ObjectType->TotalNumberOfHandles; 01846 } 01847 01848 } finally { 01849 01850 if ( HoldObjectTypeMutex ) { 01851 01852 ObpLeaveObjectTypeMutex( ObjectType ); 01853 } 01854 } 01855 01856 return( Status ); 01857 }

POBJECT_HANDLE_COUNT_ENTRY ObpInsertHandleCount POBJECT_HEADER  ObjectHeader  ) 
 

Definition at line 908 of file obhandle.c.

References _OBJECT_HANDLE_COUNT_DATABASE::CountEntries, ExAllocatePoolWithTag, ExFreePool(), _OBJECT_HEADER::Flags, _OBJECT_HEADER_HANDLE_INFO::HandleCountDataBase, _OBJECT_HANDLE_COUNT_DATABASE::HandleCountEntries, NULL, OB_FLAG_SINGLE_HANDLE_ENTRY, OBJECT_HEADER_TO_HANDLE_INFO, PAGED_CODE, PagedPool, and _OBJECT_HEADER_HANDLE_INFO::SingleEntry.

Referenced by ObpIncrementHandleDataBase().

00914 : 00915 00916 This function will increase the size of the handle database 00917 stored in the handle information of an object header. If 00918 necessary it will allocate new and free old handle databases. 00919 00920 This routine should not be called if there is already free 00921 space in the handle table. 00922 00923 Arguments: 00924 00925 ObjectHeader - The object whose handle count is being incremented 00926 00927 Return Value: 00928 00929 The pointer to the next free handle count entry within the 00930 handle database. 00931 00932 --*/ 00933 00934 { 00935 POBJECT_HEADER_HANDLE_INFO HandleInfo; 00936 POBJECT_HANDLE_COUNT_DATABASE OldHandleCountDataBase; 00937 POBJECT_HANDLE_COUNT_DATABASE NewHandleCountDataBase; 00938 POBJECT_HANDLE_COUNT_ENTRY FreeHandleCountEntry; 00939 ULONG CountEntries; 00940 ULONG OldSize; 00941 ULONG NewSize; 00942 OBJECT_HANDLE_COUNT_DATABASE SingleEntryDataBase; 00943 00944 PAGED_CODE(); 00945 00946 // 00947 // Check if the object has any handle information 00948 // 00949 00950 HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader); 00951 00952 if (HandleInfo == NULL) { 00953 00954 return NULL; 00955 } 00956 00957 // 00958 // The object does have some handle information. If it has 00959 // a single handle entry then we'll construct a local dummy 00960 // handle count database and come up with a new data base for 00961 // storing two entries. 00962 // 00963 00964 if (ObjectHeader->Flags & OB_FLAG_SINGLE_HANDLE_ENTRY) { 00965 00966 SingleEntryDataBase.CountEntries = 1; 00967 SingleEntryDataBase.HandleCountEntries[0] = HandleInfo->SingleEntry; 00968 00969 OldHandleCountDataBase = &SingleEntryDataBase; 00970 00971 OldSize = sizeof( SingleEntryDataBase ); 00972 00973 CountEntries = 2; 00974 00975 NewSize = sizeof(OBJECT_HANDLE_COUNT_DATABASE) + 00976 ((CountEntries - 1) * sizeof( OBJECT_HANDLE_COUNT_ENTRY )); 00977 00978 } else { 00979 00980 // 00981 // The object already has multiple handles so we reference the 00982 // current handle database, and compute a new size bumped by four 00983 // 00984 00985 OldHandleCountDataBase = HandleInfo->HandleCountDataBase; 00986 00987 CountEntries = OldHandleCountDataBase->CountEntries; 00988 00989 OldSize = sizeof(OBJECT_HANDLE_COUNT_DATABASE) + 00990 ((CountEntries - 1) * sizeof( OBJECT_HANDLE_COUNT_ENTRY)); 00991 00992 CountEntries += 4; 00993 00994 NewSize = sizeof(OBJECT_HANDLE_COUNT_DATABASE) + 00995 ((CountEntries - 1) * sizeof( OBJECT_HANDLE_COUNT_ENTRY)); 00996 } 00997 00998 // 00999 // Now allocate pool for the new handle database. 01000 // 01001 01002 NewHandleCountDataBase = ExAllocatePoolWithTag(PagedPool, NewSize,'dHbO'); 01003 01004 if (NewHandleCountDataBase == NULL) { 01005 01006 return NULL; 01007 } 01008 01009 // 01010 // Copy over the old database. Note that this might just copy our 01011 // local dummy entry for the single entry case 01012 // 01013 01014 RtlMoveMemory(NewHandleCountDataBase, OldHandleCountDataBase, OldSize); 01015 01016 // 01017 // If the previous mode was a single entry then remove that 01018 // indication otherwise free up with previous handle database 01019 // 01020 01021 if (ObjectHeader->Flags & OB_FLAG_SINGLE_HANDLE_ENTRY) { 01022 01023 ObjectHeader->Flags &= ~OB_FLAG_SINGLE_HANDLE_ENTRY; 01024 01025 } else { 01026 01027 ExFreePool( OldHandleCountDataBase ); 01028 } 01029 01030 // 01031 // Find the end of the new database that is used and zero out 01032 // the memory 01033 // 01034 01035 FreeHandleCountEntry = 01036 (POBJECT_HANDLE_COUNT_ENTRY)((PCHAR)NewHandleCountDataBase + OldSize); 01037 01038 RtlZeroMemory(FreeHandleCountEntry, NewSize - OldSize); 01039 01040 // 01041 // Set the new database to the proper entry count and put it 01042 // all in the object 01043 // 01044 01045 NewHandleCountDataBase->CountEntries = CountEntries; 01046 01047 HandleInfo->HandleCountDataBase = NewHandleCountDataBase; 01048 01049 // 01050 // And return to our caller 01051 // 01052 01053 return FreeHandleCountEntry; 01054 }

NTSTATUS ObpValidateDesiredAccess IN ACCESS_MASK  DesiredAccess  ) 
 

Definition at line 2752 of file obhandle.c.

Referenced by NtDuplicateObject().

02758 : 02759 02760 This routine checks the input desired access mask to see that 02761 some invalid bits are not set. The invalid bits are the top 02762 two reserved bits and the top three standard rights bits. 02763 See \nt\public\sdk\inc\ntseapi.h for more details. 02764 02765 Arguments: 02766 02767 DesiredAccess - Supplies the mask being checked 02768 02769 Return Value: 02770 02771 STATUS_ACCESS_DENIED if one or more of the wrongs bits are set and 02772 STATUS_SUCCESS otherwise 02773 02774 --*/ 02775 02776 { 02777 if (DesiredAccess & 0x0CE00000) { 02778 02779 return( STATUS_ACCESS_DENIED ); 02780 02781 } else { 02782 02783 return( STATUS_SUCCESS ); 02784 } 02785 }


Variable Documentation

KMUTANT ObpInitKillMutant
 

Definition at line 34 of file obhandle.c.

Referenced by NtDuplicateObject(), NtQueryInformationProcess(), ObFindHandleForObject(), ObInitProcess(), ObInitSystem(), and ObKillProcess().


Generated on Sat May 15 19:44:58 2004 for test by doxygen 1.3.7