Upps… über 10.000 posting in microsoft.public.de.vc

Meine Güte wo ist die Zeit hin.
Seit 1998 bin ich nun in der Gruppe nntp://microsoft.public.de.vc aktiv und jetzt sind schon über 10.000 Postings aufgelaufen.

Leider sind die Hochzeiten dieser Gruppe wirklich vorbei. Im Jahr 2001 hatten wir zu Boomzeiten über 2200 Posts pro Monat. Das hat sich gedrittelt. Sind evtl. auch die Zeiten für C++ gezählt?
Wahrscheinlich ist dies einfach ein Microsoft Trend der durch den übergroßen .NET Hype ausgelöst wurde. Wer hatte beim Start von VS.NET 2002 geahnt das C# wirklich so schnell eine Trendsprache wird… Ich hätte es nicht gedacht. Spricht hier etwa Melancholie? 😉

Quelle http://groups.google.de/group/microsoft.public.de.vc/about

PS: Es ist interessant über so lange Zeit hinweg immer wieder festzustellen, dass manche Menschen, die ich über die Gruppen kennen lernen durfte nicht nur im Computer existieren; dass manche sogar ein Gesicht haben und ein Real Life, in dem ich auch die Chance sie zu treffen…

vcredist_x86.exe VC-2005 SP1 gibt es jetzt auch als separaten Download

Visual C++ 2005 Express Edition Nutzer mussten bislang in die Röhre sehen.
vcredist_x86.exe in der SP1 Version gab es nicht als separaten Download.
D.h. sie konnten den SP1 für VC++ 2005 Express Edition installieren und nutzen, aber Ihre Programme nicht mit der neuen SP1 CRT ausliefern.

Das ist nun vorbei:
http://www.microsoft.com/downloads/details.aspx?FamilyID=200B2FD9-AE1A-4A14-984D-389C36F85647&displaylang=en

Alle Nutzer des Visual Studios 2005 finden die Merge Module in Ihrem Verzeichnis C:\Programme\Gemeinsame Dateien\Merge Modules
bzw. hier als Executable
C:\Programme\Microsoft Visual Studio 8\SDK\v2.0\BootStrapper\Packages\vcredist_x86\vcredist_x86.exe

BTW: Die neue Datei benötigt auch nur die 2.0 Version des MSI und nicht die 3.0 Version die die RTM Version!
Weitere Infos und Links zu den 64bit Versionen gibt es auch auf Nikolar Dudars Blog.

Bug in CPropertyPage und „Certified for Vista“

Der von mir gemeldete Bug Bug in der MFC71.DLL bzgl. CPropertySheet/CPropertyPage führt dazu, dass ein Programm, dass den genannten Voraussetzungen entspricht, bei den Test für „Certified for Vista“ durchfällt!

Der Application Verifier führt bei den Basic Test einen Page Boundary Check durch. Dabei werden alle Allokationen so durchgeführt, dass sie immer am Ende einer Memory Page erfolgen. Jeder Zugriff über die Grenze hinweg führt dann zu einem Crash.

Im realen Leben ist der Crash wirklich selten, aber mit dem Application Verifier kracht es sofort. Das Problem ist, dass dieser Basic Test Bestandteil von „Certified for Vista“ ist.

Die Folge man rasselt mit 100% Sicherheit durch!

Bug Report hier:
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=270493

Dämlicherweise wurde auch dieser Bug von Microsoft als „Gelöst (Nicht reproduzierbar)“ markiert. Da kann man wirklich nurmit dem Kopf schütteln.

Und ein kleines Demo findet ihr hier:
Testprogramm für CPropertyPage Bug in MFC 7.1

Probleme bei der CTime Serialisierung mit MFC 7.1 und MFC 8.0

Der operator<< und operator>> in MFC 7.1 serialisiert grundsätzlich nur 32bit Werte des CTime. Das wurde offensichtlich gemacht um rückwärtskompatibel zu sein zu time_t obwohl mittlerweile ja intern __time64_t verwendet wird.
Gleichzeitig wurde Serialize64 eingeführt.
Man muss also in VS2003 mit MFC 7.1 Serialize64 verwenden um alle 64bit zu speichern, also den komplettem Wertebereich von CTime.

In VS2005 mit der MFC 8.0 ging man jetzt einen Schritt weiter. Die Operatoren operator<< und operator>> sollten auch 64bit verarbeiten können. Man wollte 64bit speichern und 32bit Daten beim Einlesen erkennen wenn es eben aus alten Dateien stammt und nicht mit der neuen MFC geschrieben wurde.

Dazu wird bei Speicherung von 64bit CTime über den operator<< zuerst ein DWORD gespeichert mit dem Wert cTime64Mark (der Wert ist INT_MIN+10). Danach der 64bit Wert.
Beim Lesen wird zuerst ein DWORD gelesen. Ist dieses nicht cTime64Mark (also INT_MIN+10), dann wird dieser Wert als 32bit CTime Wert gelesen.
Ansonsten werden die 64bit in den CTime Wert gelesen.

operator>> bläht also auch die Ausgabe um weitere 32bit auf. Ein 64bit CTime Wert wird in der MFC 8.0 als 32+64bit Wert gespeichert, also 4Bytes mehr.

Speicherst man mit MFC 7.1 und dem operator<<, dann kannst man die Daten in MFC 7.1 und MFC 8.0 mit dem operator>> lesen, denn der Wert wird wegen des fehlenden Leadin-Bytes als 32bit Wert in der MFC 8.0 erkannt.
Speicherst man aber mit MFC 8.0 und dem operator<< dann ist das für MFC 8.0 kompatibel. Und kannst es in MFC 8.0 mit dem operator>> lesen. Allerdings speichert – wie schon gesagt – MFC 8.0 zuerst ein DWORD (das Leadin für 64bit) und dann den 64bit Wert.
Das versteht nun MFC 7.1 gar nicht, denn das liest immer nur ein DWORD mit dem operator>>.

❗ Ein Problem liegt also im Schreiben unter MFC 8.0 mit dem operator<< und im Lesen der Daten mit einem Programm das die MFC 7.1 verwendet und den operator>>!

❓ Was kann man machen um komplett kompatibel zu sein?

  • Würde in beiden Programmen Serialize64 verwendet gibt es kein Problem!
    Wichtig Serialize64 verwendet kein Leadin weder unter MFC 7.1 noch unter MFC 8.0!
  • Kompatibel zu beiden Versionen von MFC 7.1 und MFC 8.0 ist man auch wenn in der MFC 7.1 und in der MFC 8.0 immer nur ein DWORD gespeichert wird (das kann ich aber wirklich nicht mehr empfehelen). Unter MFC 8.0 muss das manuell gemacht werden.
  • Wenn man also Code-kompatibel (nicht binärkomaptibel) für alle MFC Versionen ab 7.0 bleiben will sollte man immer Serialize64 verwenden was einem auch ein kompakteres Format beim Speichern der Daten garantiert.

Eigentümlich ist, dass dies nicht als Breaking Change dokumentiert ist.
Oder ich habe es (wie so manches) einfach überlesen, aber hier steht es nicht:
ATL and MFC Changes: ATL 7.1 and MFC 7.1
ATL and MFC Changes: ATL 7.0 and MFC 7.0

PS: Ich habe CTime Aufgrund der vielen Unzulänglichkeiten nie verwendet. Mein Favorit ist seit eh und je COleDateTime bzw. DATE und die dazugehörige COleDateTimeSpan Klasse. Diese ist wirklich einfach in der Kalkulation und war durch das Design nie von einem begrenzten Wertebereich betroffen.

Eigene Vorlagen sind nach Update auf Word 2007 verschwunden

Word 2007 ist anders. Aber dass es beim Update auch Dinge ändert die vorher eingestellt waren oder die Daten nicht übernimmt ist einfach ärgerlich.

Ich hatte eigene Vorlagen in dem Standard-Ordner von Office 2003:
C:\Dokumente und Einstellungen\Martin\Anwendungsdaten\Microsoft\Vorlagen 

Nach dem Update wurden mir diese alten Vorlagen nicht mehr angezeigt. Noch mehr! Auch meine alten Arbeitsgruppenvorlagen waren nicht mehr in der Liste der Vorlagen. 😮

Also geht man auf die Suche (wie so oft am Anfang mit Office 2007)…
Wo ist das ganze eingestellt?
Gefunden: Office-Schaltfläche, Word Optionen, ziemlich weit unten Dateispeicherorte.

Und… Erstaunen 🙄
Der neue Pfad heißt:
C:\Dokumente und Einstellungen\Martin\Anwendungsdaten\Microsoft\Templates

Und der Pfad für die Arbeitsgruppenvorlagen war auch leer…
Also Pfad gesetzt, Dateien umkopiert, es geht wieder alles wie gewohnt.

Meine beiden Traumräder: Street Machine GT + Delite Black

Jetzt habe ich sie beide: Meine Traumräder.

Über Jahre habe ich immer für sie geschwärmt. Vor 6 Jahren habe ich mir mein erstes Traumrad, eine Streetmachine GT gebraucht als Schnäppchen ergattert. Gerade mal 1 Jahr alt und nur 1500km. Zu denen habe ich nun weitere 15.000km in den letzten 6 Jahren hinzugefügt.

Jetzt habe ich mein zweites Traumrad auch wieder als Schnäppchen gebraucht bekommen. Ein Riese & Müller Delite Black, das ultimative Reiserad. 5 Jahre alt, ca. 3000km.

Und das sind meine Lieblinge:

StreetMachine GTStreet Machine GT von HP-Velotechnik Und hier das zweite Edelstück:

  • XT-8fach mit DuraAce Lenkerendschalthebel
  • Magura-HS33
  • Alesa-Explorer Felgen
  • Schwalbe Marathon Slick
  • Air-Flow Sitzauflage
  • Lowrider+Gepäckträger mitgefedert
  • Balistik Federgabel 450-AII vorne
  • DNM ST8-RC -Dämpfer mit Piggy-Bag hinten
  • Union Walzendynamo mit B&M Halogenlampe und Diodenrücklicht (beide mit Standlicht)

 

Delite BlackDelite Black von Riese & Müller

  • XT-9fach Komponenten
  • Magura Clara Scheibenbremsen
  • Mavic Disk Rims
  • Schwalbe Hurricane Kevlar
  • Terry Liberator Sattel
  • Pitlock Sicherung für Räder und Sattel
  • Lowrider+Gepäckträger mit gefedert
  • RST-Delta Comp Gabel vorne
  • Suspa RH-Pro Dämpfer hinten
  • SON Nabendynamo mit B&M Halogen- / Diodenlichtanlage mit Sensorschaltung und Standlicht

Einfach geil! 😎

Geschafft: Mein Software-Baby ist „Certified for Windows Vista“

Obwohl ich im Urlaub bin hat mich diese wirklich nette Nachricht von VeriTest erreicht:

Congratulations! AG-VIP SQL has successfully completed certification testing at VeriTest for the Microsoft “Certified for Windows Vista” logo program.

PS: Baby ist gut. AG-VIP SQL ist mittlerweile ein mittlerer Bolide… 😀

VS Tipps & Tricks: Blockmodus aus VC6 in VS.NET 2003 und VS 2005

Viele haben den Blockmodus (Box-Mode) in VC6 über die Tastatur benutzt. Diesen Modus erreichte man über die Tasten Strg+Umschalt+F8. Damit war es einfach Spalten und rechteckige Textbereiche zu markieren und zu bearbeiten.
Diese Operation konnte auch durch das Festhalten der Alt-Taste ausgelöst werden, wenn man mit der Maus den Cursor über einen Bereich zog.

Spätere Visual Studio Versionen haben dafür keinen direkten Hotkey mehr zwischen Box-Mode und Stream-Mode zu wechseln. Das Ganze wurde vereinheitlicht.
Ein Block wird markiert indem die Umschalt+Alt-Taste festgehalten werden und entsprechende Navigationstasten bewegt werden.
Eigentlich logisch und sogar dokumentiert, aber wer liest denn schon die Doku! 😛

http://msdn2.microsoft.com/en-us/library/aa301672(vs.71).aspx
http://msdn2.microsoft.com/en-us/library/729s2dhh(VS.80).aspx

Patch für CPropertyPage Bug der MFC71.DLL/MFC71U.DLL

Wer keinen neuen Build bezüglich des dieses Problemes Bug in der MFC71.DLL bzgl. CPropertySheet/CPropertyPage machen kann oder auch nicht seinen Sourcecode nach entsprechenden Konstruktoren durchsuchen kann und auf die ausgelieferten Versionen von Microsoft angewiesen ist, kann auch einen kleinen Patch durchführen.

MFC71.DLL aus SP1 Version 7.10.6030
Größe 1.060.864 Bytes, Dienstag, 11. Juli 2006, 18:43:32
Patch der Adressen
0x0008E9F0 von 0x89 0x38 -> 0x90 0x90
0x0008EA09 von 0x89 0x38 -> 0x90 0x90

MFC71U.DLL aus SP1 Version 7.10.6030
Größe 1.056.768 Bytes, Dienstag, 11. Juli 2006, 19:02:30
Patch der Adressen
0x000A1ACC von 0x89 0x38 -> 0x90 0x90
0x000A1AE5 von 0x89 0x38 -> 0x90 0x90

Gesucht werden kann auch nach der Sequenz 0x8B 0x46 0x74 0x89 0x38. Diese Sequenz kommt in der MFC.DLL genau zweimal vor.

Es entspricht dem folgenden Code:

8B 46 74 mov eax,dword ptr [esi+74h]
89 38 .. mov dword ptr [eax],edi

Weggepatch wird in diesem Falle einfach das Laden der Adresse (zweites mov Statement) und durch zwei NOP ersetzt.
Wer die entsprechende PDB Datei hat sieht im Disassembly hier das Statement
m_psp.dwSize = sizeof(m_psp);
Der Bug befindet sich in der Datei dlgprop.cpp in den Zeilen 184 und 189!

Anwendung auf eigene Gefahr!

Bug in der MFC71.DLL bzgl. CPropertySheet/CPropertyPage

Ich habe ein Projekt, dass einen eigenen MFC Build verwendet. Dieser basiert zu 99,999% auf dem MFC71 SP1 Build aus VC-2003.NET. Das dies ein eigener Build ist spielt für den Bug allerdings keine Rolle, allerdings evtl. für die Lösung.

Zu den Rahmenbedingungen. Man baut eine EXE/DLL mit folgenden Eigenschaften:

  • _WIN32_IE< =0x0500.
  • Verwendet die DLL-Version der MFC (Use MFC in a Shared DLL)
  • Man verwendet CPropertyPage und CProprtySheet als Wizard.
  • Man verwendet Header-Titel und Header-Subtitel und damit einen der beiden nachfolgenden Konstruktoren:
    CPropertyPage(UINT nIDTemplate, UINT nIDCaption, UINT nIDHeaderTitle, UINT nIDHeaderSubTitle = 0, DWORD dwSize = sizeof(PROPSHEETPAGE));
    CPropertyPage(LPCTSTR lpszTemplateName, UINT nIDCaption, UINT nIDHeaderTitle, UINT nIDHeaderSubTitle = 0, DWORD dwSize = sizeof(PROPSHEETPAGE));

Die MFC71.DLL ist so gebaut, dass sie mit allen 3 Versionen der PROPSHEETPAGE Struktur klar kommen soll. Es gibt drei Versionen, die mit folgenden _WIN32_IE Definitionen unterschieden werden:

  • für WIN32_IE<0x0400, die aller erste Version die mit Windows 95 kam. Größe 40 Bytes.
  • für WIN32_IE>=0x0400 && _WIN32_WINNT<=0x0500, hier wurden Titel und Subtitel hinzugefügt (pszHeaderTitle, pszHeaderSubTitle). Größe 48 Bytes.
  • und zuletzt _WIN32_WINNT>=0x0501, hier kam noch ein Activation-Context dazu (hActCtx). Größe 52 Bytes.

Was passiert nun:

  • Einer der genannten Konstruktoren für die CPropertyPage wird aufgerufen.
  • Der letzte Parameter sizeof(PROPERTYPAGE) zeigt nun der DLL an welche Version das aufrufende Programm verwendet, damit die MFC71.DLL die entsprechenden Größen bereitstellt.
  • AllocPSP wird entsprechend aufgerufen und dynamisch diese PROPERTYPAGE allokiert.

Bis hierher ist alles prima, aber leider passiert es un, dass diese vordefinierte Größe in der Funktion CommonConstruct(LPCTSTR lpszTemplateName, UINT nIDCaption, UINT nIDHeaderTitle, UINT nIDHeaderSubTitle) überschrieben wird (Zeile 184+189 in dlgprop.cpp). Das passiert mit dem Statement:
m_psp.dwSize = sizeof(m_psp);
D.h. die PROPERTYPAGE Struktur ist mit weniger als 40 oder 48 Bytes allokiert. Im dwSize Member steht aber nun 52.
In der Funktion BuildPropPageArray() wird nun aus den einzelnen PROPERTYPAGE’s ein Array gebildet. Dabei werden jeweils dwSize-Bytes (also 52) aus den entsprechenden allokierten Bereichen kopiert. Aber Achtung, diese sind kleiner allokiert (40 oder 48 Bytes)
In der Debug Version ist das oft nicht tragisch, denn da kommen hinten dran noch einige Füllbytes. Auch in der Release Version kracht es nur manchmal. Genau nur dann, wenn einer der allokierten PROPERTYPAGE Strukturen genau auf mit einer allokierten Speicherseite endet und das 49ste Byte der Struktur eben nicht allokiert ist und die Speicherseite exakt hier endet.

Diese sehr üble Konstellation machte es mir extrem schwer diesen Fehler zu finden. Ich hasse es einfach optimierten Code zu debuggen 😉

Fix:

  • Keinen der obigen Konstruktoren verwenden und die Member m_strHeaderTitle und m_strHeaderSubTitle selbst füllen.
  • oder wie ich einen eigenen MFC Build erzeugen und verwenden. Die entsprechenden Code Zeilen 184+189 aus der dlgprop.cpp entfernen.

Hinweis:
Crashdumps zeigen meistens im Stacktrace die Funktionen BuildPropPageArray und memcpy!

BTW:
Dieser Bug betrifft sowohl die MFC71.DLL im RTM und im SP1.
In der MFC 8.0 des VS-2005 ist dieser Bug behoben.