Exactly what are these _B_var_Xxxxx and _B_str_Xxxxx members in the VBA COM libraries?

只谈情不闲聊 提交于 2019-12-06 07:24:22

Take a look at the TYPEATTR structure, and in particular, the typekind and tdescAlias members.

typedef struct tagTYPEATTR {
  GUID     guid;
  LCID     lcid;
  DWORD    dwReserved;
  MEMBERID memidConstructor;
  MEMBERID memidDestructor;
  LPOLESTR lpstrSchema;
  ULONG    cbSizeInstance;
  TYPEKIND typekind;
  WORD     cFuncs;
  WORD     cVars;
  WORD     cImplTypes;
  WORD     cbSizeVft;
  WORD     cbAlignment;
  WORD     wTypeFlags;
  WORD     wMajorVerNum;
  WORD     wMinorVerNum;
  TYPEDESC tdescAlias;
  IDLDESC  idldescType;
} TYPEATTR, *LPTYPEATTR;

tdescAlias

If typekind is TKIND_ALIAS, specifies the type for which this type is an alias.

So, UCase(String) is an Alias for _B_var_Ucase(String) (where the parameter and the return value are both implicitly Variant.

And, UCase$(String As String) As String is an Alias for _B_str_UCase(String As String) As String

You can call these underlying functions directly from VB/VBA, but you must use square brackets because _B_str_UCase and _B_var_UCase aren't valid identifiers in VB/VBA.

Dim s As String
Dim v As Variant

s = [_B_str_UCase]("abc")
v = [_B_var_UCase](Null)

's = "ABC"
'v = Null

The outrageous silence of the web is tempered by the Wayback Machine's cache of an informative and amusing series of articles by Sean Baxter, but also preserved with formatting, here.

The TKIND_ALIAS type kind indicates description of a typedef. The name of the typedef is the name of the type (acquired through GetDocumentation), and the alias type is TYPEATTR::tdescAlias.

As for the B in _B_str_UCase and _B_var_UCase it's hard to say exactly, but it's worth remembering that, in COM, a string is actually a BSTR

A BSTR (Basic string or binary string) is a string data type that is used by COM, Automation, and Interop functions

This MSDN article goes further and states:

COM code uses the BSTR to store a Unicode string, short for “Basic String”. (So called because this method of storing strings was developed for OLE Automation, which was at the time motivated by the development of the Visual Basic language engine.)

and then goes on to say:

If you write a function which takes an argument of type BSTR then you are required to accept NULL as a valid BSTR and treat it the same as a pointer to a zero-length BSTR. COM uses this convention, as do both Visual Basic and VBScript, so if you want to play well with others you have to obey this convention. If a string variable in VB happens to be an empty string then VB might pass it as NULL or as a zero-length buffer — it is entirely dependent on the internal workings of the VB program.

So maybe the B is to remind the authors of those functions that the return type should be a BSTR, or maybe the B just means base function. I doubt it is important to anyone other than the original developers.

EDIT

OleView gives these details:

module Strings{ 
    [entry(527), helpcontext(0x000f6eab)]
    BSTR _stdcall _B_str_UCase([in] BSTR String);

    [entry(528), helpcontext(0x000f659b)]
    VARIANT _stdcall _B_var_UCase([in] VARIANT* String);
}

interface _HiddenInterface {
    [restricted, helpcontext(0x000f659b)]
    void _stdcall UCase();
}

And the entries (527 and 528) can be found in the DLL exports:

ordinal hint RVA      name
    ...
    527   C8 0005E8A0 rtcUpperCaseBstr
    528   C9 00070418 rtcUpperCaseVar
    ....
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!