test: obcreate.c Source File

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

# obcreate.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1989  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     obcreate.c
    00008
    00009 Abstract:
    00010
    00011     Object creation
    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, ObCreateObject)
    00025 #pragma alloc_text(PAGE, ObDeleteCapturedInsertInfo)
    00026 #pragma alloc_text(PAGE, ObpCaptureObjectCreateInformation)
    00027 #pragma alloc_text(PAGE, ObpCaptureObjectName)
    00028 #pragma alloc_text(PAGE, ObpAllocateObject)
    00029 #pragma alloc_text(PAGE, ObpFreeObject)
    00030 #endif
    00031
    00032 #if DBG
    00033
    00034 //
    00035 //  The following variable is only used on a checked build to control
    00036 //  echoing out the allocs and frees of objects
    00037 //
    00038
    00039 BOOLEAN ObpShowAllocAndFree;
    00040
    00041 #endif
    00042
    00043 //
    00044 //  Local performance counters
    00045 //
    00046
    00047 ULONG ObpObjectsCreated;
    00048 ULONG ObpObjectsWithPoolQuota;
    00049 ULONG ObpObjectsWithHandleDB;
    00050 ULONG ObpObjectsWithName;
    00051 ULONG ObpObjectsWithCreatorInfo;
    00052
    00053
    00054 NTSTATUS
    00055 ObCreateObject (
    00056     IN KPROCESSOR_MODE ProbeMode,
    00057     IN POBJECT_TYPE ObjectType,
    00058     IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
    00059     IN KPROCESSOR_MODE OwnershipMode,
    00060     IN OUT PVOID ParseContext OPTIONAL,
    00061     IN ULONG ObjectBodySize,
    00062     IN ULONG PagedPoolCharge,
    00063     IN ULONG NonPagedPoolCharge,
    00064     OUT PVOID *Object
    00065     )
    00066
    00067 /*++
    00068
    00069 Routine Description:
    00070
    00071     This functions allocates space for an NT Object from either
    00072     Paged or NonPaged pool. It captures the optional name and
    00073     SECURITY_DESCRIPTOR parameters for later use when the object is
    00074     inserted into an object table.  No quota is charged at this time.
    00075     That occurs when the object is inserted into an object table.
    00076
    00077 Arguments:
    00078
    00079     ProbeMode - The processor mode to consider when doing a probe
    00080         of the input parameters
    00081
    00082     ObjectType - A pointer of the type returned by ObCreateObjectType
    00083         that gives the type of object being created.
    00084
    00085     ObjectAttributes - Optionally supplies the attributes of the object
    00086         being created (such as its name)
    00087
    00088     OwnershipMode - The processor mode of who is going to own the object
    00089
    00090     ParseContext - Ignored
    00091
    00092     ObjectBodySize - Number of bytes to allocate for the object body.  The
    00093         object body immediately follows the object header in memory and are
    00094         part of a single allocation.
    00095
    00096     PagedPoolCharge - Supplies the amount of paged pool to charge for the
    00097         object.  If zero is specified then the default charge for the object
    00098         type is used.
    00099
    00100     NonPagedPoolCharge - Supplies the amount of nonpaged pool to charge for
    00101         the object.  If zero is specified then the default charge for the
    00102         object type is used.
    00103
    00104     Object - Receives a pointer to the newly created object
    00105
    00106 Return Value:
    00107
    00108     Following errors can occur:
    00109
    00110         - invalid object type
    00111         - insufficient memory
    00112
    00113 --*/
    00114
    00115 {
    00116     UNICODE_STRING CapturedObjectName;
    00117     POBJECT_CREATE_INFORMATION ObjectCreateInfo;
    00118     POBJECT_HEADER ObjectHeader;
    00119     NTSTATUS Status;
    00120
    00121     PAGED_CODE();
    00122
    00123     //
    00124     //  Allocate a buffer to capture the object creation information.
    00125     //
    00126
    00127     ObjectCreateInfo = ObpAllocateObjectCreateInfoBuffer();
    00128
    00129     if (ObjectCreateInfo == NULL) {
    00130
    00131         Status = STATUS_INSUFFICIENT_RESOURCES;
    00132
    00133     } else {
    00134
    00135         //
    00136         //  Capture the object attributes, quality of service, and object
    00137         //  name, if specified. Otherwise, initialize the captured object
    00138         //  name, the security quality of service, and the create attributes
    00139         //  to default values.
    00140         //
    00141
    00142         Status = ObpCaptureObjectCreateInformation( ObjectType,
    00143                                                     ProbeMode,
    00144                                                     ObjectAttributes,
    00145                                                     &CapturedObjectName,
    00146                                                     ObjectCreateInfo,
    00147                                                     FALSE );
    00148
    00149         if (NT_SUCCESS(Status)) {
    00150
    00151             //
    00152             //  If the creation attributes are invalid, then return an error
    00153             //  status.
    00154             //
    00155
    00156             if (ObjectType->TypeInfo.InvalidAttributes & ObjectCreateInfo->Attributes) {
    00157
    00158                 Status = STATUS_INVALID_PARAMETER;
    00159
    00160             } else {
    00161
    00162                 //
    00163                 //  Set the paged and nonpaged pool quota charges for the
    00164                 //  object allocation.
    00165                 //
    00166
    00167                 if (PagedPoolCharge == 0) {
    00168
    00169                     PagedPoolCharge = ObjectType->TypeInfo.DefaultPagedPoolCharge;
    00170                 }
    00171
    00172                 if (NonPagedPoolCharge == 0) {
    00173
    00174                     NonPagedPoolCharge = ObjectType->TypeInfo.DefaultNonPagedPoolCharge;
    00175                 }
    00176
    00177                 ObjectCreateInfo->PagedPoolCharge = PagedPoolCharge;
    00178                 ObjectCreateInfo->NonPagedPoolCharge = NonPagedPoolCharge;
    00179
    00180                 //
    00181                 //  Allocate and initialize the object.
    00182                 //
    00183
    00184                 Status = ObpAllocateObject( ObjectCreateInfo,
    00185                                             OwnershipMode,
    00186                                             ObjectType,
    00187                                             &CapturedObjectName,
    00188                                             ObjectBodySize,
    00189                                             &ObjectHeader );
    00190
    00191                 if (NT_SUCCESS(Status)) {
    00192
    00193                     //
    00194                     //  If a permanent object is being created, then check if
    00195                     //  the caller has the appropriate privilege.
    00196                     //
    00197
    00198                     *Object = &ObjectHeader->Body;
    00199
    00200                     if (ObjectHeader->Flags & OB_FLAG_PERMANENT_OBJECT) {
    00201
    00202                         if (!SeSinglePrivilegeCheck( SeCreatePermanentPrivilege,
    00203                                                      ProbeMode)) {
    00204
    00205                             ObpFreeObject(*Object);
    00206
    00207                             Status = STATUS_PRIVILEGE_NOT_HELD;
    00208                         }
    00209                     }
    00210
    00211                     //
    00212                     //  Here is the only successful path out of this module but
    00213                     //  this path can also return privilege not held.
    00214                     //
    00215
    00216                     return Status;
    00217                 }
    00218             }
    00219
    00220             //
    00221             //  An error path, free the create information.
    00222             //
    00223
    00224             ObpReleaseObjectCreateInformation(ObjectCreateInfo);
    00225
    00226             if (CapturedObjectName.Buffer != NULL) {
    00227
    00228                 ObpFreeObjectNameBuffer(&CapturedObjectName);
    00229             }
    00230         }
    00231
    00232         //
    00233         //  An error path, free object creation information buffer.
    00234         //
    00235
    00236         ObpFreeObjectCreateInfoBuffer(ObjectCreateInfo);
    00237     }
    00238
    00239     //
    00240     //  An error path
    00241     //
    00242
    00243     return Status;
    00244 }
    00245
    00246
    00247 NTSTATUS
    00248 ObpCaptureObjectCreateInformation (
    00249     IN POBJECT_TYPE ObjectType OPTIONAL,
    00250     IN KPROCESSOR_MODE ProbeMode,
    00251     IN POBJECT_ATTRIBUTES ObjectAttributes,
    00252     IN OUT PUNICODE_STRING CapturedObjectName,
    00253     IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
    00254     IN LOGICAL UseLookaside
    00255     )
    00256
    00257 /*++
    00258
    00259 Routine Description:
    00260
    00261     This function captures the object creation information and stuff
    00262     it into the input variable ObjectCreateInfo
    00263
    00264 Arguments:
    00265
    00266     ObjectType - Specifies the type of object we expect to capture,
    00267         currently ignored.
    00268
    00269     ProbeMode - Specifies the processor mode for doing our parameter
    00270         probes
    00271
    00272     ObjectAttributes - Supplies the object attributes we are trying
    00273         to capture
    00274
    00275     CapturedObjectName - Recieves the name of the object being created
    00276
    00277     ObjectCreateInfo - Receives the create information for the object
    00278         like its root, attributes, and security information
    00279
    00280     UseLookaside - Specifies if we are to allocate the captured name
    00281         buffer from the lookaside list or from straight pool.
    00282
    00283 Return Value:
    00284
    00285     An appropriate status value
    00286
    00287 --*/
    00288
    00289 {
    00290     PUNICODE_STRING ObjectName;
    00291     PSECURITY_DESCRIPTOR SecurityDescriptor;
    00292     PSECURITY_QUALITY_OF_SERVICE SecurityQos;
    00293     NTSTATUS Status;
    00294     ULONG Size;
    00295
    00296     PAGED_CODE();
    00297
    00298     //
    00299     //  Capture the object attributes, the security quality of service, if
    00300     //  specified, and object name, if specified.
    00301     //
    00302
    00303     Status = STATUS_SUCCESS;
    00304
    00305     RtlZeroMemory(ObjectCreateInfo, sizeof(OBJECT_CREATE_INFORMATION));
    00306
    00307     try {
    00308
    00309         if (ARGUMENT_PRESENT(ObjectAttributes)) {
    00310
    00311             //
    00312             //  Probe the object attributes if necessary.
    00313             //
    00314
    00315             if (ProbeMode != KernelMode) {
    00316
    00317                 ProbeForRead( ObjectAttributes,
    00318                               sizeof(OBJECT_ATTRIBUTES),
    00319                               sizeof(ULONG) );
    00320             }
    00321
    00322             if (ObjectAttributes->Length != sizeof(OBJECT_ATTRIBUTES) ||
    00323                 (ObjectAttributes->Attributes & ~OBJ_VALID_ATTRIBUTES)) {
    00324
    00325                 Status = STATUS_INVALID_PARAMETER;
    00326
    00327                 goto failureExit;
    00328             }
    00329
    00330             //
    00331             //  Capture the object attributes.
    00332             //
    00333
    00334             ObjectCreateInfo->RootDirectory = ObjectAttributes->RootDirectory;
    00335             ObjectCreateInfo->Attributes = ObjectAttributes->Attributes & OBJ_VALID_ATTRIBUTES;
    00336             ObjectName = ObjectAttributes->ObjectName;
    00337             SecurityDescriptor = ObjectAttributes->SecurityDescriptor;
    00338             SecurityQos = ObjectAttributes->SecurityQualityOfService;
    00339
    00340             if (ARGUMENT_PRESENT(SecurityDescriptor)) {
    00341
    00342                 Status = SeCaptureSecurityDescriptor( SecurityDescriptor,
    00343                                                       ProbeMode,
    00344                                                       PagedPool,
    00345                                                       TRUE,
    00346                                                       &ObjectCreateInfo->SecurityDescriptor );
    00347
    00348                 if (!NT_SUCCESS(Status)) {
    00349
    00350                     KdPrint(( "OB: Failed to capture security descriptor at %08x - Status == %08x\n",
    00351                               SecurityDescriptor,
    00352                               Status) );
    00353
    00354                     //
    00355                     //  The cleanup routine depends on this being NULL if it isn't
    00356                     //  allocated.  SeCaptureSecurityDescriptor may modify this
    00357                     //  parameter even if it fails.
    00358                     //
    00359
    00360                     ObjectCreateInfo->SecurityDescriptor = NULL;
    00361
    00362                     goto failureExit;
    00363                 }
    00364
    00365                 SeComputeQuotaInformationSize(  ObjectCreateInfo->SecurityDescriptor,
    00366                                                 &Size );
    00367
    00368                 ObjectCreateInfo->SecurityDescriptorCharge = SeComputeSecurityQuota( Size );
    00369                 ObjectCreateInfo->ProbeMode = ProbeMode;
    00370             }
    00371
    00372             if (ARGUMENT_PRESENT(SecurityQos)) {
    00373
    00374                 if (ProbeMode != KernelMode) {
    00375
    00376                     ProbeForRead( SecurityQos, sizeof(*SecurityQos), sizeof(ULONG));
    00377                 }
    00378
    00379                 ObjectCreateInfo->SecurityQualityOfService = *SecurityQos;
    00380                 ObjectCreateInfo->SecurityQos = &ObjectCreateInfo->SecurityQualityOfService;
    00381             }
    00382
    00383         } else {
    00384
    00385             ObjectName = NULL;
    00386         }
    00387
    00388     } except (ExSystemExceptionFilter()) {
    00389
    00390         Status = GetExceptionCode();
    00391
    00392         goto failureExit;
    00393     }
    00394
    00395     //
    00396     //  If an object name is specified, then capture the object name.
    00397     //  Otherwise, initialize the object name descriptor and check for
    00398     //  an incorrectly specified root directory.
    00399     //
    00400
    00401     if (ARGUMENT_PRESENT(ObjectName)) {
    00402
    00403         Status = ObpCaptureObjectName( ProbeMode,
    00404                                        ObjectName,
    00405                                        CapturedObjectName,
    00406                                        UseLookaside );
    00407
    00408     } else {
    00409
    00410         CapturedObjectName->Buffer = NULL;
    00411         CapturedObjectName->Length = 0;
    00412         CapturedObjectName->MaximumLength = 0;
    00413
    00414         if (ARGUMENT_PRESENT(ObjectCreateInfo->RootDirectory)) {
    00415
    00416             Status = STATUS_OBJECT_NAME_INVALID;
    00417         }
    00418     }
    00419
    00420     //
    00421     //  If the completion status is not successful, and a security quality
    00422     //  of service parameter was specified, then free the security quality
    00423     //  of service memory.
    00424     //
    00425
    00426 failureExit:
    00427
    00428     if (!NT_SUCCESS(Status)) {
    00429
    00430         ObpReleaseObjectCreateInformation(ObjectCreateInfo);
    00431     }
    00432
    00433     return Status;
    00434 }
    00435
    00436
    00437 NTSTATUS
    00438 ObpCaptureObjectName (
    00439     IN KPROCESSOR_MODE ProbeMode,
    00440     IN PUNICODE_STRING ObjectName,
    00441     IN OUT PUNICODE_STRING CapturedObjectName,
    00442     IN LOGICAL UseLookaside
    00443     )
    00444
    00445 /*++
    00446
    00447 Routine Description:
    00448
    00449     This function captures the object name but first verifies that
    00450     it is at least properly sized.
    00451
    00452 Arguments:
    00453
    00454     ProbeMode - Supplies the processor mode to use when probing
    00455         the object name
    00456
    00457     ObjectName - Supplies the caller's version of the object name
    00458
    00459     CapturedObjectName - Receives the captured verified version
    00460         of the object name
    00461
    00462     UseLookaside - Indicates if the captured name buffer should be
    00463         allocated from the lookaside list or from straight pool
    00464
    00465 Return Value:
    00466
    00467     An appropriate status value
    00468
    00469 --*/
    00470
    00471 {
    00472     PWCH FreeBuffer;
    00473     UNICODE_STRING InputObjectName;
    00474     ULONG Length;
    00475     NTSTATUS Status;
    00476
    00477     PAGED_CODE();
    00478
    00479     //
    00480     //  Initialize the object name descriptor and capture the specified name
    00481     //  string.
    00482     //
    00483
    00484     CapturedObjectName->Buffer = NULL;
    00485     CapturedObjectName->Length = 0;
    00486     CapturedObjectName->MaximumLength = 0;
    00487
    00488     Status = STATUS_SUCCESS;
    00489
    00490     try {
    00491
    00492         //
    00493         //  Probe and capture the name string descriptor and probe the
    00494         //  name string, if necessary.
    00495         //
    00496
    00497         FreeBuffer = NULL;
    00498
    00499         if (ProbeMode != KernelMode) {
    00500
    00501             InputObjectName = ProbeAndReadUnicodeString(ObjectName);
    00502
    00503             ProbeForRead( InputObjectName.Buffer,
    00504                           InputObjectName.Length,
    00505                           sizeof(WCHAR) );
    00506
    00507         } else {
    00508
    00509             InputObjectName = *ObjectName;
    00510         }
    00511
    00512         //
    00513         //  If the length of the string is not zero, then capture the string.
    00514         //
    00515
    00516         if (InputObjectName.Length != 0) {
    00517
    00518             //
    00519             //  If the length of the string is not an even multiple of the
    00520             //  size of a UNICODE character or cannot be zero terminated,
    00521             //  then return an error.
    00522             //
    00523
    00524             Length = InputObjectName.Length;
    00525
    00526             if (((Length & (sizeof(WCHAR) - 1)) != 0) ||
    00527                 (Length == (MAXUSHORT - sizeof(WCHAR) + 1))) {
    00528
    00529                 Status = STATUS_OBJECT_NAME_INVALID;
    00530
    00531             } else {
    00532
    00533                 //
    00534                 //  Allocate a buffer for the specified name string.
    00535                 //
    00536                 //  N.B. The name buffer allocation routine adds one
    00537                 //       UNICODE character to the length and initializes
    00538                 //       the string descriptor.
    00539                 //
    00540
    00541                 FreeBuffer = ObpAllocateObjectNameBuffer( Length,
    00542                                                           UseLookaside,
    00543                                                           CapturedObjectName );
    00544
    00545                 if (FreeBuffer == NULL) {
    00546
    00547                     Status = STATUS_INSUFFICIENT_RESOURCES;
    00548
    00549                 } else {
    00550
    00551                     //
    00552                     //  Copy the specified name string to the destination
    00553                     //  buffer.
    00554                     //
    00555
    00556                     RtlMoveMemory(FreeBuffer, InputObjectName.Buffer, Length);
    00557
    00558                     //
    00559                     //  Zero terminate the name string and initialize the
    00560                     //  string descriptor.
    00561                     //
    00562
    00563                     FreeBuffer[Length / sizeof(WCHAR)] = UNICODE_NULL;
    00564                 }
    00565             }
    00566         }
    00567
    00568     } except(ExSystemExceptionFilter()) {
    00569
    00570         Status = GetExceptionCode();
    00571
    00572         if (FreeBuffer != NULL) {
    00573
    00574             ExFreePool(FreeBuffer);
    00575         }
    00576     }
    00577
    00578     return Status;
    00579 }
    00580
    00581
    00582 PWCHAR
    00583 ObpAllocateObjectNameBuffer (
    00584     IN ULONG Length,
    00585     IN LOGICAL UseLookaside,
    00586     IN OUT PUNICODE_STRING ObjectName
    00587     )
    00588
    00589 /*++
    00590
    00591 Routine Description:
    00592
    00593     This function allocates an object name buffer.
    00594
    00595     N.B. This function is nonpageable.
    00596
    00597 Arguments:
    00598
    00599     Length - Supplies the length of the required buffer in bytes.
    00600
    00601     UseLookaside - Supplies a logical variable that determines whether an
    00602         attempt is made to allocate the name buffer from the lookaside list.
    00603
    00604     ObjectName - Supplies a pointer to a name buffer string descriptor.
    00605
    00606 Return Value:
    00607
    00608     If the allocation is successful, then name buffer string descriptor
    00609     is initialized and the address of the name buffer is returned as the
    00610     function value. Otherwise, a value of NULL is returned.
    00611
    00612 --*/
    00613
    00614 {
    00615     PVOID Buffer;
    00616     ULONG Maximum;
    00617     KIRQL OldIrql;
    00618     PKPRCB Prcb;
    00619
    00620     //
    00621     //  If allocation from the lookaside lists is specified and the buffer
    00622     //  size is less than the size of lookaside list entries, then attempt
    00623     //  to allocate the name buffer from the lookaside lists. Otherwise,
    00624     //  attempt to allocate the name buffer from nonpaged pool.
    00625     //
    00626
    00627     Maximum = Length + sizeof(WCHAR);
    00628
    00629     if ((UseLookaside == FALSE) || (Maximum > OBJECT_NAME_BUFFER_SIZE)) {
    00630
    00631         //
    00632         //  Attempt to allocate the buffer from nonpaged pool.
    00633         //
    00634
    00635         Buffer = ExAllocatePoolWithTag(NonPagedPool, Maximum, 'mNbO');
    00636
    00637     } else {
    00638
    00639         //
    00640         //  Attempt to allocate the name buffer from the lookaside list. If
    00641         //  the allocation attempt fails, then attempt to allocate the name
    00642         //  buffer from pool.
    00643         //
    00644
    00645         Maximum = OBJECT_NAME_BUFFER_SIZE;
    00646         Buffer = ExAllocateFromPPNPagedLookasideList(LookasideNameBufferList);
    00647     }
    00648
    00649     //
    00650     //  Initialize the string descriptor and return the buffer address.
    00651     //
    00652
    00653     ObjectName->Length = (USHORT)Length;
    00654     ObjectName->MaximumLength = (USHORT)Maximum;
    00655     ObjectName->Buffer = Buffer;
    00656
    00657     return (PWCHAR)Buffer;
    00658 }
    00659
    00660
    00661 VOID
    00662 FASTCALL
    00663 ObpFreeObjectNameBuffer (
    00664     OUT PUNICODE_STRING ObjectName
    00665     )
    00666
    00667 /*++
    00668
    00669 Routine Description:
    00670
    00671     This function frees an object name buffer.
    00672
    00673     N.B. This function is nonpageable.
    00674
    00675 Arguments:
    00676
    00677     ObjectName - Supplies a pointer to a name buffer string descriptor.
    00678
    00679 Return Value:
    00680
    00681     None.
    00682
    00683 --*/
    00684
    00685 {
    00686     PVOID Buffer;
    00687     KIRQL OldIrql;
    00688     PKPRCB Prcb;
    00689
    00690     //
    00691     //  If the size of the buffer is not equal to the size of lookaside list
    00692     //  entries, then  free the buffer to pool. Otherwise, free the buffer to
    00693     //  the lookaside list.
    00694     //
    00695
    00696     Buffer = ObjectName->Buffer;
    00697
    00698     if (ObjectName->MaximumLength != OBJECT_NAME_BUFFER_SIZE) {
    00699
    00700         ExFreePool(Buffer);
    00701
    00702     } else {
    00703
    00704         ExFreeToPPNPagedLookasideList(LookasideNameBufferList, Buffer);
    00705     }
    00706
    00707     return;
    00708 }
    00709
    00710
    00711 NTKERNELAPI
    00712 VOID
    00713 ObDeleteCapturedInsertInfo (
    00714     IN PVOID Object
    00715     )
    00716
    00717 /*++
    00718
    00719 Routine Description:
    00720
    00721     This function frees the creation information that could be pointed at
    00722     by the object header.
    00723
    00724 Arguments:
    00725
    00726     Object - Supplies the object being modified
    00727
    00728 Return Value:
    00729
    00730     None.
    00731
    00732 --*/
    00733
    00734 {
    00735     POBJECT_HEADER ObjectHeader;
    00736
    00737     PAGED_CODE();
    00738
    00739     //
    00740     //  Get the address of the object header and free the object create
    00741     //  information object if the object is being created.
    00742     //
    00743
    00744     ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
    00745
    00746     if (ObjectHeader->Flags & OB_FLAG_NEW_OBJECT) {
    00747
    00748         if (ObjectHeader->ObjectCreateInfo != NULL) {
    00749
    00750             ObpFreeObjectCreateInformation(ObjectHeader->ObjectCreateInfo);
    00751
    00752             ObjectHeader->ObjectCreateInfo = NULL;
    00753         }
    00754     }
    00755
    00756     return;
    00757 }
    00758
    00759
    00760 NTSTATUS
    00761 ObpAllocateObject (
    00762     IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
    00763     IN KPROCESSOR_MODE OwnershipMode,
    00764     IN POBJECT_TYPE ObjectType OPTIONAL,
    00765     IN PUNICODE_STRING ObjectName,
    00766     IN ULONG ObjectBodySize,
    00767     OUT POBJECT_HEADER *ReturnedObjectHeader
    00768     )
    00769
    00770 /*++
    00771
    00772 Routine Description:
    00773
    00774     This routine allocates a new object including the object header
    00775     and body from pool and fill in the appropriate fields.
    00776
    00777 Arguments:
    00778
    00779     ObjectCreateInfo - Supplies the create information for the new object
    00780
    00781     OwnershipMode - Supplies the processor mode of who is going to own
    00782         the object
    00783
    00784     ObjectType - Optionally supplies the object type of the object being
    00785         created. If the object create info not null then this field must
    00786         be supplied.
    00787
    00788     ObjectName - Supplies the name of the object being created
    00789
    00790     ObjectBodySize - Specifies the size, in bytes, of the body of the object
    00791         being created
    00792
    00793     ReturnedObjectHeader - Receives a pointer to the object header for the
    00794         newly created objet.
    00795
    00796 Return Value:
    00797
    00798     An appropriate status value.
    00799
    00800 --*/
    00801
    00802 {
    00803     ULONG HeaderSize;
    00804     POBJECT_HEADER ObjectHeader;
    00805     NTSTATUS Status;
    00806     PVOID ZoneSegment;
    00807     ULONG QuotaInfoSize;
    00808     ULONG HandleInfoSize;
    00809     ULONG NameInfoSize;
    00810     ULONG CreatorInfoSize;
    00811     POBJECT_HEADER_QUOTA_INFO QuotaInfo;
    00812     POBJECT_HEADER_HANDLE_INFO HandleInfo;
    00813     POBJECT_HEADER_NAME_INFO NameInfo;
    00814     POBJECT_HEADER_CREATOR_INFO CreatorInfo;
    00815     POOL_TYPE PoolType;
    00816
    00817     PAGED_CODE();
    00818
    00819     ObpObjectsCreated += 1;
    00820
    00821     //
    00822     //  Compute the sizes of the optional object header components.
    00823     //
    00824
    00825     if (ObjectCreateInfo == NULL) {
    00826
    00827         QuotaInfoSize = 0;
    00828         HandleInfoSize = 0;
    00829         NameInfoSize = sizeof( OBJECT_HEADER_NAME_INFO );
    00830         CreatorInfoSize = sizeof( OBJECT_HEADER_CREATOR_INFO );
    00831
    00832     } else {
    00833
    00834         //
    00835         //  The caller specified some additional object create info
    00836         //
    00837         //  First check to see if we need to set the quota
    00838         //
    00839
    00840         if (ObjectCreateInfo->PagedPoolCharge != ObjectType->TypeInfo.DefaultPagedPoolCharge ||
    00841             ObjectCreateInfo->NonPagedPoolCharge != ObjectType->TypeInfo.DefaultNonPagedPoolCharge ||
    00842             ObjectCreateInfo->SecurityDescriptorCharge > SE_DEFAULT_SECURITY_QUOTA ||
    00843             (ObjectCreateInfo->Attributes & OBJ_EXCLUSIVE)) {
    00844
    00845             QuotaInfoSize = sizeof( OBJECT_HEADER_QUOTA_INFO );
    00846             ObpObjectsWithPoolQuota += 1;
    00847
    00848         } else {
    00849
    00850             QuotaInfoSize = 0;
    00851         }
    00852
    00853         //
    00854         //  Check if we are to allocate space to maintain handle counts
    00855         //
    00856
    00857         if (ObjectType->TypeInfo.MaintainHandleCount) {
    00858
    00859             HandleInfoSize = sizeof( OBJECT_HEADER_HANDLE_INFO );
    00860             ObpObjectsWithHandleDB += 1;
    00861
    00862         } else {
    00863
    00864             HandleInfoSize = 0;
    00865         }
    00866
    00867         //
    00868         //  Check if we are to allocate space for the name
    00869         //
    00870
    00871         if (ObjectName->Buffer != NULL) {
    00872
    00873             NameInfoSize = sizeof( OBJECT_HEADER_NAME_INFO );
    00874             ObpObjectsWithName += 1;
    00875
    00876         } else {
    00877
    00878             NameInfoSize = 0;
    00879         }
    00880
    00881         //
    00882         //  Finally check if we are to maintain the creator info
    00883         //
    00884
    00885         if (ObjectType->TypeInfo.MaintainTypeList) {
    00886
    00887             CreatorInfoSize = sizeof( OBJECT_HEADER_CREATOR_INFO );
    00888             ObpObjectsWithCreatorInfo += 1;
    00889
    00890         } else {
    00891
    00892             CreatorInfoSize = 0;
    00893         }
    00894     }
    00895
    00896     //
    00897     //  Now compute the total header size
    00898     //
    00899
    00900     HeaderSize = QuotaInfoSize +
    00901                  HandleInfoSize +
    00902                  NameInfoSize +
    00903                  CreatorInfoSize +
    00904                  FIELD_OFFSET( OBJECT_HEADER, Body );
    00905
    00906     //
    00907     //  Allocate and initialize the object.
    00908     //
    00909     //  If the object type is not specified or specifies nonpaged pool,
    00910     //  then allocate the object from nonpaged pool.
    00911     //  Otherwise, allocate the object from paged pool.
    00912     //
    00913
    00914     if ((ObjectType == NULL) || (ObjectType->TypeInfo.PoolType == NonPagedPool)) {
    00915
    00916         PoolType = NonPagedPool;
    00917
    00918     } else {
    00919
    00920         PoolType = PagedPool;
    00921     }
    00922
    00923     ObjectHeader = ExAllocatePoolWithTag( PoolType,
    00924                                           HeaderSize + ObjectBodySize,
    00925                                           (ObjectType == NULL ? 'TjbO' : ObjectType->Key) |
    00926                                             PROTECTED_POOL );
    00927
    00928     if (ObjectHeader == NULL) {
    00929
    00930         return STATUS_INSUFFICIENT_RESOURCES;
    00931     }
    00932
    00933     //
    00934     //  Now based on if we are to put in the quota, handle, name, or creator info we
    00935     //  will do the extra work.  This order is very important because we rely on
    00936     //  it to free the object.
    00937     //
    00938
    00939     if (QuotaInfoSize != 0) {
    00940
    00941         QuotaInfo = (POBJECT_HEADER_QUOTA_INFO)ObjectHeader;
    00942         QuotaInfo->PagedPoolCharge = ObjectCreateInfo->PagedPoolCharge;
    00943         QuotaInfo->NonPagedPoolCharge = ObjectCreateInfo->NonPagedPoolCharge;
    00944         QuotaInfo->SecurityDescriptorCharge = ObjectCreateInfo->SecurityDescriptorCharge;
    00945         QuotaInfo->ExclusiveProcess = NULL;
    00946         ObjectHeader = (POBJECT_HEADER)(QuotaInfo + 1);
    00947     }
    00948
    00949     if (HandleInfoSize != 0) {
    00950
    00951         HandleInfo = (POBJECT_HEADER_HANDLE_INFO)ObjectHeader;
    00952         HandleInfo->SingleEntry.HandleCount = 0;
    00953         ObjectHeader = (POBJECT_HEADER)(HandleInfo + 1);
    00954     }
    00955
    00956     if (NameInfoSize != 0) {
    00957
    00958         NameInfo = (POBJECT_HEADER_NAME_INFO)ObjectHeader;
    00959         NameInfo->Name = *ObjectName;
    00960         NameInfo->Directory = NULL;
    00961         ObjectHeader = (POBJECT_HEADER)(NameInfo + 1);
    00962     }
    00963
    00964     if (CreatorInfoSize != 0) {
    00965
    00966         CreatorInfo = (POBJECT_HEADER_CREATOR_INFO)ObjectHeader;
    00967         CreatorInfo->CreatorBackTraceIndex = 0;
    00968         CreatorInfo->CreatorUniqueProcess = PsGetCurrentProcess()->UniqueProcessId;
    00969         InitializeListHead( &CreatorInfo->TypeList );
    00970         ObjectHeader = (POBJECT_HEADER)(CreatorInfo + 1);
    00971     }
    00972
    00973     //
    00974     //  Compute the proper offsets based on what we have
    00975     //
    00976
    00977     if (QuotaInfoSize != 0) {
    00978
    00979         ObjectHeader->QuotaInfoOffset = (UCHAR)(QuotaInfoSize + HandleInfoSize + NameInfoSize + CreatorInfoSize);
    00980
    00981     } else {
    00982
    00983         ObjectHeader->QuotaInfoOffset = 0;
    00984     }
    00985
    00986     if (HandleInfoSize != 0) {
    00987
    00988         ObjectHeader->HandleInfoOffset = (UCHAR)(HandleInfoSize + NameInfoSize + CreatorInfoSize);
    00989
    00990     } else {
    00991
    00992         ObjectHeader->HandleInfoOffset = 0;
    00993     }
    00994
    00995     if (NameInfoSize != 0) {
    00996
    00997         ObjectHeader->NameInfoOffset =  (UCHAR)(NameInfoSize + CreatorInfoSize);
    00998
    00999     } else {
    01000
    01001         ObjectHeader->NameInfoOffset = 0;
    01002     }
    01003
    01004     //
    01005     //  Say that this is a new object, and conditionally set the other flags
    01006     //
    01007
    01008     ObjectHeader->Flags = OB_FLAG_NEW_OBJECT;
    01009
    01010     if (CreatorInfoSize != 0) {
    01011
    01012         ObjectHeader->Flags |= OB_FLAG_CREATOR_INFO;
    01013     }
    01014
    01015     if (HandleInfoSize != 0) {
    01016
    01017         ObjectHeader->Flags |= OB_FLAG_SINGLE_HANDLE_ENTRY;
    01018     }
    01019
    01020     //
    01021     //  Set the counters and its type
    01022     //
    01023
    01024     ObjectHeader->PointerCount = 1;
    01025     ObjectHeader->HandleCount = 0;
    01026     ObjectHeader->Type = ObjectType;
    01027
    01028     //
    01029     //  Initialize the object header.
    01030     //
    01031     //  N.B. The initialization of the object header is done field by
    01032     //       field rather than zeroing the memory and then initializing
    01033     //       the pertinent fields.
    01034     //
    01035     //  N.B. It is assumed that the caller will initialize the object
    01036     //       attributes, object ownership, and parse context.
    01037     //
    01038
    01039     if (OwnershipMode == KernelMode) {
    01040
    01041         ObjectHeader->Flags |= OB_FLAG_KERNEL_OBJECT;
    01042     }
    01043
    01044     if (ObjectCreateInfo != NULL &&
    01045         ObjectCreateInfo->Attributes & OBJ_PERMANENT ) {
    01046
    01047         ObjectHeader->Flags |= OB_FLAG_PERMANENT_OBJECT;
    01048     }
    01049
    01050     if ((ObjectCreateInfo != NULL) &&
    01051         (ObjectCreateInfo->Attributes & OBJ_EXCLUSIVE)) {
    01052
    01053         ObjectHeader->Flags |= OB_FLAG_EXCLUSIVE_OBJECT;
    01054     }
    01055
    01056     ObjectHeader->ObjectCreateInfo = ObjectCreateInfo;
    01057     ObjectHeader->SecurityDescriptor = NULL;
    01058
    01059     if (ObjectType != NULL) {
    01060
    01061         ObjectType->TotalNumberOfObjects += 1;
    01062
    01063         if (ObjectType->TotalNumberOfObjects > ObjectType->HighWaterNumberOfObjects) {
    01064
    01065             ObjectType->HighWaterNumberOfObjects = ObjectType->TotalNumberOfObjects;
    01066         }
    01067     }
    01068
    01069 #if DBG
    01070
    01071     //
    01072     //  On a checked build echo out allocs
    01073     //
    01074
    01075     if (ObpShowAllocAndFree) {
    01076
    01077         DbgPrint( "OB: Alloc %lx (%lx) %04lu", ObjectHeader, ObjectHeader, ObjectBodySize );
    01078
    01079         if (ObjectType) {
    01080
    01081             DbgPrint(" - %wZ\n", &ObjectType->Name );
    01082
    01083         } else {
    01084
    01085             DbgPrint(" - Type\n" );
    01086         }
    01087     }
    01088 #endif
    01089
    01090     *ReturnedObjectHeader = ObjectHeader;
    01091
    01092     return STATUS_SUCCESS;
    01093 }
    01094
    01095
    01096 VOID
    01097 FASTCALL
    01098 ObpFreeObject (
    01099     IN PVOID Object
    01100     )
    01101
    01102 /*++
    01103
    01104 Routine Description:
    01105
    01106     This routine undoes ObpAllocateObject.  It returns the object back to free pool.
    01107
    01108 Arguments:
    01109
    01110     Object - Supplies a pointer to the body of the object being freed.
    01111
    01112 Return Value:
    01113
    01114     None.
    01115
    01116 --*/
    01117
    01118 {
    01119     POBJECT_HEADER ObjectHeader;
    01120     POBJECT_TYPE ObjectType;
    01121     POBJECT_HEADER_QUOTA_INFO QuotaInfo;
    01122     POBJECT_HEADER_HANDLE_INFO HandleInfo;
    01123     POBJECT_HEADER_NAME_INFO NameInfo;
    01124     POBJECT_HEADER_CREATOR_INFO CreatorInfo;
    01125     PVOID FreeBuffer;
    01126     ULONG NonPagedPoolCharge;
    01127     ULONG PagedPoolCharge;
    01128
    01129     PAGED_CODE();
    01130
    01131     //
    01132     //  Get the address of the object header.
    01133     //
    01134
    01135     ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
    01136     ObjectType = ObjectHeader->Type;
    01137
    01138     //
    01139     //  Now from the header determine the start of the allocation.  We need
    01140     //  to backup based on what precedes the header.  The order is very
    01141     //  important and must be the inverse of that used by ObpAllocateObject
    01142     //
    01143
    01144     FreeBuffer = ObjectHeader;
    01145
    01146     CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO( ObjectHeader );
    01147
    01148     if (CreatorInfo != NULL) {
    01149
    01150         FreeBuffer = CreatorInfo;
    01151     }
    01152
    01153     NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader );
    01154
    01155     if (NameInfo != NULL) {
    01156
    01157         FreeBuffer = NameInfo;
    01158     }
    01159
    01160     HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO( ObjectHeader );
    01161
    01162     if (HandleInfo != NULL) {
    01163
    01164         FreeBuffer = HandleInfo;
    01165     }
    01166
    01167     QuotaInfo = OBJECT_HEADER_TO_QUOTA_INFO( ObjectHeader );
    01168
    01169     if (QuotaInfo != NULL) {
    01170
    01171         FreeBuffer = QuotaInfo;
    01172     }
    01173
    01174 #if DBG
    01175
    01176     //
    01177     //  On a checked build echo out frees
    01178     //
    01179
    01180     if (ObpShowAllocAndFree) {
    01181
    01182         DbgPrint( "OB: Free  %lx (%lx) - Type: %wZ\n", ObjectHeader, ObjectHeader, &ObjectType->Name );
    01183     }
    01184 #endif
    01185
    01186     //
    01187     //  Decrement the number of objects of this type
    01188     //
    01189
    01190     ObjectType->TotalNumberOfObjects -= 1;
    01191
    01192     //
    01193     //  Check where we were in the object initialization phase.  This
    01194     //  flag really only tests if we have charged quota for this object.
    01195     //  This is because the object create info and the quota block charged
    01196     //  are unioned together.
    01197     //
    01198
    01199     if (ObjectHeader->Flags & OB_FLAG_NEW_OBJECT) {
    01200
    01201         if (ObjectHeader->ObjectCreateInfo != NULL) {
    01202
    01203             ObpFreeObjectCreateInformation( ObjectHeader->ObjectCreateInfo );
    01204
    01205             ObjectHeader->ObjectCreateInfo = NULL;
    01206         }
    01207
    01208     } else {
    01209
    01210         if (ObjectHeader->QuotaBlockCharged != NULL) {
    01211
    01212             if (QuotaInfo != NULL) {
    01213
    01214                 PagedPoolCharge = QuotaInfo->PagedPoolCharge +
    01215                                   QuotaInfo->SecurityDescriptorCharge;
    01216
    01217                 NonPagedPoolCharge = QuotaInfo->NonPagedPoolCharge;
    01218
    01219             } else {
    01220
    01221                 PagedPoolCharge = ObjectType->TypeInfo.DefaultPagedPoolCharge;
    01222
    01223                 if (ObjectHeader->Flags & OB_FLAG_DEFAULT_SECURITY_QUOTA ) {
    01224
    01225                     PagedPoolCharge += SE_DEFAULT_SECURITY_QUOTA;
    01226                 }
    01227
    01228                 NonPagedPoolCharge = ObjectType->TypeInfo.DefaultNonPagedPoolCharge;
    01229             }
    01230
    01231             PsReturnSharedPoolQuota( ObjectHeader->QuotaBlockCharged,
    01232                                      PagedPoolCharge,
    01233                                      NonPagedPoolCharge );
    01234         }
    01235     }
    01236
    01237     if ((HandleInfo != NULL) &&
    01238         ((ObjectHeader->Flags & OB_FLAG_SINGLE_HANDLE_ENTRY) == 0)) {
    01239
    01240         //
    01241         //  If a handle database has been allocated, then free the memory.
    01242         //
    01243
    01244         ExFreePool( HandleInfo->HandleCountDataBase );
    01245
    01246         HandleInfo->HandleCountDataBase = NULL;
    01247     }
    01248
    01249     //
    01250     //  If a name string buffer has been allocated, then free the memory.
    01251     //
    01252
    01253     if (NameInfo != NULL && NameInfo->Name.Buffer != NULL) {
    01254
    01255         ExFreePool( NameInfo->Name.Buffer );
    01256
    01257         NameInfo->Name.Buffer = NULL;
    01258     }
    01259
    01260     //
    01261     //  Trash type field so we don't get far if we attempt to
    01262     //  use a stale object pointer to this object.
    01263     //
    01264     //  Sundown Note: trash it by zero-extended it.
    01265     //                sign-extension will create a valid kernel address.
    01266
    01267
    01268     ObjectHeader->Type = UIntToPtr(0xBAD0B0B0);
    01269     ExFreePoolWithTag( FreeBuffer,
    01270                        (ObjectType == NULL ? 'TjbO' : ObjectType->Key) |
    01271                             PROTECTED_POOL );
    01272
    01273     return;
    01274 }
    01275
    01276
    01277 VOID
    01278 FASTCALL
    01279 ObFreeObjectCreateInfoBuffer (
    01280     IN POBJECT_CREATE_INFORMATION ObjectCreateInfo
    01281     )
    01282
    01283 /*++
    01284
    01285 Routine Description:
    01286
    01287     This function frees a create information buffer.  Called from IO component
    01288
    01289     N.B. This function is nonpageable.
    01290
    01291 Arguments:
    01292
    01293     ObjectCreateInfo - Supplies a pointer to a create information buffer.
    01294
    01295 Return Value:
    01296
    01297     None.
    01298
    01299 --*/
    01300
    01301 {
    01302     ObpFreeObjectCreateInfoBuffer( ObjectCreateInfo );
    01303
    01304     return;
    01305 }