Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1370 lines
34 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. obcreate.c
  5. Abstract:
  6. Object creation
  7. Author:
  8. Steve Wood (stevewo) 31-Mar-1989
  9. Revision History:
  10. --*/
  11. #include "obp.h"
  12. #undef ObCreateObject
  13. #ifdef ALLOC_PRAGMA
  14. #pragma alloc_text(PAGE, ObCreateObject)
  15. #pragma alloc_text(PAGE, ObpCaptureObjectCreateInformation)
  16. #pragma alloc_text(PAGE, ObpCaptureObjectName)
  17. #pragma alloc_text(PAGE, ObpAllocateObjectNameBuffer)
  18. #pragma alloc_text(PAGE, ObpFreeObjectNameBuffer)
  19. #pragma alloc_text(PAGE, ObDeleteCapturedInsertInfo)
  20. #pragma alloc_text(PAGE, ObpAllocateObject)
  21. #pragma alloc_text(PAGE, ObpFreeObject)
  22. #pragma alloc_text(PAGE, ObFreeObjectCreateInfoBuffer)
  23. #endif
  24. #if DBG
  25. BOOLEAN ObWatchHandles = FALSE;
  26. //
  27. // The following variable is only used on a checked build to control
  28. // echoing out the allocs and frees of objects
  29. //
  30. BOOLEAN ObpShowAllocAndFree;
  31. #else
  32. const BOOLEAN ObWatchHandles = FALSE;
  33. #endif
  34. //
  35. // Local performance counters
  36. //
  37. #if DBG
  38. ULONG ObpObjectsCreated;
  39. ULONG ObpObjectsWithPoolQuota;
  40. ULONG ObpObjectsWithHandleDB;
  41. ULONG ObpObjectsWithName;
  42. ULONG ObpObjectsWithCreatorInfo;
  43. #endif // DBG
  44. C_ASSERT ( (FIELD_OFFSET (OBJECT_HEADER, Body) % MEMORY_ALLOCATION_ALIGNMENT) == 0 );
  45. C_ASSERT ( (sizeof (OBJECT_HEADER_CREATOR_INFO) % MEMORY_ALLOCATION_ALIGNMENT) == 0 );
  46. C_ASSERT ( (sizeof (OBJECT_HEADER_NAME_INFO) % MEMORY_ALLOCATION_ALIGNMENT) == 0 );
  47. C_ASSERT ( (sizeof (OBJECT_HEADER_QUOTA_INFO) % MEMORY_ALLOCATION_ALIGNMENT) == 0 );
  48. NTSTATUS
  49. ObCreateObject (
  50. IN KPROCESSOR_MODE ProbeMode,
  51. IN POBJECT_TYPE ObjectType,
  52. IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
  53. IN KPROCESSOR_MODE OwnershipMode,
  54. IN OUT PVOID ParseContext OPTIONAL,
  55. IN ULONG ObjectBodySize,
  56. IN ULONG PagedPoolCharge,
  57. IN ULONG NonPagedPoolCharge,
  58. OUT PVOID *Object
  59. )
  60. /*++
  61. Routine Description:
  62. This functions allocates space for an NT Object from either
  63. Paged or NonPaged pool. It captures the optional name and
  64. SECURITY_DESCRIPTOR parameters for later use when the object is
  65. inserted into an object table. No quota is charged at this time.
  66. That occurs when the object is inserted into an object table.
  67. Arguments:
  68. ProbeMode - The processor mode to consider when doing a probe
  69. of the input parameters
  70. ObjectType - A pointer of the type returned by ObCreateObjectType
  71. that gives the type of object being created.
  72. ObjectAttributes - Optionally supplies the attributes of the object
  73. being created (such as its name)
  74. OwnershipMode - The processor mode of who is going to own the object
  75. ParseContext - Ignored
  76. ObjectBodySize - Number of bytes to allocate for the object body. The
  77. object body immediately follows the object header in memory and are
  78. part of a single allocation.
  79. PagedPoolCharge - Supplies the amount of paged pool to charge for the
  80. object. If zero is specified then the default charge for the object
  81. type is used.
  82. NonPagedPoolCharge - Supplies the amount of nonpaged pool to charge for
  83. the object. If zero is specified then the default charge for the
  84. object type is used.
  85. Object - Receives a pointer to the newly created object
  86. Return Value:
  87. Following errors can occur:
  88. - invalid object type
  89. - insufficient memory
  90. --*/
  91. {
  92. UNICODE_STRING CapturedObjectName;
  93. POBJECT_CREATE_INFORMATION ObjectCreateInfo;
  94. POBJECT_HEADER ObjectHeader;
  95. NTSTATUS Status;
  96. PAGED_CODE();
  97. //
  98. // Allocate a buffer to capture the object creation information.
  99. //
  100. ObjectCreateInfo = ObpAllocateObjectCreateInfoBuffer();
  101. if (ObjectCreateInfo == NULL) {
  102. Status = STATUS_INSUFFICIENT_RESOURCES;
  103. } else {
  104. //
  105. // Capture the object attributes, quality of service, and object
  106. // name, if specified. Otherwise, initialize the captured object
  107. // name, the security quality of service, and the create attributes
  108. // to default values.
  109. //
  110. Status = ObpCaptureObjectCreateInformation( ObjectType,
  111. ProbeMode,
  112. OwnershipMode,
  113. ObjectAttributes,
  114. &CapturedObjectName,
  115. ObjectCreateInfo,
  116. FALSE );
  117. if (NT_SUCCESS(Status)) {
  118. //
  119. // If the creation attributes are invalid, then return an error
  120. // status.
  121. //
  122. if (ObjectType->TypeInfo.InvalidAttributes & ObjectCreateInfo->Attributes) {
  123. Status = STATUS_INVALID_PARAMETER;
  124. } else {
  125. //
  126. // Set the paged and nonpaged pool quota charges for the
  127. // object allocation.
  128. //
  129. if (PagedPoolCharge == 0) {
  130. PagedPoolCharge = ObjectType->TypeInfo.DefaultPagedPoolCharge;
  131. }
  132. if (NonPagedPoolCharge == 0) {
  133. NonPagedPoolCharge = ObjectType->TypeInfo.DefaultNonPagedPoolCharge;
  134. }
  135. ObjectCreateInfo->PagedPoolCharge = PagedPoolCharge;
  136. ObjectCreateInfo->NonPagedPoolCharge = NonPagedPoolCharge;
  137. //
  138. // Allocate and initialize the object.
  139. //
  140. Status = ObpAllocateObject( ObjectCreateInfo,
  141. OwnershipMode,
  142. ObjectType,
  143. &CapturedObjectName,
  144. ObjectBodySize,
  145. &ObjectHeader );
  146. if (NT_SUCCESS(Status)) {
  147. //
  148. // If a permanent object is being created, then check if
  149. // the caller has the appropriate privilege.
  150. //
  151. *Object = &ObjectHeader->Body;
  152. if (ObjectHeader->Flags & OB_FLAG_PERMANENT_OBJECT) {
  153. if (!SeSinglePrivilegeCheck( SeCreatePermanentPrivilege,
  154. ProbeMode)) {
  155. ObpFreeObject(*Object);
  156. Status = STATUS_PRIVILEGE_NOT_HELD;
  157. }
  158. }
  159. #ifdef POOL_TAGGING
  160. if (ObpTraceEnabled && NT_SUCCESS(Status)) {
  161. //
  162. // Register the object and push stack information for the
  163. // first reference
  164. //
  165. ObpRegisterObject( ObjectHeader );
  166. ObpPushStackInfo( ObjectHeader, TRUE );
  167. }
  168. #endif //POOL_TAGGING
  169. //
  170. // Here is the only successful path out of this module but
  171. // this path can also return privilege not held. In the
  172. // error case, all the resources have already been freed
  173. // by ObpFreeObject.
  174. //
  175. return Status;
  176. }
  177. }
  178. //
  179. // An error path, free the create information.
  180. //
  181. ObpReleaseObjectCreateInformation(ObjectCreateInfo);
  182. if (CapturedObjectName.Buffer != NULL) {
  183. ObpFreeObjectNameBuffer(&CapturedObjectName);
  184. }
  185. }
  186. //
  187. // An error path, free object creation information buffer.
  188. //
  189. ObpFreeObjectCreateInfoBuffer(ObjectCreateInfo);
  190. }
  191. //
  192. // An error path
  193. //
  194. return Status;
  195. }
  196. NTSTATUS
  197. ObpCaptureObjectCreateInformation (
  198. IN POBJECT_TYPE ObjectType OPTIONAL,
  199. IN KPROCESSOR_MODE ProbeMode,
  200. IN KPROCESSOR_MODE CreatorMode,
  201. IN POBJECT_ATTRIBUTES ObjectAttributes,
  202. IN OUT PUNICODE_STRING CapturedObjectName,
  203. IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
  204. IN LOGICAL UseLookaside
  205. )
  206. /*++
  207. Routine Description:
  208. This function captures the object creation information and stuff
  209. it into the input variable ObjectCreateInfo
  210. Arguments:
  211. ObjectType - Specifies the type of object we expect to capture,
  212. currently ignored.
  213. ProbeMode - Specifies the processor mode for doing our parameter
  214. probes
  215. CreatorMode - Specifies the mode the object is being created for
  216. ObjectAttributes - Supplies the object attributes we are trying
  217. to capture
  218. CapturedObjectName - Recieves the name of the object being created
  219. ObjectCreateInfo - Receives the create information for the object
  220. like its root, attributes, and security information
  221. UseLookaside - Specifies if we are to allocate the captured name
  222. buffer from the lookaside list or from straight pool.
  223. Return Value:
  224. An appropriate status value
  225. --*/
  226. {
  227. PUNICODE_STRING ObjectName;
  228. PSECURITY_DESCRIPTOR SecurityDescriptor;
  229. PSECURITY_QUALITY_OF_SERVICE SecurityQos;
  230. NTSTATUS Status;
  231. ULONG Size;
  232. PAGED_CODE();
  233. //
  234. // Capture the object attributes, the security quality of service, if
  235. // specified, and object name, if specified.
  236. //
  237. Status = STATUS_SUCCESS;
  238. RtlZeroMemory(ObjectCreateInfo, sizeof(OBJECT_CREATE_INFORMATION));
  239. try {
  240. if (ARGUMENT_PRESENT(ObjectAttributes)) {
  241. //
  242. // Probe the object attributes if necessary.
  243. //
  244. if (ProbeMode != KernelMode) {
  245. ProbeForReadSmallStructure( ObjectAttributes,
  246. sizeof(OBJECT_ATTRIBUTES),
  247. sizeof(ULONG_PTR) );
  248. }
  249. if (ObjectAttributes->Length != sizeof(OBJECT_ATTRIBUTES) ||
  250. (ObjectAttributes->Attributes & ~OBJ_VALID_ATTRIBUTES)) {
  251. Status = STATUS_INVALID_PARAMETER;
  252. goto failureExit;
  253. }
  254. //
  255. // Capture the object attributes.
  256. //
  257. ObjectCreateInfo->RootDirectory = ObjectAttributes->RootDirectory;
  258. ObjectCreateInfo->Attributes = ObjectAttributes->Attributes & OBJ_VALID_ATTRIBUTES;
  259. //
  260. // Remove privileged option if passed in from user mode
  261. //
  262. if (CreatorMode != KernelMode) {
  263. ObjectCreateInfo->Attributes &= ~OBJ_KERNEL_HANDLE;
  264. } else if (ObWatchHandles) {
  265. if ((ObjectCreateInfo->Attributes&OBJ_KERNEL_HANDLE) == 0 &&
  266. PsGetCurrentProcess() != PsInitialSystemProcess) {
  267. DbgBreakPoint ();
  268. }
  269. }
  270. ObjectName = ObjectAttributes->ObjectName;
  271. SecurityDescriptor = ObjectAttributes->SecurityDescriptor;
  272. SecurityQos = ObjectAttributes->SecurityQualityOfService;
  273. if (ARGUMENT_PRESENT(SecurityDescriptor)) {
  274. Status = SeCaptureSecurityDescriptor( SecurityDescriptor,
  275. ProbeMode,
  276. PagedPool,
  277. TRUE,
  278. &ObjectCreateInfo->SecurityDescriptor );
  279. if (!NT_SUCCESS(Status)) {
  280. KdPrint(( "OB: Failed to capture security descriptor at %08x - Status == %08x\n",
  281. SecurityDescriptor,
  282. Status) );
  283. //
  284. // The cleanup routine depends on this being NULL if it isn't
  285. // allocated. SeCaptureSecurityDescriptor may modify this
  286. // parameter even if it fails.
  287. //
  288. ObjectCreateInfo->SecurityDescriptor = NULL;
  289. goto failureExit;
  290. }
  291. SeComputeQuotaInformationSize( ObjectCreateInfo->SecurityDescriptor,
  292. &Size );
  293. ObjectCreateInfo->SecurityDescriptorCharge = SeComputeSecurityQuota( Size );
  294. ObjectCreateInfo->ProbeMode = ProbeMode;
  295. }
  296. if (ARGUMENT_PRESENT(SecurityQos)) {
  297. if (ProbeMode != KernelMode) {
  298. ProbeForReadSmallStructure( SecurityQos, sizeof(*SecurityQos), sizeof(ULONG));
  299. }
  300. ObjectCreateInfo->SecurityQualityOfService = *SecurityQos;
  301. ObjectCreateInfo->SecurityQos = &ObjectCreateInfo->SecurityQualityOfService;
  302. }
  303. } else {
  304. ObjectName = NULL;
  305. }
  306. } except (ExSystemExceptionFilter()) {
  307. Status = GetExceptionCode();
  308. goto failureExit;
  309. }
  310. //
  311. // If an object name is specified, then capture the object name.
  312. // Otherwise, initialize the object name descriptor and check for
  313. // an incorrectly specified root directory.
  314. //
  315. if (ARGUMENT_PRESENT(ObjectName)) {
  316. Status = ObpCaptureObjectName( ProbeMode,
  317. ObjectName,
  318. CapturedObjectName,
  319. UseLookaside );
  320. } else {
  321. CapturedObjectName->Buffer = NULL;
  322. CapturedObjectName->Length = 0;
  323. CapturedObjectName->MaximumLength = 0;
  324. if (ARGUMENT_PRESENT(ObjectCreateInfo->RootDirectory)) {
  325. Status = STATUS_OBJECT_NAME_INVALID;
  326. }
  327. }
  328. //
  329. // If the completion status is not successful, and a security quality
  330. // of service parameter was specified, then free the security quality
  331. // of service memory.
  332. //
  333. failureExit:
  334. if (!NT_SUCCESS(Status)) {
  335. ObpReleaseObjectCreateInformation(ObjectCreateInfo);
  336. }
  337. return Status;
  338. }
  339. NTSTATUS
  340. ObpCaptureObjectName (
  341. IN KPROCESSOR_MODE ProbeMode,
  342. IN PUNICODE_STRING ObjectName,
  343. IN OUT PUNICODE_STRING CapturedObjectName,
  344. IN LOGICAL UseLookaside
  345. )
  346. /*++
  347. Routine Description:
  348. This function captures the object name but first verifies that
  349. it is at least properly sized.
  350. Arguments:
  351. ProbeMode - Supplies the processor mode to use when probing
  352. the object name
  353. ObjectName - Supplies the caller's version of the object name
  354. CapturedObjectName - Receives the captured verified version
  355. of the object name
  356. UseLookaside - Indicates if the captured name buffer should be
  357. allocated from the lookaside list or from straight pool
  358. Return Value:
  359. An appropriate status value
  360. --*/
  361. {
  362. PWCH FreeBuffer;
  363. UNICODE_STRING InputObjectName;
  364. ULONG Length;
  365. NTSTATUS Status;
  366. PAGED_CODE();
  367. //
  368. // Initialize the object name descriptor and capture the specified name
  369. // string.
  370. //
  371. CapturedObjectName->Buffer = NULL;
  372. CapturedObjectName->Length = 0;
  373. CapturedObjectName->MaximumLength = 0;
  374. Status = STATUS_SUCCESS;
  375. try {
  376. //
  377. // Probe and capture the name string descriptor and probe the
  378. // name string, if necessary.
  379. //
  380. FreeBuffer = NULL;
  381. if (ProbeMode != KernelMode) {
  382. InputObjectName = ProbeAndReadUnicodeString(ObjectName);
  383. ProbeForRead( InputObjectName.Buffer,
  384. InputObjectName.Length,
  385. sizeof(WCHAR) );
  386. } else {
  387. InputObjectName = *ObjectName;
  388. }
  389. //
  390. // If the length of the string is not zero, then capture the string.
  391. //
  392. if (InputObjectName.Length != 0) {
  393. //
  394. // If the length of the string is not an even multiple of the
  395. // size of a UNICODE character or cannot be zero terminated,
  396. // then return an error.
  397. //
  398. Length = InputObjectName.Length;
  399. if (((Length & (sizeof(WCHAR) - 1)) != 0) ||
  400. (Length == (MAXUSHORT - sizeof(WCHAR) + 1))) {
  401. Status = STATUS_OBJECT_NAME_INVALID;
  402. } else {
  403. //
  404. // Allocate a buffer for the specified name string.
  405. //
  406. // N.B. The name buffer allocation routine adds one
  407. // UNICODE character to the length and initializes
  408. // the string descriptor.
  409. //
  410. FreeBuffer = ObpAllocateObjectNameBuffer( Length,
  411. UseLookaside,
  412. CapturedObjectName );
  413. if (FreeBuffer == NULL) {
  414. Status = STATUS_INSUFFICIENT_RESOURCES;
  415. } else {
  416. //
  417. // Copy the specified name string to the destination
  418. // buffer.
  419. //
  420. RtlCopyMemory(FreeBuffer, InputObjectName.Buffer, Length);
  421. //
  422. // Zero terminate the name string and initialize the
  423. // string descriptor.
  424. //
  425. FreeBuffer[Length / sizeof(WCHAR)] = UNICODE_NULL;
  426. }
  427. }
  428. }
  429. } except(ExSystemExceptionFilter()) {
  430. Status = GetExceptionCode();
  431. if (FreeBuffer != NULL) {
  432. ExFreePool(FreeBuffer);
  433. }
  434. }
  435. return Status;
  436. }
  437. PWCHAR
  438. ObpAllocateObjectNameBuffer (
  439. IN ULONG Length,
  440. IN LOGICAL UseLookaside,
  441. IN OUT PUNICODE_STRING ObjectName
  442. )
  443. /*++
  444. Routine Description:
  445. This function allocates an object name buffer.
  446. N.B. This function is nonpageable.
  447. Arguments:
  448. Length - Supplies the length of the required buffer in bytes.
  449. UseLookaside - Supplies a logical variable that determines whether an
  450. attempt is made to allocate the name buffer from the lookaside list.
  451. ObjectName - Supplies a pointer to a name buffer string descriptor.
  452. Return Value:
  453. If the allocation is successful, then name buffer string descriptor
  454. is initialized and the address of the name buffer is returned as the
  455. function value. Otherwise, a value of NULL is returned.
  456. --*/
  457. {
  458. PVOID Buffer;
  459. ULONG Maximum;
  460. KIRQL OldIrql;
  461. PKPRCB Prcb;
  462. //
  463. // If allocation from the lookaside lists is specified and the buffer
  464. // size is less than the size of lookaside list entries, then attempt
  465. // to allocate the name buffer from the lookaside lists. Otherwise,
  466. // attempt to allocate the name buffer from nonpaged pool.
  467. //
  468. Maximum = Length + sizeof(WCHAR);
  469. if ((UseLookaside == FALSE) || (Maximum > OBJECT_NAME_BUFFER_SIZE)) {
  470. //
  471. // Attempt to allocate the buffer from nonpaged pool.
  472. //
  473. Buffer = ExAllocatePoolWithTag( OB_NAMESPACE_POOL_TYPE , Maximum, 'mNbO' );
  474. } else {
  475. //
  476. // Attempt to allocate the name buffer from the lookaside list. If
  477. // the allocation attempt fails, then attempt to allocate the name
  478. // buffer from pool.
  479. //
  480. Maximum = OBJECT_NAME_BUFFER_SIZE;
  481. Buffer = ExAllocateFromPPLookasideList(LookasideNameBufferList);
  482. }
  483. //
  484. // Initialize the string descriptor and return the buffer address.
  485. //
  486. ObjectName->Length = (USHORT)Length;
  487. ObjectName->MaximumLength = (USHORT)Maximum;
  488. ObjectName->Buffer = Buffer;
  489. return (PWCHAR)Buffer;
  490. }
  491. VOID
  492. FASTCALL
  493. ObpFreeObjectNameBuffer (
  494. OUT PUNICODE_STRING ObjectName
  495. )
  496. /*++
  497. Routine Description:
  498. This function frees an object name buffer.
  499. N.B. This function is nonpageable.
  500. Arguments:
  501. ObjectName - Supplies a pointer to a name buffer string descriptor.
  502. Return Value:
  503. None.
  504. --*/
  505. {
  506. PVOID Buffer;
  507. KIRQL OldIrql;
  508. PKPRCB Prcb;
  509. //
  510. // If the size of the buffer is not equal to the size of lookaside list
  511. // entries, then free the buffer to pool. Otherwise, free the buffer to
  512. // the lookaside list.
  513. //
  514. Buffer = ObjectName->Buffer;
  515. if (ObjectName->MaximumLength != OBJECT_NAME_BUFFER_SIZE) {
  516. ExFreePool(Buffer);
  517. } else {
  518. ExFreeToPPLookasideList(LookasideNameBufferList, Buffer);
  519. }
  520. return;
  521. }
  522. NTKERNELAPI
  523. VOID
  524. ObDeleteCapturedInsertInfo (
  525. IN PVOID Object
  526. )
  527. /*++
  528. Routine Description:
  529. This function frees the creation information that could be pointed at
  530. by the object header.
  531. Arguments:
  532. Object - Supplies the object being modified
  533. Return Value:
  534. None.
  535. --*/
  536. {
  537. POBJECT_HEADER ObjectHeader;
  538. PAGED_CODE();
  539. //
  540. // Get the address of the object header and free the object create
  541. // information object if the object is being created.
  542. //
  543. ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
  544. if (ObjectHeader->Flags & OB_FLAG_NEW_OBJECT) {
  545. if (ObjectHeader->ObjectCreateInfo != NULL) {
  546. ObpFreeObjectCreateInformation(ObjectHeader->ObjectCreateInfo);
  547. ObjectHeader->ObjectCreateInfo = NULL;
  548. }
  549. }
  550. return;
  551. }
  552. NTSTATUS
  553. ObpAllocateObject (
  554. IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
  555. IN KPROCESSOR_MODE OwnershipMode,
  556. IN POBJECT_TYPE ObjectType OPTIONAL,
  557. IN PUNICODE_STRING ObjectName,
  558. IN ULONG ObjectBodySize,
  559. OUT POBJECT_HEADER *ReturnedObjectHeader
  560. )
  561. /*++
  562. Routine Description:
  563. This routine allocates a new object including the object header
  564. and body from pool and fill in the appropriate fields.
  565. Arguments:
  566. ObjectCreateInfo - Supplies the create information for the new object
  567. OwnershipMode - Supplies the processor mode of who is going to own
  568. the object
  569. ObjectType - Optionally supplies the object type of the object being
  570. created. If the object create info not null then this field must
  571. be supplied.
  572. ObjectName - Supplies the name of the object being created
  573. ObjectBodySize - Specifies the size, in bytes, of the body of the object
  574. being created
  575. ReturnedObjectHeader - Receives a pointer to the object header for the
  576. newly created objet.
  577. Return Value:
  578. An appropriate status value.
  579. --*/
  580. {
  581. ULONG HeaderSize;
  582. POBJECT_HEADER ObjectHeader;
  583. NTSTATUS Status;
  584. PVOID ZoneSegment;
  585. ULONG QuotaInfoSize;
  586. ULONG HandleInfoSize;
  587. ULONG NameInfoSize;
  588. ULONG CreatorInfoSize;
  589. POBJECT_HEADER_QUOTA_INFO QuotaInfo;
  590. POBJECT_HEADER_HANDLE_INFO HandleInfo;
  591. POBJECT_HEADER_NAME_INFO NameInfo;
  592. POBJECT_HEADER_CREATOR_INFO CreatorInfo;
  593. POOL_TYPE PoolType;
  594. PAGED_CODE();
  595. #if DBG
  596. ObpObjectsCreated += 1;
  597. #endif // DBG
  598. //
  599. // Compute the sizes of the optional object header components.
  600. //
  601. if (ObjectCreateInfo == NULL) {
  602. QuotaInfoSize = 0;
  603. HandleInfoSize = 0;
  604. NameInfoSize = sizeof( OBJECT_HEADER_NAME_INFO );
  605. CreatorInfoSize = sizeof( OBJECT_HEADER_CREATOR_INFO );
  606. } else {
  607. //
  608. // The caller specified some additional object create info
  609. //
  610. // First check to see if we need to set the quota
  611. //
  612. if (((ObjectCreateInfo->PagedPoolCharge != ObjectType->TypeInfo.DefaultPagedPoolCharge ||
  613. ObjectCreateInfo->NonPagedPoolCharge != ObjectType->TypeInfo.DefaultNonPagedPoolCharge ||
  614. ObjectCreateInfo->SecurityDescriptorCharge > SE_DEFAULT_SECURITY_QUOTA) &&
  615. PsGetCurrentProcess() != PsInitialSystemProcess) ||
  616. (ObjectCreateInfo->Attributes & OBJ_EXCLUSIVE)) {
  617. QuotaInfoSize = sizeof( OBJECT_HEADER_QUOTA_INFO );
  618. #if DBG
  619. ObpObjectsWithPoolQuota += 1;
  620. #endif // DBG
  621. } else {
  622. QuotaInfoSize = 0;
  623. }
  624. //
  625. // Check if we are to allocate space to maintain handle counts
  626. //
  627. if (ObjectType->TypeInfo.MaintainHandleCount) {
  628. HandleInfoSize = sizeof( OBJECT_HEADER_HANDLE_INFO );
  629. #if DBG
  630. ObpObjectsWithHandleDB += 1;
  631. #endif // DBG
  632. } else {
  633. HandleInfoSize = 0;
  634. }
  635. //
  636. // Check if we are to allocate space for the name
  637. //
  638. if (ObjectName->Buffer != NULL) {
  639. NameInfoSize = sizeof( OBJECT_HEADER_NAME_INFO );
  640. #if DBG
  641. ObpObjectsWithName += 1;
  642. #endif // DBG
  643. } else {
  644. NameInfoSize = 0;
  645. }
  646. //
  647. // Finally check if we are to maintain the creator info
  648. //
  649. if (ObjectType->TypeInfo.MaintainTypeList) {
  650. CreatorInfoSize = sizeof( OBJECT_HEADER_CREATOR_INFO );
  651. #if DBG
  652. ObpObjectsWithCreatorInfo += 1;
  653. #endif // DBG
  654. } else {
  655. CreatorInfoSize = 0;
  656. }
  657. }
  658. //
  659. // Now compute the total header size
  660. //
  661. HeaderSize = QuotaInfoSize +
  662. HandleInfoSize +
  663. NameInfoSize +
  664. CreatorInfoSize +
  665. FIELD_OFFSET( OBJECT_HEADER, Body );
  666. //
  667. // Allocate and initialize the object.
  668. //
  669. // If the object type is not specified or specifies nonpaged pool,
  670. // then allocate the object from nonpaged pool.
  671. // Otherwise, allocate the object from paged pool.
  672. //
  673. if ((ObjectType == NULL) || (ObjectType->TypeInfo.PoolType == NonPagedPool)) {
  674. PoolType = NonPagedPool;
  675. } else {
  676. PoolType = PagedPool;
  677. }
  678. ObjectHeader = ExAllocatePoolWithTag( PoolType,
  679. HeaderSize + ObjectBodySize,
  680. (ObjectType == NULL ? 'TjbO' : ObjectType->Key) |
  681. PROTECTED_POOL );
  682. if (ObjectHeader == NULL) {
  683. return STATUS_INSUFFICIENT_RESOURCES;
  684. }
  685. //
  686. // Now based on if we are to put in the quota, handle, name, or creator info we
  687. // will do the extra work. This order is very important because we rely on
  688. // it to free the object.
  689. //
  690. if (QuotaInfoSize != 0) {
  691. QuotaInfo = (POBJECT_HEADER_QUOTA_INFO)ObjectHeader;
  692. QuotaInfo->PagedPoolCharge = ObjectCreateInfo->PagedPoolCharge;
  693. QuotaInfo->NonPagedPoolCharge = ObjectCreateInfo->NonPagedPoolCharge;
  694. QuotaInfo->SecurityDescriptorCharge = ObjectCreateInfo->SecurityDescriptorCharge;
  695. QuotaInfo->ExclusiveProcess = NULL;
  696. ObjectHeader = (POBJECT_HEADER)(QuotaInfo + 1);
  697. }
  698. if (HandleInfoSize != 0) {
  699. HandleInfo = (POBJECT_HEADER_HANDLE_INFO)ObjectHeader;
  700. HandleInfo->SingleEntry.HandleCount = 0;
  701. ObjectHeader = (POBJECT_HEADER)(HandleInfo + 1);
  702. }
  703. if (NameInfoSize != 0) {
  704. NameInfo = (POBJECT_HEADER_NAME_INFO)ObjectHeader;
  705. NameInfo->Name = *ObjectName;
  706. NameInfo->Directory = NULL;
  707. NameInfo->QueryReferences = 1;
  708. ObjectHeader = (POBJECT_HEADER)(NameInfo + 1);
  709. }
  710. if (CreatorInfoSize != 0) {
  711. CreatorInfo = (POBJECT_HEADER_CREATOR_INFO)ObjectHeader;
  712. CreatorInfo->CreatorBackTraceIndex = 0;
  713. CreatorInfo->CreatorUniqueProcess = PsGetCurrentProcess()->UniqueProcessId;
  714. InitializeListHead( &CreatorInfo->TypeList );
  715. PERFINFO_ADD_OBJECT_TO_ALLOCATED_TYPE_LIST(CreatorInfo, ObjectType);
  716. ObjectHeader = (POBJECT_HEADER)(CreatorInfo + 1);
  717. }
  718. //
  719. // Compute the proper offsets based on what we have
  720. //
  721. if (QuotaInfoSize != 0) {
  722. ObjectHeader->QuotaInfoOffset = (UCHAR)(QuotaInfoSize + HandleInfoSize + NameInfoSize + CreatorInfoSize);
  723. } else {
  724. ObjectHeader->QuotaInfoOffset = 0;
  725. }
  726. if (HandleInfoSize != 0) {
  727. ObjectHeader->HandleInfoOffset = (UCHAR)(HandleInfoSize + NameInfoSize + CreatorInfoSize);
  728. } else {
  729. ObjectHeader->HandleInfoOffset = 0;
  730. }
  731. if (NameInfoSize != 0) {
  732. ObjectHeader->NameInfoOffset = (UCHAR)(NameInfoSize + CreatorInfoSize);
  733. } else {
  734. ObjectHeader->NameInfoOffset = 0;
  735. }
  736. //
  737. // Say that this is a new object, and conditionally set the other flags
  738. //
  739. ObjectHeader->Flags = OB_FLAG_NEW_OBJECT;
  740. if (CreatorInfoSize != 0) {
  741. ObjectHeader->Flags |= OB_FLAG_CREATOR_INFO;
  742. }
  743. if (HandleInfoSize != 0) {
  744. ObjectHeader->Flags |= OB_FLAG_SINGLE_HANDLE_ENTRY;
  745. }
  746. //
  747. // Set the counters and its type
  748. //
  749. ObjectHeader->PointerCount = 1;
  750. ObjectHeader->HandleCount = 0;
  751. ObjectHeader->Type = ObjectType;
  752. //
  753. // Initialize the object header.
  754. //
  755. // N.B. The initialization of the object header is done field by
  756. // field rather than zeroing the memory and then initializing
  757. // the pertinent fields.
  758. //
  759. // N.B. It is assumed that the caller will initialize the object
  760. // attributes, object ownership, and parse context.
  761. //
  762. if (OwnershipMode == KernelMode) {
  763. ObjectHeader->Flags |= OB_FLAG_KERNEL_OBJECT;
  764. }
  765. if (ObjectCreateInfo != NULL &&
  766. ObjectCreateInfo->Attributes & OBJ_PERMANENT ) {
  767. ObjectHeader->Flags |= OB_FLAG_PERMANENT_OBJECT;
  768. }
  769. if ((ObjectCreateInfo != NULL) &&
  770. (ObjectCreateInfo->Attributes & OBJ_EXCLUSIVE)) {
  771. ObjectHeader->Flags |= OB_FLAG_EXCLUSIVE_OBJECT;
  772. }
  773. ObjectHeader->ObjectCreateInfo = ObjectCreateInfo;
  774. ObjectHeader->SecurityDescriptor = NULL;
  775. if (ObjectType != NULL) {
  776. ObjectType->TotalNumberOfObjects += 1;
  777. if (ObjectType->TotalNumberOfObjects > ObjectType->HighWaterNumberOfObjects) {
  778. ObjectType->HighWaterNumberOfObjects = ObjectType->TotalNumberOfObjects;
  779. }
  780. }
  781. #if DBG
  782. //
  783. // On a checked build echo out allocs
  784. //
  785. if (ObpShowAllocAndFree) {
  786. DbgPrint( "OB: Alloc %lx (%lx) %04lu", ObjectHeader, ObjectHeader, ObjectBodySize );
  787. if (ObjectType) {
  788. DbgPrint(" - %wZ\n", &ObjectType->Name );
  789. } else {
  790. DbgPrint(" - Type\n" );
  791. }
  792. }
  793. #endif
  794. *ReturnedObjectHeader = ObjectHeader;
  795. return STATUS_SUCCESS;
  796. }
  797. VOID
  798. FASTCALL
  799. ObpFreeObject (
  800. IN PVOID Object
  801. )
  802. /*++
  803. Routine Description:
  804. This routine undoes ObpAllocateObject. It returns the object back to free pool.
  805. Arguments:
  806. Object - Supplies a pointer to the body of the object being freed.
  807. Return Value:
  808. None.
  809. --*/
  810. {
  811. POBJECT_HEADER ObjectHeader;
  812. POBJECT_TYPE ObjectType;
  813. POBJECT_HEADER_QUOTA_INFO QuotaInfo;
  814. POBJECT_HEADER_HANDLE_INFO HandleInfo;
  815. POBJECT_HEADER_NAME_INFO NameInfo;
  816. POBJECT_HEADER_CREATOR_INFO CreatorInfo;
  817. PVOID FreeBuffer;
  818. ULONG NonPagedPoolCharge;
  819. ULONG PagedPoolCharge;
  820. PAGED_CODE();
  821. //
  822. // Get the address of the object header.
  823. //
  824. ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
  825. ObjectType = ObjectHeader->Type;
  826. //
  827. // Now from the header determine the start of the allocation. We need
  828. // to backup based on what precedes the header. The order is very
  829. // important and must be the inverse of that used by ObpAllocateObject
  830. //
  831. FreeBuffer = ObjectHeader;
  832. CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO( ObjectHeader );
  833. if (CreatorInfo != NULL) {
  834. FreeBuffer = CreatorInfo;
  835. }
  836. NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader );
  837. if (NameInfo != NULL) {
  838. FreeBuffer = NameInfo;
  839. }
  840. HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO( ObjectHeader );
  841. if (HandleInfo != NULL) {
  842. FreeBuffer = HandleInfo;
  843. }
  844. QuotaInfo = OBJECT_HEADER_TO_QUOTA_INFO( ObjectHeader );
  845. if (QuotaInfo != NULL) {
  846. FreeBuffer = QuotaInfo;
  847. }
  848. #if DBG
  849. //
  850. // On a checked build echo out frees
  851. //
  852. if (ObpShowAllocAndFree) {
  853. DbgPrint( "OB: Free %lx (%lx) - Type: %wZ\n", ObjectHeader, ObjectHeader, &ObjectType->Name );
  854. }
  855. #endif
  856. //
  857. // Decrement the number of objects of this type
  858. //
  859. ObjectType->TotalNumberOfObjects -= 1;
  860. //
  861. // Check where we were in the object initialization phase. This
  862. // flag really only tests if we have charged quota for this object.
  863. // This is because the object create info and the quota block charged
  864. // are unioned together.
  865. //
  866. if (ObjectHeader->Flags & OB_FLAG_NEW_OBJECT) {
  867. if (ObjectHeader->ObjectCreateInfo != NULL) {
  868. ObpFreeObjectCreateInformation( ObjectHeader->ObjectCreateInfo );
  869. ObjectHeader->ObjectCreateInfo = NULL;
  870. }
  871. } else {
  872. if (ObjectHeader->QuotaBlockCharged != NULL) {
  873. if (QuotaInfo != NULL) {
  874. PagedPoolCharge = QuotaInfo->PagedPoolCharge +
  875. QuotaInfo->SecurityDescriptorCharge;
  876. NonPagedPoolCharge = QuotaInfo->NonPagedPoolCharge;
  877. } else {
  878. PagedPoolCharge = ObjectType->TypeInfo.DefaultPagedPoolCharge;
  879. if (ObjectHeader->Flags & OB_FLAG_DEFAULT_SECURITY_QUOTA ) {
  880. PagedPoolCharge += SE_DEFAULT_SECURITY_QUOTA;
  881. }
  882. NonPagedPoolCharge = ObjectType->TypeInfo.DefaultNonPagedPoolCharge;
  883. }
  884. PsReturnSharedPoolQuota( ObjectHeader->QuotaBlockCharged,
  885. PagedPoolCharge,
  886. NonPagedPoolCharge );
  887. ObjectHeader->QuotaBlockCharged = NULL;
  888. }
  889. }
  890. if ((HandleInfo != NULL) &&
  891. ((ObjectHeader->Flags & OB_FLAG_SINGLE_HANDLE_ENTRY) == 0)) {
  892. //
  893. // If a handle database has been allocated, then free the memory.
  894. //
  895. ExFreePool( HandleInfo->HandleCountDataBase );
  896. HandleInfo->HandleCountDataBase = NULL;
  897. }
  898. //
  899. // If a name string buffer has been allocated, then free the memory.
  900. //
  901. if (NameInfo != NULL && NameInfo->Name.Buffer != NULL) {
  902. ExFreePool( NameInfo->Name.Buffer );
  903. NameInfo->Name.Buffer = NULL;
  904. }
  905. PERFINFO_REMOVE_OBJECT_FROM_ALLOCATED_TYPE_LIST(CreatorInfo, ObjectHeader);
  906. //
  907. // Trash type field so we don't get far if we attempt to
  908. // use a stale object pointer to this object.
  909. //
  910. // Sundown Note: trash it by zero-extended it.
  911. // sign-extension will create a valid kernel address.
  912. ObjectHeader->Type = UIntToPtr(0xBAD0B0B0);
  913. ExFreePoolWithTag( FreeBuffer,
  914. (ObjectType == NULL ? 'TjbO' : ObjectType->Key) |
  915. PROTECTED_POOL );
  916. return;
  917. }
  918. VOID
  919. FASTCALL
  920. ObFreeObjectCreateInfoBuffer (
  921. IN POBJECT_CREATE_INFORMATION ObjectCreateInfo
  922. )
  923. /*++
  924. Routine Description:
  925. This function frees a create information buffer. Called from IO component
  926. N.B. This function is nonpageable.
  927. Arguments:
  928. ObjectCreateInfo - Supplies a pointer to a create information buffer.
  929. Return Value:
  930. None.
  931. --*/
  932. {
  933. ObpFreeObjectCreateInfoBuffer( ObjectCreateInfo );
  934. return;
  935. }