]> git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/c-lib/src/tbl-gen.c
Security-54.1.3.tar.gz
[apple/security.git] / SecuritySNACCRuntime / c-lib / src / tbl-gen.c
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 #ifdef TTBL
20 #include <stdio.h>
21 #include "tbl-gen.h"
22
23 typedef struct TagNLen
24 {
25 AsnTag tag;
26 AsnLen len;
27 unsigned int size; /* encoded len for this tag len pair */
28 } TagNLen;
29
30 #define TL_STK_SIZE 128
31
32 typedef struct STDEDecoder
33 {
34 TBL* tbl;
35 BUF_TYPE b;
36 ENV_TYPE env;
37 TagNLen tlStk[TL_STK_SIZE];
38 int nTlStk;
39 int rewindsize;
40 TdeTypeProc typeproc;
41 TdeSimpleProc simpleproc;
42 TdeExcProc excproc;
43 } * TDEDecoder;
44
45
46 #define TDEEXCEPTION(dec,code,p1,p2,p3) if ((dec)->excproc) if ((*(dec)->excproc)(code,p1,p2,p3)) longjmp((dec)->env,-236)
47
48 #define TDEERRORMSG(dec,msg) TDEEXCEPTION(dec,TDEERROR,msg,NULL,NULL)
49
50 #define TDEWARNUNEXPECTED(dec,type,elmtType) TDEEXCEPTION(dec,TDEUNEXPECTED,type,elmtType,NULL)
51 #define TDEWARNNONOPTIONAL(dec,type,elmtType) TDEEXCEPTION(dec,TDENONOPTIONAL,type,elmtType,NULL)
52 #define TDEWARNMANDATORY(dec,type) TDEEXCEPTION(dec,TDEMANDATORY,type,NULL,NULL)
53 #define TDEWARNCONSTRAINT(dec,type,cons,val) TDEEXCEPTION(dec,TDECONSTRAINT,type,cons,&val)
54 #define TDEWARNNOMATCH(dec,type,typetag,tag) TDEEXCEPTION(dec,TDENOMATCH,type,&typetag,&tag)
55
56 #define TDEINFOEOC(dec) TDEEXCEPTION(dec,TDEEOC,NULL,NULL,NULL)
57 #define TDEINFOPEEKTAG(dec,tag) TDEEXCEPTION(dec,TDEPEEKTAG,&tag,NULL,NULL)
58 #define TDEINFOPUSHTAG(dec,tag,len,size) TDEEXCEPTION(dec,TDEPUSHTAG,&tag,&len,&size)
59
60 #define TDETYPE(dec,type,val,begin) if (dec->typeproc) if ((*dec->typeproc)(type,val,begin)) longjmp(dec->env,-234)
61 #define TDESIMPLE(dec,tag,octs,begin) if (dec->simpleproc) if ((*dec->simpleproc)(tag,octs,begin)) longjmp(dec->env,-235)
62
63 #define LAST_TAG() (dec->tlStk[dec->nTlStk-1-dec->rewindsize].tag)
64 #define LAST_LEN() (dec->tlStk[dec->nTlStk-1-dec->rewindsize].len)
65 #define LAST_SIZE() (dec->tlStk[dec->nTlStk-1-dec->rewindsize].size)
66
67 AsnTag
68 TDEPeekTag PARAMS ((dec),
69 TDEDecoder dec)
70 {
71 AsnTag tag;
72 if (dec->rewindsize)
73 tag = dec->tlStk[dec->nTlStk-dec->rewindsize].tag;
74 else
75 tag = PeekTag(dec->b,dec->env);
76 TDEINFOPEEKTAG(dec,tag);
77 return tag;
78 }
79
80 AsnTag
81 TDEPushTag PARAMS ((dec),
82 TDEDecoder dec)
83 {
84 if (dec->rewindsize)
85 dec->rewindsize--;
86 else
87 {
88 unsigned long encSize = 0;
89 if (dec->nTlStk >= TL_STK_SIZE)
90 longjmp (dec->env, -1000);
91 dec->tlStk[dec->nTlStk].tag = BDecTag (dec->b, &encSize, dec->env);
92 dec->tlStk[dec->nTlStk].len = BDecLen (dec->b, &encSize, dec->env);
93 dec->tlStk[dec->nTlStk++].size = encSize;
94 TDEINFOPUSHTAG(dec,LAST_TAG(),LAST_LEN(),LAST_SIZE());
95 }
96 return LAST_TAG();
97 }
98
99 void
100 TDEDoPop PARAMS ((dec),
101 TDEDecoder dec)
102 {
103 dec->nTlStk--;
104 if (dec->nTlStk < 0)
105 longjmp (dec->env, -1001);
106 }
107
108 void
109 TDEPopTag PARAMS ((dec, bytesDecoded),
110 TDEDecoder dec _AND_
111 unsigned long int *bytesDecoded)
112 {
113 if (LAST_LEN()==INDEFINITE_LEN)
114 {
115 BDecEoc (dec->b, bytesDecoded, dec->env);
116 TDEINFOEOC(dec);
117 }
118 else if (*bytesDecoded != LAST_LEN())
119 {
120 TDEERRORMSG(dec,"Lost BER synchronisation");
121 longjmp (dec->env, -1003);
122 }
123 (*bytesDecoded) += LAST_SIZE();
124 TDEDoPop(dec);
125 }
126
127 void
128 TDECheckConstraint PARAMS ((dec, type, constraint, value),
129 TDEDecoder dec _AND_
130 TBLType* type _AND_
131 TBLRange* constraint _AND_
132 AsnInt value)
133 {
134 if (constraint && (value<constraint->from || value>constraint->to))
135 TDEWARNCONSTRAINT(dec,type,constraint,value);
136 }
137
138 int
139 TDEInTag PARAMS ((dec, bytesDecodedInTag),
140 TDEDecoder dec _AND_
141 unsigned long int bytesDecodedInTag)
142 {
143 return LAST_LEN()==INDEFINITE_LEN? !PeekEoc(dec->b): (bytesDecodedInTag<LAST_LEN());
144 }
145
146 int
147 TDECountMandatoryElmts PARAMS ((type),
148 TBLType *type)
149 {
150 TBLType *elmtType;
151 int count = 0;
152 FOR_EACH_LIST_ELMT (elmtType, type->content->a.elmts)
153 {
154 if (!elmtType->optional)
155 count++;
156 }
157 return count;
158 }
159
160 void
161 TDESimpleDecode PARAMS ((dec, bytesDecoded),
162 TDEDecoder dec _AND_
163 unsigned long int *bytesDecoded)
164 {
165 AsnTag tag = TDEPushTag(dec);
166 unsigned long int bytesDecodedInTag = 0;
167
168 BER_CLASS tclass = TAG_ID_CLASS(tag);
169 BER_FORM form = TAG_ID_FORM(tag);
170 unsigned long int code = tag & 0x1FFFFFFF;
171 BER_UNIV_CODE bcode;
172 if (tclass==UNIV)
173 bcode = code>>24;
174 else
175 bcode = OCTETSTRING_TAG_CODE;
176
177 if (TAG_IS_CONS(tag))
178 {
179 TDESIMPLE(dec,tag,NULL,1);
180 while (TDEInTag(dec,bytesDecodedInTag))
181 {
182 TDESimpleDecode (dec, &bytesDecodedInTag);
183 }
184 TDESIMPLE(dec,tag,NULL,0);
185 }
186 else
187 {
188 PrintableString v;
189 switch (bcode)
190 {
191 case INTEGER_TAG_CODE:
192 case OCTETSTRING_TAG_CODE:
193 default:
194 v.octetLen = LAST_LEN();
195 v.octs = Asn1Alloc(v.octetLen);
196 BufCopy(v.octs,dec->b,v.octetLen);
197 TDESIMPLE(dec,tag,&v,1);
198 Asn1Free(v.octs);
199 break;
200 }
201 bytesDecodedInTag += LAST_LEN();
202 }
203 TDEPopTag(dec,&bytesDecodedInTag);
204 *bytesDecoded += bytesDecodedInTag;
205 }
206
207 int
208 TDEPushTagsAndLens PARAMS ((dec, type, implicit),
209 TDEDecoder dec _AND_
210 TBLType *type _AND_
211 int implicit)
212 {
213 AsnTag tag;
214 AsnLen len;
215 AsnLen encSize;
216 TBLTag *tblTag;
217 int fullMatch = TRUE;
218 int origTLG = dec->nTlStk;
219 int origRewindsize = dec->rewindsize;
220
221 if ((type->tagList == NULL) || (LIST_EMPTY (type->tagList)))
222 return TRUE;
223
224 SET_CURR_LIST_NODE (type->tagList, FIRST_LIST_NODE (type->tagList));
225 if (implicit)
226 {
227 SET_CURR_LIST_NODE (type->tagList, NEXT_LIST_NODE (type->tagList));
228 }
229
230 FOR_REST_LIST_ELMT (tblTag, type->tagList)
231 {
232 tag = TDEPushTag(dec);
233 if (!TagsEquiv (tag, tblTag))
234 {
235 /*
236 * Whoops! The expected tags do not completely fit! So what to do?
237 *
238 * This is a complicated situation since might have already read some
239 * tags from the buffer (and pushed), but now we should return failure
240 * AND REWIND TO THE STATE WE WERE IN WHEN CALLED,
241 * so that future PeekTag and then TblDecodeTagsAndLens calls start
242 * off there again!
243 *
244 * The idea is to modify PeekTag and this routine to first check
245 * whether there is information pending that was read already.
246 *
247 * Luckily, this can not happen recursively, only in sequence:
248 * ... -> ...
249 * ... -> Tags fit -> Tags fit -> ...
250 * ... -> Tags fit -> Tags fit -> ...
251 * Tags fit -> ...
252 * Tags don't fit -<
253 * Tags don't fit -<
254 * Complete subtype decoding remaining tags in simple manner
255 * <-
256 * Tags don't fit -<
257 * Tags fit -> ...
258 * Complete subtype decoding remaining tags in simple manner
259 * <-
260 * ...
261 */
262 fullMatch = FALSE;
263 dec->rewindsize = origRewindsize + dec->nTlStk - origTLG;
264 TDEWARNNOMATCH(dec,type,tblTag->encTag,tag);
265 break;
266 }
267 }
268 if (fullMatch)
269 dec->rewindsize = 0;
270 return fullMatch;
271 }
272
273 void
274 TDEPopTagsAndLens PARAMS ((dec, bytesDecoded, type, implicit),
275 TDEDecoder dec _AND_
276 unsigned long int *bytesDecoded _AND_
277 TBLType *type _AND_
278 int implicit)
279 {
280 TBLTag *tblTag;
281 if (dec->rewindsize)
282 TDEERRORMSG(dec,"Still rewinding at end of tag");
283 FOR_EACH_LIST_ELMT_RVS (tblTag, type->tagList)
284 {
285 if (implicit && (tblTag == FIRST_LIST_ELMT (type->tagList)))
286 break;
287 TDEPopTag(dec,bytesDecoded);
288 }
289 }
290
291 int
292 TDETagsMatch PARAMS ((type, asnTag),
293 TBLType *type _AND_
294 AsnTag asnTag)
295 {
296 TBLType *tmpTblT;
297 TBLType *elmtTblT;
298 TBLTag *tblTag;
299 void *tmp;
300
301 /*
302 * skip through type refs until encounter first tag or
303 * untagged CHOICE (only TYPEREFs and CHOICEs can
304 * have empty tag lists).
305 */
306 for (tmpTblT = type; ((tmpTblT->typeId == TBL_TYPEREF) &&
307 ((tmpTblT->tagList == NULL) || LIST_EMPTY (tmpTblT->tagList)));
308 )
309 tmpTblT = tmpTblT->content->a.typeRef->typeDefPtr->type;
310
311 /*
312 * if untagged CHOICE must check for a match with the first tag
313 * of each component of the CHOICE
314 */
315 if ((tmpTblT->typeId == TBL_CHOICE) &&
316 ((tmpTblT->tagList == NULL) || LIST_EMPTY (tmpTblT->tagList)))
317 {
318 tmp = CURR_LIST_NODE (tmpTblT->content->a.elmts);
319 FOR_EACH_LIST_ELMT (elmtTblT, tmpTblT->content->a.elmts)
320 {
321 /*
322 * remember the elmt type can be an untagged choice too
323 * so call TagsMatch again.
324 */
325 if (TagsMatch (elmtTblT, asnTag))
326 {
327 SET_CURR_LIST_NODE (tmpTblT->content->a.elmts, tmp);
328 return TRUE; /* match in choice */
329 }
330 }
331 SET_CURR_LIST_NODE (tmpTblT->content->a.elmts, tmp);
332 return FALSE; /* no match in choice */
333 }
334 else /* is type other than untagged choice or type ref */
335 {
336 int result;
337 tblTag = FIRST_LIST_ELMT (tmpTblT->tagList);
338 result = TagsEquiv (asnTag, tblTag);
339 return result;
340 }
341 }
342
343 int
344 TDEDecodeType PARAMS ((dec, bytesDecoded, type, implicit, constraint),
345 TDEDecoder dec _AND_
346 unsigned long int *bytesDecoded _AND_
347 TBLType *type _AND_
348 int implicit _AND_
349 TBLRange* constraint)
350 {
351 AVal *elmtVPtr;
352 unsigned long int tmpBytesDecoded = 0;
353 unsigned int currElmt;
354 TBLType *elmtType;
355 AVal *retVal = NULL;
356 AVal *eleVal;
357 AVal **tmpHndl;
358 AsnTag asnTag;
359 int i, mandatoryCount, mandatoryElmts;
360 int implicitRef;
361 void *tmp;
362 AsnInt value;
363 char* constraintmsg = NULL;
364 int elmtfound;
365 int indefinite;
366
367 if (!TDEPushTagsAndLens (dec, type, implicit))
368 return FALSE;
369
370 #if TTBL>1
371 if (!constraint)
372 constraint = type->constraint;
373 #endif
374
375 TDETYPE(dec,type,NULL,1);
376
377 switch (type->typeId)
378 {
379 case TBL_TYPEREF:
380 /*
381 * carry over implicit ref if goes
382 * through typeref with no tags
383 */
384 implicitRef = type->content->a.typeRef->implicit ||
385 (implicit &&
386 ((type->tagList == NULL) || LIST_EMPTY (type->tagList)));
387
388 if (!TDEDecodeType (dec, &tmpBytesDecoded,
389 type->content->a.typeRef->typeDefPtr->type,
390 implicitRef, constraint))
391 {
392 TDEWARNUNEXPECTED(dec,type,type->content->a.typeRef->typeDefPtr->type);
393 TDESimpleDecode(dec, &tmpBytesDecoded);
394 }
395 break;
396
397 case TBL_SEQUENCE:
398 /* go fwd though elmt type list */
399 tmp = CURR_LIST_NODE (type->content->a.elmts);
400 FOR_EACH_LIST_ELMT (elmtType, type->content->a.elmts)
401 {
402 elmtfound = FALSE;
403 while (!elmtfound
404 && TDEInTag(dec,tmpBytesDecoded)
405 && TDETagsMatch (elmtType, TDEPeekTag (dec)))
406 elmtfound = TDEDecodeType (dec,&tmpBytesDecoded,
407 elmtType, FALSE, NULL);
408 if (!elmtfound && !elmtType->optional)
409 TDEWARNNONOPTIONAL(dec,type,elmtType);
410 }
411 SET_CURR_LIST_NODE (type->content->a.elmts, tmp);
412
413 /* process remaining stuff in sequence */
414 while (TDEInTag(dec,tmpBytesDecoded))
415 {
416 TDEWARNUNEXPECTED(dec,type,NULL);
417 TDESimpleDecode(dec, &tmpBytesDecoded);
418 }
419 break;
420
421 case TBL_SET:
422 mandatoryCount = 0;
423 mandatoryElmts = TDECountMandatoryElmts (type);
424 while (TDEInTag(dec,tmpBytesDecoded))
425 {
426 asnTag = TDEPeekTag (dec);
427 elmtfound = FALSE;
428 /* find elmt that matches the peeked tag */
429 tmp = CURR_LIST_NODE (type->content->a.elmts);
430 FOR_EACH_LIST_ELMT (elmtType,
431 type->content->a.elmts)
432 {
433 if (TDETagsMatch (elmtType, asnTag))
434 {
435 elmtfound = TRUE;
436 break;
437 }
438 }
439 SET_CURR_LIST_NODE (type->content->a.elmts, tmp);
440
441 /* didn't find a match */
442 if (!elmtfound || !TDEDecodeType (dec, &tmpBytesDecoded,
443 elmtType, FALSE, NULL))
444 {
445 TDEWARNUNEXPECTED(dec,type,elmtfound?elmtType:NULL);
446 TDESimpleDecode(dec, &tmpBytesDecoded);
447 }
448 else
449 {
450 if (!elmtType->optional)
451 mandatoryCount++;
452 }
453
454 }
455 if (mandatoryCount != mandatoryElmts)
456 TDEWARNMANDATORY(dec,type);
457 break;
458
459
460 case TBL_SEQUENCEOF:
461 case TBL_SETOF:
462 elmtType = FIRST_LIST_ELMT (type->content->a.elmts);
463 constraintmsg = "Size of SEQUENCE/SET OF";
464 value = 0;
465
466 while (TDEInTag(dec,tmpBytesDecoded))
467 {
468 if (!TDEDecodeType (dec, &tmpBytesDecoded, elmtType,
469 FALSE,NULL))
470 {
471 TDEWARNUNEXPECTED(dec,type,elmtType);
472 TDESimpleDecode(dec, &tmpBytesDecoded);
473 }
474 else
475 value++;
476 }
477 break;
478
479 case TBL_CHOICE:
480 elmtfound = FALSE;
481 if (TDEInTag(dec,tmpBytesDecoded))
482 {
483 asnTag = TDEPeekTag (dec);
484 /* find elmt that matches the peeked tag */
485 tmp = CURR_LIST_NODE (type->content->a.elmts);
486 FOR_EACH_LIST_ELMT (elmtType, type->content->a.elmts)
487 {
488 if (TDETagsMatch (elmtType, asnTag))
489 {
490 elmtfound = TRUE;
491 break;
492 }
493 }
494 }
495 SET_CURR_LIST_NODE (type->content->a.elmts, tmp);
496 if (!elmtfound || !TDEDecodeType (dec, &tmpBytesDecoded,
497 elmtType, FALSE, NULL))
498 {
499 TDEWARNUNEXPECTED(dec,type,elmtfound?elmtType:NULL);
500 TDESimpleDecode(dec, &tmpBytesDecoded);
501 }
502 break;
503
504 case TBL_BOOLEAN:
505 retVal = Asn1Alloc (sizeof (AsnBool));
506 BDecAsnBoolContent (dec->b, LAST_TAG(), LAST_LEN(),
507 (AsnBool*) retVal, &tmpBytesDecoded, dec->env);
508 break;
509
510 case TBL_INTEGER:
511 case TBL_ENUMERATED:
512 retVal = Asn1Alloc (sizeof (AsnInt));
513 BDecAsnIntContent (dec->b, LAST_TAG(), LAST_LEN(),
514 (AsnInt*) retVal, &tmpBytesDecoded, dec->env);
515 constraintmsg = "INTEGER/ENUMERATED";
516 value = *(AsnInt*)retVal;
517 break;
518
519 case TBL_BITSTRING:
520 retVal = Asn1Alloc (sizeof (AsnBits));
521 BDecAsnBitsContent (dec->b, LAST_TAG(), LAST_LEN(),
522 (AsnBits*) retVal, &tmpBytesDecoded, dec->env);
523 break;
524
525 case TBL_OCTETSTRING:
526 retVal = Asn1Alloc (sizeof (AsnOcts));
527 BDecAsnOctsContent (dec->b, LAST_TAG(), LAST_LEN(),
528 (AsnOcts*) retVal, &tmpBytesDecoded, dec->env);
529 constraintmsg = "Length of OCTET STRING";
530 value = ((AsnOcts*)retVal)->octetLen;
531 break;
532
533 case TBL_NULL:
534 retVal = Asn1Alloc (sizeof (AsnNull));
535 BDecAsnNullContent (dec->b, LAST_TAG(), LAST_LEN(),
536 (AsnNull*) retVal, &tmpBytesDecoded, dec->env);
537 break;
538
539 case TBL_OID:
540 retVal = Asn1Alloc (sizeof (AsnOid));
541 BDecAsnOidContent (dec->b, LAST_TAG(), LAST_LEN(),
542 (AsnOid*) retVal, &tmpBytesDecoded, dec->env);
543 break;
544
545 case TBL_REAL:
546 retVal = Asn1Alloc (sizeof (AsnReal));
547 BDecAsnRealContent (dec->b, LAST_TAG(), LAST_LEN(),
548 (AsnReal*) retVal, &tmpBytesDecoded, dec->env);
549 break;
550
551 default:
552 retVal = NULL;
553 break;
554 }
555
556 TDETYPE(dec,type,retVal,0);
557 if (retVal)
558 Asn1Free(retVal);
559
560 if (constraintmsg)
561 TDECheckConstraint(dec,type,constraint,value);
562
563 TDEPopTagsAndLens (dec, &tmpBytesDecoded, type, implicit);
564 (*bytesDecoded) += tmpBytesDecoded;
565 return TRUE;
566 }
567
568 int
569 TDEDecodeSpecific PARAMS ((dec, bytesDecoded, type),
570 TDEDecoder dec _AND_
571 unsigned long int *bytesDecoded _AND_
572 TBLType* type)
573 {
574 int val;
575
576 *bytesDecoded = 0;
577 dec->rewindsize = 0;
578 dec->nTlStk = 0;
579
580 if ((val = setjmp (dec->env)) == 0)
581 {
582 TDEDecodeType (dec, bytesDecoded, type, FALSE, NULL);
583 return TRUE;
584 }
585 return FALSE;
586 }
587
588 int
589 TDEDecodeUnknown PARAMS ((dec, bytesDecoded),
590 TDEDecoder dec _AND_
591 unsigned long int *bytesDecoded)
592 {
593 TBLModule *tblMod = NULL;
594 TBLTypeDef *tblTd = NULL;
595
596 *bytesDecoded = 0;
597
598 FOR_EACH_LIST_ELMT (tblMod, dec->tbl->modules)
599 break;
600 if (!tblMod)
601 {
602 TDEERRORMSG (dec,"No module in grammar");
603 return FALSE;
604 }
605
606 FOR_EACH_LIST_ELMT_RVS (tblTd, tblMod->typeDefs)
607 break;
608 if (!tblTd)
609 {
610 TDEERRORMSG (dec,"No type in first module of grammar");
611 return FALSE;
612 }
613
614 return TDEDecodeSpecific (dec, bytesDecoded, tblTd->type);
615 }
616
617 struct STDEDecoder sdec;
618
619 void
620 TDEErrorHandler PARAMS ((str, severity),
621 char* str _AND_
622 int severity)
623 {
624 TDEERRORMSG(&sdec,str);
625 }
626
627 int
628 TdeDecodeSpecific PARAMS ((tbl, b, type, bytesDecoded, typeproc, simpleproc, excproc),
629 TBL *tbl _AND_
630 BUF_TYPE b _AND_
631 TBLType* type _AND_
632 unsigned long int *bytesDecoded _AND_
633 TdeTypeProc typeproc _AND_
634 TdeSimpleProc simpleproc _AND_
635 TdeExcProc excproc)
636 {
637 int result;
638 Asn1ErrorHandler former = Asn1InstallErrorHandler(TDEErrorHandler);
639 sdec.tbl = tbl;
640 sdec.b = b;
641 sdec.typeproc = typeproc;
642 sdec.simpleproc = simpleproc;
643 sdec.excproc = excproc;
644 result = TDEDecodeSpecific(&sdec,bytesDecoded,type);
645 Asn1InstallErrorHandler(former);
646 return result;
647 }
648
649 int
650 TdeDecode PARAMS ((tbl, b, bytesDecoded, typeproc, simpleproc, excproc),
651 TBL *tbl _AND_
652 BUF_TYPE b _AND_
653 unsigned long int *bytesDecoded _AND_
654 TdeTypeProc typeproc _AND_
655 TdeSimpleProc simpleproc _AND_
656 TdeExcProc excproc)
657 {
658 int result;
659 Asn1ErrorHandler former = Asn1InstallErrorHandler(TDEErrorHandler);
660 sdec.tbl = tbl;
661 sdec.b = b;
662 sdec.typeproc = typeproc;
663 sdec.simpleproc = simpleproc;
664 sdec.excproc = excproc;
665 result = TDEDecodeUnknown(&sdec,bytesDecoded);
666 Asn1InstallErrorHandler(former);
667 return result;
668 }
669 #endif