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 | /******************************************************************************/ |
13 | char* 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 | |
29 | void 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 | |
45 | void 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 | |
59 | void 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 | |
76 | static 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 | |
89 | const 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 | |
99 | PCCOR_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 | //***************************************************************************** |
107 | ULONG 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 | /******************************************************************************/ |
141 | const 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 | |
187 | const 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 | |
418 | PCCOR_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 | |
465 | PCCOR_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 | /******************************************************************/ |
748 | const 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 | |
987 | const 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 | |
1056 | bool 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 |
1078 | char* 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 |
1502 | error: |
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 | |
1546 | char* 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 | |