Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / libpkix / pkix_pl_nss / system / pkix_pl_object.c
blob3fee61dc9aae23af38278f922f4bf1e4d94ea06f
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * Sun Microsystems
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 * pkix_pl_object.c
40 * Object Construction, Destruction and Callback Functions
44 #include "pkix_pl_object.h"
46 /* --Debugging---------------------------------------------------- */
48 static PKIX_UInt32 refCountTotal = 0;
50 /* --Class-Table-Initializers------------------------------------ */
53 * Create storage space for 20 Class Table buckets.
54 * These are only for user-defined types. System types are registered
55 * separately by PKIX_PL_Initialize.
58 static pkix_pl_HT_Elem*
59 pkix_Raw_ClassTable_Buckets[] = {
60 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
61 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
65 * Allocate static memory for a ClassTable.
66 * XXX This assumes the bucket pointer will fit into a PKIX_UInt32
68 static pkix_pl_PrimHashTable pkix_Raw_ClassTable = {
69 (void *)pkix_Raw_ClassTable_Buckets, /* Buckets */
70 20 /* Number of Buckets */
72 static pkix_pl_PrimHashTable * classTable = &pkix_Raw_ClassTable;
74 /* --Private-Functions-------------------------------------------- */
77 * FUNCTION: pkix_pl_Object_GetHeader
78 * DESCRIPTION:
80 * Shifts Object pointed to by "object" by the sizeof(PKIX_PL_Object) and
81 * stores the value at "pObjectHeader".
83 * PARAMETERS:
84 * "object"
85 * Address of Object to shift. Must be non-NULL.
86 * "pObjectHeader"
87 * Address where object pointer will be stored. Must be non-NULL.
88 * "plContext"
89 * Platform-specific context pointer.
90 * THREAD SAFETY:
91 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
92 * RETURNS:
93 * Returns NULL if the function succeeds.
94 * Returns a Fatal Error if the function fails in an unrecoverable way.
96 static PKIX_Error *
97 pkix_pl_Object_GetHeader(
98 PKIX_PL_Object *object,
99 PKIX_PL_Object **pObjectHeader,
100 void *plContext)
102 PKIX_PL_Object *header = NULL;
103 pkix_ClassTable_Entry *ctEntry = NULL;
104 PKIX_UInt32 myType;
106 PKIX_ENTER(OBJECT, "pkix_pl_Object_GetHeader");
107 PKIX_NULLCHECK_TWO(object, pObjectHeader);
109 PKIX_OBJECT_DEBUG("\tShifting object pointer).\n");
111 /* The header is sizeof(PKIX_PL_Object) before the object pointer */
112 header = (PKIX_PL_Object *)((char *)object - sizeof(PKIX_PL_Object));
114 myType = header->type;
116 if (myType >= PKIX_NUMTYPES) { /* if this is a user-defined type */
117 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
118 PR_Lock(classTableLock);
120 PKIX_CHECK(pkix_pl_PrimHashTable_Lookup
121 (classTable,
122 (void *)&myType,
123 header->type,
124 NULL,
125 (void **)&ctEntry,
126 plContext),
127 PKIX_ERRORGETTINGCLASSTABLEENTRY);
129 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
130 PR_Unlock(classTableLock);
132 if (ctEntry == NULL) {
133 PKIX_ERROR_FATAL(PKIX_UNKNOWNOBJECTTYPE);
137 if ((header == NULL)||
138 (header->magicHeader != PKIX_MAGIC_HEADER)) {
139 return (PKIX_ALLOC_ERROR());
142 *pObjectHeader = header;
144 cleanup:
146 PKIX_RETURN(OBJECT);
150 * FUNCTION: pkix_Destroy_Object
151 * DESCRIPTION:
153 * Destroys and deallocates Object pointed to by "object". The caller is
154 * assumed to hold the Object's lock, which is acquired in
155 * PKIX_PL_Object_DecRef().
157 * PARAMETERS:
158 * "object"
159 * Address of Object to destroy. Must be non-NULL.
160 * "plContext"
161 * Platform-specific context pointer.
162 * THREAD SAFETY:
163 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
164 * RETURNS:
165 * Returns NULL if the function succeeds.
166 * Returns a Fatal Error if the function fails in an unrecoverable way.
168 static PKIX_Error *
169 pkix_pl_Object_Destroy(
170 PKIX_PL_Object *object,
171 void *plContext)
173 PKIX_PL_Object *objectHeader = NULL;
175 PKIX_ENTER(OBJECT, "pkix_pl_Object_Destroy");
176 PKIX_NULLCHECK_ONE(object);
178 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
179 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
181 /* Attempt to delete an object still being used */
182 if (objectHeader->references != 0) {
183 PKIX_ERROR_FATAL(PKIX_OBJECTSTILLREFERENCED);
186 objectHeader->magicHeader = 0;
187 PKIX_DECREF(objectHeader->stringRep);
189 PKIX_CHECK(pkix_UnlockObject(object, plContext),
190 PKIX_ERRORUNLOCKINGOBJECT);
192 /* Destroy this object's lock */
193 PKIX_OBJECT_DEBUG("\tCalling PR_DestroyLock).\n");
194 PR_DestroyLock(objectHeader->lock);
195 objectHeader->lock = NULL;
196 object = NULL;
198 PKIX_FREE(objectHeader);
200 cleanup:
202 PKIX_RETURN(OBJECT);
205 /* --Default-Callbacks-------------------------------------------- */
208 * FUNCTION: pkix_pl_Object_Equals_Default
209 * DESCRIPTION:
211 * Default Object_Equals callback: Compares the address of the Object pointed
212 * to by "firstObject" with the address of the Object pointed to by
213 * "secondObject" and stores the Boolean result at "pResult".
215 * PARAMETERS:
216 * "firstObject"
217 * Address of first Object to compare. Must be non-NULL.
218 * "secondObject"
219 * Address of second Object to compare. Must be non-NULL.
220 * "pResult"
221 * Address where Boolean result will be stored. Must be non-NULL.
222 * "plContext"
223 * Platform-specific context pointer.
224 * THREAD SAFETY:
225 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
226 * RETURNS:
227 * Returns NULL if the function succeeds.
228 * Returns a Fatal Error if the function fails in an unrecoverable way.
230 static PKIX_Error *
231 pkix_pl_Object_Equals_Default(
232 PKIX_PL_Object *firstObject,
233 PKIX_PL_Object *secondObject,
234 PKIX_Boolean *pResult,
235 void *plContext)
237 PKIX_ENTER(OBJECT, "pkix_pl_Object_Equals_Default");
238 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
240 /* Just compare pointer values */
241 *pResult = (firstObject == secondObject)?PKIX_TRUE:PKIX_FALSE;
243 PKIX_RETURN(OBJECT);
247 * FUNCTION: pkix_pl_Object_ToString_Default
248 * DESCRIPTION:
250 * Default Object_ToString callback: Creates a string consisting of the
251 * typename and address of the Object pointed to by "object" and stores
252 * the result at "pString". The format for the string is
253 * "TypeName@Address: <address>", where the default typename is "Object".
255 * PARAMETERS:
256 * "object"
257 * Address of Object to convert to a string. Must be non-NULL.
258 * "pString"
259 * Address where object pointer will be stored. Must be non-NULL.
260 * "plContext"
261 * Platform-specific context pointer.
262 * THREAD SAFETY:
263 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
264 * RETURNS:
265 * Returns NULL if the function succeeds.
266 * Returns an Object Error if the function fails in a non-fatal way.
267 * Returns a Fatal Error if the function fails in an unrecoverable way.
269 static PKIX_Error *
270 pkix_pl_Object_ToString_Default(
271 PKIX_PL_Object *object,
272 PKIX_PL_String **pString,
273 void *plContext)
275 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
276 pkix_ClassTable_Entry *ctEntry = NULL;
277 PKIX_PL_String *formatString = NULL;
278 PKIX_PL_String *descString = NULL;
279 char *format = "%s@Address: %x";
280 char *description = NULL;
281 PKIX_UInt32 type;
283 PKIX_ENTER(OBJECT, "pkix_pl_Object_ToString_Default");
284 PKIX_NULLCHECK_TWO(object, pString);
286 PKIX_CHECK(PKIX_PL_Object_GetType(object, &type, plContext),
287 PKIX_OBJECTGETTYPEFAILED);
289 /* Ensure that type code is known. Otherwise, default to Object */
290 /* See pkixt.h for all known types. */
291 /* XXX Throw an illegal type error here? */
292 if (type >= PKIX_NUMTYPES) {
293 type = 0;
296 /* first, special handling for system types */
297 if (type < PKIX_NUMTYPES){
298 description = systemClasses[type].description;
299 } else {
300 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
301 PR_Lock(classTableLock);
302 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
303 (classTable,
304 (void *)&type,
305 type,
306 NULL,
307 (void **)&ctEntry,
308 plContext);
309 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
310 PR_Unlock(classTableLock);
311 if (pkixErrorResult){
312 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY);
315 if (ctEntry == NULL){
316 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCLASSTABLEENTRY);
317 } else {
318 description = ctEntry->description;
322 PKIX_CHECK(PKIX_PL_String_Create
323 (PKIX_ESCASCII,
324 (void *)format,
326 &formatString,
327 plContext),
328 PKIX_STRINGCREATEFAILED);
330 PKIX_CHECK(PKIX_PL_String_Create
331 (PKIX_ESCASCII,
332 (void *)description,
334 &descString,
335 plContext),
336 PKIX_STRINGCREATEFAILED);
338 PKIX_CHECK(PKIX_PL_Sprintf
339 (pString,
340 plContext,
341 formatString,
342 descString,
343 object),
344 PKIX_SPRINTFFAILED);
346 cleanup:
348 PKIX_DECREF(formatString);
349 PKIX_DECREF(descString);
351 PKIX_RETURN(OBJECT);
355 * FUNCTION: pkix_pl_Object_Hashcode_Default
356 * DESCRIPTION:
358 * Default Object_Hashcode callback. Creates the a hashcode value using the
359 * address of the Object pointed to by "object" and stores the result at
360 * "pValue".
362 * XXX This isn't great since addresses are not uniformly distributed.
364 * PARAMETERS:
365 * "object"
366 * Address of Object to compute hashcode for. Must be non-NULL.
367 * "pValue"
368 * Address where PKIX_UInt32 will be stored. Must be non-NULL.
369 * "plContext"
370 * Platform-specific context pointer.
371 * THREAD SAFETY:
372 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
373 * RETURNS:
374 * Returns NULL if the function succeeds.
375 * Returns a Fatal Error if the function fails in an unrecoverable way.
377 static PKIX_Error *
378 pkix_pl_Object_Hashcode_Default(
379 PKIX_PL_Object *object,
380 PKIX_UInt32 *pValue,
381 void *plContext)
383 #ifdef NSS_USE_64
384 union {
385 void *pointer;
386 PKIX_UInt32 hilo[2];
387 } extracter;
388 #endif
390 PKIX_ENTER(OBJECT, "pkix_pl_Object_Hashcode_Default");
391 PKIX_NULLCHECK_TWO(object, pValue);
393 #ifdef NSS_USE_64
394 extracter.pointer = object;
395 *pValue = extracter.hilo[1];
396 #else
397 *pValue = (PKIX_UInt32)object;
398 #endif
400 PKIX_RETURN(OBJECT);
404 * FUNCTION: pkix_pl_Object_RetrieveEqualsCallback
405 * DESCRIPTION:
407 * Retrieves Equals callback function of Object pointed to by "object and
408 * stores it at "pEqualsCallback". If the object's type is one of the system
409 * types, its callback function is retrieved from the systemClasses array;
410 * otherwise, its callback function is retrieve from the classTable hash
411 * table where user-defined types are stored.
413 * PARAMETERS:
414 * "object"
415 * Address of Object whose equals callback is desired. Must be non-NULL.
416 * "pEqualsCallback"
417 * Address where EqualsCallback function pointer will be stored.
418 * Must be non-NULL.
419 * "plContext"
420 * Platform-specific context pointer.
421 * THREAD SAFETY:
422 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
423 * RETURNS:
424 * Returns NULL if the function succeeds.
425 * Returns an Object Error if the function fails in a non-fatal way.
426 * Returns a Fatal Error if the function fails in an unrecoverable way.
428 PKIX_Error *
429 pkix_pl_Object_RetrieveEqualsCallback(
430 PKIX_PL_Object *object,
431 PKIX_PL_EqualsCallback *pEqualsCallback,
432 void *plContext)
434 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
435 PKIX_PL_Object *objectHeader = NULL;
436 pkix_ClassTable_Entry *ctEntry = NULL;
437 PKIX_PL_EqualsCallback func = NULL;
438 pkix_ClassTable_Entry entry;
440 PKIX_ENTER(OBJECT, "pkix_pl_Object_RetrieveEqualsCallback");
441 PKIX_NULLCHECK_TWO(object, pEqualsCallback);
443 PKIX_CHECK(pkix_pl_Object_GetHeader
444 (object, &objectHeader, plContext),
445 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
447 /* first, special handling for system types */
448 if (objectHeader->type < PKIX_NUMTYPES){
449 entry = systemClasses[objectHeader->type];
450 func = entry.equalsFunction;
451 if (func == NULL){
452 func = pkix_pl_Object_Equals_Default;
454 *pEqualsCallback = func;
455 } else {
456 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
457 PR_Lock(classTableLock);
458 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
459 (classTable,
460 (void *)&objectHeader->type,
461 objectHeader->type,
462 NULL,
463 (void **)&ctEntry,
464 plContext);
465 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
466 PR_Unlock(classTableLock);
467 if (pkixErrorResult){
468 PKIX_ERROR(PKIX_ERRORGETTINGCLASSTABLEENTRY);
471 if ((ctEntry == NULL) || (ctEntry->equalsFunction == NULL)) {
472 PKIX_ERROR(PKIX_UNDEFINEDEQUALSCALLBACK);
473 } else {
474 *pEqualsCallback = ctEntry->equalsFunction;
478 cleanup:
480 PKIX_RETURN(OBJECT);
483 /* --Public-Functions------------------------------------------------------- */
486 * FUNCTION: PKIX_PL_Object_Alloc (see comments in pkix_pl_system.h)
488 PKIX_Error *
489 PKIX_PL_Object_Alloc(
490 PKIX_UInt32 type,
491 PKIX_UInt32 size,
492 PKIX_PL_Object **pObject,
493 void *plContext)
495 PKIX_PL_Object *object = NULL;
496 pkix_ClassTable_Entry *ctEntry = NULL;
497 PKIX_Boolean typeRegistered;
499 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Alloc");
500 PKIX_NULLCHECK_ONE(pObject);
503 * We need to ensure that user-defined types have been registered.
504 * All system types have already been registered by PKIX_PL_Initialize.
507 if (type >= PKIX_NUMTYPES) { /* i.e. if this is a user-defined type */
508 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
509 PR_Lock(classTableLock);
510 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
511 (classTable,
512 (void *)&type,
513 type,
514 NULL,
515 (void **)&ctEntry,
516 plContext);
517 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
518 PR_Unlock(classTableLock);
519 if (pkixErrorResult){
520 PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE);
523 typeRegistered = (ctEntry != NULL);
525 if (!typeRegistered) {
526 PKIX_ERROR_FATAL(PKIX_UNKNOWNTYPEARGUMENT);
530 /* Allocate space for the object header and the requested size */
531 PKIX_CHECK(PKIX_PL_Malloc
532 (((PKIX_UInt32)sizeof (PKIX_PL_Object))+size,
533 (void **)&object,
534 plContext),
535 PKIX_MALLOCFAILED);
537 /* Initialize all object fields */
538 object->magicHeader = PKIX_MAGIC_HEADER;
539 object->type = type;
540 object->references = 1; /* Default to a single reference */
541 object->stringRep = NULL;
542 object->hashcode = 0;
543 object->hashcodeCached = 0;
545 /* XXX Debugging - not thread safe */
546 refCountTotal++;
548 PKIX_REF_COUNT_DEBUG_ARG("PKIX_PL_Object_Alloc: refCountTotal == %d \n",
549 refCountTotal);
551 /* Cannot use PKIX_PL_Mutex because it depends on Object */
552 /* Using NSPR Locks instead */
553 PKIX_OBJECT_DEBUG("\tCalling PR_NewLock).\n");
554 object->lock = PR_NewLock();
555 if (object->lock == NULL) {
556 PKIX_FREE(pObject);
557 return (PKIX_ALLOC_ERROR());
560 PKIX_OBJECT_DEBUG("\tShifting object pointer).\n");
562 /* Return a pointer to the user data. Need to offset by object size */
563 *pObject = object + 1;
565 cleanup:
567 PKIX_RETURN(OBJECT);
571 * FUNCTION: PKIX_PL_Object_IsTypeRegistered (see comments in pkix_pl_system.h)
573 PKIX_Error *
574 PKIX_PL_Object_IsTypeRegistered(
575 PKIX_UInt32 type,
576 PKIX_Boolean *pBool,
577 void *plContext)
579 pkix_ClassTable_Entry *ctEntry = NULL;
581 PKIX_ENTER(OBJECT, "PKIX_PL_Object_IsTypeRegistered");
582 PKIX_NULLCHECK_ONE(pBool);
584 /* first, we handle the system types */
585 if (type < PKIX_NUMTYPES) {
586 *pBool = PKIX_TRUE;
587 goto cleanup;
590 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
591 PR_Lock(classTableLock);
592 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
593 (classTable,
594 (void *)&type,
595 type,
596 NULL,
597 (void **)&ctEntry,
598 plContext);
599 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
600 PR_Unlock(classTableLock);
602 if (pkixErrorResult){
603 PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE);
606 *pBool = (ctEntry != NULL);
608 cleanup:
610 PKIX_RETURN(OBJECT);
614 * FUNCTION: PKIX_PL_Object_RegisterType (see comments in pkix_pl_system.h)
616 PKIX_Error *
617 PKIX_PL_Object_RegisterType(
618 PKIX_UInt32 type,
619 char *description,
620 PKIX_PL_DestructorCallback destructor,
621 PKIX_PL_EqualsCallback equalsFunction,
622 PKIX_PL_HashcodeCallback hashcodeFunction,
623 PKIX_PL_ToStringCallback toStringFunction,
624 PKIX_PL_ComparatorCallback comparator,
625 PKIX_PL_DuplicateCallback duplicateFunction,
626 void *plContext)
628 pkix_ClassTable_Entry *ctEntry = NULL;
629 pkix_pl_Integer *key = NULL;
631 PKIX_ENTER(OBJECT, "PKIX_PL_Object_RegisterType");
634 * System types are registered on startup by PKIX_PL_Initialize.
635 * These can not be overwritten.
638 if (type < PKIX_NUMTYPES) { /* if this is a system type */
639 PKIX_ERROR(PKIX_CANTREREGISTERSYSTEMTYPE);
642 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
643 PR_Lock(classTableLock);
644 PKIX_CHECK(pkix_pl_PrimHashTable_Lookup
645 (classTable,
646 (void *)&type,
647 type,
648 NULL,
649 (void **)&ctEntry,
650 plContext),
651 PKIX_PRIMHASHTABLELOOKUPFAILED);
653 /* If the type is already registered, throw an error */
654 if (ctEntry) {
655 PKIX_ERROR(PKIX_TYPEALREADYREGISTERED);
658 PKIX_CHECK(PKIX_PL_Malloc
659 (((PKIX_UInt32)sizeof (pkix_ClassTable_Entry)),
660 (void **)&ctEntry,
661 plContext),
662 PKIX_MALLOCFAILED);
664 /* Set Default Values if none specified */
666 if (description == NULL){
667 description = "Object";
670 if (equalsFunction == NULL) {
671 equalsFunction = pkix_pl_Object_Equals_Default;
674 if (toStringFunction == NULL) {
675 toStringFunction = pkix_pl_Object_ToString_Default;
678 if (hashcodeFunction == NULL) {
679 hashcodeFunction = pkix_pl_Object_Hashcode_Default;
682 ctEntry->destructor = destructor;
683 ctEntry->equalsFunction = equalsFunction;
684 ctEntry->toStringFunction = toStringFunction;
685 ctEntry->hashcodeFunction = hashcodeFunction;
686 ctEntry->comparator = comparator;
687 ctEntry->duplicateFunction = duplicateFunction;
688 ctEntry->description = description;
690 PKIX_CHECK(PKIX_PL_Malloc
691 (((PKIX_UInt32)sizeof (pkix_pl_Integer)),
692 (void **)&key,
693 plContext),
694 PKIX_COULDNOTMALLOCNEWKEY);
696 key->ht_int = type;
698 PKIX_CHECK(pkix_pl_PrimHashTable_Add
699 (classTable,
700 (void *)key,
701 (void *)ctEntry,
702 type,
703 NULL,
704 plContext),
705 PKIX_PRIMHASHTABLEADDFAILED);
707 cleanup:
708 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
709 PR_Unlock(classTableLock);
711 PKIX_RETURN(OBJECT);
715 * FUNCTION: PKIX_PL_Object_IncRef (see comments in pkix_pl_system.h)
717 PKIX_Error *
718 PKIX_PL_Object_IncRef(
719 PKIX_PL_Object *object,
720 void *plContext)
722 PKIX_Boolean refCountError = PKIX_FALSE;
723 PKIX_PL_Object *objectHeader = NULL;
724 PKIX_PL_NssContext *context = NULL;
726 PKIX_ENTER(OBJECT, "PKIX_PL_Object_IncRef");
727 PKIX_NULLCHECK_ONE(object);
729 if (plContext){
731 * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't
732 * have a header therefore we cannot verify its type before
733 * casting.
735 context = (PKIX_PL_NssContext *) plContext;
736 if (context->arena != NULL) {
737 goto cleanup;
741 if (object == (PKIX_PL_Object*)PKIX_ALLOC_ERROR()) {
742 PKIX_ERROR_FATAL(PKIX_ATTEMPTTOINCREFALLOCERROR);
745 /* Shift pointer from user data to object header */
746 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
747 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
749 /* Lock the test and increment */
750 PKIX_OBJECT_DEBUG("\tAcquiring object lock).\n");
751 PKIX_CHECK(pkix_LockObject(object, plContext),
752 PKIX_ERRORLOCKINGOBJECT);
754 /* This object should never have zero references */
755 refCountError = (objectHeader->references == 0);
757 if (!refCountError) {
758 objectHeader->references++;
759 refCountTotal++;
760 PKIX_REF_COUNT_DEBUG_ARG("PKIX_PL_Object_IncRef: "
761 "refCountTotal == %d \n", refCountTotal);
764 PKIX_CHECK(pkix_UnlockObject(object, plContext),
765 PKIX_ERRORUNLOCKINGOBJECT);
767 if (refCountError) {
768 PKIX_THROW
769 (FATAL,
770 PKIX_ErrorText[PKIX_OBJECTWITHNONPOSITIVEREFERENCES]);
773 cleanup:
775 PKIX_RETURN(OBJECT);
779 * FUNCTION: PKIX_PL_Object_DecRef (see comments in pkix_pl_system.h)
781 PKIX_Error *
782 PKIX_PL_Object_DecRef(
783 PKIX_PL_Object *object,
784 void *plContext)
786 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
787 PKIX_PL_DestructorCallback destructor = NULL;
788 pkix_ClassTable_Entry *ctEntry = NULL;
789 PKIX_PL_DestructorCallback func = NULL;
790 PKIX_PL_Object *objectHeader = NULL;
791 pkix_ClassTable_Entry entry;
792 PKIX_PL_NssContext *context = NULL;
793 PKIX_Boolean refCountError = PKIX_FALSE;
795 PKIX_ENTER(OBJECT, "PKIX_PL_Object_DecRef");
796 PKIX_NULLCHECK_ONE(object);
798 if (plContext){
800 * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't
801 * have a header therefore we cannot verify its type before
802 * casting.
804 context = (PKIX_PL_NssContext *) plContext;
805 if (context->arena != NULL) {
806 goto cleanup;
810 if (object == (PKIX_PL_Object*)PKIX_ALLOC_ERROR()) {
811 PKIX_ERROR_FATAL(PKIX_ATTEMPTTODECREFALLOCERROR);
814 /* Shift pointer from user data to object header */
815 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
816 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
818 /* Lock the test for the reference count and the decrement */
819 PKIX_OBJECT_DEBUG("\tAcquiring object lock).\n");
820 PKIX_CHECK(pkix_LockObject(object, plContext),
821 PKIX_ERRORLOCKINGOBJECT);
823 refCountError = (objectHeader->references == 0);
825 if (!refCountError) {
826 objectHeader->references--;
827 refCountTotal--;
829 PKIX_REF_COUNT_DEBUG_ARG("PKIX_PL_Object_DecRef: "
830 "refCountTotal == %d \n", refCountTotal);
832 if (objectHeader->references == 0) {
833 /* first, special handling for system types */
834 if (objectHeader->type < PKIX_NUMTYPES){
835 entry = systemClasses[objectHeader->type];
836 func = entry.destructor;
837 if (func != NULL){
838 /* Call destructor on user data if necessary */
839 PKIX_CHECK_FATAL(func(object, plContext),
840 PKIX_ERRORINOBJECTDEFINEDESTROY);
842 } else {
843 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
844 PR_Lock(classTableLock);
845 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
846 (classTable,
847 (void *)&objectHeader->type,
848 objectHeader->type,
849 NULL,
850 (void **)&ctEntry,
851 plContext);
852 PKIX_OBJECT_DEBUG
853 ("\tCalling PR_Unlock).\n");
854 PR_Unlock(classTableLock);
855 if (pkixErrorResult){
856 PKIX_ERROR_FATAL
857 (PKIX_ERRORINGETTINGDESTRUCTOR);
860 if (ctEntry != NULL){
861 destructor = ctEntry->destructor;
864 if (destructor != NULL) {
865 /* Call destructor on user data if necessary */
866 PKIX_CHECK_FATAL(destructor
867 (object, plContext),
868 PKIX_ERRORINOBJECTDEFINEDESTROY);
872 /* pkix_pl_Object_Destroy assumes the lock is held */
873 /* It will call unlock and destroy the object */
874 return (pkix_pl_Object_Destroy(object, plContext));
879 PKIX_OBJECT_DEBUG("\tReleasing object lock).\n");
880 PKIX_CHECK(pkix_UnlockObject(object, plContext),
881 PKIX_ERRORUNLOCKINGOBJECT);
883 /* if a reference count was already zero, throw an error */
884 if (refCountError) {
885 return (PKIX_ALLOC_ERROR());
888 cleanup:
890 PKIX_RETURN(OBJECT);
896 * FUNCTION: PKIX_PL_Object_Equals (see comments in pkix_pl_system.h)
898 PKIX_Error *
899 PKIX_PL_Object_Equals(
900 PKIX_PL_Object *firstObject,
901 PKIX_PL_Object *secondObject,
902 PKIX_Boolean *pResult,
903 void *plContext)
905 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
906 PKIX_PL_Object *firstObjectHeader = NULL;
907 PKIX_PL_Object *secondObjectHeader = NULL;
908 pkix_ClassTable_Entry *ctEntry = NULL;
909 PKIX_PL_EqualsCallback func = NULL;
910 pkix_ClassTable_Entry entry;
912 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Equals");
913 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
915 PKIX_CHECK(pkix_pl_Object_GetHeader
916 (firstObject, &firstObjectHeader, plContext),
917 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
919 PKIX_CHECK(pkix_pl_Object_GetHeader
920 (secondObject, &secondObjectHeader, plContext),
921 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
923 /* if hashcodes are cached but not equal, objects can't be equal */
924 if (firstObjectHeader->hashcodeCached &&
925 secondObjectHeader->hashcodeCached){
926 if (firstObjectHeader->hashcode !=
927 secondObjectHeader->hashcode){
928 *pResult = PKIX_FALSE;
929 goto cleanup;
933 /* first, special handling for system types */
934 if (firstObjectHeader->type < PKIX_NUMTYPES){
935 entry = systemClasses[firstObjectHeader->type];
936 func = entry.equalsFunction;
937 if (func == NULL){
938 func = pkix_pl_Object_Equals_Default;
940 } else {
941 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
942 PR_Lock(classTableLock);
943 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
944 (classTable,
945 (void *)&firstObjectHeader->type,
946 firstObjectHeader->type,
947 NULL,
948 (void **)&ctEntry,
949 plContext);
950 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
951 PR_Unlock(classTableLock);
953 if (pkixErrorResult){
954 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY);
957 if ((ctEntry == NULL) || (ctEntry->equalsFunction == NULL)) {
958 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
959 } else {
960 func = ctEntry->equalsFunction;
964 PKIX_CHECK(func(firstObject, secondObject, pResult, plContext),
965 PKIX_OBJECTSPECIFICFUNCTIONFAILED);
967 cleanup:
969 PKIX_RETURN(OBJECT);
973 * FUNCTION: PKIX_PL_Object_Duplicate (see comments in pkix_pl_system.h)
975 PKIX_Error *
976 PKIX_PL_Object_Duplicate(
977 PKIX_PL_Object *firstObject,
978 PKIX_PL_Object **pNewObject,
979 void *plContext)
981 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
982 PKIX_PL_Object *firstObjectHeader = NULL;
983 pkix_ClassTable_Entry *ctEntry = NULL;
984 PKIX_PL_DuplicateCallback func = NULL;
985 pkix_ClassTable_Entry entry;
987 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Duplicate");
988 PKIX_NULLCHECK_TWO(firstObject, pNewObject);
990 PKIX_CHECK(pkix_pl_Object_GetHeader
991 (firstObject, &firstObjectHeader, plContext),
992 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
994 /* first, special handling for system types */
995 if (firstObjectHeader->type < PKIX_NUMTYPES){
996 entry = systemClasses[firstObjectHeader->type];
997 func = entry.duplicateFunction;
998 if (!func){
999 PKIX_ERROR_FATAL(PKIX_UNDEFINEDDUPLICATEFUNCTION);
1001 } else {
1002 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
1003 PR_Lock(classTableLock);
1004 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
1005 (classTable,
1006 (void *)&firstObjectHeader->type,
1007 firstObjectHeader->type,
1008 NULL,
1009 (void **)&ctEntry,
1010 plContext);
1011 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
1012 PR_Unlock(classTableLock);
1014 if (pkixErrorResult){
1015 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY);
1018 if ((ctEntry == NULL) || (ctEntry->duplicateFunction == NULL)) {
1019 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
1020 } else {
1021 func = ctEntry->duplicateFunction;
1025 PKIX_CHECK(func(firstObject, pNewObject, plContext),
1026 PKIX_OBJECTSPECIFICFUNCTIONFAILED);
1028 cleanup:
1030 PKIX_RETURN(OBJECT);
1034 * FUNCTION: PKIX_PL_Object_Hashcode (see comments in pkix_pl_system.h)
1036 PKIX_Error *
1037 PKIX_PL_Object_Hashcode(
1038 PKIX_PL_Object *object,
1039 PKIX_UInt32 *pValue,
1040 void *plContext)
1042 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
1043 PKIX_PL_Object *objectHeader = NULL;
1044 pkix_ClassTable_Entry *ctEntry = NULL;
1045 PKIX_PL_HashcodeCallback func = NULL;
1046 pkix_ClassTable_Entry entry;
1047 PKIX_Boolean objectLocked = PKIX_FALSE;
1048 PKIX_UInt32 objectHash;
1050 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Hashcode");
1051 PKIX_NULLCHECK_TWO(object, pValue);
1053 /* Shift pointer from user data to object header */
1054 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
1055 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
1057 /* if we don't have a cached copy from before, we create one */
1058 if (!objectHeader->hashcodeCached){
1060 /* first, special handling for system types */
1061 if (objectHeader->type < PKIX_NUMTYPES){
1062 entry = systemClasses[objectHeader->type];
1063 func = entry.hashcodeFunction;
1064 if (func == NULL){
1065 func = pkix_pl_Object_Hashcode_Default;
1067 } else {
1068 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
1069 PR_Lock(classTableLock);
1070 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
1071 (classTable,
1072 (void *)&objectHeader->type,
1073 objectHeader->type,
1074 NULL,
1075 (void **)&ctEntry,
1076 plContext);
1077 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
1078 PR_Unlock(classTableLock);
1080 if (pkixErrorResult){
1081 PKIX_ERROR_FATAL
1082 (PKIX_ERRORGETTINGCLASSTABLEENTRY);
1085 if ((ctEntry == NULL) ||
1086 (ctEntry->hashcodeFunction == NULL)) {
1087 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
1090 func = ctEntry->hashcodeFunction;
1093 PKIX_CHECK(func(object, &objectHash, plContext),
1094 PKIX_OBJECTSPECIFICFUNCTIONFAILED);
1096 if (!objectHeader->hashcodeCached){
1098 PKIX_CHECK(pkix_LockObject(object, plContext),
1099 PKIX_ERRORLOCKINGOBJECT);
1100 objectLocked = PKIX_TRUE;
1102 if (!objectHeader->hashcodeCached){
1103 /* save cached copy in case we need it again */
1104 objectHeader->hashcode = objectHash;
1105 objectHeader->hashcodeCached = PKIX_TRUE;
1108 PKIX_CHECK(pkix_UnlockObject(object, plContext),
1109 PKIX_ERRORUNLOCKINGOBJECT);
1110 objectLocked = PKIX_FALSE;
1114 *pValue = objectHeader->hashcode;
1116 cleanup:
1118 if (objectLocked){
1119 pkixTempResult = pkix_UnlockObject(object, plContext);
1120 if (pkixTempResult) return pkixTempResult;
1123 PKIX_RETURN(OBJECT);
1127 * FUNCTION: PKIX_PL_Object_ToString (see comments in pkix_pl_system.h)
1129 PKIX_Error *
1130 PKIX_PL_Object_ToString(
1131 PKIX_PL_Object *object,
1132 PKIX_PL_String **pString,
1133 void *plContext)
1135 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
1136 PKIX_PL_Object *objectHeader = NULL;
1137 pkix_ClassTable_Entry *ctEntry = NULL;
1138 PKIX_PL_ToStringCallback func = NULL;
1139 pkix_ClassTable_Entry entry;
1140 PKIX_Boolean objectLocked = PKIX_FALSE;
1141 PKIX_PL_String *objectString;
1143 PKIX_ENTER(OBJECT, "PKIX_PL_Object_ToString");
1144 PKIX_NULLCHECK_TWO(object, pString);
1146 /* Shift pointer from user data to object header */
1147 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
1148 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
1150 /* if we don't have a cached copy from before, we create one */
1151 if (!objectHeader->stringRep){
1153 /* first, special handling for system types */
1154 if (objectHeader->type < PKIX_NUMTYPES){
1155 entry = systemClasses[objectHeader->type];
1156 func = entry.toStringFunction;
1157 if (func == NULL){
1158 func = pkix_pl_Object_ToString_Default;
1160 } else {
1161 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
1162 PR_Lock(classTableLock);
1163 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
1164 (classTable,
1165 (void *)&objectHeader->type,
1166 objectHeader->type,
1167 NULL,
1168 (void **)&ctEntry,
1169 plContext);
1170 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
1171 PR_Unlock(classTableLock);
1172 if (pkixErrorResult){
1173 PKIX_ERROR_FATAL
1174 (PKIX_ERRORGETTINGCLASSTABLEENTRY);
1177 if ((ctEntry == NULL) ||
1178 (ctEntry->toStringFunction == NULL)) {
1179 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
1182 func = ctEntry->toStringFunction;
1185 PKIX_CHECK(func(object, &objectString, plContext),
1186 PKIX_OBJECTSPECIFICFUNCTIONFAILED);
1188 if (!objectHeader->stringRep){
1190 PKIX_CHECK(pkix_LockObject(object, plContext),
1191 PKIX_ERRORLOCKINGOBJECT);
1192 objectLocked = PKIX_TRUE;
1194 if (!objectHeader->stringRep){
1195 /* save a cached copy */
1196 objectHeader->stringRep = objectString;
1199 PKIX_CHECK(pkix_UnlockObject(object, plContext),
1200 PKIX_ERRORUNLOCKINGOBJECT);
1201 objectLocked = PKIX_FALSE;
1205 PKIX_INCREF(objectHeader->stringRep);
1206 *pString = objectHeader->stringRep;
1208 cleanup:
1210 PKIX_RETURN(OBJECT);
1214 * FUNCTION: PKIX_PL_Object_InvalidateCache (see comments in pkix_pl_system.h)
1216 PKIX_Error *
1217 PKIX_PL_Object_InvalidateCache(
1218 PKIX_PL_Object *object,
1219 void *plContext)
1221 PKIX_PL_Object *objectHeader = NULL;
1222 PKIX_Boolean objectLocked = PKIX_FALSE;
1224 PKIX_ENTER(OBJECT, "PKIX_PL_Object_InvalidateCache");
1225 PKIX_NULLCHECK_ONE(object);
1227 /* Shift pointer from user data to object header */
1228 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
1229 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
1231 PKIX_CHECK(pkix_LockObject(object, plContext),
1232 PKIX_ERRORLOCKINGOBJECT);
1233 objectLocked = PKIX_TRUE;
1235 /* invalidate hashcode */
1236 objectHeader->hashcode = 0;
1237 objectHeader->hashcodeCached = PKIX_FALSE;
1239 PKIX_DECREF(objectHeader->stringRep);
1241 PKIX_CHECK(pkix_UnlockObject(object, plContext),
1242 PKIX_ERRORUNLOCKINGOBJECT);
1243 objectLocked = PKIX_FALSE;
1246 cleanup:
1248 PKIX_RETURN(OBJECT);
1252 * FUNCTION: PKIX_PL_Object_Compare (see comments in pkix_pl_system.h)
1254 PKIX_Error *
1255 PKIX_PL_Object_Compare(
1256 PKIX_PL_Object *firstObject,
1257 PKIX_PL_Object *secondObject,
1258 PKIX_Int32 *pResult,
1259 void *plContext)
1261 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
1262 PKIX_PL_Object *firstObjectHeader = NULL;
1263 PKIX_PL_Object *secondObjectHeader = NULL;
1264 pkix_ClassTable_Entry *ctEntry = NULL;
1265 PKIX_PL_ComparatorCallback func = NULL;
1266 pkix_ClassTable_Entry entry;
1268 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Compare");
1269 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
1271 /* Shift pointer from user data to object header */
1272 PKIX_CHECK(pkix_pl_Object_GetHeader
1273 (firstObject, &firstObjectHeader, plContext),
1274 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
1276 /* Shift pointer from user data to object header */
1277 PKIX_CHECK(pkix_pl_Object_GetHeader
1278 (secondObject, &secondObjectHeader, plContext),
1279 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
1281 /* first, special handling for system types */
1282 if (firstObjectHeader->type < PKIX_NUMTYPES){
1283 entry = systemClasses[firstObjectHeader->type];
1284 func = entry.comparator;
1285 if (!func){
1286 PKIX_ERROR(PKIX_UNDEFINEDCOMPARATOR);
1288 } else {
1289 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
1290 PR_Lock(classTableLock);
1291 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
1292 (classTable,
1293 (void *)&firstObjectHeader->type,
1294 firstObjectHeader->type,
1295 NULL,
1296 (void **)&ctEntry,
1297 plContext);
1298 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
1299 PR_Unlock(classTableLock);
1300 if (pkixErrorResult){
1301 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY);
1304 if ((ctEntry == NULL) || (ctEntry->comparator == NULL)) {
1305 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCOMPARATOR);
1308 func = ctEntry->comparator;
1311 PKIX_CHECK(func(firstObject, secondObject, pResult, plContext),
1312 PKIX_OBJECTSPECIFICFUNCTIONFAILED);
1314 cleanup:
1316 PKIX_RETURN(OBJECT);
1320 * FUNCTION: PKIX_PL_Object_Lock (see comments in pkix_pl_system.h)
1322 PKIX_Error *
1323 PKIX_PL_Object_Lock(
1324 PKIX_PL_Object *object,
1325 void *plContext)
1327 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Lock");
1328 PKIX_NULLCHECK_ONE(object);
1330 PKIX_CHECK(pkix_LockObject(object, plContext),
1331 PKIX_LOCKOBJECTFAILED);
1333 cleanup:
1335 PKIX_RETURN(OBJECT);
1339 * FUNCTION: PKIX_PL_Object_Unlock (see comments in pkix_pl_system.h)
1341 PKIX_Error *
1342 PKIX_PL_Object_Unlock(
1343 PKIX_PL_Object *object,
1344 void *plContext)
1346 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Unlock");
1347 PKIX_NULLCHECK_ONE(object);
1349 PKIX_CHECK(pkix_UnlockObject(object, plContext),
1350 PKIX_UNLOCKOBJECTFAILED);
1352 cleanup:
1354 PKIX_RETURN(OBJECT);
1359 * FUNCTION: PKIX_PL_Object_GetType (see comments in pkix_pl_system.h)
1361 PKIX_Error *
1362 PKIX_PL_Object_GetType(
1363 PKIX_PL_Object *object,
1364 PKIX_UInt32 *pType,
1365 void *plContext)
1367 PKIX_PL_Object *objectHeader = NULL;
1369 PKIX_ENTER(OBJECT, "PKIX_PL_Object_GetType");
1370 PKIX_NULLCHECK_TWO(object, pType);
1372 /* Shift pointer from user data to object header */
1373 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
1374 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
1376 *pType = objectHeader->type;
1378 cleanup:
1380 PKIX_RETURN(OBJECT);