Leaked source code of windows server 2003

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