1 /****************************************************************************** 2 * 3 * Module Name: utobject - ACPI object create/delete/size/cache routines 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include "acpi.h" 45 #include "accommon.h" 46 #include "acnamesp.h" 47 48 49 #define _COMPONENT ACPI_UTILITIES 50 ACPI_MODULE_NAME ("utobject") 51 52 /* Local prototypes */ 53 54 static ACPI_STATUS 55 AcpiUtGetSimpleObjectSize ( 56 ACPI_OPERAND_OBJECT *Obj, 57 ACPI_SIZE *ObjLength); 58 59 static ACPI_STATUS 60 AcpiUtGetPackageObjectSize ( 61 ACPI_OPERAND_OBJECT *Obj, 62 ACPI_SIZE *ObjLength); 63 64 static ACPI_STATUS 65 AcpiUtGetElementLength ( 66 UINT8 ObjectType, 67 ACPI_OPERAND_OBJECT *SourceObject, 68 ACPI_GENERIC_STATE *State, 69 void *Context); 70 71 72 /******************************************************************************* 73 * 74 * FUNCTION: AcpiUtCreateInternalObjectDbg 75 * 76 * PARAMETERS: ModuleName - Source file name of caller 77 * LineNumber - Line number of caller 78 * ComponentId - Component type of caller 79 * Type - ACPI Type of the new object 80 * 81 * RETURN: A new internal object, null on failure 82 * 83 * DESCRIPTION: Create and initialize a new internal object. 84 * 85 * NOTE: We always allocate the worst-case object descriptor because 86 * these objects are cached, and we want them to be 87 * one-size-satisifies-any-request. This in itself may not be 88 * the most memory efficient, but the efficiency of the object 89 * cache should more than make up for this! 90 * 91 ******************************************************************************/ 92 93 ACPI_OPERAND_OBJECT * 94 AcpiUtCreateInternalObjectDbg ( 95 const char *ModuleName, 96 UINT32 LineNumber, 97 UINT32 ComponentId, 98 ACPI_OBJECT_TYPE Type) 99 { 100 ACPI_OPERAND_OBJECT *Object; 101 ACPI_OPERAND_OBJECT *SecondObject; 102 103 104 ACPI_FUNCTION_TRACE_STR (UtCreateInternalObjectDbg, 105 AcpiUtGetTypeName (Type)); 106 107 108 /* Allocate the raw object descriptor */ 109 110 Object = AcpiUtAllocateObjectDescDbg ( 111 ModuleName, LineNumber, ComponentId); 112 if (!Object) 113 { 114 return_PTR (NULL); 115 } 116 117 switch (Type) 118 { 119 case ACPI_TYPE_REGION: 120 case ACPI_TYPE_BUFFER_FIELD: 121 case ACPI_TYPE_LOCAL_BANK_FIELD: 122 123 /* These types require a secondary object */ 124 125 SecondObject = AcpiUtAllocateObjectDescDbg ( 126 ModuleName, LineNumber, ComponentId); 127 if (!SecondObject) 128 { 129 AcpiUtDeleteObjectDesc (Object); 130 return_PTR (NULL); 131 } 132 133 SecondObject->Common.Type = ACPI_TYPE_LOCAL_EXTRA; 134 SecondObject->Common.ReferenceCount = 1; 135 136 /* Link the second object to the first */ 137 138 Object->Common.NextObject = SecondObject; 139 break; 140 141 default: 142 143 /* All others have no secondary object */ 144 break; 145 } 146 147 /* Save the object type in the object descriptor */ 148 149 Object->Common.Type = (UINT8) Type; 150 151 /* Init the reference count */ 152 153 Object->Common.ReferenceCount = 1; 154 155 /* Any per-type initialization should go here */ 156 157 return_PTR (Object); 158 } 159 160 161 /******************************************************************************* 162 * 163 * FUNCTION: AcpiUtCreatePackageObject 164 * 165 * PARAMETERS: Count - Number of package elements 166 * 167 * RETURN: Pointer to a new Package object, null on failure 168 * 169 * DESCRIPTION: Create a fully initialized package object 170 * 171 ******************************************************************************/ 172 173 ACPI_OPERAND_OBJECT * 174 AcpiUtCreatePackageObject ( 175 UINT32 Count) 176 { 177 ACPI_OPERAND_OBJECT *PackageDesc; 178 ACPI_OPERAND_OBJECT **PackageElements; 179 180 181 ACPI_FUNCTION_TRACE_U32 (UtCreatePackageObject, Count); 182 183 184 /* Create a new Package object */ 185 186 PackageDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PACKAGE); 187 if (!PackageDesc) 188 { 189 return_PTR (NULL); 190 } 191 192 /* 193 * Create the element array. Count+1 allows the array to be null 194 * terminated. 195 */ 196 PackageElements = ACPI_ALLOCATE_ZEROED ( 197 ((ACPI_SIZE) Count + 1) * sizeof (void *)); 198 if (!PackageElements) 199 { 200 ACPI_FREE (PackageDesc); 201 return_PTR (NULL); 202 } 203 204 PackageDesc->Package.Count = Count; 205 PackageDesc->Package.Elements = PackageElements; 206 return_PTR (PackageDesc); 207 } 208 209 210 /******************************************************************************* 211 * 212 * FUNCTION: AcpiUtCreateIntegerObject 213 * 214 * PARAMETERS: InitialValue - Initial value for the integer 215 * 216 * RETURN: Pointer to a new Integer object, null on failure 217 * 218 * DESCRIPTION: Create an initialized integer object 219 * 220 ******************************************************************************/ 221 222 ACPI_OPERAND_OBJECT * 223 AcpiUtCreateIntegerObject ( 224 UINT64 InitialValue) 225 { 226 ACPI_OPERAND_OBJECT *IntegerDesc; 227 228 229 ACPI_FUNCTION_TRACE (UtCreateIntegerObject); 230 231 232 /* Create and initialize a new integer object */ 233 234 IntegerDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 235 if (!IntegerDesc) 236 { 237 return_PTR (NULL); 238 } 239 240 IntegerDesc->Integer.Value = InitialValue; 241 return_PTR (IntegerDesc); 242 } 243 244 245 /******************************************************************************* 246 * 247 * FUNCTION: AcpiUtCreateBufferObject 248 * 249 * PARAMETERS: BufferSize - Size of buffer to be created 250 * 251 * RETURN: Pointer to a new Buffer object, null on failure 252 * 253 * DESCRIPTION: Create a fully initialized buffer object 254 * 255 ******************************************************************************/ 256 257 ACPI_OPERAND_OBJECT * 258 AcpiUtCreateBufferObject ( 259 ACPI_SIZE BufferSize) 260 { 261 ACPI_OPERAND_OBJECT *BufferDesc; 262 UINT8 *Buffer = NULL; 263 264 265 ACPI_FUNCTION_TRACE_U32 (UtCreateBufferObject, BufferSize); 266 267 268 /* Create a new Buffer object */ 269 270 BufferDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER); 271 if (!BufferDesc) 272 { 273 return_PTR (NULL); 274 } 275 276 /* Create an actual buffer only if size > 0 */ 277 278 if (BufferSize > 0) 279 { 280 /* Allocate the actual buffer */ 281 282 Buffer = ACPI_ALLOCATE_ZEROED (BufferSize); 283 if (!Buffer) 284 { 285 ACPI_ERROR ((AE_INFO, "Could not allocate size %u", 286 (UINT32) BufferSize)); 287 288 AcpiUtRemoveReference (BufferDesc); 289 return_PTR (NULL); 290 } 291 } 292 293 /* Complete buffer object initialization */ 294 295 BufferDesc->Buffer.Flags |= AOPOBJ_DATA_VALID; 296 BufferDesc->Buffer.Pointer = Buffer; 297 BufferDesc->Buffer.Length = (UINT32) BufferSize; 298 299 /* Return the new buffer descriptor */ 300 301 return_PTR (BufferDesc); 302 } 303 304 305 /******************************************************************************* 306 * 307 * FUNCTION: AcpiUtCreateStringObject 308 * 309 * PARAMETERS: StringSize - Size of string to be created. Does not 310 * include NULL terminator, this is added 311 * automatically. 312 * 313 * RETURN: Pointer to a new String object 314 * 315 * DESCRIPTION: Create a fully initialized string object 316 * 317 ******************************************************************************/ 318 319 ACPI_OPERAND_OBJECT * 320 AcpiUtCreateStringObject ( 321 ACPI_SIZE StringSize) 322 { 323 ACPI_OPERAND_OBJECT *StringDesc; 324 char *String; 325 326 327 ACPI_FUNCTION_TRACE_U32 (UtCreateStringObject, StringSize); 328 329 330 /* Create a new String object */ 331 332 StringDesc = AcpiUtCreateInternalObject (ACPI_TYPE_STRING); 333 if (!StringDesc) 334 { 335 return_PTR (NULL); 336 } 337 338 /* 339 * Allocate the actual string buffer -- (Size + 1) for NULL terminator. 340 * NOTE: Zero-length strings are NULL terminated 341 */ 342 String = ACPI_ALLOCATE_ZEROED (StringSize + 1); 343 if (!String) 344 { 345 ACPI_ERROR ((AE_INFO, "Could not allocate size %u", 346 (UINT32) StringSize)); 347 348 AcpiUtRemoveReference (StringDesc); 349 return_PTR (NULL); 350 } 351 352 /* Complete string object initialization */ 353 354 StringDesc->String.Pointer = String; 355 StringDesc->String.Length = (UINT32) StringSize; 356 357 /* Return the new string descriptor */ 358 359 return_PTR (StringDesc); 360 } 361 362 363 /******************************************************************************* 364 * 365 * FUNCTION: AcpiUtValidInternalObject 366 * 367 * PARAMETERS: Object - Object to be validated 368 * 369 * RETURN: TRUE if object is valid, FALSE otherwise 370 * 371 * DESCRIPTION: Validate a pointer to be of type ACPI_OPERAND_OBJECT 372 * 373 ******************************************************************************/ 374 375 BOOLEAN 376 AcpiUtValidInternalObject ( 377 void *Object) 378 { 379 380 ACPI_FUNCTION_NAME (UtValidInternalObject); 381 382 383 /* Check for a null pointer */ 384 385 if (!Object) 386 { 387 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "**** Null Object Ptr\n")); 388 return (FALSE); 389 } 390 391 /* Check the descriptor type field */ 392 393 switch (ACPI_GET_DESCRIPTOR_TYPE (Object)) 394 { 395 case ACPI_DESC_TYPE_OPERAND: 396 397 /* The object appears to be a valid ACPI_OPERAND_OBJECT */ 398 399 return (TRUE); 400 401 default: 402 403 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 404 "%p is not an ACPI operand obj [%s]\n", 405 Object, AcpiUtGetDescriptorName (Object))); 406 break; 407 } 408 409 return (FALSE); 410 } 411 412 413 /******************************************************************************* 414 * 415 * FUNCTION: AcpiUtAllocateObjectDescDbg 416 * 417 * PARAMETERS: ModuleName - Caller's module name (for error output) 418 * LineNumber - Caller's line number (for error output) 419 * ComponentId - Caller's component ID (for error output) 420 * 421 * RETURN: Pointer to newly allocated object descriptor. Null on error 422 * 423 * DESCRIPTION: Allocate a new object descriptor. Gracefully handle 424 * error conditions. 425 * 426 ******************************************************************************/ 427 428 void * 429 AcpiUtAllocateObjectDescDbg ( 430 const char *ModuleName, 431 UINT32 LineNumber, 432 UINT32 ComponentId) 433 { 434 ACPI_OPERAND_OBJECT *Object; 435 436 437 ACPI_FUNCTION_TRACE (UtAllocateObjectDescDbg); 438 439 440 Object = AcpiOsAcquireObject (AcpiGbl_OperandCache); 441 if (!Object) 442 { 443 ACPI_ERROR ((ModuleName, LineNumber, 444 "Could not allocate an object descriptor")); 445 446 return_PTR (NULL); 447 } 448 449 /* Mark the descriptor type */ 450 451 ACPI_SET_DESCRIPTOR_TYPE (Object, ACPI_DESC_TYPE_OPERAND); 452 453 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p Size %X\n", 454 Object, (UINT32) sizeof (ACPI_OPERAND_OBJECT))); 455 456 return_PTR (Object); 457 } 458 459 460 /******************************************************************************* 461 * 462 * FUNCTION: AcpiUtDeleteObjectDesc 463 * 464 * PARAMETERS: Object - An Acpi internal object to be deleted 465 * 466 * RETURN: None. 467 * 468 * DESCRIPTION: Free an ACPI object descriptor or add it to the object cache 469 * 470 ******************************************************************************/ 471 472 void 473 AcpiUtDeleteObjectDesc ( 474 ACPI_OPERAND_OBJECT *Object) 475 { 476 ACPI_FUNCTION_TRACE_PTR (UtDeleteObjectDesc, Object); 477 478 479 /* Object must be of type ACPI_OPERAND_OBJECT */ 480 481 if (ACPI_GET_DESCRIPTOR_TYPE (Object) != ACPI_DESC_TYPE_OPERAND) 482 { 483 ACPI_ERROR ((AE_INFO, 484 "%p is not an ACPI Operand object [%s]", Object, 485 AcpiUtGetDescriptorName (Object))); 486 return_VOID; 487 } 488 489 (void) AcpiOsReleaseObject (AcpiGbl_OperandCache, Object); 490 return_VOID; 491 } 492 493 494 /******************************************************************************* 495 * 496 * FUNCTION: AcpiUtGetSimpleObjectSize 497 * 498 * PARAMETERS: InternalObject - An ACPI operand object 499 * ObjLength - Where the length is returned 500 * 501 * RETURN: Status 502 * 503 * DESCRIPTION: This function is called to determine the space required to 504 * contain a simple object for return to an external user. 505 * 506 * The length includes the object structure plus any additional 507 * needed space. 508 * 509 ******************************************************************************/ 510 511 static ACPI_STATUS 512 AcpiUtGetSimpleObjectSize ( 513 ACPI_OPERAND_OBJECT *InternalObject, 514 ACPI_SIZE *ObjLength) 515 { 516 ACPI_SIZE Length; 517 ACPI_SIZE Size; 518 ACPI_STATUS Status = AE_OK; 519 520 521 ACPI_FUNCTION_TRACE_PTR (UtGetSimpleObjectSize, InternalObject); 522 523 524 /* Start with the length of the (external) Acpi object */ 525 526 Length = sizeof (ACPI_OBJECT); 527 528 /* A NULL object is allowed, can be a legal uninitialized package element */ 529 530 if (!InternalObject) 531 { 532 /* 533 * Object is NULL, just return the length of ACPI_OBJECT 534 * (A NULL ACPI_OBJECT is an object of all zeroes.) 535 */ 536 *ObjLength = ACPI_ROUND_UP_TO_NATIVE_WORD (Length); 537 return_ACPI_STATUS (AE_OK); 538 } 539 540 /* A Namespace Node should never appear here */ 541 542 if (ACPI_GET_DESCRIPTOR_TYPE (InternalObject) == ACPI_DESC_TYPE_NAMED) 543 { 544 /* A namespace node should never get here */ 545 546 return_ACPI_STATUS (AE_AML_INTERNAL); 547 } 548 549 /* 550 * The final length depends on the object type 551 * Strings and Buffers are packed right up against the parent object and 552 * must be accessed bytewise or there may be alignment problems on 553 * certain processors 554 */ 555 switch (InternalObject->Common.Type) 556 { 557 case ACPI_TYPE_STRING: 558 559 Length += (ACPI_SIZE) InternalObject->String.Length + 1; 560 break; 561 562 case ACPI_TYPE_BUFFER: 563 564 Length += (ACPI_SIZE) InternalObject->Buffer.Length; 565 break; 566 567 case ACPI_TYPE_INTEGER: 568 case ACPI_TYPE_PROCESSOR: 569 case ACPI_TYPE_POWER: 570 571 /* No extra data for these types */ 572 573 break; 574 575 case ACPI_TYPE_LOCAL_REFERENCE: 576 577 switch (InternalObject->Reference.Class) 578 { 579 case ACPI_REFCLASS_NAME: 580 /* 581 * Get the actual length of the full pathname to this object. 582 * The reference will be converted to the pathname to the object 583 */ 584 Size = AcpiNsGetPathnameLength (InternalObject->Reference.Node); 585 if (!Size) 586 { 587 return_ACPI_STATUS (AE_BAD_PARAMETER); 588 } 589 590 Length += ACPI_ROUND_UP_TO_NATIVE_WORD (Size); 591 break; 592 593 default: 594 /* 595 * No other reference opcodes are supported. 596 * Notably, Locals and Args are not supported, but this may be 597 * required eventually. 598 */ 599 ACPI_ERROR ((AE_INFO, "Cannot convert to external object - " 600 "unsupported Reference Class [%s] 0x%X in object %p", 601 AcpiUtGetReferenceName (InternalObject), 602 InternalObject->Reference.Class, InternalObject)); 603 Status = AE_TYPE; 604 break; 605 } 606 break; 607 608 default: 609 610 ACPI_ERROR ((AE_INFO, "Cannot convert to external object - " 611 "unsupported type [%s] 0x%X in object %p", 612 AcpiUtGetObjectTypeName (InternalObject), 613 InternalObject->Common.Type, InternalObject)); 614 Status = AE_TYPE; 615 break; 616 } 617 618 /* 619 * Account for the space required by the object rounded up to the next 620 * multiple of the machine word size. This keeps each object aligned 621 * on a machine word boundary. (preventing alignment faults on some 622 * machines.) 623 */ 624 *ObjLength = ACPI_ROUND_UP_TO_NATIVE_WORD (Length); 625 return_ACPI_STATUS (Status); 626 } 627 628 629 /******************************************************************************* 630 * 631 * FUNCTION: AcpiUtGetElementLength 632 * 633 * PARAMETERS: ACPI_PKG_CALLBACK 634 * 635 * RETURN: Status 636 * 637 * DESCRIPTION: Get the length of one package element. 638 * 639 ******************************************************************************/ 640 641 static ACPI_STATUS 642 AcpiUtGetElementLength ( 643 UINT8 ObjectType, 644 ACPI_OPERAND_OBJECT *SourceObject, 645 ACPI_GENERIC_STATE *State, 646 void *Context) 647 { 648 ACPI_STATUS Status = AE_OK; 649 ACPI_PKG_INFO *Info = (ACPI_PKG_INFO *) Context; 650 ACPI_SIZE ObjectSpace; 651 652 653 switch (ObjectType) 654 { 655 case ACPI_COPY_TYPE_SIMPLE: 656 /* 657 * Simple object - just get the size (Null object/entry is handled 658 * here also) and sum it into the running package length 659 */ 660 Status = AcpiUtGetSimpleObjectSize (SourceObject, &ObjectSpace); 661 if (ACPI_FAILURE (Status)) 662 { 663 return (Status); 664 } 665 666 Info->Length += ObjectSpace; 667 break; 668 669 case ACPI_COPY_TYPE_PACKAGE: 670 671 /* Package object - nothing much to do here, let the walk handle it */ 672 673 Info->NumPackages++; 674 State->Pkg.ThisTargetObj = NULL; 675 break; 676 677 default: 678 679 /* No other types allowed */ 680 681 return (AE_BAD_PARAMETER); 682 } 683 684 return (Status); 685 } 686 687 688 /******************************************************************************* 689 * 690 * FUNCTION: AcpiUtGetPackageObjectSize 691 * 692 * PARAMETERS: InternalObject - An ACPI internal object 693 * ObjLength - Where the length is returned 694 * 695 * RETURN: Status 696 * 697 * DESCRIPTION: This function is called to determine the space required to 698 * contain a package object for return to an external user. 699 * 700 * This is moderately complex since a package contains other 701 * objects including packages. 702 * 703 ******************************************************************************/ 704 705 static ACPI_STATUS 706 AcpiUtGetPackageObjectSize ( 707 ACPI_OPERAND_OBJECT *InternalObject, 708 ACPI_SIZE *ObjLength) 709 { 710 ACPI_STATUS Status; 711 ACPI_PKG_INFO Info; 712 713 714 ACPI_FUNCTION_TRACE_PTR (UtGetPackageObjectSize, InternalObject); 715 716 717 Info.Length = 0; 718 Info.ObjectSpace = 0; 719 Info.NumPackages = 1; 720 721 Status = AcpiUtWalkPackageTree ( 722 InternalObject, NULL, AcpiUtGetElementLength, &Info); 723 if (ACPI_FAILURE (Status)) 724 { 725 return_ACPI_STATUS (Status); 726 } 727 728 /* 729 * We have handled all of the objects in all levels of the package. 730 * just add the length of the package objects themselves. 731 * Round up to the next machine word. 732 */ 733 Info.Length += ACPI_ROUND_UP_TO_NATIVE_WORD ( 734 sizeof (ACPI_OBJECT)) * (ACPI_SIZE) Info.NumPackages; 735 736 /* Return the total package length */ 737 738 *ObjLength = Info.Length; 739 return_ACPI_STATUS (Status); 740 } 741 742 743 /******************************************************************************* 744 * 745 * FUNCTION: AcpiUtGetObjectSize 746 * 747 * PARAMETERS: InternalObject - An ACPI internal object 748 * ObjLength - Where the length will be returned 749 * 750 * RETURN: Status 751 * 752 * DESCRIPTION: This function is called to determine the space required to 753 * contain an object for return to an API user. 754 * 755 ******************************************************************************/ 756 757 ACPI_STATUS 758 AcpiUtGetObjectSize ( 759 ACPI_OPERAND_OBJECT *InternalObject, 760 ACPI_SIZE *ObjLength) 761 { 762 ACPI_STATUS Status; 763 764 765 ACPI_FUNCTION_ENTRY (); 766 767 768 if ((ACPI_GET_DESCRIPTOR_TYPE (InternalObject) == 769 ACPI_DESC_TYPE_OPERAND) && 770 (InternalObject->Common.Type == ACPI_TYPE_PACKAGE)) 771 { 772 Status = AcpiUtGetPackageObjectSize (InternalObject, ObjLength); 773 } 774 else 775 { 776 Status = AcpiUtGetSimpleObjectSize (InternalObject, ObjLength); 777 } 778 779 return (Status); 780 } 781