IC4.0/WndBufMode
-
*push*
Habe inzwischen meine selbstgebastelte Ausgabefunktion fertig.
Das laeuft jetzt so, dass bei der Initialisirung (wie bei der IC ohne Buffered Mode) die Konsole auf eine feste Groesse gesetzt wird und die standard handler fuer Ein-/Ausgabe werden geholt. Dann kopiere ich damit den ScreenBuffer mit ReadConsoleOutputA in ein Array und schreibe alle Ausgaben auch erstmal in selbiges. Am Ende meiner Ausgabefunktion wird WriteConsoleOutputA aufgerufen, um den Puffer mit seinen Aenderungen anzuzeigen.
Klappt so weit auch, aber was mich nicht unerheblich stoert ist, dass die Aenderung nicht sofort umgesetzt wird.KA, wovon das genau abhaengt, aber so weit ich das ueberblicke, erscheint der geaenderte ScreenBuffer im Moment erst auf der Konsole, wenn das Programm beendet wird.
Im OllyDbg ist von der Ausgabe daher zB. nichts zu sehen und auch während mein getch (mit ReadConsoleInputA gebastelt) auf eine Taste wartet, bekommt man neue Textausgaben nicht zu sehen.Ich habe schon versucht FlushFileBuffers mit dem StdOut-Handle aufzurufen, das bringt aber genau gar nichts.
Hat jemand Ideen, wie ich meinen ScreenBuffer sofort auf den Bildschirm zaubern kann?
-
Weiss das hier echt keiner? Naja, kann ich auch niemandem verdenken. Die Frickeleien in dieser API sind ja echt haarstraeubend. <_<
Sieht so aus, als waere in WinXP die ueberaus einleuchtend dokumentierte Funktion ntdll.KiFastSystemCall, eax = C8 dafuer gut, den Puffer auf den Schirm zu zaubern - das tut sie zumindest in WriteConsole.
In Win9x funktioniert mein Code mit WriteConsoleOut uebrigens korrekt und wie erwartet.
*grrr* Kotzt an.
-
Ich kann mich nicht erinnern, dass ich so ein Problem hatte. Zeig mal den Code zur Ausgabe, vielleicht kann ich dann helfen.
MfG SideWinder
-
Waere ja wirklich erfreulich, wenn dir dazu noch was einfaellt - ich bin damit echt langsam am verzweifeln.
Ok, also einmal den Code zur Ausgabe... Ist allerdings assembler...
Naja, habe es in den Kommentaren in etwa in C-Code umgesetzt, fuer alle Faelle...UpdateTextCursor: ; wird beim Verlassen der Ausgabefunktion aufgerufen push eax push edi push esi ; einige Werte sichern - egal ; lpWriteRegion.top=lpWriteRegion.left=0; mov dword [lpWriteRegion], 0 ; lpWriteRegion.right=79; ; lpWriteRegion.bottom=24; mov dword [lpWriteRegion + 4], 24 << 16 | 79 ; Display0_ScreenBasePtr ist ein Zeiger auf ein 2Dim-Array aus diesen ; 4Byte Screen-Info-Dingern, das vorher entsprechend befuellt wird. Da man wie ; gesagt die Ausgabe manchmal lesen kann, scheint das Befuellen vor Aufruf ; dieses Codes korrekt zu funktionieren... ; WriteConsoleOutputA(hConsoleOutput, Display0_ScreenBasePtr, 25<<16|80, 0, &lpWriteRegion); push lpWriteRegion; push 0 push 25<<16|80 push dword [Display0_ScreenBasePtr] push dword [hConsoleOutput] call WriteConsoleOutputA ; // FlushFileBuffers(hConsoleOutput); ; push dword [hConsoleOutput] ; call FlushFileBuffers ; SetConsoleCursorPosition(hConsoleOutput, ((LastScreenPos>>1)/80)<<16|(LastScreenPos>>1)%80); ; Funktioniert in WinXP uebrigens genau so wenig wie CounsoleOutput movzx eax, word [LastScreenPos] mov ebx, 50h shr eax, 1 xor edx, edx div ebx shl eax, 16 or eax, edx push eax push dword [hConsoleOutput] call SetConsoleCursorPosition pop esi pop edi pop eax ; Werte wieder zuruecksichern - auch egal ; return; ret
-
Was mir sofort auffällt: Das Sichern des Cursors kannst du dir sparen, da WriteConsoleOutput() den Cursor nicht versetzt *g*
Gibts in deinen ASM-Programmen keine bessere Versionen? Ich benutze immer die wchar_t-Funktionen...
Aber das hilft dir beides nicht weiter, ansonsten sieht mir alles Koscha aus, wenn der Funktionsaufruf klappt sollte das eigentlich sofort am Bildschirm zu sehen sein
MfG SideWinder
-
SideWinder schrieb:
Was mir sofort auffällt: Das Sichern des Cursors kannst du dir sparen, da WriteConsoleOutput() den Cursor nicht versetzt *g*
Jup, eben drum. Da mein code praktisch eine cout-Implementierung darstellt, setze ich so den Cursor hinter das zuletzt ausgegebene Zeichen.
SideWinder schrieb:
Gibts in deinen ASM-Programmen keine bessere Versionen? Ich benutze immer die wchar_t-Funktionen...
Was heisst hier "bessere Versionen"? Wegen dem unicode? Wo waere denn da die Verbesserung oder der Vorteil, wenn ich eh nur ASCII-Zeichen verwende?
Naja, aber aus Spass an der Freud koennte ich es eigentlich auch mal mit der UniCode-Version versuchen. Muesste eigentlich genauso funktionieren.SideWinder schrieb:
Aber das hilft dir beides nicht weiter, ansonsten sieht mir alles Koscha aus, wenn der Funktionsaufruf klappt sollte das eigentlich sofort am Bildschirm zu sehen sein
Hm, jetzt wo du es sagst: Ich habe das ganze nochmal mit dem Olly durchleuchtet und das WriteConsoleOutA gibt ein ERROR_NOACCESS (000003E6) zurueck, genau wie das SetCursor oder FlushBuffers
Kann doch aber eigentlich nicht sein, dass man auf den mit GetStdHandle(STD_OUTPUT_HANDLE) geholten ScreenBuffer keinen Zugriff mit diesen Funktionen hat..??
-
Dann übergibst du die Parameter wohl falsch bzw. dein CHAR_INFO-Array ist zu klein/falsch dimensioniert.
MfG SideWinder
-
Auch nach mehrmaligem Durchgehen kann ich nicht recht nachvollziehen, wo der Fehler liegen koennte.
Ich gehe stark davon aus, dass die Parameterreihenfolge korrekt ist, das Array sollte auch gross genug sein - schliesslich lese ich vorher schon mit
lpWriteRegion.left=lpWriteRegion.top=0;
lpWriteRegion.right=79; lpWriteRegion=24;
ReadConsoleOutputA(hConsoleOutput, Display0_ScreenBasePtr, 25<<16|80, 0, &lpWriteRegion);
den ScreenBuffer ein, und das klappt auch unter XP problemlos...Wird LastErr eigentlich bei jedem API-Aufruf neu gesetzt? Soll heissen: Wird das nach einem fehlerhaften Aufruf beim Naechsten auch wieder auf ERROR_SUCCESS zurueckgesetzt?
Weil, dass WriteConsoleOutputA wegen irgendwelcher Macken in den Parametern einen Fehler schmeisst, koennte ich ja vielleicht noch nachvollziehen, aber weshalb schlaegt dann SetConsoleCursorPosition(hConsoleOutput, COORD(0,4)); fehl?
-
Nobuo T schrieb:
Wird LastErr eigentlich bei jedem API-Aufruf neu gesetzt?
Nicht jede API-Funktion macht das. Um sicherzugehen, musst Du vor jedem Aufruf via SetLastError () den LastErr selbst zurücksetzen.
VOID SetLastError ( DWORD dwErrCode // per-thread error code );
-
Ooooojeeee... Den kleinen Racker zu finden hat mich diesmal aber echt so einige Haare gekostet.
Das Problem war offenbar, dass der Stack beim Aufruf der fehlschlagenden Funktionen nicht dword-aligned war. Da muss man erstmal drauf kommen...Danke auf jeden Fall an alle, die sich hier bemueht haben.
-
Das kann dir mit einer ordentlichen Programmiersprache nicht passieren
MfG SideWinder
-
Jaja. :p Wo bleibt denn da der Spass?