rtcTypeNameAuthor: David Zimmer Date: 05.26.21 - 7:14am Dim i As Long, c As New Class1, s As String s = TypeName(i) s = TypeName(c) Lets consider the following pcode: 401C08 04 78FF FLdRfVar var_88 401C0B 4D 5CFF0340 CVarRef var_A4 0x4003 (I4 | ByRef) 401C10 0B 00000400 ImpAdCallI2 rtcTypeName 0x4 401C15 31 70FF FStStr var_90 401C18 04 74FF FLdRfVar var_8C 401C1B 56 0100 NewIfNullAd Class1 401C1E FCF8 58FF FStAd var_A8 401C22 04 58FF FLdRfVar var_A8 401C25 4D 5CFF0940 CVarRef var_A4 0x4009 (IDisp | ByRef) 401C2A 0B 00000400 ImpAdCallI2 rtcTypeName 0x4 So rtcTypeName takes a variant as the argument. In both examples our hard type is first converted to a variant with CVarRef. Inside the msvbvm60.dll rtcTypeName export, there are several code paths. If the variant.vt field is one of the COM (and VB) intrinsic types, then the value is used as a direct lookup into a hardcoded string array. 6608D8F9 MOV EDI,DWORD PTR DS:[EDI*4+66116070] Thats where it looks up the string name from the numeric type as an offset into the array at 66116070, looking at that address in olly dump window view as long address shows: $ ==> >6609B724 UNICODE "Empty" ; element 0 Const vbEmpty = 0 $+4 >6609B718 UNICODE "Null" ; element 1 Const vbNull = 1 $+8 >6609B708 UNICODE "Integer" $+C >6609B6FC UNICODE "Long" $+10 >6609B6EC UNICODE "Single" $+14 >6609B6DC UNICODE "Double" $+18 >6609B6C8 UNICODE "Currency" $+1C >6609B6BC UNICODE "Date" $+20 >6609B6AC UNICODE "String" $+24 >6609B69C UNICODE "Object" ; element 9 Const vbObject = 9 $+28 >6609B690 UNICODE "Error" $+2C >6609B680 UNICODE "Boolean" $+30 >6609B670 UNICODE "Variant" $+34 >6609B660 UNICODE "Unknown" $+38 >6609B650 UNICODE "Decimal" $+3C >66001E62 MSVBVM60.66001E62 -> 00000000 element 15 $+40 >66001E62 MSVBVM60.66001E62 $+44 >6609B644 UNICODE "Byte" Const vbByte = 17 $+48 >6609B634 UNICODE "Record" If its a class object (even a vb user class) then it takes the following path if ( (**v6)(v6, &IID_IProvideClassInfo, &v23) < 0 )// QueryInterface { if ( (**v6)(v6, &IID_IDispatch, &v22) < 0 ) goto LABEL_60; v7 = (*(*v22 + 16))(v22, 0, 1033, &v24); // MSVBVM60.BASIC_DISPINTERFACE_GetTypeInfo v8 = v22; } ... v9 = (*(*v24 + 48))(v24, -1, &Dest, 0, 0, 0); // MSVBVM60.CEcTypeInfo::GetDocumentation Finally it returns the string name retrieved with an alloc and copy v13 = wcslen(v12); Dest = SysAllocStringLen(0, v13 + 2); wcscpy(Dest, v12); If its an array the () are manually added later. rtcVarType, also receives the converted type as a variant, and then just extracts the variant.vt field numeric value. It does a little error checking, but no need for a string lookup, class query, and string alloc. So it will be much faster. Comments: (0) |
About Me More Blogs Main Site |