VirtualBox

source: vbox/trunk/src/VBox/Devices/Trace/VBoxTraceLogDecoders.cpp@ 104918

Last change on this file since 104918 was 104918, checked in by vboxsync, 6 months ago

Devices/Trace: Some more decoding for TPM commands, bugref:10701

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.0 KB
Line 
1/* $Id: VBoxTraceLogDecoders.cpp 104918 2024-06-14 09:01:03Z vboxsync $ */
2/** @file
3 * RTTraceLogDecoders - Implement decoders for the tracing driver.
4 */
5
6/*
7 * Copyright (C) 2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP RTLOGGROUP_DEFAULT
33#include <iprt/assert.h>
34#include <iprt/errcore.h>
35#include <iprt/log.h>
36#include <iprt/message.h>
37#include <iprt/tracelog-decoder-plugin.h>
38
39#include <iprt/formats/tpm.h>
40
41
42/*********************************************************************************************************************************
43* Structures and Typedefs *
44*********************************************************************************************************************************/
45
46/**
47 */
48typedef DECLCALLBACKTYPE(void, FNDECODETPM2CC, (PCTPMREQHDR pHdr, size_t cb));
49/** Pointer to an event decode callback. */
50typedef FNDECODETPM2CC *PFNFNDECODETPM2CC;
51
52
53/*********************************************************************************************************************************
54* Static Variables *
55*********************************************************************************************************************************/
56
57
58/*********************************************************************************************************************************
59* Internal Functions *
60*********************************************************************************************************************************/
61
62static DECLCALLBACK(void) vboxTraceLogDecodeEvtTpmDecodeStartupShutdown(PCTPMREQHDR pHdr, size_t cb)
63{
64 if (cb >= sizeof(uint16_t))
65 {
66 uint16_t u16TpmSu = RT_BE2H_U16(*(const uint16_t *)(pHdr + 1));
67 if (u16TpmSu == TPM2_SU_CLEAR)
68 RTMsgInfo(" TPM2_SU_CLEAR\n");
69 else if (u16TpmSu == TPM2_SU_STATE)
70 RTMsgInfo(" TPM2_SU_STATE\n");
71 else
72 RTMsgInfo(" Unknown: %#x\n", u16TpmSu);
73 return;
74 }
75
76 RTMsgError("Malformed TPM2_CC_STARTUP/TPM2_CC_SHUTDOWN command, not enough room for TPM_SU constant\n");
77}
78
79
80static struct
81{
82 const char *pszCap;
83 const uint32_t *paProperties;
84} s_aTpm2Caps[] =
85{
86 { RT_STR(TPM2_CAP_ALGS), NULL },
87 { RT_STR(TPM2_CAP_HANDLES), NULL },
88 { RT_STR(TPM2_CAP_COMMANDS), NULL },
89 { RT_STR(TPM2_CAP_PP_COMMANDS), NULL },
90 { RT_STR(TPM2_CAP_AUDIT_COMMANDS), NULL },
91 { RT_STR(TPM2_CAP_PCRS), NULL },
92 { RT_STR(TPM2_CAP_TPM_PROPERTIES), NULL },
93 { RT_STR(TPM2_CAP_PCR_PROPERTIES), NULL },
94 { RT_STR(TPM2_CAP_ECC_CURVES), NULL },
95 { RT_STR(TPM2_CAP_AUTH_POLICIES), NULL },
96 { RT_STR(TPM2_CAP_ACT), NULL },
97};
98
99static DECLCALLBACK(void) vboxTraceLogDecodeEvtTpmDecodeGetCapability(PCTPMREQHDR pHdr, size_t cb)
100{
101 if (cb >= sizeof(TPM2REQGETCAPABILITY))
102 {
103 PCTPM2REQGETCAPABILITY pReq = (PCTPM2REQGETCAPABILITY)pHdr;
104 uint32_t u32Cap = RT_BE2H_U32(pReq->u32Cap);
105 uint32_t u32Property = RT_BE2H_U32(pReq->u32Property);
106 uint32_t u32Count = RT_BE2H_U32(pReq->u32Count);
107 if (u32Cap < RT_ELEMENTS(s_aTpm2Caps))
108 RTMsgInfo(" u32Cap: %s\n"
109 " u32Property: %#x\n"
110 " u32Count: %#x\n",
111 s_aTpm2Caps[u32Cap], u32Property, u32Count);
112 else
113 RTMsgInfo(" u32Cap: %#x (UNKNOWN)\n"
114 " u32Property: %#x\n"
115 " u32Count: %#x\n",
116 u32Cap, u32Property, u32Count);
117 return;
118 }
119
120 RTMsgError("Malformed TPM2_CC_GET_CAPABILITY command, not enough room for the input\n");
121}
122
123
124static DECLCALLBACK(void) vboxTraceLogDecodeEvtTpmDecodeReadPublic(PCTPMREQHDR pHdr, size_t cb)
125{
126 if (cb >= sizeof(TPM2REQREADPUBLIC))
127 {
128 PCTPM2REQREADPUBLIC pReq = (PCTPM2REQREADPUBLIC)pHdr;
129 TPMIDHOBJECT hObj = RT_BE2H_U32(pReq->hObj);
130 RTMsgInfo(" hObj: %#x\n", hObj);
131 return;
132 }
133
134 RTMsgError("Malformed TPM2_CC_READ_PUBLIC command, not enough room for the input\n");
135}
136
137
138static struct
139{
140 uint32_t u32CmdCode;
141 const char *pszCmdCode;
142 PFNFNDECODETPM2CC pfnDecode;
143} s_aTpmCmdCodes[] =
144{
145#define TPM_CMD_CODE_INIT(a_CmdCode, a_Desc) { a_CmdCode, #a_CmdCode, a_Desc }
146 TPM_CMD_CODE_INIT(TPM2_CC_NV_UNDEFINE_SPACE_SPECIAL, NULL),
147 TPM_CMD_CODE_INIT(TPM2_CC_EVICT_CONTROL, NULL),
148 TPM_CMD_CODE_INIT(TPM2_CC_HIERARCHY_CONTROL, NULL),
149 TPM_CMD_CODE_INIT(TPM2_CC_NV_UNDEFINE_SPACE, NULL),
150 TPM_CMD_CODE_INIT(TPM2_CC_CHANGE_EPS, NULL),
151 TPM_CMD_CODE_INIT(TPM2_CC_CHANGE_PPS, NULL),
152 TPM_CMD_CODE_INIT(TPM2_CC_CLEAR, NULL),
153 TPM_CMD_CODE_INIT(TPM2_CC_CLEAR_CONTROL, NULL),
154 TPM_CMD_CODE_INIT(TPM2_CC_CLOCK_SET, NULL),
155 TPM_CMD_CODE_INIT(TPM2_CC_HIERARCHY_CHANGE_AUTH, NULL),
156 TPM_CMD_CODE_INIT(TPM2_CC_NV_DEFINE_SPACE, NULL),
157 TPM_CMD_CODE_INIT(TPM2_CC_PCR_ALLOCATE, NULL),
158 TPM_CMD_CODE_INIT(TPM2_CC_PCR_SET_AUTH_POLICY, NULL),
159 TPM_CMD_CODE_INIT(TPM2_CC_PP_COMMANDS, NULL),
160 TPM_CMD_CODE_INIT(TPM2_CC_SET_PRIMARY_POLICY, NULL),
161 TPM_CMD_CODE_INIT(TPM2_CC_FIELD_UPGRADE_START, NULL),
162 TPM_CMD_CODE_INIT(TPM2_CC_CLOCK_RATE_ADJUST, NULL),
163 TPM_CMD_CODE_INIT(TPM2_CC_CREATE_PRIMARY, NULL),
164 TPM_CMD_CODE_INIT(TPM2_CC_NV_GLOBAL_WRITE_LOCK, NULL),
165 TPM_CMD_CODE_INIT(TPM2_CC_GET_COMMAND_AUDIT_DIGEST, NULL),
166 TPM_CMD_CODE_INIT(TPM2_CC_NV_INCREMENT, NULL),
167 TPM_CMD_CODE_INIT(TPM2_CC_NV_SET_BITS, NULL),
168 TPM_CMD_CODE_INIT(TPM2_CC_NV_EXTEND, NULL),
169 TPM_CMD_CODE_INIT(TPM2_CC_NV_WRITE, NULL),
170 TPM_CMD_CODE_INIT(TPM2_CC_NV_WRITE_LOCK, NULL),
171 TPM_CMD_CODE_INIT(TPM2_CC_DICTIONARY_ATTACK_LOCK_RESET, NULL),
172 TPM_CMD_CODE_INIT(TPM2_CC_DICTIONARY_ATTACK_PARAMETERS, NULL),
173 TPM_CMD_CODE_INIT(TPM2_CC_NV_CHANGE_AUTH, NULL),
174 TPM_CMD_CODE_INIT(TPM2_CC_PCR_EVENT, NULL),
175 TPM_CMD_CODE_INIT(TPM2_CC_PCR_RESET, NULL),
176 TPM_CMD_CODE_INIT(TPM2_CC_SEQUENCE_COMPLETE, NULL),
177 TPM_CMD_CODE_INIT(TPM2_CC_SET_ALGORITHM_SET, NULL),
178 TPM_CMD_CODE_INIT(TPM2_CC_SET_COMMAND_CODE_AUDIT_STATUS, NULL),
179 TPM_CMD_CODE_INIT(TPM2_CC_FIELD_UPGRADE_DATA, NULL),
180 TPM_CMD_CODE_INIT(TPM2_CC_INCREMENTAL_SELF_TEST, NULL),
181 TPM_CMD_CODE_INIT(TPM2_CC_SELF_TEST, NULL),
182 TPM_CMD_CODE_INIT(TPM2_CC_STARTUP, vboxTraceLogDecodeEvtTpmDecodeStartupShutdown),
183 TPM_CMD_CODE_INIT(TPM2_CC_SHUTDOWN, vboxTraceLogDecodeEvtTpmDecodeStartupShutdown),
184 TPM_CMD_CODE_INIT(TPM2_CC_STIR_RANDOM, NULL),
185 TPM_CMD_CODE_INIT(TPM2_CC_ACTIVATE_CREDENTIAL, NULL),
186 TPM_CMD_CODE_INIT(TPM2_CC_CERTIFY, NULL),
187 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_NV, NULL),
188 TPM_CMD_CODE_INIT(TPM2_CC_CERTIFY_CREATION, NULL),
189 TPM_CMD_CODE_INIT(TPM2_CC_DUPLICATE, NULL),
190 TPM_CMD_CODE_INIT(TPM2_CC_GET_TIME, NULL),
191 TPM_CMD_CODE_INIT(TPM2_CC_GET_SESSION_AUDIT_DIGEST, NULL),
192 TPM_CMD_CODE_INIT(TPM2_CC_NV_READ, NULL),
193 TPM_CMD_CODE_INIT(TPM2_CC_NV_READ_LOCK, NULL),
194 TPM_CMD_CODE_INIT(TPM2_CC_OBJECT_CHANGE_AUTH, NULL),
195 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_SECRET, NULL),
196 TPM_CMD_CODE_INIT(TPM2_CC_REWRAP, NULL),
197 TPM_CMD_CODE_INIT(TPM2_CC_CREATE, NULL),
198 TPM_CMD_CODE_INIT(TPM2_CC_ECDH_ZGEN, NULL),
199 TPM_CMD_CODE_INIT(TPM2_CC_HMAC_MAC, NULL),
200 TPM_CMD_CODE_INIT(TPM2_CC_IMPORT, NULL),
201 TPM_CMD_CODE_INIT(TPM2_CC_LOAD, NULL),
202 TPM_CMD_CODE_INIT(TPM2_CC_QUOTE, NULL),
203 TPM_CMD_CODE_INIT(TPM2_CC_RSA_DECRYPT, NULL),
204 TPM_CMD_CODE_INIT(TPM2_CC_HMAC_MAC_START, NULL),
205 TPM_CMD_CODE_INIT(TPM2_CC_SEQUENCE_UPDATE, NULL),
206 TPM_CMD_CODE_INIT(TPM2_CC_SIGN, NULL),
207 TPM_CMD_CODE_INIT(TPM2_CC_UNSEAL, NULL),
208 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_SIGNED, NULL),
209 TPM_CMD_CODE_INIT(TPM2_CC_CONTEXT_LOAD, NULL),
210 TPM_CMD_CODE_INIT(TPM2_CC_CONTEXT_SAVE, NULL),
211 TPM_CMD_CODE_INIT(TPM2_CC_ECDH_KEY_GEN, NULL),
212 TPM_CMD_CODE_INIT(TPM2_CC_ENCRYPT_DECRYPT, NULL),
213 TPM_CMD_CODE_INIT(TPM2_CC_FLUSH_CONTEXT, NULL),
214 TPM_CMD_CODE_INIT(TPM2_CC_LOAD_EXTERNAL, NULL),
215 TPM_CMD_CODE_INIT(TPM2_CC_MAKE_CREDENTIAL, NULL),
216 TPM_CMD_CODE_INIT(TPM2_CC_NV_READ_PUBLIC, NULL),
217 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_AUTHORIZE, NULL),
218 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_AUTH_VALUE, NULL),
219 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_COMMAND_CODE, NULL),
220 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_COUNTER_TIMER, NULL),
221 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_CP_HASH, NULL),
222 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_LOCALITY, NULL),
223 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_NAME_HASH, NULL),
224 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_OR, NULL),
225 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_TICKET, NULL),
226 TPM_CMD_CODE_INIT(TPM2_CC_READ_PUBLIC, vboxTraceLogDecodeEvtTpmDecodeReadPublic),
227 TPM_CMD_CODE_INIT(TPM2_CC_RSA_ENCRYPT, NULL),
228 TPM_CMD_CODE_INIT(TPM2_CC_START_AUTH_SESSION, NULL),
229 TPM_CMD_CODE_INIT(TPM2_CC_VERIFY_SIGNATURE, NULL),
230 TPM_CMD_CODE_INIT(TPM2_CC_ECC_PARAMETERS, NULL),
231 TPM_CMD_CODE_INIT(TPM2_CC_FIRMWARE_READ, NULL),
232 TPM_CMD_CODE_INIT(TPM2_CC_GET_CAPABILITY, vboxTraceLogDecodeEvtTpmDecodeGetCapability),
233 TPM_CMD_CODE_INIT(TPM2_CC_GET_RANDOM, NULL),
234 TPM_CMD_CODE_INIT(TPM2_CC_GET_TEST_RESULT, NULL),
235 TPM_CMD_CODE_INIT(TPM2_CC_GET_HASH, NULL),
236 TPM_CMD_CODE_INIT(TPM2_CC_PCR_READ, NULL),
237 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_PCR, NULL),
238 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_RESTART, NULL),
239 TPM_CMD_CODE_INIT(TPM2_CC_READ_CLOCK, NULL),
240 TPM_CMD_CODE_INIT(TPM2_CC_PCR_EXTEND, NULL),
241 TPM_CMD_CODE_INIT(TPM2_CC_PCR_SET_AUTH_VALUE, NULL),
242 TPM_CMD_CODE_INIT(TPM2_CC_NV_CERTIFY, NULL),
243 TPM_CMD_CODE_INIT(TPM2_CC_EVENT_SEQUENCE_COMPLETE, NULL),
244 TPM_CMD_CODE_INIT(TPM2_CC_HASH_SEQUENCE_START, NULL),
245 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_PHYSICAL_PRESENCE, NULL),
246 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_DUPLICATION_SELECT, NULL),
247 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_GET_DIGEST, NULL),
248 TPM_CMD_CODE_INIT(TPM2_CC_TEST_PARMS, NULL),
249 TPM_CMD_CODE_INIT(TPM2_CC_COMMIT, NULL),
250 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_PASSWORD, NULL),
251 TPM_CMD_CODE_INIT(TPM2_CC_ZGEN_2PHASE, NULL),
252 TPM_CMD_CODE_INIT(TPM2_CC_EC_EPHEMERAL, NULL),
253 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_NV_WRITTEN, NULL),
254 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_TEMPLATE, NULL),
255 TPM_CMD_CODE_INIT(TPM2_CC_CREATE_LOADED, NULL),
256 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_AUTHORIZE_NV, NULL),
257 TPM_CMD_CODE_INIT(TPM2_CC_ENCRYPT_DECRYPT_2, NULL),
258 TPM_CMD_CODE_INIT(TPM2_CC_AC_GET_CAPABILITY, NULL),
259 TPM_CMD_CODE_INIT(TPM2_CC_AC_SEND, NULL),
260 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_AC_SEND_SELECT, NULL),
261 TPM_CMD_CODE_INIT(TPM2_CC_CERTIFY_X509, NULL),
262 TPM_CMD_CODE_INIT(TPM2_CC_ACT_SET_TIMEOUT, NULL),
263 TPM_CMD_CODE_INIT(TPM2_CC_ECC_ENCRYPT, NULL),
264 TPM_CMD_CODE_INIT(TPM2_CC_ECC_DECRYPT, NULL),
265 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_CAPABILITY, NULL),
266 TPM_CMD_CODE_INIT(TPM2_CC_POLICY_PARAMETERS, NULL),
267 TPM_CMD_CODE_INIT(TPM2_CC_NV_DEFINE_SPACE_2, NULL),
268 TPM_CMD_CODE_INIT(TPM2_CC_NV_READ_PUBLIC_2, NULL),
269 TPM_CMD_CODE_INIT(TPM2_CC_SET_CAPABILITY, NULL)
270#undef TPM_CMD_CODE_INIT
271};
272
273static void vboxTraceLogDecodeEvtTpmDecodeCmdBuffer(const uint8_t *pbCmd, size_t cbCmd)
274{
275 PCTPMREQHDR pHdr = (PCTPMREQHDR)pbCmd;
276 if (cbCmd >= sizeof(*pHdr))
277 {
278 uint32_t u32CmdCode = RT_BE2H_U32(pHdr->u32Ordinal);
279 for (uint32_t i = 0; i < RT_ELEMENTS(s_aTpmCmdCodes); i++)
280 {
281 if (s_aTpmCmdCodes[i].u32CmdCode == u32CmdCode)
282 {
283 RTMsgInfo(" %s:\n", s_aTpmCmdCodes[i].pszCmdCode);
284 if (s_aTpmCmdCodes[i].pfnDecode)
285 s_aTpmCmdCodes[i].pfnDecode(pHdr, RT_BE2H_U32(pHdr->cbReq));
286 return;
287 }
288 }
289 RTMsgInfo(" <Unknown command code>: %#x\n", u32CmdCode);
290 }
291 else
292 RTMsgError("Command buffer is smaller than the request header (required %u, given %zu\n", sizeof(*pHdr), cbCmd);
293}
294
295
296static void vboxTraceLogDecodeEvtTpmDecodeRespBuffer(const uint8_t *pbResp, size_t cbResp)
297{
298 PCTPMRESPHDR pHdr = (PCTPMRESPHDR)pbResp;
299 if (cbResp >= sizeof(*pHdr))
300 {
301 RTMsgInfo(" Status code: %#x\n", RT_BE2H_U32(pHdr->u32ErrCode));
302 }
303 else
304 RTMsgError("Response buffer is smaller than the request header (required %u, given %zu\n", sizeof(*pHdr), cbResp);
305}
306
307
308static DECLCALLBACK(int) vboxTraceLogDecodeEvtTpmCmdExecReq(RTTRACELOGRDREVT hTraceLogEvt, PCRTTRACELOGEVTDESC pEvtDesc,
309 PRTTRACELOGEVTVAL paVals, uint32_t cVals)
310{
311 RT_NOREF(hTraceLogEvt, pEvtDesc);
312 for (uint32_t i = 0; i < cVals; i++)
313 {
314 /* Look for the pvCmd item which stores the command buffer. */
315 if ( !strcmp(paVals[i].pItemDesc->pszName, "pvCmd")
316 && paVals[i].pItemDesc->enmType == RTTRACELOGTYPE_RAWDATA)
317 {
318 vboxTraceLogDecodeEvtTpmDecodeCmdBuffer(paVals[i].u.RawData.pb, paVals[i].u.RawData.cb);
319 return VINF_SUCCESS;
320 }
321 }
322 RTMsgError("Failed to find the TPM command data buffer for the given event\n");
323 return VERR_NOT_FOUND;
324}
325
326
327static DECLCALLBACK(int) vboxTraceLogDecodeEvtTpmCmdExecResp(RTTRACELOGRDREVT hTraceLogEvt, PCRTTRACELOGEVTDESC pEvtDesc,
328 PRTTRACELOGEVTVAL paVals, uint32_t cVals)
329{
330 RT_NOREF(hTraceLogEvt, pEvtDesc);
331 for (uint32_t i = 0; i < cVals; i++)
332 {
333 /* Look for the pvCmd item which stores the response buffer. */
334 if ( !strcmp(paVals[i].pItemDesc->pszName, "pvResp")
335 && paVals[i].pItemDesc->enmType == RTTRACELOGTYPE_RAWDATA)
336 {
337 vboxTraceLogDecodeEvtTpmDecodeRespBuffer(paVals[i].u.RawData.pb, paVals[i].u.RawData.cb);
338 return VINF_SUCCESS;
339 }
340 }
341 RTMsgError("Failed to find the TPM command data buffer for the given event\n");
342 return VERR_NOT_FOUND;
343}
344
345
346/**
347 * Filter plugin interface.
348 */
349const RTTRACELOGDECODERDECODEEVENT g_aTraceLogDecode[] =
350{
351 { "ITpmConnector.CmdExecReq", vboxTraceLogDecodeEvtTpmCmdExecReq },
352 { "ITpmConnector.CmdExecResp", vboxTraceLogDecodeEvtTpmCmdExecResp },
353};
354
355
356/**
357 * Shared object initialization callback.
358 */
359extern "C" DECLCALLBACK(DECLEXPORT(int)) RTTraceLogDecoderLoad(void *pvUser, PRTTRACELOGDECODERREGISTER pRegisterCallbacks)
360{
361 AssertLogRelMsgReturn(pRegisterCallbacks->u32Version == RT_TRACELOG_DECODERREG_CB_VERSION,
362 ("pRegisterCallbacks->u32Version=%#x RT_TRACELOG_DECODERREG_CB_VERSION=%#x\n",
363 pRegisterCallbacks->u32Version, RT_TRACELOG_DECODERREG_CB_VERSION),
364 VERR_VERSION_MISMATCH);
365
366 return pRegisterCallbacks->pfnRegisterDecoders(pvUser, &g_aTraceLogDecode[0], RT_ELEMENTS(g_aTraceLogDecode));
367}
368
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