1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//
5
6//
7/******************************************************************************/
8/* formatType.cpp */
9/******************************************************************************/
10#include "formattype.h"
11
12/******************************************************************************/
13char* asString(CQuickBytes *out) {
14 CONTRACTL
15 {
16 THROWS;
17 GC_NOTRIGGER;
18 }
19 CONTRACTL_END;
20
21 SIZE_T oldSize = out->Size();
22 out->ReSizeThrows(oldSize + 1);
23 char* cur = &((char*) out->Ptr())[oldSize];
24 *cur = 0;
25 out->ReSizeThrows(oldSize); // Don't count the null character
26 return((char*) out->Ptr());
27}
28
29void appendStr(CQuickBytes *out, const char* str, unsigned len) {
30 CONTRACTL
31 {
32 THROWS;
33 GC_NOTRIGGER;
34 }
35 CONTRACTL_END;
36
37 if(len == (unsigned)(-1)) len = (unsigned)strlen(str);
38 SIZE_T oldSize = out->Size();
39 out->ReSizeThrows(oldSize + len);
40 char* cur = &((char*) out->Ptr())[oldSize];
41 memcpy(cur, str, len);
42 // Note no trailing null!
43}
44
45void appendChar(CQuickBytes *out, char chr) {
46 CONTRACTL
47 {
48 THROWS;
49 GC_NOTRIGGER;
50 }
51 CONTRACTL_END;
52
53 SIZE_T oldSize = out->Size();
54 out->ReSizeThrows(oldSize + 1);
55 ((char*) out->Ptr())[oldSize] = chr;
56 // Note no trailing null!
57}
58
59void insertStr(CQuickBytes *out, const char* str) {
60 CONTRACTL
61 {
62 THROWS;
63 GC_NOTRIGGER;
64 }
65 CONTRACTL_END;
66
67 unsigned len = (unsigned)strlen(str);
68 SIZE_T oldSize = out->Size();
69 out->ReSizeThrows(oldSize + len);
70 char* cur = &((char*) out->Ptr())[len];
71 memmove(cur,out->Ptr(),oldSize);
72 memcpy(out->Ptr(), str, len);
73 // Note no trailing null!
74}
75
76static void appendStrNum(CQuickBytes *out, int num) {
77 CONTRACTL
78 {
79 THROWS;
80 GC_NOTRIGGER;
81 }
82 CONTRACTL_END;
83
84 char buff[16];
85 sprintf_s(buff, COUNTOF(buff), "%d", num);
86 appendStr(out, buff);
87}
88
89const PCCOR_SIGNATURE PrettyPrintSignature(
90 PCCOR_SIGNATURE typePtr, // type to convert,
91 unsigned typeLen, // the lenght of 'typePtr'
92 const char* name, // can be "", the name of the method for this sig 0 means local var sig
93 CQuickBytes *out, // where to put the pretty printed string
94 IMDInternalImport *pIMDI, // ptr to IMDInternalImport class with ComSig
95 _In_opt_z_ const char* inlabel, // prefix for names (NULL if no names required)
96 BOOL printTyArity=FALSE);
97
98
99PCCOR_SIGNATURE PrettyPrintTypeOrDef(
100 PCCOR_SIGNATURE typePtr, // type to convert,
101 CQuickBytes *out, // where to put the pretty printed string
102 IMDInternalImport *pIMDI); // ptr to IMDInternal class with ComSig
103
104//*****************************************************************************
105// Parse a length, return the length, size of the length.
106//*****************************************************************************
107ULONG GetLength( // Length or -1 on error.
108 void const *pData, // First byte of length.
109 int *pSizeLen) // Put size of length here, if not 0.
110{
111 LIMITED_METHOD_CONTRACT;
112
113 BYTE const *pBytes = reinterpret_cast<BYTE const*>(pData);
114
115 if(pBytes)
116 {
117 if ((*pBytes & 0x80) == 0x00) // 0??? ????
118 {
119 if (pSizeLen) *pSizeLen = 1;
120 return (*pBytes & 0x7f);
121 }
122
123 if ((*pBytes & 0xC0) == 0x80) // 10?? ????
124 {
125 if (pSizeLen) *pSizeLen = 2;
126 return ((*pBytes & 0x3f) << 8 | *(pBytes+1));
127 }
128
129 if ((*pBytes & 0xE0) == 0xC0) // 110? ????
130 {
131 if (pSizeLen) *pSizeLen = 4;
132 return ((*pBytes & 0x1f) << 24 | *(pBytes+1) << 16 | *(pBytes+2) << 8 | *(pBytes+3));
133 }
134 }
135 if(pSizeLen) *pSizeLen = 0;
136 return 0;
137}
138
139
140/******************************************************************************/
141const char* PrettyPrintSig(
142 PCCOR_SIGNATURE typePtr, // type to convert,
143 unsigned typeLen, // the length of 'typePtr'
144 const char* name, // can be "", the name of the method for this sig 0 means local var sig
145 CQuickBytes *out, // where to put the pretty printed string
146 IMDInternalImport *pIMDI, // ptr to IMDInternalImport class with ComSig
147 const char* inlabel, // prefix for names (NULL if no names required)
148 BOOL printTyArity)
149{
150 STATIC_CONTRACT_THROWS;
151
152 // This had a _try/__except handler earlier that would swallow exceptions like
153 // SO and breakpoint. Obviously, swallowing any of them is not the right thing to do.
154 //
155 // Thus, we replace it with EX_TRY/EX_CATCH that automatically kicks in with SO
156 // handling if it sees any SO going past it. Also, C++ catch will not swallow
157 // the breakpoint exception (which is what we want).
158 EX_TRY
159 {
160 PrettyPrintSignature(typePtr,
161 typeLen,
162 name,
163 out,
164 pIMDI,
165 inlabel,
166 printTyArity);
167 }
168 EX_CATCH
169 {
170 out->Shrink(0);
171 appendStr(out,"ERROR PARSING THE SIGNATURE");
172 }
173#if defined(__ILDASM__)
174 // Dont allow ildasm to swallow bad SEH exceptions
175 EX_END_CATCH(RethrowCorruptingExceptions);
176#else // __ILDASM__
177 EX_END_CATCH(SwallowAllExceptions);
178#endif // __ILDASM__
179
180 return(asString(out));
181}
182
183/********************************************************************************/
184// Converts a com signature to a printable signature.
185// Note that return value is pointing at the CQuickBytes buffer,
186
187const PCCOR_SIGNATURE PrettyPrintSignature(
188 PCCOR_SIGNATURE typePtr, // type to convert,
189 unsigned typeLen, // the lenght of 'typePtr'
190 const char* name, // can be "", the name of the method for this sig 0 means local var sig
191 CQuickBytes *out, // where to put the pretty printed string
192 IMDInternalImport *pIMDI, // ptr to IMDInternalImport class with ComSig
193 const char* inlabel, // prefix for names (NULL if no names required)
194 BOOL printTyArity)
195{
196 CONTRACTL
197 {
198 THROWS;
199 GC_NOTRIGGER;
200 }
201 CONTRACTL_END;
202
203 unsigned numArgs;
204 unsigned numTyArgs = 0;
205 PCCOR_SIGNATURE typeEnd = typePtr + typeLen;
206 unsigned ixArg= 0; //arg index
207 char argname[1024];
208 char label[MAX_PREFIX_SIZE];
209 const char* openpar = "(";
210 const char* closepar = ")";
211 ParamDescriptor* pszArgName = NULL; // ptr to array of names (if provided by debug info)
212
213 if(inlabel && *inlabel) // check for *inlabel is totally unnecessary, added to pacify the PREFIX
214 {
215 strcpy_s(label,MAX_PREFIX_SIZE,inlabel);
216 ixArg = label[strlen(label)-1] - '0';
217 label[strlen(label)-1] = 0;
218 if(label[0] == '@') // it's pointer!
219 {
220#ifdef _WIN64
221 pszArgName = (ParamDescriptor*)_atoi64(&label[1]);
222#else // !_WIN64
223 pszArgName = (ParamDescriptor*)(size_t)atoi(&label[1]);
224#endif // _WIN64
225 }
226 }
227
228 // 0 means a local var sig
229 if (name != 0)
230 {
231 // get the calling convention out
232 unsigned callConv = CorSigUncompressData(typePtr);
233
234 // should not be a local var sig
235 _ASSERTE(!isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_LOCAL_SIG));
236
237 if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD))
238 {
239 typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI);
240 if (*name)
241 {
242 appendChar(out, ' ');
243 appendStr(out, name);
244 }
245 return(typePtr);
246 }
247
248 if (callConv & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS)
249 appendStr(out, KEYWORD("explicit "));
250
251 if (callConv & IMAGE_CEE_CS_CALLCONV_HASTHIS)
252 appendStr(out, KEYWORD("instance "));
253
254 if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_GENERICINST))
255 {
256 openpar = LTN();
257 closepar = GTN();
258 }
259 else
260 {
261 static const char* const callConvNames[8] = {
262 "",
263 "unmanaged cdecl ",
264 "unmanaged stdcall ",
265 "unmanaged thiscall ",
266 "unmanaged fastcall ",
267 "vararg ",
268 "<error> ",
269 "<error> "
270 };
271 appendStr(out, KEYWORD(callConvNames[callConv & 7]));
272 }
273
274 if (callConv & IMAGE_CEE_CS_CALLCONV_GENERIC)
275 {
276 numTyArgs = CorSigUncompressData(typePtr);
277 }
278 numArgs = CorSigUncompressData(typePtr);
279 if (!isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_GENERICINST))
280 {
281 // do return type
282 if(pszArgName)
283 {
284 argname[0] = 0;
285 DumpParamAttr(argname,COUNTOF(argname),pszArgName[ixArg+numArgs].attr);
286 appendStr(out,argname);
287 }
288 typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI);
289 if(pszArgName)
290 {
291 argname[0] = ' '; argname[1] = 0;
292 DumpMarshaling(pIMDI,argname,COUNTOF(argname),pszArgName[ixArg+numArgs].tok);
293 appendStr(out,argname);
294 }
295 if(*name != 0)
296 {
297 appendChar(out, ' ');
298 appendStr(out, name);
299 }
300 if((numTyArgs != 0)&&printTyArity)
301 {
302 appendStr(out,LTN());
303 appendChar(out,'[');
304 appendStrNum(out,numTyArgs);
305 appendChar(out,']');
306 appendStr(out,GTN());
307 }
308 }
309 }
310 else
311 {
312 // get the calling convention out
313#ifdef _DEBUG
314 unsigned callConv =
315#endif
316 CorSigUncompressData(typePtr);
317#ifdef _DEBUG
318 (void)callConv; //prevent "unused variable" warning from GCC
319 // should be a local var sig
320 _ASSERTE(callConv == IMAGE_CEE_CS_CALLCONV_LOCAL_SIG);
321#endif
322
323 numArgs = CorSigUncompressData(typePtr);
324 }
325
326 appendStr(out, openpar);
327
328 bool needComma = false;
329 while(typePtr < typeEnd)
330 {
331 if(name) // printing the arguments
332 {
333 PREFIX_ASSUME(typePtr != NULL);
334 if (*typePtr == ELEMENT_TYPE_SENTINEL)
335 {
336 if (needComma)
337 appendChar(out, ',');
338 appendStr(out, "...");
339 typePtr++;
340 }
341 else
342 {
343 if (numArgs <= 0)
344 break;
345 if (needComma)
346 appendChar(out, ',');
347 if(pszArgName)
348 {
349 argname[0] = 0;
350 DumpParamAttr(argname,COUNTOF(argname),pszArgName[ixArg].attr);
351 appendStr(out,argname);
352 }
353 typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI);
354 if(inlabel)
355 {
356 if(pszArgName)
357 {
358 argname[0] = ' '; argname[1] = 0;
359 DumpMarshaling(pIMDI,argname,COUNTOF(argname),pszArgName[ixArg].tok);
360 strcat_s(argname, COUNTOF(argname), ProperName(pszArgName[ixArg++].name));
361 }
362 else sprintf_s(argname,COUNTOF(argname)," %s_%d",label,ixArg++);
363 appendStr(out,argname);
364 }
365 --numArgs;
366 }
367 }
368 else // printing local vars
369 {
370 if (numArgs <= 0)
371 break;
372 if(pszArgName)
373 {
374 if(pszArgName[ixArg].attr == 0xFFFFFFFF)
375 {
376 CQuickBytes fake_out;
377 typePtr = PrettyPrintTypeOrDef(typePtr, &fake_out, pIMDI);
378 ixArg++;
379 numArgs--;
380 continue;
381 }
382 }
383 if (needComma)
384 appendChar(out, ',');
385 if(pszArgName)
386 {
387 sprintf_s(argname,COUNTOF(argname),"[%d] ",pszArgName[ixArg].attr);
388 appendStr(out,argname);
389 }
390 typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI);
391 if(inlabel)
392 {
393 if(pszArgName)
394 {
395 sprintf_s(argname,COUNTOF(argname)," %s",ProperLocalName(pszArgName[ixArg++].name));
396 }
397 else sprintf_s(argname,COUNTOF(argname)," %s_%d",label,ixArg++);
398 appendStr(out,argname);
399 }
400 --numArgs;
401 }
402 needComma = true;
403 }
404 // Have we finished printing all the arguments?
405 if (numArgs > 0) {
406 appendStr(out, ERRORMSG(" [SIGNATURE ENDED PREMATURELY]"));
407 }
408
409 appendStr(out, closepar);
410 return(typePtr);
411}
412
413
414/******************************************************************************/
415// pretty prints 'type' or its 'typedef' to the buffer 'out' returns a pointer to the next type,
416// or 0 on a format failure; outside ILDASM -- simple wrapper for PrettyPrintType
417
418PCCOR_SIGNATURE PrettyPrintTypeOrDef(
419 PCCOR_SIGNATURE typePtr, // type to convert,
420 CQuickBytes *out, // where to put the pretty printed string
421 IMDInternalImport *pIMDI) // ptr to IMDInternal class with ComSig
422{
423 CONTRACTL
424 {
425 THROWS;
426 SO_TOLERANT;
427 GC_NOTRIGGER;
428 }
429 CONTRACTL_END;
430
431 PCCOR_SIGNATURE pBegin, pEnd=NULL;
432
433 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(ThrowStackOverflow());
434
435#ifdef __ILDASM__
436 ULONG L = (ULONG)(out->Size());
437#endif
438 pBegin = typePtr;
439 pEnd = PrettyPrintType(typePtr,out,pIMDI);
440#ifdef __ILDASM__
441 if(pEnd > pBegin) // PrettyPrintType can return NULL
442 {
443 DWORD i;
444 ULONG l = (ULONG)(pEnd - pBegin);
445 for(i=0; i < g_NumTypedefs; i++)
446 {
447 if(((*g_typedefs)[i].cb == l)
448 && (memcmp((*g_typedefs)[i].psig,pBegin,l)==0))
449 {
450 out->Shrink(L); // discard output of PrettyPrintType
451 appendStr(out, JUMPPT(ProperName((*g_typedefs)[i].szName),(*g_typedefs)[i].tkSelf));
452 break;
453 }
454 }
455 }
456#endif
457 END_SO_INTOLERANT_CODE;
458 return pEnd;
459}
460
461/******************************************************************************/
462// pretty prints 'type' to the buffer 'out' returns a pointer to the next type,
463// or 0 on a format failure
464
465PCCOR_SIGNATURE PrettyPrintType(
466 PCCOR_SIGNATURE typePtr, // type to convert,
467 CQuickBytes *out, // where to put the pretty printed string
468 IMDInternalImport *pIMDI) // ptr to IMDInternal class with ComSig
469{
470 CONTRACTL
471 {
472 THROWS;
473 GC_NOTRIGGER;
474 }
475 CONTRACTL_END;
476
477 mdToken tk;
478 const char* str;
479 int typ;
480 CQuickBytes tmp;
481 CQuickBytes Appendix;
482 BOOL Reiterate;
483 int n;
484
485 do {
486 Reiterate = FALSE;
487 switch(typ = *typePtr++) {
488 case ELEMENT_TYPE_VOID :
489 str = "void"; goto APPEND;
490 case ELEMENT_TYPE_BOOLEAN :
491 str = "bool"; goto APPEND;
492 case ELEMENT_TYPE_CHAR :
493 str = "char"; goto APPEND;
494 case ELEMENT_TYPE_I1 :
495 str = "int8"; goto APPEND;
496 case ELEMENT_TYPE_U1 :
497 str = "uint8"; goto APPEND;
498 case ELEMENT_TYPE_I2 :
499 str = "int16"; goto APPEND;
500 case ELEMENT_TYPE_U2 :
501 str = "uint16"; goto APPEND;
502 case ELEMENT_TYPE_I4 :
503 str = "int32"; goto APPEND;
504 case ELEMENT_TYPE_U4 :
505 str = "uint32"; goto APPEND;
506 case ELEMENT_TYPE_I8 :
507 str = "int64"; goto APPEND;
508 case ELEMENT_TYPE_U8 :
509 str = "uint64"; goto APPEND;
510 case ELEMENT_TYPE_R4 :
511 str = "float32"; goto APPEND;
512 case ELEMENT_TYPE_R8 :
513 str = "float64"; goto APPEND;
514 case ELEMENT_TYPE_U :
515 str = "native uint"; goto APPEND;
516 case ELEMENT_TYPE_I :
517 str = "native int"; goto APPEND;
518 case ELEMENT_TYPE_OBJECT :
519 str = "object"; goto APPEND;
520 case ELEMENT_TYPE_STRING :
521 str = "string"; goto APPEND;
522 case ELEMENT_TYPE_TYPEDBYREF :
523 str = "typedref"; goto APPEND;
524 APPEND:
525 appendStr(out, KEYWORD((char*)str));
526 break;
527
528 case ELEMENT_TYPE_VALUETYPE :
529 str = "valuetype ";
530 goto DO_CLASS;
531 case ELEMENT_TYPE_CLASS :
532 str = "class ";
533 goto DO_CLASS;
534
535 DO_CLASS:
536 appendStr(out, KEYWORD((char*)str));
537 typePtr += CorSigUncompressToken(typePtr, &tk);
538 if(IsNilToken(tk))
539 {
540 appendStr(out, "[ERROR! NIL TOKEN]");
541 }
542 else PrettyPrintClass(out, tk, pIMDI);
543 REGISTER_REF(g_tkRefUser,tk)
544 break;
545
546 case ELEMENT_TYPE_SZARRAY :
547 insertStr(&Appendix,"[]");
548 Reiterate = TRUE;
549 break;
550
551 case ELEMENT_TYPE_ARRAY :
552 {
553 typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI);
554 PREFIX_ASSUME(typePtr != NULL);
555 unsigned rank = CorSigUncompressData(typePtr);
556 // <TODO> what is the syntax for the rank 0 case? </TODO>
557 if (rank == 0) {
558 appendStr(out, ERRORMSG("[BAD: RANK == 0!]"));
559 }
560 else {
561 _ASSERTE(rank != 0);
562
563#ifdef _PREFAST_
564#pragma prefast(push)
565#pragma prefast(disable:22009 "Suppress PREFAST warnings about integer overflow")
566#endif
567 int* lowerBounds = (int*) _alloca(sizeof(int)*2*rank);
568 int* sizes = &lowerBounds[rank];
569 memset(lowerBounds, 0, sizeof(int)*2*rank);
570
571 unsigned numSizes = CorSigUncompressData(typePtr);
572 _ASSERTE(numSizes <= rank);
573 unsigned i;
574 for(i =0; i < numSizes; i++)
575 sizes[i] = CorSigUncompressData(typePtr);
576
577 unsigned numLowBounds = CorSigUncompressData(typePtr);
578 _ASSERTE(numLowBounds <= rank);
579 for(i = 0; i < numLowBounds; i++)
580 typePtr+=CorSigUncompressSignedInt(typePtr,&lowerBounds[i]);
581
582 appendChar(out, '[');
583 if (rank == 1 && numSizes == 0 && numLowBounds == 0)
584 appendStr(out, "...");
585 else {
586 for(i = 0; i < rank; i++)
587 {
588 //if (sizes[i] != 0 || lowerBounds[i] != 0)
589 {
590 if (lowerBounds[i] == 0 && i < numSizes)
591 appendStrNum(out, sizes[i]);
592 else
593 {
594 if(i < numLowBounds)
595 {
596 appendStrNum(out, lowerBounds[i]);
597 appendStr(out, "...");
598 if (/*sizes[i] != 0 && */i < numSizes)
599 appendStrNum(out, lowerBounds[i] + sizes[i] - 1);
600 }
601 }
602 }
603 if (i < rank-1)
604 appendChar(out, ',');
605 }
606 }
607 appendChar(out, ']');
608#ifdef _PREFAST_
609#pragma prefast(pop)
610#endif
611 }
612 } break;
613
614 case ELEMENT_TYPE_VAR :
615 appendChar(out, '!');
616 n = CorSigUncompressData(typePtr);
617#ifdef __ILDASM__
618 if(!PrettyPrintGP(g_tkVarOwner,out,n))
619#endif
620 appendStrNum(out, n);
621 break;
622
623 case ELEMENT_TYPE_MVAR :
624 appendChar(out, '!');
625 appendChar(out, '!');
626 n = CorSigUncompressData(typePtr);
627#ifdef __ILDASM__
628 if(!PrettyPrintGP(g_tkMVarOwner,out,n))
629#endif
630 appendStrNum(out, n);
631 break;
632
633 case ELEMENT_TYPE_FNPTR :
634 appendStr(out, KEYWORD("method "));
635 typePtr = PrettyPrintSignature(typePtr, 0x7FFF, "*", out, pIMDI, NULL);
636 break;
637
638 case ELEMENT_TYPE_GENERICINST :
639 {
640 typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI);
641 appendStr(out, LTN());
642 unsigned numArgs = CorSigUncompressData(typePtr);
643 bool needComma = false;
644 while(numArgs--)
645 {
646 if (needComma)
647 appendChar(out, ',');
648 typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI);
649 needComma = true;
650 }
651 appendStr(out, GTN());
652 break;
653 }
654
655#ifndef __ILDASM__
656 case ELEMENT_TYPE_INTERNAL :
657 {
658 // ELEMENT_TYPE_INTERNAL <TypeHandle>
659 _ASSERTE(sizeof(TypeHandle) == sizeof(void *));
660 TypeHandle typeHandle;
661 typePtr += CorSigUncompressPointer(typePtr, (void **)&typeHandle);
662
663 MethodTable *pMT = NULL;
664 if (typeHandle.IsTypeDesc())
665 {
666 pMT = typeHandle.AsTypeDesc()->GetMethodTable();
667 if (pMT)
668 {
669 PrettyPrintClass(out, pMT->GetCl(), pMT->GetMDImport());
670
671 // It could be a "native version" of the managed type used in interop
672 if (typeHandle.AsTypeDesc()->IsNativeValueType())
673 appendStr(out, "_NativeValueType");
674 }
675 else
676 appendStr(out, "(null)");
677 }
678 else
679 {
680 pMT = typeHandle.AsMethodTable();
681 if (pMT)
682 PrettyPrintClass(out, pMT->GetCl(), pMT->GetMDImport());
683 else
684 appendStr(out, "(null)");
685 }
686
687 char sz[32];
688 if(IsCompilationProcess())
689 {
690 sprintf_s(sz, COUNTOF(sz), " /* TOKEN: 0x%x */", pMT != NULL ? pMT->GetCl() : 0);
691 }
692 else
693 {
694 sprintf_s(sz, COUNTOF(sz), " /* MT: 0x%p */", pMT);
695 }
696 appendStr(out, sz);
697 break;
698 }
699#endif
700
701
702 // Modifiers or depedent types
703 case ELEMENT_TYPE_CMOD_OPT :
704 str = " modopt("; goto ADDCLASSTOCMOD;
705 case ELEMENT_TYPE_CMOD_REQD :
706 str = " modreq(";
707 ADDCLASSTOCMOD:
708 typePtr += CorSigUncompressToken(typePtr, &tk);
709 if (IsNilToken(tk))
710 {
711 Debug_ReportError("Nil token in custom modifier");
712 }
713 tmp.Shrink(0);
714 appendStr(&tmp, KEYWORD((char*)str));
715 PrettyPrintClass(&tmp, tk, pIMDI);
716 appendChar(&tmp,')');
717 str = (const char *) asString(&tmp);
718 goto MODIFIER;
719 case ELEMENT_TYPE_PINNED :
720 str = " pinned"; goto MODIFIER;
721 case ELEMENT_TYPE_PTR :
722 str = "*"; goto MODIFIER;
723 case ELEMENT_TYPE_BYREF :
724 str = AMP(); goto MODIFIER;
725 MODIFIER:
726 insertStr(&Appendix, str);
727 Reiterate = TRUE;
728 break;
729
730 default:
731 case ELEMENT_TYPE_SENTINEL :
732 case ELEMENT_TYPE_END :
733 //_ASSERTE(!"Unknown Type");
734 if(typ)
735 {
736 char sz[64];
737 sprintf_s(sz,COUNTOF(sz),"/* UNKNOWN TYPE (0x%X)*/",typ);
738 appendStr(out, ERRORMSG(sz));
739 }
740 break;
741 } // end switch
742 } while(Reiterate);
743 appendStr(out,asString(&Appendix));
744 return(typePtr);
745}
746
747/******************************************************************/
748const char* PrettyPrintClass(
749 CQuickBytes *out, // where to put the pretty printed string
750 mdToken tk, // The class token to look up
751 IMDInternalImport *pIMDI) // ptr to IMDInternalImport class with ComSig
752{
753 CONTRACTL
754 {
755 THROWS;
756 GC_NOTRIGGER;
757 }
758 CONTRACTL_END;
759
760 if(tk == mdTokenNil) // Zero resolution scope for "somewhere here" TypeRefs
761 {
762 appendStr(out,"[*]");
763 return(asString(out));
764 }
765 if(!pIMDI->IsValidToken(tk))
766 {
767 char str[1024];
768 sprintf_s(str,COUNTOF(str)," [ERROR: INVALID TOKEN 0x%8.8X] ",tk);
769 appendStr(out,ERRORMSG(str));
770 return(asString(out));
771 }
772 switch(TypeFromToken(tk))
773 {
774 case mdtTypeRef:
775 case mdtTypeDef:
776#ifdef __ILDASM__
777 DWORD ix;
778 for(ix = 0; ix < g_NumTypedefs; ix++)
779 {
780 if((*g_typedefs)[ix].tkTypeSpec == tk) break;
781 }
782 if(ix < g_NumTypedefs)
783 {
784 appendStr(out,JUMPPT(ProperName((*g_typedefs)[ix].szName),(*g_typedefs)[ix].tkSelf));
785 }
786 else
787#endif
788 {
789 const char *nameSpace = 0;
790 const char *name = 0;
791 mdToken tkEncloser;
792
793 if (TypeFromToken(tk) == mdtTypeRef)
794 {
795 if (FAILED(pIMDI->GetResolutionScopeOfTypeRef(tk, &tkEncloser)))
796 {
797 tkEncloser = mdTypeDefNil;
798 }
799 if (FAILED(pIMDI->GetNameOfTypeRef(tk, &nameSpace, &name)))
800 {
801 nameSpace = name = "Invalid TypeRef record";
802 }
803 }
804 else
805 {
806 if (FAILED(pIMDI->GetNestedClassProps(tk,&tkEncloser)))
807 {
808 tkEncloser = mdTypeDefNil;
809 }
810 if (FAILED(pIMDI->GetNameOfTypeDef(tk, &name, &nameSpace)))
811 {
812 nameSpace = name = "Invalid TypeDef record";
813 }
814 }
815 MAKE_NAME_IF_NONE(name,tk);
816 if((tkEncloser == mdTokenNil) || RidFromToken(tkEncloser))
817 {
818 PrettyPrintClass(out,tkEncloser,pIMDI);
819 if (TypeFromToken(tkEncloser) == mdtTypeRef || TypeFromToken(tkEncloser) == mdtTypeDef)
820 {
821 appendChar(out, '/');
822 //nameSpace = ""; //don't print namespaces for nested classes!
823 }
824 }
825 if(TypeFromToken(tk)==mdtTypeDef)
826 {
827 unsigned L = (unsigned)strlen(ProperName(name))+1;
828 char* szFN = NULL;
829 if(nameSpace && *nameSpace)
830 {
831 const char* sz = ProperName(nameSpace);
832 L+= (unsigned)strlen(sz)+1;
833 szFN = new char[L];
834 sprintf_s(szFN,L,"%s.",sz);
835 }
836 else
837 {
838 szFN = new char[L];
839 *szFN = 0;
840 }
841 strcat_s(szFN,L, ProperName(name));
842 appendStr(out,JUMPPT(szFN,tk));
843 VDELETE(szFN);
844 }
845 else
846 {
847 if (nameSpace && *nameSpace) {
848 appendStr(out, ProperName(nameSpace));
849 appendChar(out, '.');
850 }
851
852 appendStr(out, ProperName(name));
853 }
854 if(g_fDumpTokens)
855 {
856 char tmp[16];
857 sprintf_s(tmp,COUNTOF(tmp),"/*%08X*/",tk);
858 appendStr(out,COMMENT(tmp));
859 }
860 }
861 break;
862
863 case mdtAssemblyRef:
864 {
865 LPCSTR szName = NULL;
866#ifdef __ILDASM__
867 if (rAsmRefName && (RidFromToken(tk) <= ulNumAsmRefs))
868 {
869 szName = rAsmRefName[RidFromToken(tk)-1];
870 }
871 else
872#endif
873 {
874 if (FAILED(pIMDI->GetAssemblyRefProps(tk,NULL,NULL,&szName,NULL,NULL,NULL,NULL)))
875 {
876 szName = NULL;
877 }
878 }
879 if ((szName != NULL) && ((*szName) != 0 ))
880 {
881 appendChar(out, '[');
882 appendStr(out,JUMPPT(ProperName(szName),tk));
883 if(g_fDumpTokens)
884 {
885 char tmp[16];
886 sprintf_s(tmp,COUNTOF(tmp),"/*%08X*/",tk);
887 appendStr(out,COMMENT(tmp));
888 }
889 appendChar(out, ']');
890 }
891 }
892 break;
893 case mdtAssembly:
894 {
895 LPCSTR szName;
896 if (FAILED(pIMDI->GetAssemblyProps(tk,NULL,NULL,NULL,&szName,NULL,NULL)))
897 {
898 szName = NULL;
899 }
900 if ((szName != NULL) && ((*szName) != 0))
901 {
902 appendChar(out, '[');
903 appendStr(out,JUMPPT(ProperName(szName),tk));
904 if(g_fDumpTokens)
905 {
906 char tmp[16];
907 sprintf_s(tmp,COUNTOF(tmp),"/* %08X */",tk);
908 appendStr(out,COMMENT(tmp));
909 }
910 appendChar(out, ']');
911 }
912 }
913 break;
914 case mdtModuleRef:
915 {
916 LPCSTR szName;
917 if (FAILED(pIMDI->GetModuleRefProps(tk, &szName)))
918 {
919 szName = NULL;
920 }
921 if ((szName != NULL) && ((*szName) != 0))
922 {
923 appendChar(out, '[');
924 appendStr(out,KEYWORD(".module "));
925 appendStr(out,JUMPPT(ProperName(szName),tk));
926 if(g_fDumpTokens)
927 {
928 char tmp[16];
929 sprintf_s(tmp,COUNTOF(tmp),"/*%08X*/",tk);
930 appendStr(out,COMMENT(tmp));
931 }
932 appendChar(out, ']');
933 }
934 }
935 break;
936
937 case mdtTypeSpec:
938 {
939#ifdef __ILDASM__
940 DWORD ix;
941 for(ix = 0; ix < g_NumTypedefs; ix++)
942 {
943 if((*g_typedefs)[ix].tkTypeSpec == tk) break;
944 }
945 if(ix < g_NumTypedefs)
946 {
947 appendStr(out,JUMPPT(ProperName((*g_typedefs)[ix].szName),(*g_typedefs)[ix].tkSelf));
948 }
949 else
950#endif
951 {
952 ULONG cSig;
953 PCCOR_SIGNATURE sig;
954 if (FAILED(pIMDI->GetSigFromToken(tk, &cSig, &sig)))
955 {
956 char tmp[64];
957 sprintf_s(tmp, COUNTOF(tmp), "/*Invalid %08X record*/", tk);
958 appendStr(out, COMMENT(tmp));
959 }
960 else
961 {
962 PrettyPrintType(sig, out, pIMDI);
963 }
964 }
965 if(g_fDumpTokens)
966 {
967 char tmp[16];
968 sprintf_s(tmp,COUNTOF(tmp),"/*%08X*/",tk);
969 appendStr(out,COMMENT(tmp));
970 }
971 }
972 break;
973
974 case mdtModule:
975 break;
976
977 default:
978 {
979 char str[128];
980 sprintf_s(str,COUNTOF(str)," [ERROR: INVALID TOKEN TYPE 0x%8.8X] ",tk);
981 appendStr(out,ERRORMSG(str));
982 }
983 }
984 return(asString(out));
985}
986
987const char* TrySigUncompressAndDumpSimpleNativeType(
988 PCCOR_SIGNATURE pData, // [IN] compressed data
989 ULONG *pDataOut, // [OUT] the expanded *pData
990 ULONG &cbCur,
991 SString &buf)
992{
993 const char* sz = NULL;
994 ULONG ulSize = CorSigUncompressData(pData, pDataOut);
995 if (ulSize != (ULONG)-1)
996 {
997 switch (*pDataOut)
998 {
999 case NATIVE_TYPE_VOID: sz = " void"; break;
1000 case NATIVE_TYPE_BOOLEAN: sz = " bool"; break;
1001 case NATIVE_TYPE_I1: sz = " int8"; break;
1002 case NATIVE_TYPE_U1: sz = " unsigned int8"; break;
1003 case NATIVE_TYPE_I2: sz = " int16"; break;
1004 case NATIVE_TYPE_U2: sz = " unsigned int16"; break;
1005 case NATIVE_TYPE_I4: sz = " int32"; break;
1006 case NATIVE_TYPE_U4: sz = " unsigned int32"; break;
1007 case NATIVE_TYPE_I8: sz = " int64"; break;
1008 case NATIVE_TYPE_U8: sz = " unsigned int64"; break;
1009 case NATIVE_TYPE_R4: sz = " float32"; break;
1010 case NATIVE_TYPE_R8: sz = " float64"; break;
1011 case NATIVE_TYPE_SYSCHAR: sz = " syschar"; break;
1012 case NATIVE_TYPE_VARIANT: sz = " variant"; break;
1013 case NATIVE_TYPE_CURRENCY: sz = " currency"; break;
1014 case NATIVE_TYPE_DECIMAL: sz = " decimal"; break;
1015 case NATIVE_TYPE_DATE: sz = " date"; break;
1016 case NATIVE_TYPE_BSTR: sz = " bstr"; break;
1017 case NATIVE_TYPE_LPSTR: sz = " lpstr"; break;
1018 case NATIVE_TYPE_LPWSTR: sz = " lpwstr"; break;
1019 case NATIVE_TYPE_LPTSTR: sz = " lptstr"; break;
1020 case NATIVE_TYPE_OBJECTREF: sz = " objectref"; break;
1021 case NATIVE_TYPE_STRUCT: sz = " struct"; break;
1022 case NATIVE_TYPE_ERROR: sz = " error"; break;
1023 case NATIVE_TYPE_INT: sz = " int"; break;
1024 case NATIVE_TYPE_UINT: sz = " uint"; break;
1025 case NATIVE_TYPE_NESTEDSTRUCT: sz = " nested struct"; break;
1026 case NATIVE_TYPE_BYVALSTR: sz = " byvalstr"; break;
1027 case NATIVE_TYPE_ANSIBSTR: sz = " ansi bstr"; break;
1028 case NATIVE_TYPE_TBSTR: sz = " tbstr"; break;
1029 case NATIVE_TYPE_VARIANTBOOL: sz = " variant bool"; break;
1030 case NATIVE_TYPE_FUNC: sz = " method"; break;
1031 case NATIVE_TYPE_ASANY: sz = " as any"; break;
1032 case NATIVE_TYPE_LPSTRUCT: sz = " lpstruct"; break;
1033 case NATIVE_TYPE_PTR:
1034 case NATIVE_TYPE_SAFEARRAY:
1035 case NATIVE_TYPE_ARRAY:
1036 case NATIVE_TYPE_FIXEDSYSSTRING:
1037 case NATIVE_TYPE_FIXEDARRAY:
1038 case NATIVE_TYPE_INTF:
1039 case NATIVE_TYPE_IUNKNOWN:
1040 case NATIVE_TYPE_IDISPATCH:
1041 case NATIVE_TYPE_CUSTOMMARSHALER:
1042 case NATIVE_TYPE_END:
1043 case NATIVE_TYPE_MAX:
1044 sz = ""; break;
1045 default: sz = NULL;
1046 }
1047 }
1048 if (sz)
1049 cbCur += ulSize;
1050 else
1051 buf.Clear();
1052
1053 return sz;
1054}
1055
1056bool TrySigUncompress(PCCOR_SIGNATURE pData, // [IN] compressed data
1057 ULONG *pDataOut, // [OUT] the expanded *pData
1058 ULONG &cbCur,
1059 SString &buf)
1060{
1061 ULONG ulSize = CorSigUncompressData(pData, pDataOut);
1062 if (ulSize == (ULONG)-1)
1063 {
1064 buf.Clear();
1065 return false;
1066 } else
1067 {
1068 cbCur += ulSize;
1069 return true;
1070 }
1071}
1072
1073
1074#ifdef _PREFAST_
1075#pragma warning(push)
1076#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
1077#endif
1078char* DumpMarshaling(IMDInternalImport* pImport,
1079 __inout_ecount(cchszString) char* szString,
1080 DWORD cchszString,
1081 mdToken tok)
1082{
1083 CONTRACTL
1084 {
1085 THROWS;
1086 GC_NOTRIGGER;
1087 }
1088 CONTRACTL_END;
1089
1090 PCCOR_SIGNATURE pSigNativeType = NULL;
1091 ULONG cbNativeType = 0;
1092 SString buf;
1093 if (RidFromToken(tok) &&
1094 SUCCEEDED(pImport->GetFieldMarshal( // return error if no native type associate with the token
1095 tok, // [IN] given fielddef
1096 &pSigNativeType, // [OUT] the native type signature
1097 &cbNativeType))) // [OUT] the count of bytes of *ppvNativeType
1098 {
1099 ULONG cbCur = 0;
1100 ULONG ulData;
1101 const char *sz = NULL;
1102 BOOL fAddAsterisk = FALSE, fAddBrackets = FALSE;
1103 buf.AppendPrintf(" %s(", KEYWORD("marshal"));
1104 while (cbCur < cbNativeType)
1105 {
1106 ulData = NATIVE_TYPE_MAX;
1107 sz = TrySigUncompressAndDumpSimpleNativeType(&pSigNativeType[cbCur], &ulData, cbCur, buf);
1108 if (!sz)
1109 goto error;
1110 if(*sz == 0)
1111 {
1112 switch (ulData)
1113 {
1114 case NATIVE_TYPE_PTR:
1115 sz = "";
1116 fAddAsterisk = TRUE;
1117 break;
1118 case NATIVE_TYPE_SAFEARRAY:
1119 sz = "";
1120 buf.AppendASCII(KEYWORD(" safearray"));
1121 ulData = VT_EMPTY;
1122 if (cbCur < cbNativeType)
1123 {
1124 if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf))
1125 goto error;
1126 }
1127 switch(ulData & VT_TYPEMASK)
1128 {
1129 case VT_EMPTY: sz=""; break;
1130 case VT_NULL: sz=" null"; break;
1131 case VT_VARIANT: sz=" variant"; break;
1132 case VT_CY: sz=" currency"; break;
1133 case VT_VOID: sz=" void"; break;
1134 case VT_BOOL: sz=" bool"; break;
1135 case VT_I1: sz=" int8"; break;
1136 case VT_I2: sz=" int16"; break;
1137 case VT_I4: sz=" int32"; break;
1138 case VT_I8: sz=" int64"; break;
1139 case VT_R4: sz=" float32"; break;
1140 case VT_R8: sz=" float64"; break;
1141 case VT_UI1: sz=" unsigned int8"; break;
1142 case VT_UI2: sz=" unsigned int16"; break;
1143 case VT_UI4: sz=" unsigned int32"; break;
1144 case VT_UI8: sz=" unsigned int64"; break;
1145 case VT_PTR: sz=" *"; break;
1146 case VT_DECIMAL: sz=" decimal"; break;
1147 case VT_DATE: sz=" date"; break;
1148 case VT_BSTR: sz=" bstr"; break;
1149 case VT_LPSTR: sz=" lpstr"; break;
1150 case VT_LPWSTR: sz=" lpwstr"; break;
1151 case VT_UNKNOWN: sz=" iunknown"; break;
1152 case VT_DISPATCH: sz=" idispatch"; break;
1153 case VT_SAFEARRAY: sz=" safearray"; break;
1154 case VT_INT: sz=" int"; break;
1155 case VT_UINT: sz=" unsigned int"; break;
1156 case VT_ERROR: sz=" error"; break;
1157 case VT_HRESULT: sz=" hresult"; break;
1158 case VT_CARRAY: sz=" carray"; break;
1159 case VT_USERDEFINED: sz=" userdefined"; break;
1160 case VT_RECORD: sz=" record"; break;
1161 case VT_FILETIME: sz=" filetime"; break;
1162 case VT_BLOB: sz=" blob"; break;
1163 case VT_STREAM: sz=" stream"; break;
1164 case VT_STORAGE: sz=" storage"; break;
1165 case VT_STREAMED_OBJECT: sz=" streamed_object"; break;
1166 case VT_STORED_OBJECT: sz=" stored_object"; break;
1167 case VT_BLOB_OBJECT: sz=" blob_object"; break;
1168 case VT_CF: sz=" cf"; break;
1169 case VT_CLSID: sz=" clsid"; break;
1170 default: sz=NULL; break;
1171 }
1172 if(sz) buf.AppendASCII(KEYWORD(sz));
1173 else
1174 {
1175 // buf.AppendPrintf(ERRORMSG(" [ILLEGAL VARIANT TYPE 0x%X]"),ulData & VT_TYPEMASK);
1176 buf.Clear();
1177 goto error;
1178 }
1179 sz="";
1180 switch(ulData & (~VT_TYPEMASK))
1181 {
1182 case VT_ARRAY: sz = "[]"; break;
1183 case VT_VECTOR: sz = " vector"; break;
1184 case VT_BYREF: sz = "&"; break;
1185 case VT_BYREF|VT_ARRAY: sz = "&[]"; break;
1186 case VT_BYREF|VT_VECTOR: sz = "& vector"; break;
1187 case VT_ARRAY|VT_VECTOR: sz = "[] vector"; break;
1188 case VT_BYREF|VT_ARRAY|VT_VECTOR: sz = "&[] vector"; break;
1189 }
1190 buf.AppendASCII(KEYWORD(sz));
1191 sz="";
1192
1193 // Extract the user defined sub type name.
1194 if (cbCur < cbNativeType)
1195 {
1196 LPUTF8 strTemp = NULL;
1197 int strLen = 0;
1198 int ByteCountLength = 0;
1199 strLen = GetLength(&pSigNativeType[cbCur], &ByteCountLength);
1200 cbCur += ByteCountLength;
1201 if(strLen)
1202 {
1203#ifdef _PREFAST_
1204#pragma prefast(push)
1205#pragma prefast(disable:22009 "Suppress PREFAST warnings about integer overflow")
1206#endif
1207 strTemp = (LPUTF8)_alloca(strLen + 1);
1208 memcpy(strTemp, (LPUTF8)&pSigNativeType[cbCur], strLen);
1209 strTemp[strLen] = 0;
1210 buf.AppendPrintf(", \"%s\"", UnquotedProperName(strTemp));
1211 cbCur += strLen;
1212#ifdef _PREFAST_
1213#pragma prefast(pop)
1214#endif
1215 }
1216 }
1217 break;
1218
1219 case NATIVE_TYPE_ARRAY:
1220 sz = "";
1221 fAddBrackets = TRUE;
1222 break;
1223 case NATIVE_TYPE_FIXEDSYSSTRING:
1224 {
1225 sz = "";
1226 buf.AppendASCII(KEYWORD(" fixed sysstring"));
1227 buf.AppendASCII(" [");
1228 if (cbCur < cbNativeType)
1229 {
1230 if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf))
1231 goto error;
1232 buf.AppendPrintf("%d",ulData);
1233 }
1234 buf.AppendASCII("]");
1235 }
1236 break;
1237 case NATIVE_TYPE_FIXEDARRAY:
1238 {
1239 sz = "";
1240 buf.AppendASCII(KEYWORD(" fixed array"));
1241 buf.AppendASCII(" [");
1242 if (cbCur < cbNativeType)
1243 {
1244 if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf))
1245 goto error;
1246 buf.AppendPrintf("%d",ulData);
1247 }
1248 buf.AppendASCII("]");
1249 if (cbCur < cbNativeType)
1250 {
1251 sz = TrySigUncompressAndDumpSimpleNativeType(&pSigNativeType[cbCur], &ulData, cbCur, buf);
1252 if (!sz)
1253 goto error;
1254 }
1255 }
1256 break;
1257
1258 case NATIVE_TYPE_INTF:
1259 buf.AppendASCII(KEYWORD(" interface"));
1260 goto DumpIidParamIndex;
1261 case NATIVE_TYPE_IUNKNOWN:
1262 buf.AppendASCII(KEYWORD(" iunknown"));
1263 goto DumpIidParamIndex;
1264 case NATIVE_TYPE_IDISPATCH:
1265 buf.AppendASCII(KEYWORD(" idispatch"));
1266 DumpIidParamIndex:
1267 sz = " ";
1268 if (cbCur < cbNativeType)
1269 {
1270 if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf))
1271 goto error;
1272 buf.AppendPrintf("(%s = %d)",KEYWORD("iidparam"),ulData);
1273 }
1274 break;
1275
1276 case NATIVE_TYPE_CUSTOMMARSHALER:
1277 {
1278 LPUTF8 strTemp = NULL;
1279 int strLen = 0;
1280 int ByteCountLength = 0;
1281 BOOL fFourStrings = FALSE;
1282
1283 sz = "";
1284 buf.AppendASCII(KEYWORD(" custom"));
1285 buf.AppendASCII(" (");
1286 // Extract the typelib GUID.
1287 strLen = GetLength(&pSigNativeType[cbCur], &ByteCountLength);
1288 cbCur += ByteCountLength;
1289 if(strLen)
1290 {
1291 fFourStrings = TRUE;
1292 strTemp = (LPUTF8)(new char[strLen + 1]);
1293 if(strTemp)
1294 {
1295 memcpy(strTemp, (LPUTF8)&pSigNativeType[cbCur], strLen);
1296 strTemp[strLen] = 0;
1297 buf.AppendPrintf("\"%s\",",UnquotedProperName(strTemp));
1298 cbCur += strLen;
1299 VDELETE(strTemp);
1300 }
1301 }
1302 if(cbCur >= cbNativeType)
1303 {
1304 // buf.AppendASCII(ERRORMSG("/* INCOMPLETE MARSHALER INFO */"));
1305 buf.Clear();
1306 goto error;
1307 }
1308 else
1309 {
1310 //_ASSERTE(cbCur < cbNativeType);
1311
1312 // Extract the name of the native type.
1313 strLen = GetLength(&pSigNativeType[cbCur], &ByteCountLength);
1314 cbCur += ByteCountLength;
1315 if(fFourStrings)
1316 {
1317 if(strLen)
1318 {
1319 strTemp = (LPUTF8)(new char[strLen + 1]);
1320 if(strTemp)
1321 {
1322 memcpy(strTemp, (LPUTF8)&pSigNativeType[cbCur], strLen);
1323 strTemp[strLen] = 0;
1324 buf.AppendPrintf("\"%s\",",UnquotedProperName(strTemp));
1325 cbCur += strLen;
1326 VDELETE(strTemp);
1327 }
1328 }
1329 else buf.AppendASCII("\"\",");
1330 }
1331 if(cbCur >= cbNativeType)
1332 {
1333 // buf.AppendASCII(ERRORMSG("/* INCOMPLETE MARSHALER INFO */"));
1334 buf.Clear();
1335 goto error;
1336 }
1337 else
1338 {
1339 //_ASSERTE(cbCur < cbNativeType);
1340
1341 // Extract the name of the custom marshaler.
1342 strLen = GetLength(&pSigNativeType[cbCur], &ByteCountLength);
1343 cbCur += ByteCountLength;
1344 if(strLen)
1345 {
1346 strTemp = (LPUTF8)(new char[strLen + 1]);
1347 if(strTemp)
1348 {
1349 memcpy(strTemp, (LPUTF8)&pSigNativeType[cbCur], strLen);
1350 strTemp[strLen] = 0;
1351 buf.AppendPrintf("\"%s\",",UnquotedProperName(strTemp));
1352 cbCur += strLen;
1353 VDELETE(strTemp);
1354 }
1355 }
1356 else buf.AppendASCII("\"\",");
1357 if(cbCur >= cbNativeType)
1358 {
1359 // buf.AppendASCII(ERRORMSG("/* INCOMPLETE MARSHALER INFO */"));
1360 buf.Clear();
1361 goto error;
1362 }
1363 else
1364 {
1365 // Extract the cookie string.
1366 strLen = GetLength(&pSigNativeType[cbCur], &ByteCountLength);
1367 cbCur += ByteCountLength;
1368
1369 if(cbCur+strLen > cbNativeType)
1370 {
1371 // buf.AppendASCII(ERRORMSG("/* INCOMPLETE MARSHALER INFO */"));
1372 buf.Clear();
1373 goto error;
1374 }
1375 else
1376 {
1377 if(strLen)
1378 {
1379 strTemp = (LPUTF8)(new (nothrow) char[strLen + 1]);
1380 if(strTemp)
1381 {
1382 memcpy(strTemp, (LPUTF8)&pSigNativeType[cbCur], strLen);
1383 strTemp[strLen] = 0;
1384
1385 buf.AppendASCII("\"");
1386 // Copy the cookie string and transform the embedded nulls into \0's.
1387 for (int i = 0; i < strLen - 1; i++, cbCur++)
1388 {
1389 if (strTemp[i] == 0)
1390 buf.AppendASCII("\\0");
1391 else
1392 {
1393 buf.AppendPrintf("%c", strTemp[i]);
1394 }
1395 }
1396 buf.AppendPrintf("%c\"", strTemp[strLen - 1]);
1397 cbCur++;
1398 VDELETE(strTemp);
1399 }
1400 }
1401 else
1402 buf.AppendASCII("\"\"");
1403 //_ASSERTE(cbCur <= cbNativeType);
1404 }
1405 }
1406 }
1407 }
1408 buf.AppendASCII(")");
1409 }
1410 break;
1411 default:
1412 {
1413 sz = "";
1414 }
1415 } // end switch
1416 }
1417 if(*sz)
1418 {
1419 buf.AppendASCII(KEYWORD(sz));
1420 if(fAddAsterisk)
1421 {
1422 buf.AppendASCII("*");
1423 fAddAsterisk = FALSE;
1424 }
1425 if(fAddBrackets)
1426 {
1427 ULONG ulSizeParam=(ULONG)-1,ulSizeConst=(ULONG)-1;
1428 buf.AppendASCII("[");
1429 fAddBrackets = FALSE;
1430 if (cbCur < cbNativeType)
1431 {
1432 if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf))
1433 goto error;
1434 ulSizeParam = ulData;
1435 if (cbCur < cbNativeType)
1436 {
1437 if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf))
1438 goto error;
1439 ulSizeConst = ulData;
1440 if (cbCur < cbNativeType)
1441 {
1442 // retrieve flags
1443 if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf))
1444 goto error;
1445 if((ulData & 1) == 0) ulSizeParam = 0xFFFFFFFF;
1446 }
1447 }
1448 }
1449 if(ulSizeConst != 0xFFFFFFFF)
1450 {
1451 buf.AppendPrintf("%d",ulSizeConst);
1452 // if(ulSizeParam == 0) ulSizeParam = 0xFFFFFFFF; // don't need +0
1453 }
1454 if(ulSizeParam != 0xFFFFFFFF)
1455 {
1456 buf.AppendPrintf(" + %d",ulSizeParam);
1457 }
1458 buf.AppendASCII("]");
1459 }
1460
1461 }
1462
1463 if (ulData >= NATIVE_TYPE_MAX)
1464 break;
1465 } // end while (cbCur < cbNativeType)
1466 // still can have outstanding asterisk or brackets
1467 if(fAddAsterisk)
1468 {
1469 buf.AppendASCII("*");
1470 fAddAsterisk = FALSE;
1471 }
1472 if(fAddBrackets)
1473 {
1474 ULONG ulSizeParam=(ULONG)-1,ulSizeConst=(ULONG)-1;
1475 buf.AppendASCII("[");
1476 fAddBrackets = FALSE;
1477 if (cbCur < cbNativeType)
1478 {
1479 if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf))
1480 goto error;
1481 ulSizeParam = ulData;
1482 if (cbCur < cbNativeType)
1483 {
1484 if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf))
1485 goto error;
1486 ulSizeConst = ulData;
1487 }
1488 }
1489 if(ulSizeConst != 0xFFFFFFFF)
1490 {
1491 buf.AppendPrintf("%d",ulSizeConst);
1492 // if(ulSizeParam == 0) ulSizeParam = 0xFFFFFFFF; // don't need +0
1493 }
1494 if(ulSizeParam != 0xFFFFFFFF)
1495 {
1496 buf.AppendPrintf(" + %d",ulSizeParam);
1497 }
1498 buf.AppendASCII("]");
1499 }
1500 buf.AppendASCII(") ");
1501 }// end if(SUCCEEDED
1502error:
1503 if (buf.IsEmpty() && cbNativeType != 0)
1504 {
1505 // There was something that we didn't grok in the signature.
1506 // Just dump out the blob as hex
1507 buf.AppendPrintf(" %s({", KEYWORD("marshal"));
1508 while (cbNativeType--)
1509 buf.AppendPrintf(" %2.2X", *pSigNativeType++);
1510 buf.AppendASCII(" }) ");
1511
1512 char * tgt = szString + strlen(szString);
1513 int sprintf_ret = sprintf_s(tgt, cchszString - (tgt - szString), "%S", buf.GetUnicode());
1514 if (sprintf_ret == -1)
1515 {
1516 // Hit an error. Oh well, nothing to do...
1517 return tgt;
1518 }
1519 else
1520 {
1521 return tgt + sprintf_ret;
1522 }
1523 }
1524 else
1525 {
1526 char * tgt = szString + strlen(szString);
1527 int sprintf_ret = sprintf_s(tgt, cchszString - (tgt - szString), "%S", buf.GetUnicode());
1528 if (sprintf_ret == -1)
1529 {
1530 // There was an error, possibly with converting the Unicode characters.
1531 buf.Clear();
1532 if (cbNativeType != 0)
1533 goto error;
1534 return tgt; // Oh well, nothing to do...
1535 }
1536 else
1537 {
1538 return tgt + sprintf_ret;
1539 }
1540 }
1541}
1542#ifdef _PREFAST_
1543#pragma warning(pop)
1544#endif
1545
1546char* DumpParamAttr(__inout_ecount(cchszString) char* szString, DWORD cchszString, DWORD dwAttr)
1547{
1548 CONTRACTL
1549 {
1550 THROWS;
1551 GC_NOTRIGGER;
1552 }
1553 CONTRACTL_END;
1554
1555 char *szptr = &szString[strlen(szString)];
1556 char *was_szptr = szptr;
1557 if(IsPdIn(dwAttr))
1558 {
1559 szptr+=sprintf_s(szptr,cchszString - (szptr - was_szptr), KEYWORD("[in]"));
1560 }
1561 if(IsPdOut(dwAttr))
1562 {
1563 szptr+=sprintf_s(szptr,cchszString - (szptr - was_szptr),KEYWORD("[out]"));
1564 }
1565 if(IsPdOptional(dwAttr))
1566 {
1567 szptr+=sprintf_s(szptr,cchszString - (szptr - was_szptr),KEYWORD("[opt]"));
1568 }
1569 if(szptr != was_szptr)
1570 {
1571 szptr+=sprintf_s(szptr,cchszString - (szptr - was_szptr)," ");
1572 }
1573 return szptr;
1574}
1575