COM-Problem



  • Hallo zusammen,

    ich hab folgenden Methode:

    BOOL _MeineKlasse::ComMethode(LPCTSTR sRTFStream)
    {
        BOOL result;
        static BYTE parms[] =
            VTS_BSTR;
        InvokeHelper(0x60030009, DISPATCH_METHOD, VT_BOOL, (void*)&result, parms,   sRTFStream);
        return result;
    }
    

    _MeineKlasse ist abgeleitet von COleDispatchDriver.

    Damit rufe ich eine Methode in einer VB-DLL auf.

    Public Function ComMethode(ByVal sRTFStream As String) As Boolean
    

    Wie schon zu erkennen ist, beinhaltet der CString einen RTFStream. Leider kann der manchmal ziemlich groß werden, wenn da z.B. Bilder drin sind.
    Ich hab jetzt ein RTF-Dokument, das ca. 1MB groß ist und diese 1Mio Zeichen auch tatsächlich im CString stehen.
    Versuch ich jetzt die VB-DLL per COM aufzurufen, stürzt meine Anwendung mit nem Stack Overflow Fehler ab.

    Ich befürchte, dass da irgendwas beim Umwandeln des CStrings/LPCTSTR in einen BSTR schiefgeht, weil der Quellstring zu groß ist.

    Weiß jemand, wie ich das Problem an besten lösen kann?



  • Hast Du beachtet, dass VB nur BSTRs verarbeitet?
    Ich würde also das ganze so realisieren:

    BOOL _MeineKlasse::ComMethode(LPCOLESTR sRTFStream)
    {
        BOOL result;
        static BYTE parms[] =
            VTS_BSTR;
        InvokeHelper(0x60030009, DISPATCH_METHOD, VT_BOOL, (void*)&result, parms,   sRTFStream);
        return result;
    }
    
    // Aufruf mit:
    CString strRTF = ...;
    BSTR bstr = str.AllocSysString();
    ComMethode( bstr);
    ::SysFreeString( bstr);
    


  • Achtung: Beim Parameter der ComMethode handelt es sich jetzt um einen LPCOLESTR, nicht um ein LPCTSTR, da LPTSTR im MultiByte kompiliert einem char* entsprechen, welches nicht automatisierungskompatibel ist.

    [ Dieser Beitrag wurde am 28.02.2003 um 09:43 Uhr von RenéG editiert. ]



  • Und wo wird da jetzt der Inhalt in den BSTR übertragen? Irgendwie kommt da nur das erste Zeichen in der VB-DLL an.
    [cpp]
    // Hier?
    BSTR bstr = strRTF.AllocSysString();[/cpp]



  • Ups, ne liegt nicht daran, habe gesehn, dass in der MFC VTS_BSTR == automatisch übersetzt wird.

    Tja, dann hab ich im Moment auch keine Ahnung 😉



  • Apropos, wenn es sich um einen RTF-Stream handelt, kann es sein, dass MFC den LPCTSTR falsch übersetzt, da der String ja bei '\0' zu Ende ist, welches bei Images durchaus vorkommen kann.
    Ich denke, sowas kann man nicht über Strings handeln.



  • Da mach dir mal keine Sorgen. \0 gibts nicht mittendrin im RTF-Stream.



  • Und wie siehts mit den Bilddaten aus?

    Ich denke mir, ein RTF-Stream ist ein IStorage-Objekt.

    Zusammensetzung:
    IStream mit CLSID_TextDocument, dahinter serialisierte Textdaten
    IStream mit CLSID_Picture, dahinter serialisierte Bilddaten

    Und Bilder können wohl schwarze Punkte besitzen



  • Da ja die Daten nicht über den Stack übergeben werden, dürfte kein Stack-Overflow auftreten, egal, wie gross Dein Stream ist. Daher muss etwas bei der Endauswertung des Strings in der VB-DLL schief gehen !



  • Im RTF-Stream wird ein Bild als Daten gespeichet, ungefähr so:

    {\pict\picscalex100\picscaley100\piccropl0\piccropr0\piccropt0\piccropb0
    \picw13494\pich9102\picwgoal7650\pichgoal5160\pngblip\bliptag-319491372{\*\blipuid ecf4f2d4d132fd38e276c0e70fb25511}
    89504e470d0a1a0a0000000d49484452000001fe00000
    15808020000003d4809810000000467414d410000b188
    9598f4a6000000097048597300000ec400000e...
    

    Mit ... gleich noch tausende solcher Zahlen.

    Da ist mit Sicherheit kein Hex-00 drin. Außerdem wäre das schon bei den Anwendern aufgefallen.

    Und leider passiert der Fehler nicht in der VB-DLL, sondern beim Umwandeln des CStrings/LPCTSTR in den BSTR. Er kommt ja erst gar nicht in der VB-DLL an.

    Ich bin jetzt mal mit dem Debugger durchgesteppt und kann dir genau sagen, wo der Fehler auftritt.
    In der OLEDISP2.CPP:

    #if !defined(_UNICODE) && !defined(OLE2ANSI)
                case VT_BSTRA:
                    {
                        LPCSTR lpsz = va_arg(argList, LPSTR);
                        pArg->bstrVal = ::SysAllocString(T2COLE(lpsz));//<- Hier 
                        if (lpsz != NULL && pArg->bstrVal == NULL)
                            AfxThrowMemoryException();
                        pArg->vt = VT_BSTR;
                    }
                    break;
    

    Bei der markierten Zeile wird die Assemblerdatei CHKSTK.ASM aufgerufen; bin jetzt nicht sicher, ob der Aufruf von SysAllocString oder T2COLE kommt.

    probepages:
            sub     ecx,_PAGESIZE_          ; yes, move down a page
            sub     eax,_PAGESIZE_          ; adjust request and...
    
            test    dword ptr [ecx],eax     ; ...probe it <- Hier stürzt er nach zig Durchläufen ab
    
            cmp     eax,_PAGESIZE_          ; more than one page requested?
            jae     short probepages        ; no
    

    [ Dieser Beitrag wurde am 28.02.2003 um 12:38 Uhr von thomas80d editiert. ]



  • Na da haben wir doch den Fehler 😉
    Denn T2COLE nutzt tatsächlich den Stack ;), einfach, um das ganze schneller zu machen. Meist werden ja auch nur 'kurze' Strings damit konvertiert!

    Das heisst also, dass Du entweder einen grösseren Stack für Dein Programm anlegen musst oder das Makro T2COLE überschreibst, indem Du es vorher löschst (#undef) und dann Deine Speicherallozierung auf 'new'-Basis erledigst.



  • Wie bekomm ich denn nen größeren Stack?

    Der Com-Aufruf ist in der DLL und ich arbeite mit den Visual Studio 6.0.

    [ Dieser Beitrag wurde am 28.02.2003 um 14:45 Uhr von thomas80d editiert. ]



  • Bei den Linkereinstellungen

    Standardmässig sind das nämlich 0x100000, also 1MByte

    [ Dieser Beitrag wurde am 28.02.2003 um 15:02 Uhr von RenéG editiert. ]



  • Ich hab die Stackgröße mal auf Maximum gestellt, leider klappt es immer noch nicht. Ich befürchte, ich muss die Stackgröße der EXE-Datei ändern, da ich Com-Aufrufe in DLL's ausgelagert sind. Die Stackgröße der DLL zu ändern bringt anscheinend gar nix.
    Tja, nur schade, dass ich an der EXE gar nix ändern kann, da die von außen kommt.



  • Hm, Stack kann leider nur in der EXE geändert werden.



  • Hmm, na trotzdem danke.
    Muss ich mal mit den Verantwortlichen für die EXE reden.


Anmelden zum Antworten