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

obinsert.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 obinsert.c 00008 00009 Abstract: 00010 00011 Object instantiation API 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,ObInsertObject) 00025 #endif 00026 00027 00028 NTSTATUS 00029 ObInsertObject ( 00030 IN PVOID Object, 00031 IN PACCESS_STATE AccessState OPTIONAL, 00032 IN ACCESS_MASK DesiredAccess OPTIONAL, 00033 IN ULONG ObjectPointerBias, 00034 OUT PVOID *NewObject OPTIONAL, 00035 OUT PHANDLE Handle 00036 ) 00037 00038 /*++ 00039 00040 Routine Description: 00041 00042 This routine inserts an object into the current processes handle table. 00043 00044 The Object header includes a pointer to a SecurityDescriptor passed in 00045 an object creation call. This SecurityDescriptor is not assumed to have 00046 been captured. This routine is responsible for making an appropriate 00047 SecurityDescriptor and removing the reference in the object header. 00048 00049 Arguments: 00050 00051 Object - Supplies a pointer to the new object body 00052 00053 AccessState - Optionally supplies the access state for the new 00054 handle 00055 00056 DesiredAccess - Optionally supplies the desired access we want for the 00057 new handle 00058 00059 ObjectPointerBias - Supplies a bias to apply for the pointer count for the 00060 object 00061 00062 NewObject - Optionally receives the pointer to the new object that we've 00063 created a handle for 00064 00065 Handle - Receives the new handle 00066 00067 Return Value: 00068 00069 An appropriate NTSTATUS value. 00070 00071 --*/ 00072 00073 { 00074 POBJECT_CREATE_INFORMATION ObjectCreateInfo; 00075 POBJECT_HEADER ObjectHeader; 00076 PUNICODE_STRING ObjectName; 00077 POBJECT_TYPE ObjectType; 00078 POBJECT_HEADER_NAME_INFO NameInfo; 00079 PSECURITY_DESCRIPTOR ParentDescriptor = NULL; 00080 PVOID InsertObject; 00081 HANDLE NewHandle; 00082 BOOLEAN DirectoryLocked; 00083 OB_OPEN_REASON OpenReason; 00084 NTSTATUS Status = STATUS_SUCCESS; 00085 ACCESS_STATE LocalAccessState; 00086 AUX_ACCESS_DATA AuxData; 00087 BOOLEAN SecurityDescriptorAllocated; 00088 KPROCESSOR_MODE PreviousMode; 00089 NTSTATUS ReturnStatus; 00090 PVOID DirObject = NULL; 00091 00092 00093 PAGED_CODE(); 00094 00095 ObpValidateIrql("ObInsertObject"); 00096 00097 // 00098 // Get the address of the object header, the object create information, 00099 // the object type, and the address of the object name descriptor, if 00100 // specified. 00101 // 00102 00103 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 00104 00105 #if DBG 00106 00107 if ((ObjectHeader->Flags & OB_FLAG_NEW_OBJECT) == 0) { 00108 00109 KdPrint(("OB: Attempting to insert existing object %08x\n", Object)); 00110 KdBreakPoint(); 00111 00112 ObDereferenceObject(Object); 00113 00114 return STATUS_INVALID_PARAMETER; 00115 } 00116 00117 #endif 00118 00119 ObjectCreateInfo = ObjectHeader->ObjectCreateInfo; 00120 00121 ObjectType = ObjectHeader->Type; 00122 00123 NameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader); 00124 00125 ObjectName = NULL; 00126 00127 if ((NameInfo != NULL) && (NameInfo->Name.Buffer != NULL)) { 00128 00129 ObjectName = &NameInfo->Name; 00130 } 00131 00132 // 00133 // If security checks are not required and an object name is not 00134 // specified, insert an unnamed object, biasing the count 00135 // by one, dereference the bias, and return to our caller 00136 // 00137 00138 PreviousMode = KeGetPreviousMode(); 00139 00140 if (!ObjectType->TypeInfo.SecurityRequired && (ObjectName == NULL)) { 00141 00142 ObjectHeader->ObjectCreateInfo = NULL; 00143 00144 *Handle = NULL; 00145 00146 Status = ObpCreateUnnamedHandle( Object, 00147 DesiredAccess, 00148 1 + ObjectPointerBias, 00149 ObjectCreateInfo->Attributes, 00150 PreviousMode, 00151 NewObject, 00152 Handle ); 00153 00154 // 00155 // Free the object creation information and dereference the object. 00156 // 00157 00158 ObpFreeObjectCreateInformation(ObjectCreateInfo); 00159 00160 ObDereferenceObject(Object); 00161 00162 return Status; 00163 } 00164 00165 // 00166 // The object is either named or requires full security checks. If the 00167 // caller hasn't specified an access state then dummy up a local one 00168 // using the requested desired access 00169 // 00170 00171 if (!ARGUMENT_PRESENT(AccessState)) { 00172 00173 AccessState = &LocalAccessState; 00174 00175 Status = SeCreateAccessState( &LocalAccessState, 00176 &AuxData, 00177 DesiredAccess, 00178 &ObjectType->TypeInfo.GenericMapping ); 00179 00180 if (!NT_SUCCESS(Status)) { 00181 00182 ObDereferenceObject(Object); 00183 00184 return Status; 00185 } 00186 } 00187 00188 AccessState->SecurityDescriptor = ObjectCreateInfo->SecurityDescriptor; 00189 00190 // 00191 // Check the desired access mask against the security descriptor 00192 // 00193 00194 Status = ObpValidateAccessMask( AccessState ); 00195 00196 if (!NT_SUCCESS( Status )) { 00197 00198 ObDereferenceObject(Object); 00199 00200 return( Status ); 00201 } 00202 00203 // 00204 // Set some local state variables 00205 // 00206 00207 DirectoryLocked = FALSE; 00208 InsertObject = Object; 00209 OpenReason = ObCreateHandle; 00210 00211 // 00212 // Check if we have an object name. If so then 00213 // lookup the name 00214 // 00215 00216 if (ObjectName != NULL) { 00217 00218 Status = ObpLookupObjectName( ObjectCreateInfo->RootDirectory, 00219 ObjectName, 00220 ObjectCreateInfo->Attributes, 00221 ObjectType, 00222 (KPROCESSOR_MODE)(ObjectHeader->Flags & OB_FLAG_KERNEL_OBJECT 00223 ? KernelMode : UserMode), 00224 ObjectCreateInfo->ParseContext, 00225 ObjectCreateInfo->SecurityQos, 00226 Object, 00227 AccessState, 00228 &DirectoryLocked, 00229 &InsertObject ); 00230 00231 // 00232 // We found the name and it is not the object we have as our input. 00233 // So we cannot insert the object again so we'll return an 00234 // appropriate status 00235 // 00236 00237 if (NT_SUCCESS(Status) && 00238 (InsertObject != NULL) && 00239 (InsertObject != Object)) { 00240 00241 OpenReason = ObOpenHandle; 00242 00243 if (ObjectCreateInfo->Attributes & OBJ_OPENIF) { 00244 00245 if (ObjectType != OBJECT_TO_OBJECT_HEADER(InsertObject)->Type) { 00246 00247 Status = STATUS_OBJECT_TYPE_MISMATCH; 00248 00249 } else { 00250 00251 Status = STATUS_OBJECT_NAME_EXISTS; // Warning only 00252 } 00253 00254 } else { 00255 00256 Status = STATUS_OBJECT_NAME_COLLISION; 00257 } 00258 } 00259 00260 // 00261 // We did not find the name so we'll cleanup after ourselves 00262 // and return to our caller 00263 // 00264 00265 if (!NT_SUCCESS( Status )) { 00266 00267 if (DirectoryLocked) { 00268 00269 ObpLeaveRootDirectoryMutex(); 00270 } 00271 00272 ObDereferenceObject( Object ); 00273 00274 // 00275 // Free security information if we allocated it 00276 // 00277 00278 if (AccessState == &LocalAccessState) { 00279 00280 SeDeleteAccessState( AccessState ); 00281 } 00282 00283 return( Status ); 00284 00285 } else { 00286 00287 // 00288 // Otherwise we did locate the object name 00289 // 00290 // If we just created a named symbolic link then call out to 00291 // handle any Dos Device name semanatics. 00292 // 00293 00294 if (ObjectType == ObpSymbolicLinkObjectType) { 00295 00296 ObpCreateSymbolicLinkName( (POBJECT_SYMBOLIC_LINK)InsertObject ); 00297 } 00298 } 00299 } 00300 00301 // 00302 // If we are creating a new object, then we need assign security 00303 // to it. A pointer to the captured caller-proposed security 00304 // descriptor is contained in the AccessState structure. The 00305 // SecurityDescriptor field in the object header must point to 00306 // the final security descriptor, or to NULL if no security is 00307 // to be assigned to the object. 00308 // 00309 00310 if (InsertObject == Object) { 00311 00312 // 00313 // Only the following objects have security descriptors: 00314 // 00315 // - Named Objects 00316 // - Unnamed objects whose object-type information explicitly 00317 // indicates a security descriptor is required. 00318 // 00319 00320 if ((ObjectName != NULL) || ObjectType->TypeInfo.SecurityRequired) { 00321 00322 // 00323 // Get the parent's descriptor, if there is one... 00324 // 00325 00326 if ((NameInfo != NULL) && (NameInfo->Directory != NULL)) { 00327 00328 // 00329 // This will allocate a block of memory and copy 00330 // the parent's security descriptor into it, and 00331 // return the pointer to the block. 00332 // 00333 // Call ObReleaseObjectSecurity to free up this 00334 // memory. 00335 // 00336 00337 ObGetObjectSecurity( NameInfo->Directory, 00338 &ParentDescriptor, 00339 &SecurityDescriptorAllocated ); 00340 } 00341 00342 // 00343 // Take the captured security descriptor in the AccessState, 00344 // put it into the proper format, and call the object's 00345 // security method to assign the new security descriptor to 00346 // the new object. 00347 // 00348 00349 Status = ObAssignSecurity( AccessState, 00350 ParentDescriptor, 00351 Object, 00352 ObjectType ); 00353 00354 if (ParentDescriptor != NULL) { 00355 00356 ObReleaseObjectSecurity( ParentDescriptor, 00357 SecurityDescriptorAllocated ); 00358 00359 } else if (NT_SUCCESS( Status )) { 00360 00361 SeReleaseSecurityDescriptor( ObjectCreateInfo->SecurityDescriptor, 00362 ObjectCreateInfo->ProbeMode, 00363 TRUE ); 00364 00365 ObjectCreateInfo->SecurityDescriptor = NULL; 00366 AccessState->SecurityDescriptor = NULL; 00367 } 00368 } 00369 00370 if (!NT_SUCCESS( Status )) { 00371 00372 // 00373 // The attempt to assign the security descriptor to 00374 // the object failed. 00375 // 00376 00377 if (DirectoryLocked) { 00378 00379 // 00380 // If ObpLookupObjectName already inserted the 00381 // object into the directory we have to backup this 00382 // 00383 00384 // 00385 // Capture the object Directory 00386 // 00387 00388 DirObject = NameInfo->Directory; 00389 00390 ObpDeleteDirectoryEntry( NameInfo->Directory ); 00391 00392 NameInfo->Directory = NULL; 00393 00394 ObpLeaveRootDirectoryMutex(); 00395 00396 // 00397 // If ObpLookupObjectName inserted the object into the directory 00398 // it added a reference to the object and to its directory 00399 // object. We should remove the extra-references 00400 // 00401 00402 if (DirObject) { 00403 00404 ObDereferenceObject( Object ); 00405 ObDereferenceObject( DirObject ); 00406 } 00407 } 00408 00409 // 00410 // *** The first backout logic used ObpDeleteNameCheck 00411 // which is wrong because the security descriptor for 00412 // the object is not initialized. Actually ObpDeleteNameCheck 00413 // had no effect because the object was removed before from 00414 // the directory 00415 // 00416 00417 ObDereferenceObject( Object ); 00418 00419 // 00420 // Free security information if we allocated it 00421 // 00422 00423 if (AccessState == &LocalAccessState) { 00424 00425 SeDeleteAccessState( AccessState ); 00426 } 00427 00428 return( Status ); 00429 } 00430 } 00431 00432 ReturnStatus = Status; 00433 00434 ObjectHeader->ObjectCreateInfo = NULL; 00435 00436 // 00437 // Create a named handle for the object with a pointer bias 00438 // This call also will unlock the directory lock is necessary 00439 // on return 00440 // 00441 00442 Status = ObpCreateHandle( OpenReason, 00443 InsertObject, 00444 NULL, 00445 AccessState, 00446 1 + ObjectPointerBias, 00447 ObjectCreateInfo->Attributes, 00448 DirectoryLocked, 00449 PreviousMode, 00450 NewObject, 00451 &NewHandle ); 00452 00453 ObpFreeObjectCreateInformation( ObjectCreateInfo ); 00454 00455 // 00456 // If the insertion failed, the following dereference will cause 00457 // the newly created object to be deallocated. 00458 // 00459 00460 if (!NT_SUCCESS( Status )) { 00461 00462 // 00463 // Make the name reference go away if an error. 00464 // 00465 00466 if (ObjectName != NULL) { 00467 00468 ObpDeleteNameCheck( Object, FALSE ); 00469 } 00470 } 00471 00472 ObDereferenceObject( Object ); 00473 00474 if (NT_SUCCESS( Status )) { 00475 00476 *Handle = NewHandle; 00477 00478 } else { 00479 00480 *Handle = NULL; 00481 00482 ReturnStatus = Status; 00483 } 00484 00485 // 00486 // Free security information if we allocated it 00487 // 00488 00489 if (AccessState == &LocalAccessState) { 00490 00491 SeDeleteAccessState( AccessState ); 00492 } 00493 00494 return( ReturnStatus ); 00495 }

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