Krass: Eine unverhoffte Antwort auf eine meiner ewigen Fragen
Link: http://www.spiegel.de/panorama/0,1518,378168,00.html
Was ich mich schon immer gefragt habe, ist die Frage: Wann wurde eigentlich das Photo des Jungen auf der Kinderschokolade-Packung gemacht. Solange ich mich erinnern kann, ist das dasselbe Bild und es sieht immer ein bisschen nach Kindheit in den Siebzigern aus, als die Welt noch in Ordnung war. Und wie dieser Beitrag auf Spiegel-Online zeigt, war das tatsächlich vor 32 Jahren. Damals war ich 4 Jahre alt und kann mich vermutlich deswegen an kein anderes Gesicht erinnern.
So, jetzt bleiben eigentlich nur noch zwei ewige Fragen von mir übrig, vielleicht kann es irgendjemand für mich auflösen:
- Was macht Calle Del'Haye heute
- Wie hieß nochmal der Joker des FC Bayern in den 80ern, der immer in der 60sten Minute eingewechselt wurde und dann das entscheidende Tor gemacht hatte
Any clues?
64 bit Windows - Teil 6
So, wir haben jetzt einen großen Teil technischen Zeugs hinter uns - keine Angst, wenn's um Registry Reflection oder Registry und File System Redirection geht, heben wir diesbezüglich nochmal ab. Aber vielleicht sollten wir uns jetzt auch mal die Frage der Beancounters und Suits, die in unserer Firma arbeiten und auch von unserer Software ernährt werden, stellen:
Wann braucht man überhaupt native Binaries für x64?
Gute Frage. Sind native x64 Binaries vielleicht eine Lösung für ein Problem, das sich eigentlich gar nicht stellt? Ja und nein.
Gegenfrage: Sind 16-bit Binaries eigentlich noch lauffähig auf x64 Plattformen? Das ist zwar ein orthogonales Problem, aber passt hier thematisch ganz gut.
MS hat sich bei x64 schwer angestrengt um den Übergang zu der neuen Plattform möglichst schmerzlos zu gestalten, das muß man ihnen lassen. Aber 16-bit Binaries (also MS-DOS Binaries und Win16 Binaries) laufen auf x64 Systemen nicht mehr. Punkt. Damit, ähem, endet eine 23-jährige Ära von Binärkompatibilität mit DOS. Von, naja, einer Reihe von Ausnahmen abgesehen, die zum großen Teil von einer Unart einer den Kollegen bei επτ€σ nicht ganz unbekannten Firma namens InstallShield herrührt. InstallShield hatte nämlich die unangenehme Angewohnheit, lange Zeit (ich glaube für alle 5.xer Produkte) den Bootstrapper ihrer Setups, also den setup.exe, als 16-bit Windows Applikation auszuliefern. Das führte dazu, daß alle Setups, die InstallShield in dieser Version verwendeten, unter NT erstmal zum Start einer ntvdm führten, in der dann der 16-bittige setup-stub lief, der dann wiederum einen reinrassigen Win32-Prozess startete, welcher schließlich die eigentliche Installation vornahm. Ziemlich braindamaged, das Ganze, aber es gab dafür sicher einen Grund. Ganz bestimmt. Drum werden auf x64 Windows auch solche setups ausgeführt - obwohl sie 16-bittig sind - jedoch anders als man denkt: Der Programmlader erkennt ein derartiges setup.exe und führt stattdessen ein 32-bittiges setup aus, das von MS und InstallShield entwickelt wurde und mit dem OS mitshippt.
Aber jetzt zur Gretchenfrage: Wann braucht man unbedingt native x64 Binaries und kann nicht mit 32-bittigen Binaries auskommen, wann muß man also wirklich portieren?
Gretchenantwort: In der Regel laufen x86 binaries für 32-bit Windows unverändert und ohne Probleme auf x64. Sogar der Service Control Manager auf einem x64-System weiß mit 32-bittigen Services umzugehen, was mich während der Beta von XP x64 Edition am allermeisten erstaunt hat. Daher bleiben also für mich jetzt erstmal nur vier Kategorien von Softwareprodukten, die für x64 native übersetzt werden müssen:
- Software, die unmittelbar von den Goodies von x64 profitieren will, beispielsweise dem größeren Adreßraum
- Treiber: Kernel-Mode Code muß native vorliegen, um auf x64 zur Ausführung kommen zu können
- Plugins für System Binaries wie Shell Extensions, ISAPI extensions (?)
- Hook-DLLs für User mode processes
Die letzten drei Kategorien lassen sich auf ein fundamentales Problem zurückführen: Ein nativer x64 Prozeß kann keine 32-bittigen x86-DLLs laden (es sei denn es sind resource-only DLLs) und umgekehrt. All dieser Schmuh mit step-up-thunks von Win16 nach Win32 und die step-down-thunks von Win32 nach Win16, die es früher so gab als WinNT, Windows9x und Windows 3.x nebeneinander her sehr verbreitet waren, gibt es nicht unter x64. Puh, eine Sorge weniger!
Natürlich ist es auch so, daß alle DLLs, die ein portiertes Binary nachlädt, auch entsprechend native übersetzt sein müssen. Das bedeutet: Wen man eine Shell Extension oder eine Hook-DLL portiert hat, muß man natürlich auch all die Binaries noch portieren, die dieses Binary so der Reihe nach nachlädt.
Generell läßt sich aber als Fazit festhalten: Win32 Binaries für x86 Plattformen sollten von Ausnahmen abgesehen allesamt laufen. Muß man für ein Produkt native x64 Binaries erzeugen, so ist ein Mischbetrieb von x86 Binaries und x64 Binaries für *ein komplettes Produkt* durchaus möglich. Das soll heißen: Teile eines Produktes können durchaus x86 Binaries sein und nur diejenigen Teile müssen neu und native übersetzt sein, die wirklich native sein müssen.
(Edited: Fixed Typos)
64 bit Windows - Teil 5
Weiter geht's! In diesem Teil der Serie will ich darauf eingehen, was es mit meiner anfänglichen Zurückhaltung auf sich hat, was den Einsatz von MFC auf x64 angeht. Ich will außerdem ein Wort über Visual Studio 6 auf x64 verlieren und was über's Debuggen von nativen x64-Anwendungen erzählen.
Doch zu aller erst ein Zitat von Mark Russinovich aus seinem vorletzten Blog Posting was die Zukunft des IA64 angeht:
"...you might have noticed that there?s little support for Itanium, which reflects my belief, and I think that of others, including Microsoft and Dell, that Itanium has a limited future, one only guaranteed so long as there are no 64-way Opteron systems."
OK, jetzt zu dem MFC für x64: Die gute Nachricht ist ja, wie bereits erwähnt, daß mit dem allerneuesten PlatSDK vom Mai 2005 auch MFC libraries shippen, die man auch genauso wie im letzten Beitrag dieser Serie beschrieben, benutzen kann, um auch MFC-Applikationen zu übersetzen. Diese funktionieren auch exakt so wie erwartet, bis auf den ....., tja, hüstel, ... Shared MFC Debug Build und zwar in der ANSI wie in der Unicode-Variante. Wenn man in dieser Buildumgebung Binaries buildet, so erhält man zwar keinen Fehler während des Builds, aber die Binaries laufen schlicht und einfach nicht, sie werden mit einer Fehlermeldung gleich während der Initialisierung beendet. Das gilt sowohl für exe files wie auch für DLLs die man mit diesen beiden Targets buildet. Will man einen shared debug build mit MFC auf x64, bleibt einem daher nichts anderes übrig, als von MS die shared libs für MFC Version 7.1 anzufordern, so wie sie in einer x86-Version mit Visual Studio 2003 mitkommen. Wie das geht, ist beschrieben im KB-Artikel
875446 "How to obtain the 64-bit version of the Visual C++ 7.1 libraries and build tools". Im Prinzip muß man eine Emailadresse bei MS anschreiben und zum Ausdruck bringen, daß man gerne die 7.1er MFC libs für x64 hätte. Dann erhält man Post von denen zurück und muß ein paar Fragen beantworten und eine EULA abnicken. Als nächstes muß man einen ftp-Zugang stellen, wo dann die Kontaktperson bei MS die libs ("SDKAMD64") draufkopiert. Ja, und man darf IIRC keine Produkte shippen die mit diesen libs gemacht wurden.
Wenn man also MFC Code hat, der anders als der von επτ€σ so programmiert ist, daß er mit jeder MFC-Version funktioniert, nicht nur mit der aus VC6, dann kann man für seine Shared MFC Debug Builds einfach die Suchpfade so umstellen, so daß sie auf das SDKAMD64 zeigen.
So und jetzt zum Debuggen. Der in VC6 integrierte Debugger ist ein x86-Debugger und der kann natürlich auf einer x64-Umgebung überhaupt nicht verwendet werden. Glücklicherweise kommen aber mit dem PlatSDK vom Mai 2005 eine aktualisierte Version der Debugging Tools for Windows mit, und damit der WinDbg (sprich: "Wind-Bag") für x64. Mit dem läßt sich sehr komfortabel alles Debuggen, was man an x64 Binaries so erzeugen kann, so daß eigentlich nur der Wechel der Tools ein bißchen lästig ist. Um den Code zu schreiben und zu übersetzen, setzt man also Visual Studio 6 ein, um zu Debuggen nimmt man dann den WinDbg. Was aber wirklich doof ist an der Situation, ist daß man den Debugger von VC6 auch nicht mehr richtig zum Debuggen vonn x86-Prozessen auf einer x64-Maschine verwenden kann, denn sobald man aus dem Debugger heraus seinen Debuggee beendet, der Prozeß sich also nicht selbst beendet hat, lebt der Debuggee als Zombieprozeß weiter. Das sieht zwar erstmal nicht schlimm aus, aber weil der Prozeß weiterlebt, hat man Probleme, wenn man einfach nur im Code des Debuggee was ändern weill und ihn dann neu übersetzen will, denn man kann ja die exe oder DLL nicht überschreiben. Und weil man den Debuggee nur beenden kann, indem man seinen Elternprozeß (also msdev.exe) beendet, muß man devstudio beenden und neu starten, um das Binary des Debuggees neu zu erzeugen. Ziemlich lästig ist das. Ich denke, wenn man auf einer x64-Maschine VC6 benützen will um x86 Binaries zu entwickeln, testen und debuggen, so sollte man das in einer VMWare Session tun tun, die auf dem x64-Host läuft.
So, was ich beim nächsten Mal schreibe muß ich erst noch rausfinden. Folgende Themen sind noch zu beackern:
- Datentypen auf x64
- Wann braucht man überhaupt native Binaries für x64?
- Die Sache mit der File System Redirection und der Registry Redirection
- Häufig gemachte Fehler bei x64 Ports
Inci beim Fußballkucken
Hier ist Inci beim Fußballkucken. Ich finde, sie hätte sich dafür nicht so aufbrezeln müssen...
"Hacking" the Starteam Client
Bei Starteam hat mich in dem Client schon immer aufgeregt, daß man einen "Compare Contents" (anderswo auch "Diff" genannt) immer nur über die Maus machen kann, sei es mit einem Klick auf einen Toolbarbutton oder mit einem Kontextmenüitem nach einem rechten Mausklick. Andere Clients von Versionskontrollsystemen wie etwa WinCVS bieten hier eine Schnelltaste ("Accelerator"), beispielsweise Ctrl-D. Nach einer Umfrage per Email unter meinen Kollegen, die leider keinen Hinweis ergab, ob sich dieses Verhalten irgendwie customizen liesse, habe ich mir kurz Gedanken gemacht, ob man das irgendwie von außen ändern könnte. Meine ersten Ideen waren erstmal höllisch kompliziert, wie etwa einen Messagehook oder einen Low-Level Keyboard-Hook, aber das ist ja alles Mist und viel zu aufwendig. Viel einfacher ist es, das Binary zu patchen und das Ganze ist in nicht mal 5 Minuten mit einem installierten VS6 erledigt.
Zunächst mal muss man sich darüber im klaren sein, daß Starteam.exe eine reinrassige MFC-Applikation ist. Das erkennt man mit Spyxx an den Fensterklassennamen der Applikation, die alle irgendwie mit Afx... beginnen. Und in MFC-Applikationen ist klar, daß ein Klick auf einen Toolbarbutton, ebenso wie die Auswahl aus einem Kontextmenü letztlich in der Message WM_COMMAND münden. Fraglich ist nur, welche ID dabei mitgeschickt wird. Aber zu dem Zweck gibt es ja den Spyxx. Dort wählt man bei einer geöffneten Starteam-View das zugehörige MDI Child Window aus und selektiert als zu überwachende Message den WM_COMMAND. Dann wählt man einmal den "Compare Contents" für ein File in Starteam aus. Spyxx zeigt einem dann Folgendes an:
Man erkennt also, daß für "Compare Contents" die ID 41059 mitgeschickt wird. Nun macht man sich am Besten eine Kopie von starteam.exe, bespielsweise als _starteam.exe. Diese Datei öffnet man jetzt in Visual Studio, aber als Ressource. Man erhält dann eine Übersicht der Ressourcen, die etwa folgendermaßen ausschaut:
Hier sind die Accelerator Tables ausgeklappt und man erkennt, daß es davon 4 Stück gibt. Ich bescheiße jetzt mal ein bißchen und behaupte, wir müssen diejenige mit der ID 15002 auswählen. Diese wählen wir an und klicken in die leere Fläche für den nächsten neuen Eintrag. Es öffnet sich dann ein Dialog, den wir wie folgt ausfüllen:
Um die Eingaben zu übernehmen klicken wir einfach neben den Dialog und dann schaut die Accelerator-Table etwa so aus:
Nun beenden wir msdev.exe und bejahen die Frage, ob die Veränderungen gespeichert werden. Voilá, ab jetzt wird mit Ctr-D der Differ gestartet, weil natürlich die Messageloop in den MFC eine klassische TranslateAccelerator-TranslateMessage/DispatchMessage-Loop ist, wie etwa folgender Code:
while( GetMessage(&msg, NULL, 0, 0) ) { if( !TranslateAccelerator (msg.hwnd, hAccelTable, &msg) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } }
Das bedeutet schlicht und einfach, daß Accelerator-Aufrufe durch TranslateAccelerator in Messages vom Typ WM_COMMAND mit der ID des Accelerators umgewandelt werden. Praktisch, oder?
Die einzige Kröte, die man jetzt noch schlucken muß ist der Umstand, daß das List-Control von Starteam immer den Fokus verliert wenn man zwischen Prozessen hin- und herswitcht. Aber immerhin kann man jetzt beispielsweise die rechte Hand immer an der Maus zum Klicken lassen und muß nicht immer hin- und herutschen, und mit der linken Hand kann man auf dem Keyboard Ctrl-D und Alt-F4 bedienen fuer den Aufruf und das Beenden des Differs.