Pasando cadenas de VBA a C ++ DLL

Estoy realmente confundido acerca de pasar cadenas de VBA a C ++. Aquí está el código VBA:

Private Declare Sub passBSTRVal Lib "foo.dll" (ByVal s As String)
Private Declare Sub passBSTRRef Lib "foo.dll" (ByRef s As String)
Private Declare Sub passByNarrowVal Lib "foo.dll" (ByVal s As String)
Private Declare Sub passByNarrowRef Lib "foo.dll" (ByRef s As String)
Private Declare Sub passByWideVal Lib "foo.dll" (ByVal s As String)
Private Declare Sub passByWideRef Lib "foo.dll" (ByRef s As String)

Sub foobar()
    Dim s As String, str As String
    str = "Hello There, World!"

    s = str
    Call passByBSTRVal(s)
    s = str
    Call passByBSTRRef(s)
    s = str
    Call passByNarrowVal(s)
    s = str
    Call passByNarrowRef(s)
    s = str
    Call passByWideVal(s)
    s = str
    Call passByWideRef(s)
End Sub

Y el código DLL de C ++:

void __stdcall passByBSTRVal( BSTR s )
{
    MessageBox(NULL, s, L"Pass BSTR by value", MB_OK | MB_ICONINFORMATION);
}

void __stdcall passByBSTRRef( BSTR *s )
{
    MessageBox(NULL, *s, L"Pass BSTR by ref", MB_OK | MB_ICONINFORMATION);
}

void __stdcall passByNarrowVal( LPCSTR s )
{
    USES_CONVERSION;
    MessageBox(NULL, A2W(s), L"Pass by Narrow Val", MB_OK | MB_ICONINFORMATION);
}

void __stdcall passByNarrowRef( LPCSTR* s )
{
    USES_CONVERSION;
    MessageBox(NULL, A2W(*s), L"Pass by Narrow Ref", MB_OK | MB_ICONINFORMATION);
}

void __stdcall passByWideVal( LPCWSTR s )
{
    MessageBox(NULL, s, L"Pass by Wide Val", MB_OK | MB_ICONINFORMATION);
}

void __stdcall passByWideRef( LPCWSTR* s )
{
    MessageBox(NULL, *s, L"Pass by Wide Ref", MB_OK | MB_ICONINFORMATION);
}

Mi expectativa era que las dos primeras llamadas a passByBSTRVal y passByBSTRRef funcionarían. ¿Por qué? Porque las cadenas de VBA son objetos COM BSTR. Sin embargo, mientras recorría el código C ++, el valor de s para ambas funciones era basura (un montón de kanji). Además, el cuadro de mensaje mostrado era (el mismo). Estoy realmente sorprendido de que las dos primeras funciones no hayan funcionado.

Mi siguiente expectativa era que las dos últimas llamadas a passByNarrowVal y passByNarrowRef no funcionen porque un BSTR se define como "typedef OLECHAR * BSTR", y un OLECHAR es un tipo de caracteres anchos, mientras que LPCSTR es un tipo de caracteres estrecho. Sin embargo, al contrario de lo que esperaba, estas dos funciones realmente funcionaron. Cuando revisé el código de C ++, el parámetro s era exactamente lo que esperaba. Mi expectativa estaba mal otra vez.

Por último, mi expectativa para las 2 funciones finales (pasar por wide val y ref) era que funcionarían, ya que un OLECHAR es una cadena de caracteres anchos, por lo que un LPCWSTR debería poder apuntar a un BSTR. Pero como con el caso # 1 (supongo que estos dos casos son idénticos) mi expectativa estaba equivocada. El parámetro s estaba compuesto de caracteres basura (y el cuadro de mensaje mostraba los mismos caracteres basura).

¿Por qué mi intuición estaba completamente equivocada? ¿Alguien puede explicar lo que no entiendo aquí?