VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/asn1/asn1-ut-objid.cpp@ 95624

Last change on this file since 95624 was 95624, checked in by vboxsync, 2 years ago

IPRT/RTAsn1,RTCrSpc: Generate setter functions for RTASN1TMPL_MEMBER_OPT_XTAG_EX and RTASN1TMPL_MEMBER_OPT_ITAG_EX members. Added setter prototypes to the spc.h header. bugref:8691

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.3 KB
Line 
1/* $Id: asn1-ut-objid.cpp 95624 2022-07-13 20:31:41Z vboxsync $ */
2/** @file
3 * IPRT - ASN.1, OBJECT IDENTIFIER Type.
4 */
5
6/*
7 * Copyright (C) 2006-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include "internal/iprt.h"
32#include <iprt/asn1.h>
33
34#include <iprt/alloca.h>
35#include <iprt/bignum.h>
36#include <iprt/ctype.h>
37#include <iprt/err.h>
38#include <iprt/string.h>
39#include <iprt/uni.h>
40
41#include <iprt/formats/asn1.h>
42
43
44/*********************************************************************************************************************************
45* Global Variables *
46*********************************************************************************************************************************/
47static char const g_szDefault[] = "2.16.840.1.113894";
48static uint32_t const g_auDefault[] = { 2, 16, 840, 1, 113894 };
49static uint8_t const g_abDefault[] =
50{
51 2*40 + 16, 0x80 | (840 >> 7), 840 & 0x7f, 1, 0x80 | (113894 >> 14), 0x80 | ((113894 >> 7) & 0x7f), 113894 & 0x7f
52};
53
54
55/*********************************************************************************************************************************
56* Internal Functions *
57*********************************************************************************************************************************/
58DECLHIDDEN(int) rtAsn1ObjId_InternalFormatComponent(uint32_t uValue, char **ppszObjId, size_t *pcbObjId); /* asn1-ut-objid.cpp */
59/** @todo check if we really need this. */
60
61
62
63/*
64 * ASN.1 OBJECT IDENTIFIER - Special Methods.
65 */
66
67/**
68 * Encodes the ASN.1 byte sequence for a set of components.
69 *
70 * @returns IPRT status code.
71 * @param cComponents The number of components. Must be at least two.
72 * @param pauComponents The components array.
73 * @param pbEncoded The output buffer.
74 * @param pcbEncoded On input, this holds the size of the output buffer.
75 * On successful return it's the encoded size in bytes.
76 */
77static int rtAsn1ObjId_EncodeComponents(uint32_t cComponents, uint32_t const *pauComponents,
78 uint8_t *pbEncoded, uint32_t *pcbEncoded)
79{
80 uint8_t *pbCur = pbEncoded;
81 uint32_t cbLeft = *pcbEncoded;
82
83 /* The first two componets are encoded together to save a byte, so the loop
84 organization is a little special. */
85 AssertReturn(cComponents >= 2, VERR_ASN1_INTERNAL_ERROR_1);
86 AssertReturn(pauComponents[0] <= 2, VERR_ASN1_INTERNAL_ERROR_1);
87 AssertReturn(pauComponents[1] <= (pauComponents[0] < 2 ? 39 : UINT32_MAX - 80), VERR_ASN1_INTERNAL_ERROR_1);
88 uint32_t i = 1;
89 uint32_t uValue = pauComponents[0] * 40 + pauComponents[1];
90
91 for (;;)
92 {
93 if (uValue < 0x80)
94 {
95 if (RT_UNLIKELY(cbLeft < 1))
96 return VERR_BUFFER_OVERFLOW;
97 cbLeft -= 1;
98 *pbCur++ = (uint8_t)uValue;
99 }
100 else if (uValue < 0x4000)
101 {
102 if (RT_UNLIKELY(cbLeft < 2))
103 return VERR_BUFFER_OVERFLOW;
104 cbLeft -= 2;
105 pbCur[0] = (uValue >> 7) | 0x80;
106 pbCur[1] = uValue & 0x7f;
107 pbCur += 2;
108 }
109 else if (uValue < 0x200000)
110 {
111 if (RT_UNLIKELY(cbLeft < 3))
112 return VERR_BUFFER_OVERFLOW;
113 cbLeft -= 3;
114 pbCur[0] = (uValue >> 14) | 0x80;
115 pbCur[1] = ((uValue >> 7) & 0x7f) | 0x80;
116 pbCur[2] = uValue & 0x7f;
117 pbCur += 3;
118 }
119 else if (uValue < 0x10000000)
120 {
121 if (RT_UNLIKELY(cbLeft < 4))
122 return VERR_BUFFER_OVERFLOW;
123 cbLeft -= 4;
124 pbCur[0] = (uValue >> 21) | 0x80;
125 pbCur[1] = ((uValue >> 14) & 0x7f) | 0x80;
126 pbCur[2] = ((uValue >> 7) & 0x7f) | 0x80;
127 pbCur[3] = uValue & 0x7f;
128 pbCur += 4;
129 }
130 else
131 {
132 if (RT_UNLIKELY(cbLeft < 5))
133 return VERR_BUFFER_OVERFLOW;
134 cbLeft -= 5;
135 pbCur[0] = (uValue >> 28) | 0x80;
136 pbCur[1] = ((uValue >> 21) & 0x7f) | 0x80;
137 pbCur[2] = ((uValue >> 14) & 0x7f) | 0x80;
138 pbCur[3] = ((uValue >> 7) & 0x7f) | 0x80;
139 pbCur[4] = uValue & 0x7f;
140 pbCur += 5;
141 }
142
143 /* Advance / return. */
144 i++;
145 if (i >= cComponents)
146 {
147 *pcbEncoded = (uint32_t)(pbCur - pbEncoded);
148 return VINF_SUCCESS;
149 }
150 uValue = pauComponents[i];
151 }
152}
153
154
155RTDECL(int) RTAsn1ObjId_InitFromString(PRTASN1OBJID pThis, const char *pszObjId, PCRTASN1ALLOCATORVTABLE pAllocator)
156{
157 RT_ZERO(*pThis);
158
159 /*
160 * Check the string, counting the number of components and checking their validity.
161 */
162 size_t cbObjId = strlen(pszObjId) + 1;
163 AssertReturn(cbObjId < sizeof(pThis->szObjId), VERR_ASN1_OBJID_TOO_LONG_STRING_FORM);
164
165 const char *psz = pszObjId;
166
167 /* Special checking of the first component. It has only three valid values: 0,1,2. */
168 char ch = *psz++;
169 if (RT_UNLIKELY(ch < '0' || ch > '2'))
170 return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
171 char const chFirst = ch;
172 ch = *psz++;
173 if (RT_UNLIKELY(ch != '.'))
174 return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
175
176 /* The 2nd component. It the first is 0 or 1, it has a max of 39. */
177 uint32_t cComponents = 1;
178 if (chFirst < '2')
179 {
180 ch = *psz++;
181 if (*psz == '.')
182 {
183 if (RT_UNLIKELY(!RT_C_IS_DIGIT(ch)))
184 return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
185 }
186 else
187 {
188 if (RT_UNLIKELY(ch < '0' || ch > '3'))
189 return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
190 ch = *psz++;
191 if (RT_UNLIKELY(!RT_C_IS_DIGIT(ch)))
192 return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
193 if (*psz != '.')
194 return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
195 }
196 cComponents++;
197 }
198 else
199 psz--;
200
201 /* Subsequent components have max values of UINT32_MAX - 80. */
202 while ((ch = *psz++) != '\0')
203 {
204 if (RT_UNLIKELY(ch != '.'))
205 return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
206 const char *pszStart = psz;
207
208 /* Special treatment of the first digit. Need to make sure it isn't an
209 unnecessary leading 0. */
210 ch = *psz++;
211 if (RT_UNLIKELY(!RT_C_IS_DIGIT(ch)))
212 return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
213 if (RT_UNLIKELY(ch == '0' && RT_C_IS_DIGIT(*psz)))
214 return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
215
216 /* The rest of the digits. */
217 while ((ch = *psz) != '.' && ch != '\0')
218 {
219 if (RT_UNLIKELY(!RT_C_IS_DIGIT(ch)))
220 return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
221 psz++;
222 }
223
224 /* Check the value range. */
225 if (RT_UNLIKELY(psz - pszStart >= 9))
226 if ( psz - pszStart > 9
227 || strncmp(pszStart, "4294967216", 9) >= 0) /* 2^32 - 80 */
228 return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
229
230 cComponents++;
231 }
232
233 if (RT_UNLIKELY(cComponents >= 128))
234 return VERR_ASN1_OBJID_TOO_MANY_COMPONENTS;
235 pThis->cComponents = (uint8_t)cComponents;
236
237 /*
238 * Find space for the component array, either at the unused end of szObjId
239 * or on the heap.
240 */
241 int rc;
242 RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator);
243#if 0 /** @todo breaks with arrays of ObjIds or structs containing them. They get resized and repositioned in memory, thus invalidating the pointer. Add recall-pointers callback, or just waste memory? Or maybe make all arrays pointer-arrays? */
244 size_t cbLeft = sizeof(pThis->szObjId) - cbObjId;
245 if (cbLeft >= cComponents * sizeof(uint32_t))
246 {
247 pThis->pauComponents = (uint32_t *)&pThis->szObjId[sizeof(pThis->szObjId) - cComponents * sizeof(uint32_t)];
248 cbLeft -= cComponents * sizeof(uint32_t);
249 rc = VINF_SUCCESS;
250 }
251 else
252#endif
253 rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->pauComponents, cComponents * sizeof(uint32_t));
254 if (RT_SUCCESS(rc))
255 {
256 /*
257 * Fill the elements array.
258 */
259 uint32_t *pauComponents = (uint32_t *)pThis->pauComponents;
260 rc = VINF_SUCCESS;
261 psz = pszObjId;
262 for (uint32_t i = 0; i < cComponents; i++)
263 {
264 uint32_t uValue = 0;
265 rc = RTStrToUInt32Ex(psz, (char **)&psz, 10, &uValue);
266 if (rc == VWRN_TRAILING_CHARS)
267 {
268 pauComponents[i] = uValue;
269 AssertBreakStmt(*psz == '.', rc = VERR_TRAILING_CHARS);
270 psz++;
271 }
272 else if (rc == VINF_SUCCESS)
273 {
274 pauComponents[i] = uValue;
275 Assert(*psz == '\0');
276 }
277 else if (RT_FAILURE(rc))
278 break;
279 else
280 {
281 rc = -rc;
282 break;
283 }
284 }
285 if (rc == VINF_SUCCESS && *psz == '\0')
286 {
287 /*
288 * Initialize the core structure before we start on the encoded bytes.
289 */
290 RTAsn1Core_InitEx(&pThis->Asn1Core,
291 ASN1_TAG_OID,
292 ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_PRIMITIVE,
293 &g_RTAsn1ObjId_Vtable,
294 RTASN1CORE_F_PRESENT | RTASN1CORE_F_PRIMITE_TAG_STRUCT);
295
296 /*
297 * Encode the value into the string buffer. This will NOT overflow
298 * because the string representation is much less efficient than the
299 * binary ASN.1 representation (base-10 + separators vs. base-128).
300 */
301 pThis->Asn1Core.cb = (uint32_t)cbObjId;
302 rc = rtAsn1ObjId_EncodeComponents(cComponents, pThis->pauComponents,
303 (uint8_t *)&pThis->szObjId[0], &pThis->Asn1Core.cb);
304 if (RT_SUCCESS(rc))
305 {
306 /*
307 * Now, find a place for the encoded bytes. There might be
308 * enough room left in the szObjId for it if we're lucky.
309 */
310#if 0 /** @todo breaks with arrays of ObjIds or structs containing them. They get resized and repositioned in memory, thus invalidating the pointer. Add recall-pointers callback, or just waste memory? Or maybe make all arrays pointer-arrays? */
311 if (pThis->Asn1Core.cb >= cbLeft)
312 pThis->Asn1Core.uData.pv = memmove(&pThis->szObjId[cbObjId], &pThis->szObjId[0], pThis->Asn1Core.cb);
313 else
314#endif
315 rc = RTAsn1ContentDup(&pThis->Asn1Core, pThis->szObjId, pThis->Asn1Core.cb, pAllocator);
316 if (RT_SUCCESS(rc))
317 {
318 /*
319 * Finally, copy the dotted string.
320 */
321 memcpy(pThis->szObjId, pszObjId, cbObjId);
322 return VINF_SUCCESS;
323 }
324 }
325 else
326 {
327 AssertMsgFailed(("%Rrc\n", rc));
328 rc = VERR_ASN1_INTERNAL_ERROR_3;
329 }
330 }
331 else
332 rc = VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
333 }
334 RT_ZERO(*pThis);
335 return rc;
336}
337
338
339RTDECL(int) RTAsn1ObjId_SetFromString(PRTASN1OBJID pThis, const char *pszObjId, PCRTASN1ALLOCATORVTABLE pAllocator)
340{
341 RTAsn1ObjId_Delete(pThis);
342 int rc = RTAsn1ObjId_InitFromString(pThis, pszObjId, pAllocator);
343 if (RT_FAILURE(rc))
344 RTAsn1ObjId_Init(pThis, pAllocator);
345 return rc;
346}
347
348
349RTDECL(int) RTAsn1ObjId_CompareWithString(PCRTASN1OBJID pThis, const char *pszRight)
350{
351 return strcmp(pThis->szObjId, pszRight);
352}
353
354
355RTDECL(bool) RTAsn1ObjId_StartsWith(PCRTASN1OBJID pThis, const char *pszStartsWith)
356{
357 size_t cchStartsWith = strlen(pszStartsWith);
358 return !strncmp(pThis->szObjId, pszStartsWith, cchStartsWith)
359 && ( pszStartsWith[cchStartsWith] == '.'
360 || pszStartsWith[cchStartsWith] == '\0');
361}
362
363
364RTDECL(uint8_t) RTAsn1ObjIdCountComponents(PCRTASN1OBJID pThis)
365{
366 return pThis->cComponents;
367}
368
369
370RTDECL(uint32_t) RTAsn1ObjIdGetComponentsAsUInt32(PCRTASN1OBJID pThis, uint8_t iComponent)
371{
372 if (iComponent < pThis->cComponents)
373 return pThis->pauComponents[iComponent];
374 return UINT32_MAX;
375}
376
377
378RTDECL(uint32_t) RTAsn1ObjIdGetLastComponentsAsUInt32(PCRTASN1OBJID pThis)
379{
380 return pThis->pauComponents[pThis->cComponents - 1];
381}
382
383
384/*
385 * ASN.1 OBJECT IDENTIFIER - Standard Methods.
386 */
387
388RT_DECL_DATA_CONST(RTASN1COREVTABLE const) g_RTAsn1ObjId_Vtable =
389{
390 "RTAsn1ObjId",
391 sizeof(RTASN1OBJID),
392 ASN1_TAG_OID,
393 ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_PRIMITIVE,
394 0,
395 (PFNRTASN1COREVTDTOR)RTAsn1ObjId_Delete,
396 NULL,
397 (PFNRTASN1COREVTCLONE)RTAsn1ObjId_Clone,
398 (PFNRTASN1COREVTCOMPARE)RTAsn1ObjId_Compare,
399 (PFNRTASN1COREVTCHECKSANITY)RTAsn1ObjId_CheckSanity,
400 NULL,
401 NULL
402};
403
404
405RTDECL(int) RTAsn1ObjId_Init(PRTASN1OBJID pThis, PCRTASN1ALLOCATORVTABLE pAllocator)
406{
407 RT_NOREF_PV(pAllocator);
408 RTAsn1Core_InitEx(&pThis->Asn1Core,
409 ASN1_TAG_OID,
410 ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_PRIMITIVE,
411 &g_RTAsn1ObjId_Vtable,
412 RTASN1CORE_F_PRESENT | RTASN1CORE_F_PRIMITE_TAG_STRUCT);
413 pThis->Asn1Core.cb = sizeof(g_abDefault);
414 pThis->Asn1Core.uData.pv = (void *)&g_abDefault[0];
415 pThis->cComponents = RT_ELEMENTS(g_auDefault);
416 pThis->pauComponents = g_auDefault;
417 AssertCompile(sizeof(g_szDefault) <= sizeof(pThis->szObjId));
418 memcpy(pThis->szObjId, g_szDefault, sizeof(g_szDefault));
419 return VINF_SUCCESS;
420}
421
422
423RTDECL(int) RTAsn1ObjId_Clone(PRTASN1OBJID pThis, PCRTASN1OBJID pSrc, PCRTASN1ALLOCATORVTABLE pAllocator)
424{
425 AssertPtr(pSrc); AssertPtr(pThis); AssertPtr(pAllocator);
426 RT_ZERO(*pThis);
427 if (RTAsn1ObjId_IsPresent(pSrc))
428 {
429 AssertReturn(pSrc->Asn1Core.pOps == &g_RTAsn1ObjId_Vtable, VERR_INTERNAL_ERROR_3);
430
431 /* Copy the dotted string representation. */
432 size_t cbObjId = strlen(pSrc->szObjId) + 1;
433 AssertReturn(cbObjId <= sizeof(pThis->szObjId), VERR_INTERNAL_ERROR_5);
434 memcpy(pThis->szObjId, pSrc->szObjId, cbObjId);
435
436 /* Copy the integer component array. Try fit it in the unused space of
437 the dotted object string buffer. We place it at the end of the
438 buffer as that is simple alignment wise and avoid wasting bytes that
439 could be used to sequueze in the content bytes (see below). */
440 int rc;
441 RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator);
442 pThis->cComponents = pSrc->cComponents;
443#if 0 /** @todo breaks with arrays of ObjIds or structs containing them. They get resized and repositioned in memory, thus invalidating the pointer. Add recall-pointers callback, or just waste memory? Or maybe make all arrays pointer-arrays? */
444 size_t cbLeft = sizeof(pThis->szObjId);
445 if (pSrc->cComponents * sizeof(uint32_t) <= cbLeft)
446 {
447 pThis->pauComponents = (uint32_t *)&pThis->szObjId[sizeof(pThis->szObjId) - pSrc->cComponents * sizeof(uint32_t)];
448 memcpy((uint32_t *)pThis->pauComponents, pSrc->pauComponents, pSrc->cComponents * sizeof(uint32_t));
449 cbLeft -= pSrc->cComponents * sizeof(uint32_t);
450 rc = VINF_SUCCESS;
451 }
452 else
453#endif
454 {
455 rc = RTAsn1MemDup(&pThis->Allocation, (void **)&pThis->pauComponents, pSrc->pauComponents,
456 pSrc->cComponents * sizeof(uint32_t));
457 }
458 if (RT_SUCCESS(rc))
459 {
460 /* See if we can fit the content value into the szObjId as well.
461 It will follow immediately after the string as the component
462 array is the end of the string buffer, when present. */
463#if 0 /** @todo breaks with arrays of ObjIds or structs containing them. They get resized and repositioned in memory, thus invalidating the pointer. Add recall-pointers callback, or just waste memory? Or maybe make all arrays pointer-arrays? */
464 uint32_t cbContent = pSrc->Asn1Core.cb;
465 if (cbContent <= cbLeft)
466 {
467 rc = RTAsn1Core_CloneNoContent(&pThis->Asn1Core, &pSrc->Asn1Core);
468 if (RT_SUCCESS(rc))
469 {
470 pThis->Asn1Core.uData.pv = memcpy(&pThis->szObjId[cbObjId], pSrc->Asn1Core.uData.pv, cbContent);
471 return VINF_SUCCESS;
472 }
473 }
474 else
475#endif
476 {
477 rc = RTAsn1Core_CloneContent(&pThis->Asn1Core, &pSrc->Asn1Core, pAllocator);
478 if (RT_SUCCESS(rc))
479 return VINF_SUCCESS;
480 }
481 }
482
483 /* failed, clean up. */
484 if (pThis->Allocation.cbAllocated)
485 RTAsn1MemFree(&pThis->Allocation, (uint32_t *)pThis->pauComponents);
486 RT_ZERO(*pThis);
487 return rc;
488 }
489 return VINF_SUCCESS;
490}
491
492
493RTDECL(void) RTAsn1ObjId_Delete(PRTASN1OBJID pThis)
494{
495 if ( pThis
496 && RTAsn1ObjId_IsPresent(pThis))
497 {
498 Assert(pThis->Asn1Core.pOps == &g_RTAsn1ObjId_Vtable);
499
500 if (pThis->Allocation.cbAllocated)
501 RTAsn1MemFree(&pThis->Allocation, (uint32_t *)pThis->pauComponents);
502 RTAsn1ContentFree(&pThis->Asn1Core);
503 RT_ZERO(*pThis);
504 }
505}
506
507
508RTDECL(int) RTAsn1ObjId_Enum(PRTASN1OBJID pThis, PFNRTASN1ENUMCALLBACK pfnCallback, uint32_t uDepth, void *pvUser)
509{
510 RT_NOREF_PV(pThis); RT_NOREF_PV(pfnCallback); RT_NOREF_PV(uDepth); RT_NOREF_PV(pvUser);
511 Assert(pThis && (!RTAsn1ObjId_IsPresent(pThis) || pThis->Asn1Core.pOps == &g_RTAsn1ObjId_Vtable));
512
513 /* No children to enumerate. */
514 return VINF_SUCCESS;
515}
516
517
518RTDECL(int) RTAsn1ObjId_Compare(PCRTASN1OBJID pLeft, PCRTASN1OBJID pRight)
519{
520 if (RTAsn1ObjId_IsPresent(pLeft))
521 {
522 if (RTAsn1ObjId_IsPresent(pRight))
523 {
524 uint8_t cComponents = RT_MIN(pLeft->cComponents, pRight->cComponents);
525 for (uint32_t i = 0; i < cComponents; i++)
526 if (pLeft->pauComponents[i] != pRight->pauComponents[i])
527 return pLeft->pauComponents[i] < pRight->pauComponents[i] ? -1 : 1;
528
529 if (pLeft->cComponents == pRight->cComponents)
530 return 0;
531 return pLeft->cComponents < pRight->cComponents ? -1 : 1;
532 }
533 return 1;
534 }
535 return 0 - (int)RTAsn1ObjId_IsPresent(pRight);
536}
537
538
539RTDECL(int) RTAsn1ObjId_CheckSanity(PCRTASN1OBJID pThis, uint32_t fFlags, PRTERRINFO pErrInfo, const char *pszErrorTag)
540{
541 RT_NOREF_PV(fFlags);
542 if (RT_UNLIKELY(!RTAsn1ObjId_IsPresent(pThis)))
543 return RTErrInfoSetF(pErrInfo, VERR_ASN1_NOT_PRESENT, "%s: Missing (OBJID).", pszErrorTag);
544 return VINF_SUCCESS;
545}
546
547
548/*
549 * Generate code for the associated collection types.
550 */
551#define RTASN1TMPL_TEMPLATE_FILE "../common/asn1/asn1-ut-objid-template.h"
552#include <iprt/asn1-generator-internal-header.h>
553#include <iprt/asn1-generator-core.h>
554#include <iprt/asn1-generator-init.h>
555#include <iprt/asn1-generator-sanity.h>
556
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette