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

obclose.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 obclose.c 00008 00009 Abstract: 00010 00011 Object close system service 00012 00013 Author: 00014 00015 Steve Wood (stevewo) 31-Mar-1989 00016 00017 Revision History: 00018 00019 --*/ 00020 00021 #include "obp.h" 00022 00023 #ifdef ALLOC_PRAGMA 00024 #pragma alloc_text(PAGE,NtMakeTemporaryObject) 00025 #pragma alloc_text(PAGE,ObMakeTemporaryObject) 00026 #endif 00027 00028 // 00029 // Indicates if auditing is enabled so we have to close down the object 00030 // audit alarm 00031 // 00032 00033 extern BOOLEAN SepAdtAuditingEnabled; 00034 00035 00036 NTSTATUS 00037 NtClose ( 00038 IN HANDLE Handle 00039 ) 00040 00041 /*++ 00042 00043 Routine Description: 00044 00045 This function is used to close access to the specified handle 00046 00047 Arguments: 00048 00049 Handle - Supplies the handle being closed 00050 00051 Return Value: 00052 00053 An appropriate status value 00054 00055 --*/ 00056 00057 { 00058 PHANDLE_TABLE ObjectTable; 00059 PHANDLE_TABLE_ENTRY ObjectTableEntry; 00060 PVOID Object; 00061 ULONG CapturedGrantedAccess; 00062 ULONG CapturedAttributes; 00063 POBJECT_HEADER ObjectHeader; 00064 POBJECT_TYPE ObjectType; 00065 NTSTATUS Status; 00066 BOOLEAN AttachedToProcess = FALSE; 00067 KAPC_STATE ApcState; 00068 00069 // 00070 // Protect ourselves from being interrupted while we hold a handle table 00071 // entry lock 00072 // 00073 00074 KeEnterCriticalRegion(); 00075 00076 try { 00077 00078 #if DBG 00079 KIRQL SaveIrql; 00080 #endif // DBG 00081 00082 ObpValidateIrql( "NtClose" ); 00083 00084 ObpBeginTypeSpecificCallOut( SaveIrql ); 00085 00086 #if DBG 00087 00088 // 00089 // On checked builds, check that if the Kernel handle bit is set, then 00090 // we're coming from Kernel mode. We should probably fail the call if 00091 // bit set && !Kmode 00092 // 00093 00094 if ((Handle != NtCurrentThread()) && (Handle != NtCurrentProcess())) { 00095 00096 ASSERT((Handle < 0 ) ? (KeGetPreviousMode() == KernelMode) : TRUE); 00097 } 00098 00099 #endif 00100 // 00101 // For the current process we will grab its handle/object table and 00102 // translate the handle to its corresponding table entry. If the 00103 // call is successful it also lock down the handle table. But first 00104 // check for a kernel handle and attach and use that table if so. 00105 // 00106 00107 if (IsKernelHandle( Handle, KeGetPreviousMode() )) { 00108 00109 Handle = DecodeKernelHandle( Handle ); 00110 00111 ObjectTable = ObpKernelHandleTable; 00112 00113 // 00114 // Go to the system process if we have to 00115 // 00116 if (PsGetCurrentProcess() != PsInitialSystemProcess) { 00117 KeStackAttachProcess (&PsInitialSystemProcess->Pcb, &ApcState); 00118 AttachedToProcess = TRUE; 00119 } 00120 00121 } else { 00122 00123 ObjectTable = ObpGetObjectTable(); 00124 } 00125 00126 ObjectTableEntry = ExMapHandleToPointer( ObjectTable, 00127 Handle ); 00128 00129 // 00130 // Check that the specified handle is legitimate otherwise we can 00131 // assume the caller just passed in some bogus handle value 00132 // 00133 00134 if (ObjectTableEntry != NULL) { 00135 00136 // 00137 // From the object table entry we can grab a pointer to the object 00138 // header, get its type and its body 00139 // 00140 00141 ObjectHeader = (POBJECT_HEADER)(((ULONG_PTR)(ObjectTableEntry->Object)) & ~OBJ_HANDLE_ATTRIBUTES); 00142 ObjectType = ObjectHeader->Type; 00143 Object = &ObjectHeader->Body; 00144 00145 // 00146 // If the object type specifies an okay to close procedure then we 00147 // need to invoke that callback. If the callback doesn't want us to 00148 // close handle then unlock the object table and return the error 00149 // to our caller 00150 // 00151 00152 if (ObjectType->TypeInfo.OkayToCloseProcedure != NULL) { 00153 00154 if (!(*ObjectType->TypeInfo.OkayToCloseProcedure)( PsGetCurrentProcess(), Object, Handle )) { 00155 00156 ObpEndTypeSpecificCallOut( SaveIrql, "NtClose", ObjectType, Object ); 00157 00158 ExUnlockHandleTableEntry( ObjectTable, ObjectTableEntry ); 00159 00160 // 00161 // If we are attached to the system process then return 00162 // back to our caller 00163 // 00164 00165 if (AttachedToProcess) { 00166 00167 KeUnstackDetachProcess(&ApcState); 00168 AttachedToProcess = FALSE; 00169 } 00170 00171 Status = STATUS_HANDLE_NOT_CLOSABLE; 00172 leave; 00173 } 00174 } 00175 00176 CapturedAttributes = ObjectTableEntry->ObAttributes; 00177 00178 // 00179 // If the previous mode was user and the handle is protected from 00180 // being closed, then we'll either raise or return an error depending 00181 // on the global flags and debugger port situation. 00182 // 00183 00184 if ((CapturedAttributes & OBJ_PROTECT_CLOSE) != 0) { 00185 00186 if (KeGetPreviousMode() != KernelMode) { 00187 00188 ExUnlockHandleTableEntry( ObjectTable, ObjectTableEntry ); 00189 00190 if ((NtGlobalFlag & FLG_ENABLE_CLOSE_EXCEPTIONS) || 00191 (PsGetCurrentProcess()->DebugPort != NULL)) { 00192 00193 // 00194 // If we are attached to the system process then return 00195 // back to our caller 00196 // 00197 00198 if (AttachedToProcess) { 00199 KeUnstackDetachProcess(&ApcState); 00200 AttachedToProcess = FALSE; 00201 } 00202 00203 Status = KeRaiseUserException(STATUS_HANDLE_NOT_CLOSABLE); 00204 leave; 00205 00206 } else { 00207 00208 // 00209 // If we are attached to the system process then return 00210 // back to our caller 00211 // 00212 00213 if (AttachedToProcess) { 00214 KeUnstackDetachProcess(&ApcState); 00215 AttachedToProcess = FALSE; 00216 } 00217 00218 Status = STATUS_HANDLE_NOT_CLOSABLE; 00219 leave; 00220 } 00221 00222 } else { 00223 00224 if ((!PsIsThreadTerminating(PsGetCurrentThread())) && 00225 (PsGetCurrentProcess()->Peb != NULL)) { 00226 00227 ExUnlockHandleTableEntry( ObjectTable, ObjectTableEntry ); 00228 00229 #if DBG 00230 // 00231 // bugcheck here on checked builds if kernel mode code is 00232 // closing a protected handle and process is not exiting. 00233 // Ignore if no PEB as this occurs if process is killed 00234 // before really starting. 00235 // 00236 00237 KeBugCheckEx(INVALID_KERNEL_HANDLE, (ULONG_PTR)Handle, 0, 0, 0); 00238 #else 00239 // 00240 // If we are attached to the system process then return 00241 // back to our caller 00242 // 00243 00244 if (AttachedToProcess) { 00245 KeUnstackDetachProcess(&ApcState); 00246 AttachedToProcess = FALSE; 00247 } 00248 00249 Status = STATUS_HANDLE_NOT_CLOSABLE; 00250 leave; 00251 #endif // DBG 00252 00253 } 00254 } 00255 } 00256 00257 // 00258 // Get the granted access for the handle 00259 // 00260 00261 #if i386 && !FPO 00262 00263 if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) { 00264 00265 CapturedGrantedAccess = ObpTranslateGrantedAccessIndex( ObjectTableEntry->GrantedAccessIndex ); 00266 00267 } else { 00268 00269 CapturedGrantedAccess = ObjectTableEntry->GrantedAccess; 00270 } 00271 00272 #else 00273 00274 CapturedGrantedAccess = ObjectTableEntry->GrantedAccess; 00275 00276 #endif // i386 && !FPO 00277 00278 // 00279 // Now remove the handle from the handle table 00280 // 00281 00282 ExDestroyHandle( ObjectTable, 00283 Handle, 00284 ObjectTableEntry ); 00285 00286 // 00287 // perform any auditing required 00288 // 00289 00290 // 00291 // Extract the value of the GenerateOnClose bit stored 00292 // after object open auditing is performed. This value 00293 // was stored by a call to ObSetGenerateOnClosed. 00294 // 00295 00296 if (CapturedAttributes & OBJ_AUDIT_OBJECT_CLOSE) { 00297 00298 if ( SepAdtAuditingEnabled ) { 00299 00300 SeCloseObjectAuditAlarm( Object, 00301 (HANDLE)((ULONG_PTR)Handle & ~OBJ_HANDLE_TAGBITS), // Mask off the tagbits defined for OB objects. 00302 TRUE ); 00303 } 00304 } 00305 00306 // 00307 // Since we took the handle away we need to decrement the objects 00308 // handle count, and remove a reference 00309 // 00310 00311 ObpDecrementHandleCount( PsGetCurrentProcess(), 00312 ObjectHeader, 00313 ObjectHeader->Type, 00314 CapturedGrantedAccess ); 00315 00316 ObDereferenceObject( Object ); 00317 00318 ObpEndTypeSpecificCallOut( SaveIrql, "NtClose", ObjectType, Object ); 00319 00320 // 00321 // If we are attached to the system process then return 00322 // back to our caller 00323 // 00324 00325 if (AttachedToProcess) { 00326 KeUnstackDetachProcess(&ApcState); 00327 AttachedToProcess = FALSE; 00328 } 00329 00330 // 00331 // And return to our caller 00332 // 00333 00334 Status = STATUS_SUCCESS; 00335 leave; 00336 00337 } else { 00338 00339 // 00340 // At this point the input handle did not translate to a valid 00341 // object table entry 00342 // 00343 00344 ObpEndTypeSpecificCallOut( SaveIrql, "NtClose", ObpTypeObjectType, Handle ); 00345 00346 // 00347 // If we are attached to the system process then return 00348 // back to our caller 00349 // 00350 00351 if (AttachedToProcess) { 00352 KeUnstackDetachProcess(&ApcState); 00353 AttachedToProcess = FALSE; 00354 } 00355 00356 // 00357 // Now if the handle is not null and it does not represent the 00358 // current thread or process then if we're user mode we either raise 00359 // or return an error 00360 // 00361 00362 if ((Handle != NULL) && 00363 (Handle != NtCurrentThread()) && 00364 (Handle != NtCurrentProcess())) { 00365 00366 if (KeGetPreviousMode() != KernelMode) { 00367 00368 if ((NtGlobalFlag & FLG_ENABLE_CLOSE_EXCEPTIONS) || 00369 (PsGetCurrentProcess()->DebugPort != NULL)) { 00370 00371 Status = KeRaiseUserException(STATUS_INVALID_HANDLE); 00372 leave; 00373 00374 } else { 00375 00376 Status = STATUS_INVALID_HANDLE; 00377 leave; 00378 } 00379 00380 } else { 00381 00382 // 00383 // bugcheck here if kernel debugger is enabled and if kernel mode code is 00384 // closing a bogus handle and process is not exiting. Ignore 00385 // if no PEB as this occurs if process is killed before 00386 // really starting. 00387 // 00388 00389 if (( !PsIsThreadTerminating(PsGetCurrentThread())) && 00390 (PsGetCurrentProcess()->Peb != NULL)) { 00391 00392 if (KdDebuggerEnabled) { 00393 KeBugCheckEx(INVALID_KERNEL_HANDLE, (ULONG_PTR)Handle, 1, 0, 0); 00394 } 00395 } 00396 00397 } 00398 } 00399 00400 Status = STATUS_INVALID_HANDLE; 00401 leave; 00402 } 00403 00404 } finally { 00405 00406 KeLeaveCriticalRegion(); 00407 } 00408 00409 return Status; 00410 } 00411 00412 00413 NTSTATUS 00414 NtMakeTemporaryObject ( 00415 IN HANDLE Handle 00416 ) 00417 00418 /*++ 00419 00420 Routine Description: 00421 00422 This routine makes the specified object non permanent. 00423 00424 Arguments: 00425 00426 Handle - Supplies a handle to the object being modified 00427 00428 Return Value: 00429 00430 An appropriate status value. 00431 00432 --*/ 00433 00434 { 00435 KPROCESSOR_MODE PreviousMode; 00436 NTSTATUS Status; 00437 PVOID Object; 00438 OBJECT_HANDLE_INFORMATION HandleInformation; 00439 00440 PAGED_CODE(); 00441 00442 // 00443 // Get previous processor mode and probe output argument if necessary. 00444 // 00445 00446 PreviousMode = KeGetPreviousMode(); 00447 00448 Status = ObReferenceObjectByHandle( Handle, 00449 DELETE, 00450 (POBJECT_TYPE)NULL, 00451 PreviousMode, 00452 &Object, 00453 &HandleInformation ); 00454 if (!NT_SUCCESS( Status )) { 00455 00456 return( Status ); 00457 } 00458 00459 // 00460 // Make the object temporary. Note that the object should still 00461 // have a name and directory entry because its handle count is not 00462 // zero 00463 // 00464 00465 ObMakeTemporaryObject( Object ); 00466 00467 // 00468 // Check if we need to generate a delete object audit/alarm 00469 // 00470 00471 if (HandleInformation.HandleAttributes & OBJ_AUDIT_OBJECT_CLOSE) { 00472 00473 SeDeleteObjectAuditAlarm( Object, 00474 Handle ); 00475 } 00476 00477 ObDereferenceObject( Object ); 00478 00479 return( Status ); 00480 } 00481 00482 00483 VOID 00484 ObMakeTemporaryObject ( 00485 IN PVOID Object 00486 ) 00487 00488 /*++ 00489 00490 Routine Description: 00491 00492 This routine removes the name of the object from its parent 00493 directory. The object is only removed if it has a non zero 00494 handle count and a name. Otherwise the object is simply 00495 made non permanent 00496 00497 Arguments: 00498 00499 Object - Supplies the object being modified 00500 00501 Return Value: 00502 00503 None. 00504 00505 --*/ 00506 00507 { 00508 POBJECT_HEADER ObjectHeader; 00509 00510 PAGED_CODE(); 00511 00512 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 00513 ObjectHeader->Flags &= ~OB_FLAG_PERMANENT_OBJECT; 00514 00515 ObpDeleteNameCheck( Object, FALSE ); 00516 00517 return; 00518 } 00519

Generated on Sat May 15 19:41:04 2004 for test by doxygen 1.3.7