nss: import at 3.0.1 beta 1
[mozilla-nss.git] / security / nss / lib / libpkix / pkix_pl_nss / system / pkix_pl_object.c
blob49de05e19b7dcaeefebdb94cf3a8c35b9effe47b
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 PKIX-C library.
16 * The Initial Developer of the Original Code is
17 * Sun Microsystems, Inc.
18 * Portions created by the Initial Developer are
19 * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
21 * Contributor(s):
22 * Sun Microsystems, Inc.
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 #ifdef PKIX_USER_OBJECT_TYPE
47 /* --Class-Table-Initializers------------------------------------ */
50 * Create storage space for 20 Class Table buckets.
51 * These are only for user-defined types. System types are registered
52 * separately by PKIX_PL_Initialize.
55 static pkix_pl_HT_Elem*
56 pkix_Raw_ClassTable_Buckets[] = {
57 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
58 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
62 * Allocate static memory for a ClassTable.
63 * XXX This assumes the bucket pointer will fit into a PKIX_UInt32
65 static pkix_pl_PrimHashTable pkix_Raw_ClassTable = {
66 (void *)pkix_Raw_ClassTable_Buckets, /* Buckets */
67 20 /* Number of Buckets */
69 static pkix_pl_PrimHashTable * classTable = &pkix_Raw_ClassTable;
70 #endif /* PKIX_USER_OBJECT_TYPE */
72 /* --Private-Functions-------------------------------------------- */
75 * FUNCTION: pkix_pl_Object_GetHeader
76 * DESCRIPTION:
78 * Shifts Object pointed to by "object" by the sizeof(PKIX_PL_Object) and
79 * stores the value at "pObjectHeader".
81 * PARAMETERS:
82 * "object"
83 * Address of Object to shift. Must be non-NULL.
84 * "pObjectHeader"
85 * Address where object pointer will be stored. Must be non-NULL.
86 * "plContext"
87 * Platform-specific context pointer.
88 * THREAD SAFETY:
89 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
90 * RETURNS:
91 * Returns NULL if the function succeeds.
92 * Returns a Fatal Error if the function fails in an unrecoverable way.
94 static PKIX_Error *
95 pkix_pl_Object_GetHeader(
96 PKIX_PL_Object *object,
97 PKIX_PL_Object **pObjectHeader,
98 void *plContext)
100 PKIX_PL_Object *header = NULL;
101 PKIX_UInt32 objType;
103 PKIX_ENTER(OBJECT, "pkix_pl_Object_GetHeader");
104 PKIX_NULLCHECK_TWO(object, pObjectHeader);
106 PKIX_OBJECT_DEBUG("\tShifting object pointer).\n");
108 /* The header is sizeof(PKIX_PL_Object) before the object pointer */
109 header = (PKIX_PL_Object *)((char *)object - sizeof(PKIX_PL_Object));
111 objType = header->type;
113 if (objType >= PKIX_NUMTYPES) { /* if this is a user-defined type */
114 #ifdef PKIX_USER_OBJECT_TYPE
115 pkix_ClassTable_Entry *ctEntry = NULL;
117 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
118 PR_Lock(classTableLock);
120 PKIX_CHECK(pkix_pl_PrimHashTable_Lookup
121 (classTable,
122 (void *)&objType,
123 objType,
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);
135 #else
136 PORT_Assert(objType < PKIX_NUMTYPES);
137 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
138 pkixErrorClass = PKIX_FATAL_ERROR;
139 goto cleanup;
140 #endif /* PKIX_USER_OBJECT_TYPE */
143 #ifdef PKIX_OBJECT_LEAK_TEST
144 PORT_Assert(header && header->magicHeader == PKIX_MAGIC_HEADER);
145 #endif /* PKIX_OBJECT_LEAK_TEST */
147 if ((header == NULL)||
148 (header->magicHeader != PKIX_MAGIC_HEADER)) {
149 PKIX_ERROR_ALLOC_ERROR();
152 *pObjectHeader = header;
154 cleanup:
156 PKIX_RETURN(OBJECT);
160 * FUNCTION: pkix_Destroy_Object
161 * DESCRIPTION:
163 * Destroys and deallocates Object pointed to by "object". The caller is
164 * assumed to hold the Object's lock, which is acquired in
165 * PKIX_PL_Object_DecRef().
167 * PARAMETERS:
168 * "object"
169 * Address of Object to destroy. Must be non-NULL.
170 * "plContext"
171 * Platform-specific context pointer.
172 * THREAD SAFETY:
173 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
174 * RETURNS:
175 * Returns NULL if the function succeeds.
176 * Returns a Fatal Error if the function fails in an unrecoverable way.
178 static PKIX_Error *
179 pkix_pl_Object_Destroy(
180 PKIX_PL_Object *object,
181 void *plContext)
183 PKIX_PL_Object *objectHeader = NULL;
185 PKIX_ENTER(OBJECT, "pkix_pl_Object_Destroy");
186 PKIX_NULLCHECK_ONE(object);
188 #ifdef PKIX_OBJECT_LEAK_TEST
189 PKIX_CHECK_FATAL(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
190 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
191 #else
192 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
193 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
194 #endif /* PKIX_OBJECT_LEAK_TEST */
196 /* Attempt to delete an object still being used */
197 if (objectHeader->references != 0) {
198 PKIX_ERROR_FATAL(PKIX_OBJECTSTILLREFERENCED);
201 PKIX_DECREF(objectHeader->stringRep);
203 /* Destroy this object's lock */
204 PKIX_OBJECT_DEBUG("\tCalling PR_DestroyLock).\n");
205 PR_DestroyLock(objectHeader->lock);
206 objectHeader->lock = NULL;
207 object = NULL;
209 objectHeader->magicHeader = PKIX_MAGIC_HEADER_DESTROYED;
211 #ifdef PKIX_OBJECT_LEAK_TEST
212 memset(objectHeader, 0xbf, systemClasses[PKIX_OBJECT_TYPE].typeObjectSize);
213 #endif
215 PKIX_FREE(objectHeader);
217 cleanup:
218 #ifdef PKIX_OBJECT_LEAK_TEST
219 fatal:
220 #endif
222 PKIX_RETURN(OBJECT);
225 /* --Default-Callbacks-------------------------------------------- */
228 * FUNCTION: pkix_pl_Object_Equals_Default
229 * DESCRIPTION:
231 * Default Object_Equals callback: Compares the address of the Object pointed
232 * to by "firstObject" with the address of the Object pointed to by
233 * "secondObject" and stores the Boolean result at "pResult".
235 * PARAMETERS:
236 * "firstObject"
237 * Address of first Object to compare. Must be non-NULL.
238 * "secondObject"
239 * Address of second Object to compare. Must be non-NULL.
240 * "pResult"
241 * Address where Boolean result will be stored. Must be non-NULL.
242 * "plContext"
243 * Platform-specific context pointer.
244 * THREAD SAFETY:
245 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
246 * RETURNS:
247 * Returns NULL if the function succeeds.
248 * Returns a Fatal Error if the function fails in an unrecoverable way.
250 static PKIX_Error *
251 pkix_pl_Object_Equals_Default(
252 PKIX_PL_Object *firstObject,
253 PKIX_PL_Object *secondObject,
254 PKIX_Boolean *pResult,
255 void *plContext)
257 PKIX_ENTER(OBJECT, "pkix_pl_Object_Equals_Default");
258 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
260 /* Just compare pointer values */
261 *pResult = (firstObject == secondObject)?PKIX_TRUE:PKIX_FALSE;
263 PKIX_RETURN(OBJECT);
267 * FUNCTION: pkix_pl_Object_ToString_Default
268 * DESCRIPTION:
270 * Default Object_ToString callback: Creates a string consisting of the
271 * typename and address of the Object pointed to by "object" and stores
272 * the result at "pString". The format for the string is
273 * "TypeName@Address: <address>", where the default typename is "Object".
275 * PARAMETERS:
276 * "object"
277 * Address of Object to convert to a string. Must be non-NULL.
278 * "pString"
279 * Address where object pointer will be stored. Must be non-NULL.
280 * "plContext"
281 * Platform-specific context pointer.
282 * THREAD SAFETY:
283 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
284 * RETURNS:
285 * Returns NULL if the function succeeds.
286 * Returns an Object Error if the function fails in a non-fatal way.
287 * Returns a Fatal Error if the function fails in an unrecoverable way.
289 static PKIX_Error *
290 pkix_pl_Object_ToString_Default(
291 PKIX_PL_Object *object,
292 PKIX_PL_String **pString,
293 void *plContext)
295 PKIX_PL_String *formatString = NULL;
296 PKIX_PL_String *descString = NULL;
297 char *format = "%s@Address: %x";
298 char *description = NULL;
299 PKIX_UInt32 objType;
301 PKIX_ENTER(OBJECT, "pkix_pl_Object_ToString_Default");
302 PKIX_NULLCHECK_TWO(object, pString);
304 PKIX_CHECK(PKIX_PL_Object_GetType(object, &objType, plContext),
305 PKIX_OBJECTGETTYPEFAILED);
307 if (objType >= PKIX_NUMTYPES){
308 #ifdef PKIX_USER_OBJECT_TYPE
309 pkix_ClassTable_Entry *ctEntry = NULL;
311 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
312 PR_Lock(classTableLock);
313 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
314 (classTable,
315 (void *)&objType,
316 objType,
317 NULL,
318 (void **)&ctEntry,
319 plContext);
320 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
321 PR_Unlock(classTableLock);
322 if (pkixErrorResult){
323 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY);
326 if (ctEntry == NULL){
327 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCLASSTABLEENTRY);
328 } else {
329 description = ctEntry->description;
330 if (description == NULL) {
331 description = "User Type Object";
334 #else
335 PORT_Assert (0);
336 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
337 pkixErrorClass = PKIX_FATAL_ERROR;
338 goto cleanup;
339 #endif /* PKIX_USER_OBJECT_TYPE */
340 } else {
341 description = systemClasses[objType].description;
343 PKIX_CHECK(PKIX_PL_String_Create
344 (PKIX_ESCASCII,
345 (void *)format,
347 &formatString,
348 plContext),
349 PKIX_STRINGCREATEFAILED);
351 PKIX_CHECK(PKIX_PL_String_Create
352 (PKIX_ESCASCII,
353 (void *)description,
355 &descString,
356 plContext),
357 PKIX_STRINGCREATEFAILED);
359 PKIX_CHECK(PKIX_PL_Sprintf
360 (pString,
361 plContext,
362 formatString,
363 descString,
364 object),
365 PKIX_SPRINTFFAILED);
367 cleanup:
369 PKIX_DECREF(formatString);
370 PKIX_DECREF(descString);
372 PKIX_RETURN(OBJECT);
376 * FUNCTION: pkix_pl_Object_Hashcode_Default
377 * DESCRIPTION:
379 * Default Object_Hashcode callback. Creates the a hashcode value using the
380 * address of the Object pointed to by "object" and stores the result at
381 * "pValue".
383 * XXX This isn't great since addresses are not uniformly distributed.
385 * PARAMETERS:
386 * "object"
387 * Address of Object to compute hashcode for. Must be non-NULL.
388 * "pValue"
389 * Address where PKIX_UInt32 will be stored. Must be non-NULL.
390 * "plContext"
391 * Platform-specific context pointer.
392 * THREAD SAFETY:
393 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
394 * RETURNS:
395 * Returns NULL if the function succeeds.
396 * Returns a Fatal Error if the function fails in an unrecoverable way.
398 static PKIX_Error *
399 pkix_pl_Object_Hashcode_Default(
400 PKIX_PL_Object *object,
401 PKIX_UInt32 *pValue,
402 void *plContext)
404 #ifdef NSS_USE_64
405 union {
406 void *pointer;
407 PKIX_UInt32 hilo[2];
408 } extracter;
409 #endif
411 PKIX_ENTER(OBJECT, "pkix_pl_Object_Hashcode_Default");
412 PKIX_NULLCHECK_TWO(object, pValue);
414 #ifdef NSS_USE_64
415 extracter.pointer = object;
416 *pValue = extracter.hilo[1];
417 #else
418 *pValue = (PKIX_UInt32)object;
419 #endif
421 PKIX_RETURN(OBJECT);
425 * FUNCTION: pkix_pl_Object_RetrieveEqualsCallback
426 * DESCRIPTION:
428 * Retrieves Equals callback function of Object pointed to by "object and
429 * stores it at "pEqualsCallback". If the object's type is one of the system
430 * types, its callback function is retrieved from the systemClasses array;
431 * otherwise, its callback function is retrieve from the classTable hash
432 * table where user-defined types are stored.
434 * PARAMETERS:
435 * "object"
436 * Address of Object whose equals callback is desired. Must be non-NULL.
437 * "pEqualsCallback"
438 * Address where EqualsCallback function pointer will be stored.
439 * Must be non-NULL.
440 * "plContext"
441 * Platform-specific context pointer.
442 * THREAD SAFETY:
443 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
444 * RETURNS:
445 * Returns NULL if the function succeeds.
446 * Returns an Object Error if the function fails in a non-fatal way.
447 * Returns a Fatal Error if the function fails in an unrecoverable way.
449 PKIX_Error *
450 pkix_pl_Object_RetrieveEqualsCallback(
451 PKIX_PL_Object *object,
452 PKIX_PL_EqualsCallback *pEqualsCallback,
453 void *plContext)
455 PKIX_PL_Object *objectHeader = NULL;
456 PKIX_PL_EqualsCallback func = NULL;
457 pkix_ClassTable_Entry entry;
458 PKIX_UInt32 objType;
460 PKIX_ENTER(OBJECT, "pkix_pl_Object_RetrieveEqualsCallback");
461 PKIX_NULLCHECK_TWO(object, pEqualsCallback);
463 PKIX_CHECK(pkix_pl_Object_GetHeader
464 (object, &objectHeader, plContext),
465 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
467 objType = objectHeader->type;
469 if (objType >= PKIX_NUMTYPES){
470 #ifdef PKIX_USER_OBJECT_TYPE
471 pkix_ClassTable_Entry *ctEntry = NULL;
473 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
474 PR_Lock(classTableLock);
475 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
476 (classTable,
477 (void *)&objType,
478 objType,
479 NULL,
480 (void **)&ctEntry,
481 plContext);
482 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
483 PR_Unlock(classTableLock);
484 if (pkixErrorResult){
485 PKIX_ERROR(PKIX_ERRORGETTINGCLASSTABLEENTRY);
488 if ((ctEntry == NULL) || (ctEntry->equalsFunction == NULL)) {
489 PKIX_ERROR(PKIX_UNDEFINEDEQUALSCALLBACK);
490 } else {
491 *pEqualsCallback = ctEntry->equalsFunction;
493 #else
494 PORT_Assert (0);
495 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
496 pkixErrorClass = PKIX_FATAL_ERROR;
497 goto cleanup;
498 #endif /* PKIX_USER_OBJECT_TYPE */
499 } else {
500 entry = systemClasses[objType];
501 func = entry.equalsFunction;
502 if (func == NULL){
503 func = pkix_pl_Object_Equals_Default;
505 *pEqualsCallback = func;
508 cleanup:
510 PKIX_RETURN(OBJECT);
514 * FUNCTION: pkix_pl_Object_RegisterSelf
515 * DESCRIPTION:
516 * Registers PKIX_OBJECT_TYPE and its related functions with systemClasses[]
517 * THREAD SAFETY:
518 * Not Thread Safe - for performance and complexity reasons
520 * Since this function is only called by PKIX_PL_Initialize, which should
521 * only be called once, it is acceptable that this function is not
522 * thread-safe.
524 * PKIX_PL_Object should have all function pointes to be to NULL: they
525 * work as proxy function to a real objects.
528 PKIX_Error *
529 pkix_pl_Object_RegisterSelf(void *plContext)
531 pkix_ClassTable_Entry entry;
533 PKIX_ENTER(ERROR, "pkix_pl_Object_RegisterSelf");
535 entry.description = "Object";
536 entry.objCounter = 0;
537 entry.typeObjectSize = sizeof(PKIX_PL_Object);
538 entry.destructor = NULL;
539 entry.equalsFunction = NULL;
540 entry.hashcodeFunction = NULL;
541 entry.toStringFunction = NULL;
542 entry.comparator = NULL;
543 entry.duplicateFunction = NULL;
545 systemClasses[PKIX_OBJECT_TYPE] = entry;
547 PKIX_RETURN(ERROR);
550 /* --Public-Functions------------------------------------------------------- */
553 * FUNCTION: PKIX_PL_Object_Alloc (see comments in pkix_pl_system.h)
555 PKIX_Error *
556 PKIX_PL_Object_Alloc(
557 PKIX_TYPENUM objType,
558 PKIX_UInt32 size,
559 PKIX_PL_Object **pObject,
560 void *plContext)
562 PKIX_PL_Object *object = NULL;
563 pkix_ClassTable_Entry *ctEntry = NULL;
565 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Alloc");
566 PKIX_NULLCHECK_ONE(pObject);
569 * We need to ensure that user-defined types have been registered.
570 * All system types have already been registered by PKIX_PL_Initialize.
573 if (objType >= PKIX_NUMTYPES) { /* i.e. if this is a user-defined type */
574 #ifdef PKIX_USER_OBJECT_TYPE
575 PKIX_Boolean typeRegistered;
576 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
577 PR_Lock(classTableLock);
578 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
579 (classTable,
580 (void *)&objType,
581 objType,
582 NULL,
583 (void **)&ctEntry,
584 plContext);
585 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
586 PR_Unlock(classTableLock);
587 if (pkixErrorResult){
588 PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE);
591 typeRegistered = (ctEntry != NULL);
593 if (!typeRegistered) {
594 PKIX_ERROR_FATAL(PKIX_UNKNOWNTYPEARGUMENT);
596 #else
597 PORT_Assert (0);
598 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
599 pkixErrorClass = PKIX_FATAL_ERROR;
600 goto cleanup;
601 #endif /* PKIX_USER_OBJECT_TYPE */
602 } else {
603 ctEntry = &systemClasses[objType];
606 PORT_Assert(size == ctEntry->typeObjectSize);
608 /* Allocate space for the object header and the requested size */
609 #ifdef PKIX_OBJECT_LEAK_TEST
610 PKIX_CHECK(PKIX_PL_Calloc
612 ((PKIX_UInt32)sizeof (PKIX_PL_Object))+size,
613 (void **)&object,
614 plContext),
615 PKIX_MALLOCFAILED);
616 #else
617 PKIX_CHECK(PKIX_PL_Malloc
618 (((PKIX_UInt32)sizeof (PKIX_PL_Object))+size,
619 (void **)&object,
620 plContext),
621 PKIX_MALLOCFAILED);
622 #endif /* PKIX_OBJECT_LEAK_TEST */
624 /* Initialize all object fields */
625 object->magicHeader = PKIX_MAGIC_HEADER;
626 object->type = objType;
627 object->references = 1; /* Default to a single reference */
628 object->stringRep = NULL;
629 object->hashcode = 0;
630 object->hashcodeCached = 0;
632 /* Cannot use PKIX_PL_Mutex because it depends on Object */
633 /* Using NSPR Locks instead */
634 PKIX_OBJECT_DEBUG("\tCalling PR_NewLock).\n");
635 object->lock = PR_NewLock();
636 if (object->lock == NULL) {
637 PKIX_ERROR_ALLOC_ERROR();
640 PKIX_OBJECT_DEBUG("\tShifting object pointer).\n");
643 /* Return a pointer to the user data. Need to offset by object size */
644 *pObject = object + 1;
645 object = NULL;
647 /* Atomically increment object counter */
648 PR_AtomicIncrement(&ctEntry->objCounter);
650 cleanup:
652 PKIX_FREE(object);
654 PKIX_RETURN(OBJECT);
658 * FUNCTION: PKIX_PL_Object_IsTypeRegistered (see comments in pkix_pl_system.h)
660 PKIX_Error *
661 PKIX_PL_Object_IsTypeRegistered(
662 PKIX_UInt32 objType,
663 PKIX_Boolean *pBool,
664 void *plContext)
666 #ifdef PKIX_USER_OBJECT_TYPE
667 pkix_ClassTable_Entry *ctEntry = NULL;
668 #endif
670 PKIX_ENTER(OBJECT, "PKIX_PL_Object_IsTypeRegistered");
671 PKIX_NULLCHECK_ONE(pBool);
673 /* first, we handle the system types */
674 if (objType < PKIX_NUMTYPES) {
675 *pBool = PKIX_TRUE;
676 goto cleanup;
679 #ifndef PKIX_USER_OBJECT_TYPE
680 PORT_Assert (0);
681 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
682 pkixErrorClass = PKIX_FATAL_ERROR;
683 #else
684 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
685 PR_Lock(classTableLock);
686 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
687 (classTable,
688 (void *)&objType,
689 objType,
690 NULL,
691 (void **)&ctEntry,
692 plContext);
693 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
694 PR_Unlock(classTableLock);
696 if (pkixErrorResult){
697 PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE);
700 *pBool = (ctEntry != NULL);
701 #endif /* PKIX_USER_OBJECT_TYPE */
703 cleanup:
705 PKIX_RETURN(OBJECT);
708 #ifdef PKIX_USER_OBJECT_TYPE
710 * FUNCTION: PKIX_PL_Object_RegisterType (see comments in pkix_pl_system.h)
712 PKIX_Error *
713 PKIX_PL_Object_RegisterType(
714 PKIX_UInt32 objType,
715 char *description,
716 PKIX_PL_DestructorCallback destructor,
717 PKIX_PL_EqualsCallback equalsFunction,
718 PKIX_PL_HashcodeCallback hashcodeFunction,
719 PKIX_PL_ToStringCallback toStringFunction,
720 PKIX_PL_ComparatorCallback comparator,
721 PKIX_PL_DuplicateCallback duplicateFunction,
722 void *plContext)
724 pkix_ClassTable_Entry *ctEntry = NULL;
725 pkix_pl_Integer *key = NULL;
727 PKIX_ENTER(OBJECT, "PKIX_PL_Object_RegisterType");
730 * System types are registered on startup by PKIX_PL_Initialize.
731 * These can not be overwritten.
734 if (objType < PKIX_NUMTYPES) { /* if this is a system type */
735 PKIX_ERROR(PKIX_CANTREREGISTERSYSTEMTYPE);
738 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
739 PR_Lock(classTableLock);
740 PKIX_CHECK(pkix_pl_PrimHashTable_Lookup
741 (classTable,
742 (void *)&objType,
743 objType,
744 NULL,
745 (void **)&ctEntry,
746 plContext),
747 PKIX_PRIMHASHTABLELOOKUPFAILED);
749 /* If the type is already registered, throw an error */
750 if (ctEntry) {
751 PKIX_ERROR(PKIX_TYPEALREADYREGISTERED);
754 PKIX_CHECK(PKIX_PL_Malloc
755 (((PKIX_UInt32)sizeof (pkix_ClassTable_Entry)),
756 (void **)&ctEntry,
757 plContext),
758 PKIX_MALLOCFAILED);
760 /* Set Default Values if none specified */
762 if (description == NULL){
763 description = "Object";
766 if (equalsFunction == NULL) {
767 equalsFunction = pkix_pl_Object_Equals_Default;
770 if (toStringFunction == NULL) {
771 toStringFunction = pkix_pl_Object_ToString_Default;
774 if (hashcodeFunction == NULL) {
775 hashcodeFunction = pkix_pl_Object_Hashcode_Default;
778 ctEntry->destructor = destructor;
779 ctEntry->equalsFunction = equalsFunction;
780 ctEntry->toStringFunction = toStringFunction;
781 ctEntry->hashcodeFunction = hashcodeFunction;
782 ctEntry->comparator = comparator;
783 ctEntry->duplicateFunction = duplicateFunction;
784 ctEntry->description = description;
786 PKIX_CHECK(PKIX_PL_Malloc
787 (((PKIX_UInt32)sizeof (pkix_pl_Integer)),
788 (void **)&key,
789 plContext),
790 PKIX_COULDNOTMALLOCNEWKEY);
792 key->ht_int = objType;
794 PKIX_CHECK(pkix_pl_PrimHashTable_Add
795 (classTable,
796 (void *)key,
797 (void *)ctEntry,
798 objType,
799 NULL,
800 plContext),
801 PKIX_PRIMHASHTABLEADDFAILED);
803 cleanup:
804 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
805 PR_Unlock(classTableLock);
807 PKIX_RETURN(OBJECT);
809 #endif /* PKIX_USER_OBJECT_TYPE */
812 * FUNCTION: PKIX_PL_Object_IncRef (see comments in pkix_pl_system.h)
814 PKIX_Error *
815 PKIX_PL_Object_IncRef(
816 PKIX_PL_Object *object,
817 void *plContext)
819 PKIX_PL_Object *objectHeader = NULL;
820 PKIX_PL_NssContext *context = NULL;
821 PKIX_Int32 refCount = 0;
823 PKIX_ENTER(OBJECT, "PKIX_PL_Object_IncRef");
824 PKIX_NULLCHECK_ONE(object);
826 if (plContext){
828 * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't
829 * have a header therefore we cannot verify its type before
830 * casting.
832 context = (PKIX_PL_NssContext *) plContext;
833 if (context->arena != NULL) {
834 goto cleanup;
838 if (object == (PKIX_PL_Object*)PKIX_ALLOC_ERROR()) {
839 goto cleanup;
842 /* Shift pointer from user data to object header */
843 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
844 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
846 /* This object should never have zero references */
847 refCount = PR_AtomicIncrement(&objectHeader->references);
849 if (refCount <= 1) {
850 PKIX_THROW(FATAL, PKIX_OBJECTWITHNONPOSITIVEREFERENCES);
853 cleanup:
855 PKIX_RETURN(OBJECT);
859 * FUNCTION: PKIX_PL_Object_DecRef (see comments in pkix_pl_system.h)
861 PKIX_Error *
862 PKIX_PL_Object_DecRef(
863 PKIX_PL_Object *object,
864 void *plContext)
866 PKIX_Int32 refCount = 0;
867 PKIX_PL_Object *objectHeader = NULL;
868 PKIX_PL_NssContext *context = NULL;
870 PKIX_ENTER(OBJECT, "PKIX_PL_Object_DecRef");
871 PKIX_NULLCHECK_ONE(object);
873 if (plContext){
875 * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't
876 * have a header therefore we cannot verify its type before
877 * casting.
879 context = (PKIX_PL_NssContext *) plContext;
880 if (context->arena != NULL) {
881 goto cleanup;
885 if (object == (PKIX_PL_Object*)PKIX_ALLOC_ERROR()) {
886 goto cleanup;
889 /* Shift pointer from user data to object header */
890 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
891 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
893 refCount = PR_AtomicDecrement(&objectHeader->references);
895 if (refCount == 0) {
896 PKIX_PL_DestructorCallback destructor = NULL;
897 pkix_ClassTable_Entry *ctEntry = NULL;
898 PKIX_UInt32 objType = objectHeader->type;
900 /* first, special handling for system types */
901 if (objType >= PKIX_NUMTYPES){
902 #ifdef PKIX_USER_OBJECT_TYPE
903 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
904 PR_Lock(classTableLock);
905 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
906 (classTable,
907 (void *)&objType,
908 objType,
909 NULL,
910 (void **)&ctEntry,
911 plContext);
912 PKIX_OBJECT_DEBUG
913 ("\tCalling PR_Unlock).\n");
914 PR_Unlock(classTableLock);
915 if (pkixErrorResult){
916 PKIX_ERROR_FATAL
917 (PKIX_ERRORINGETTINGDESTRUCTOR);
920 if (ctEntry != NULL){
921 destructor = ctEntry->destructor;
923 #else
924 PORT_Assert (0);
925 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
926 pkixErrorClass = PKIX_FATAL_ERROR;
927 goto cleanup;
928 #endif /* PKIX_USER_OBJECT_TYPE */
929 } else {
930 ctEntry = &systemClasses[objType];
931 destructor = ctEntry->destructor;
934 if (destructor != NULL){
935 /* Call destructor on user data if necessary */
936 pkixErrorResult = destructor(object, plContext);
937 if (pkixErrorResult) {
938 pkixErrorClass = PKIX_FATAL_ERROR;
939 PKIX_DoAddError(stdVarsPtr, pkixErrorResult, plContext);
940 pkixErrorResult = NULL;
944 /* Atomically decrement object counter */
945 PR_AtomicDecrement(&ctEntry->objCounter);
947 /* pkix_pl_Object_Destroy assumes the lock is held */
948 /* It will call unlock and destroy the object */
949 pkixErrorResult = pkix_pl_Object_Destroy(object, plContext);
950 goto cleanup;
953 if (refCount < 0) {
954 PKIX_ERROR_ALLOC_ERROR();
957 cleanup:
959 PKIX_RETURN(OBJECT);
965 * FUNCTION: PKIX_PL_Object_Equals (see comments in pkix_pl_system.h)
967 PKIX_Error *
968 PKIX_PL_Object_Equals(
969 PKIX_PL_Object *firstObject,
970 PKIX_PL_Object *secondObject,
971 PKIX_Boolean *pResult,
972 void *plContext)
974 PKIX_PL_Object *firstObjectHeader = NULL;
975 PKIX_PL_Object *secondObjectHeader = NULL;
976 PKIX_PL_EqualsCallback func = NULL;
977 pkix_ClassTable_Entry entry;
978 PKIX_UInt32 objType;
980 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Equals");
981 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
983 PKIX_CHECK(pkix_pl_Object_GetHeader
984 (firstObject, &firstObjectHeader, plContext),
985 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
987 PKIX_CHECK(pkix_pl_Object_GetHeader
988 (secondObject, &secondObjectHeader, plContext),
989 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
991 /* if hashcodes are cached but not equal, objects can't be equal */
992 if (firstObjectHeader->hashcodeCached &&
993 secondObjectHeader->hashcodeCached){
994 if (firstObjectHeader->hashcode !=
995 secondObjectHeader->hashcode){
996 *pResult = PKIX_FALSE;
997 goto cleanup;
1001 objType = firstObjectHeader->type;
1003 if (objType >= PKIX_NUMTYPES) {
1004 #ifdef PKIX_USER_OBJECT_TYPE
1005 pkix_ClassTable_Entry *ctEntry = NULL;
1006 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
1007 PR_Lock(classTableLock);
1008 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
1009 (classTable,
1010 (void *)&firstObjectHeader->type,
1011 firstObjectHeader->type,
1012 NULL,
1013 (void **)&ctEntry,
1014 plContext);
1015 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
1016 PR_Unlock(classTableLock);
1018 if (pkixErrorResult){
1019 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY);
1022 if ((ctEntry == NULL) || (ctEntry->equalsFunction == NULL)) {
1023 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
1024 } else {
1025 func = ctEntry->equalsFunction;
1027 #else
1028 PORT_Assert (0);
1029 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
1030 pkixErrorClass = PKIX_FATAL_ERROR;
1031 goto cleanup;
1032 #endif /* PKIX_USER_OBJECT_TYPE */
1033 } else {
1034 entry = systemClasses[objType];
1035 func = entry.equalsFunction;
1036 if (func == NULL){
1037 func = pkix_pl_Object_Equals_Default;
1041 PKIX_CHECK(func(firstObject, secondObject, pResult, plContext),
1042 PKIX_OBJECTSPECIFICFUNCTIONFAILED);
1044 cleanup:
1046 PKIX_RETURN(OBJECT);
1050 * FUNCTION: PKIX_PL_Object_Duplicate (see comments in pkix_pl_system.h)
1052 PKIX_Error *
1053 PKIX_PL_Object_Duplicate(
1054 PKIX_PL_Object *firstObject,
1055 PKIX_PL_Object **pNewObject,
1056 void *plContext)
1058 PKIX_PL_Object *firstObjectHeader = NULL;
1059 PKIX_PL_DuplicateCallback func = NULL;
1060 pkix_ClassTable_Entry entry;
1061 PKIX_UInt32 objType;
1063 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Duplicate");
1064 PKIX_NULLCHECK_TWO(firstObject, pNewObject);
1066 PKIX_CHECK(pkix_pl_Object_GetHeader
1067 (firstObject, &firstObjectHeader, plContext),
1068 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
1070 objType = firstObjectHeader->type;
1072 if (objType >= PKIX_NUMTYPES) {
1073 #ifdef PKIX_USER_OBJECT_TYPE
1074 pkix_ClassTable_Entry *ctEntry = NULL;
1076 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
1077 PR_Lock(classTableLock);
1078 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
1079 (classTable,
1080 (void *)&objType,
1081 objType,
1082 NULL,
1083 (void **)&ctEntry,
1084 plContext);
1085 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
1086 PR_Unlock(classTableLock);
1088 if (pkixErrorResult){
1089 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY);
1092 if ((ctEntry == NULL) || (ctEntry->duplicateFunction == NULL)) {
1093 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
1094 } else {
1095 func = ctEntry->duplicateFunction;
1097 #else
1098 PORT_Assert (0);
1099 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
1100 pkixErrorClass = PKIX_FATAL_ERROR;
1101 goto cleanup;
1102 #endif /* PKIX_USER_OBJECT_TYPE */
1103 } else {
1104 entry = systemClasses[objType];
1105 func = entry.duplicateFunction;
1106 if (!func){
1107 PKIX_ERROR_FATAL(PKIX_UNDEFINEDDUPLICATEFUNCTION);
1111 PKIX_CHECK(func(firstObject, pNewObject, plContext),
1112 PKIX_OBJECTSPECIFICFUNCTIONFAILED);
1114 cleanup:
1116 PKIX_RETURN(OBJECT);
1120 * FUNCTION: PKIX_PL_Object_Hashcode (see comments in pkix_pl_system.h)
1122 PKIX_Error *
1123 PKIX_PL_Object_Hashcode(
1124 PKIX_PL_Object *object,
1125 PKIX_UInt32 *pValue,
1126 void *plContext)
1128 PKIX_PL_Object *objectHeader = NULL;
1129 PKIX_PL_HashcodeCallback func = NULL;
1130 pkix_ClassTable_Entry entry;
1131 PKIX_UInt32 objectHash;
1133 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Hashcode");
1134 PKIX_NULLCHECK_TWO(object, pValue);
1136 /* Shift pointer from user data to object header */
1137 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
1138 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
1140 /* if we don't have a cached copy from before, we create one */
1141 if (!objectHeader->hashcodeCached){
1143 PKIX_UInt32 objType = objectHeader->type;
1145 /* first, special handling for system types */
1146 if (objType >= PKIX_NUMTYPES){
1147 #ifdef PKIX_USER_OBJECT_TYPE
1148 pkix_ClassTable_Entry *ctEntry = NULL;
1150 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
1151 PR_Lock(classTableLock);
1152 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
1153 (classTable,
1154 (void *)&objType,
1155 objType,
1156 NULL,
1157 (void **)&ctEntry,
1158 plContext);
1159 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
1160 PR_Unlock(classTableLock);
1162 if (pkixErrorResult){
1163 PKIX_ERROR_FATAL
1164 (PKIX_ERRORGETTINGCLASSTABLEENTRY);
1167 if ((ctEntry == NULL) ||
1168 (ctEntry->hashcodeFunction == NULL)) {
1169 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
1172 func = ctEntry->hashcodeFunction;
1173 #else
1174 PORT_Assert (0);
1175 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
1176 pkixErrorClass = PKIX_FATAL_ERROR;
1177 goto cleanup;
1178 #endif /* PKIX_USER_OBJECT_TYPE */
1179 } else {
1180 entry = systemClasses[objType];
1181 func = entry.hashcodeFunction;
1182 if (func == NULL){
1183 func = pkix_pl_Object_Hashcode_Default;
1187 PKIX_CHECK(func(object, &objectHash, plContext),
1188 PKIX_OBJECTSPECIFICFUNCTIONFAILED);
1190 if (!objectHeader->hashcodeCached){
1192 PKIX_CHECK(pkix_LockObject(object, plContext),
1193 PKIX_ERRORLOCKINGOBJECT);
1195 if (!objectHeader->hashcodeCached){
1196 /* save cached copy in case we need it again */
1197 objectHeader->hashcode = objectHash;
1198 objectHeader->hashcodeCached = PKIX_TRUE;
1201 PKIX_CHECK(pkix_UnlockObject(object, plContext),
1202 PKIX_ERRORUNLOCKINGOBJECT);
1206 *pValue = objectHeader->hashcode;
1208 cleanup:
1210 PKIX_RETURN(OBJECT);
1214 * FUNCTION: PKIX_PL_Object_ToString (see comments in pkix_pl_system.h)
1216 PKIX_Error *
1217 PKIX_PL_Object_ToString(
1218 PKIX_PL_Object *object,
1219 PKIX_PL_String **pString,
1220 void *plContext)
1222 PKIX_PL_Object *objectHeader = NULL;
1223 PKIX_PL_ToStringCallback func = NULL;
1224 pkix_ClassTable_Entry entry;
1225 PKIX_PL_String *objectString = NULL;
1227 PKIX_ENTER(OBJECT, "PKIX_PL_Object_ToString");
1228 PKIX_NULLCHECK_TWO(object, pString);
1230 /* Shift pointer from user data to object header */
1231 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
1232 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
1234 /* if we don't have a cached copy from before, we create one */
1235 if (!objectHeader->stringRep){
1237 PKIX_UInt32 objType = objectHeader->type;
1239 if (objType >= PKIX_NUMTYPES){
1240 #ifdef PKIX_USER_OBJECT_TYPE
1241 pkix_ClassTable_Entry *ctEntry = NULL;
1243 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
1244 PR_Lock(classTableLock);
1245 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
1246 (classTable,
1247 (void *)&objType,
1248 objType,
1249 NULL,
1250 (void **)&ctEntry,
1251 plContext);
1252 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
1253 PR_Unlock(classTableLock);
1254 if (pkixErrorResult){
1255 PKIX_ERROR_FATAL
1256 (PKIX_ERRORGETTINGCLASSTABLEENTRY);
1259 if ((ctEntry == NULL) ||
1260 (ctEntry->toStringFunction == NULL)) {
1261 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
1264 func = ctEntry->toStringFunction;
1265 #else
1266 PORT_Assert (0);
1267 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
1268 pkixErrorClass = PKIX_FATAL_ERROR;
1269 goto cleanup;
1270 #endif /* PKIX_USER_OBJECT_TYPE */
1271 } else {
1272 entry = systemClasses[objType];
1273 func = entry.toStringFunction;
1274 if (func == NULL){
1275 func = pkix_pl_Object_ToString_Default;
1279 PKIX_CHECK(func(object, &objectString, plContext),
1280 PKIX_OBJECTSPECIFICFUNCTIONFAILED);
1282 if (!objectHeader->stringRep){
1284 PKIX_CHECK(pkix_LockObject(object, plContext),
1285 PKIX_ERRORLOCKINGOBJECT);
1287 if (!objectHeader->stringRep){
1288 /* save a cached copy */
1289 objectHeader->stringRep = objectString;
1290 objectString = NULL;
1293 PKIX_CHECK(pkix_UnlockObject(object, plContext),
1294 PKIX_ERRORUNLOCKINGOBJECT);
1299 *pString = objectHeader->stringRep;
1300 objectHeader->stringRep = NULL;
1302 cleanup:
1303 if (objectHeader) {
1304 PKIX_DECREF(objectHeader->stringRep);
1306 PKIX_DECREF(objectString);
1308 PKIX_RETURN(OBJECT);
1312 * FUNCTION: PKIX_PL_Object_InvalidateCache (see comments in pkix_pl_system.h)
1314 PKIX_Error *
1315 PKIX_PL_Object_InvalidateCache(
1316 PKIX_PL_Object *object,
1317 void *plContext)
1319 PKIX_PL_Object *objectHeader = NULL;
1321 PKIX_ENTER(OBJECT, "PKIX_PL_Object_InvalidateCache");
1322 PKIX_NULLCHECK_ONE(object);
1324 /* Shift pointer from user data to object header */
1325 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
1326 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
1328 PKIX_CHECK(pkix_LockObject(object, plContext),
1329 PKIX_ERRORLOCKINGOBJECT);
1331 /* invalidate hashcode */
1332 objectHeader->hashcode = 0;
1333 objectHeader->hashcodeCached = PKIX_FALSE;
1335 PKIX_DECREF(objectHeader->stringRep);
1337 PKIX_CHECK(pkix_UnlockObject(object, plContext),
1338 PKIX_ERRORUNLOCKINGOBJECT);
1340 cleanup:
1342 PKIX_RETURN(OBJECT);
1346 * FUNCTION: PKIX_PL_Object_Compare (see comments in pkix_pl_system.h)
1348 PKIX_Error *
1349 PKIX_PL_Object_Compare(
1350 PKIX_PL_Object *firstObject,
1351 PKIX_PL_Object *secondObject,
1352 PKIX_Int32 *pResult,
1353 void *plContext)
1355 PKIX_PL_Object *firstObjectHeader = NULL;
1356 PKIX_PL_Object *secondObjectHeader = NULL;
1357 PKIX_PL_ComparatorCallback func = NULL;
1358 pkix_ClassTable_Entry entry;
1359 PKIX_UInt32 objType;
1361 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Compare");
1362 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
1364 /* Shift pointer from user data to object header */
1365 PKIX_CHECK(pkix_pl_Object_GetHeader
1366 (firstObject, &firstObjectHeader, plContext),
1367 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
1369 /* Shift pointer from user data to object header */
1370 PKIX_CHECK(pkix_pl_Object_GetHeader
1371 (secondObject, &secondObjectHeader, plContext),
1372 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
1374 objType = firstObjectHeader->type;
1376 if (objType >= PKIX_NUMTYPES){
1377 #ifdef PKIX_USER_OBJECT_TYPE
1378 pkix_ClassTable_Entry *ctEntry = NULL;
1380 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
1381 PR_Lock(classTableLock);
1382 pkixErrorResult = pkix_pl_PrimHashTable_Lookup
1383 (classTable,
1384 (void *)&objType,
1385 objType,
1386 NULL,
1387 (void **)&ctEntry,
1388 plContext);
1389 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
1390 PR_Unlock(classTableLock);
1391 if (pkixErrorResult){
1392 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY);
1395 if ((ctEntry == NULL) || (ctEntry->comparator == NULL)) {
1396 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCOMPARATOR);
1399 func = ctEntry->comparator;
1400 #else
1401 PORT_Assert (0);
1402 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
1403 pkixErrorClass = PKIX_FATAL_ERROR;
1404 goto cleanup;
1405 #endif /* PKIX_USER_OBJECT_TYPE */
1406 } else {
1407 /* special handling for system types */
1408 entry = systemClasses[objType];
1409 func = entry.comparator;
1410 if (!func){
1411 PKIX_ERROR(PKIX_UNDEFINEDCOMPARATOR);
1415 PKIX_CHECK(func(firstObject, secondObject, pResult, plContext),
1416 PKIX_OBJECTSPECIFICFUNCTIONFAILED);
1418 cleanup:
1420 PKIX_RETURN(OBJECT);
1424 * FUNCTION: PKIX_PL_Object_Lock (see comments in pkix_pl_system.h)
1426 PKIX_Error *
1427 PKIX_PL_Object_Lock(
1428 PKIX_PL_Object *object,
1429 void *plContext)
1431 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Lock");
1432 PKIX_NULLCHECK_ONE(object);
1434 PKIX_CHECK(pkix_LockObject(object, plContext),
1435 PKIX_LOCKOBJECTFAILED);
1437 cleanup:
1439 PKIX_RETURN(OBJECT);
1443 * FUNCTION: PKIX_PL_Object_Unlock (see comments in pkix_pl_system.h)
1445 PKIX_Error *
1446 PKIX_PL_Object_Unlock(
1447 PKIX_PL_Object *object,
1448 void *plContext)
1450 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Unlock");
1451 PKIX_NULLCHECK_ONE(object);
1453 PKIX_CHECK(pkix_UnlockObject(object, plContext),
1454 PKIX_UNLOCKOBJECTFAILED);
1456 cleanup:
1458 PKIX_RETURN(OBJECT);
1463 * FUNCTION: PKIX_PL_Object_GetType (see comments in pkix_pl_system.h)
1465 PKIX_Error *
1466 PKIX_PL_Object_GetType(
1467 PKIX_PL_Object *object,
1468 PKIX_UInt32 *pType,
1469 void *plContext)
1471 PKIX_PL_Object *objectHeader = NULL;
1473 PKIX_ENTER(OBJECT, "PKIX_PL_Object_GetType");
1474 PKIX_NULLCHECK_TWO(object, pType);
1476 /* Shift pointer from user data to object header */
1477 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
1478 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
1480 *pType = objectHeader->type;
1482 cleanup:
1484 PKIX_RETURN(OBJECT);