test: obinsert.c Source File

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 }