VB always uses BSTR, it simply passes an Ansi BSTR when you use the Declare interface. This looks just like an LPSTR, but in fact it is that and more: it's a real, true BSTR in Ansi format.
Passing a string ByVal to a Declared procedure passes a pointer to an Ansi BSTR (not ASCII -- big difference). BSTRs, Unicode or otherwise, are always terminated with a null character, so this looks like LPSTR or *char to the called procedure.
Nothing about BSTR requires that the string be Unicode (though that's a common misconception). When VB passes a string or string array through the Declare interface, it converts the Unicode BSTR to Ansi BSTR, and (in case any changes or additions were made) converts back from Ansi BSTR to Unicode BSTR on return. So any changes or creations you make must be in Ansi.
No, there's no conversion from BSTR to LPSTR, though there is an automatic conversion from Unicode BSTR to Ansi BSTR for Declared external procedures.
The reason why you can pass a BSTR where an LPSTR is needed lies in how a BSTR is constructed and stored. It is in fact just a pointer to a zero-terminated series of characters (LPSZ). What makes it a BSTR is that the byte length is stored in a dword at a -negative- offset to the string body. Routines that expect LPSTR don't know to look "backward" for this length prefix and so they never see it.
И на закуску - по-русски:
То есть BSTR, на самом деле, может быть по смыслу как юникодный, так и анси, только то, какой он, хранится в моей собственной голове.
Странно как-то получается, что 2 разных типа на самом деле описываются одним BSTR-ом.