Selten blöd

Heute bin ich mal der Ursache auf den Grund gegangen, warum SpeedCommander bei einem Absturz .dmp-Dateien erzeugt, die nur 0 Byte groß sind und keine Informationen enthalten. Eigentlich hatte ich die Funktion ja vorher gestestet. Dann fand ich dieses:

// Dump erzeugen
HANDLE hDumpFile = CreateFile(szDumpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
if (INVALID_HANDLE_VALUE != m_hReportFile)
{
    ....
}

Ziemlich dumm gelaufen. Das zeigt wieder einmal, dass man Funktionen nicht nach dem Testen optimieren sollte sondern vorher.

Aus und vorbei

Letztes Jahr im April hatte ich euch von den Problemen mit meinem Matrix-RAID berichtet. Nach einem Tip von Christof Windeck hatte ich es dann noch einmal versucht und ab da lief das RAID auch ziemlich problemlos. Vor zwei Wochen fing es aber wieder an herumzuzicken. Völlig überraschend verabschiedete sich Vista mit einem BSOD und der Meldung

***STOP: 0×00008086 (0×00000000, 0×00000000, 0×00000000, 0×00000000)

Die Ursache war mir völlig unklar. Keine neue Hardware, kein BIOS-Update, keine neuen Treiber. Nach einem Neustart überprüfte der Intel Storage Manager das RAID-1 auf Beschädigungen. Das läuft zwar unter Windows im Hintergrund, allerdings ist aufgrund der hohen Festplattenbelastung kein normales Arbeiten möglich. Lässt man den Rechner in dieser Zeit in Ruhe, ist die Aktion in einer reichlichen Stunde vorbei.

Sicherheitshalber spielte ich das letzte Image von Ende November zurück, welches ja von da bis eben auch fehlerfrei gearbeitet hat. Geholfen hat das aber nicht, zwei weitere BSOD folgten in unterschiedlichen Abständen. Zudem fror der Rechner nun auch das eine oder andere Mal kurz ein und die Festplattenleuchte zeigte sich dabei im Dauerbetrieb. Mal erholte sich der Rechner wieder, mal half nur noch der Reset-Schalter. Im letzteren Fall folgte wieder eine Überprüfung durch den Intel Storage Manager. Und bei jedem Zwischenfall tauchte in der Ereignisanzeige teilweise mehrfach die Meldung

Das Gerät \Device\Ide\iaStor0 hat innerhalb der Fehlerwartezeit nicht geantwortet.

auf. Keine Ahnung, woher das plötzlich kam.

Normalerweise lasse ich mir Entscheidungen ja nicht vom Rechner aufdrängen, aber in diesem Fall hat er jetzt endgültig gewonnen. Eine neue Platte hat die zwei RAID-Platten verdrängt. Nach dem Kopieren der Daten und dem Zurückspielen der letzten Images läuft nun alles wieder (auch ohne Neuinstallation). Für den ersten Start musste ich noch den RAID-Modus aktiviert lassen, wobei die neue Platte wie auch zuvor meine zweite Datenplatte als Non-RAID angeschlossen war. Für die Umstellung auf AHCI brauchte ich nur die von Media Addicted zur Verfügung gestellte REG-Datei doppelklicken (IaStor.sys war ja bereits installiert) und den IDE-Modus im BIOS von RAID auf ACHI stellen. Vista war auch großzügig gestimmt und verzichtete auf eine neue Zwangsaktivierung.

Mag sein, dass die RAID-Probleme auch auf das Board zurückzuführen sind. Mal schauen, ob es ohne RAID jetzt ruhiger zugeht.

Vista SP1 auf MSDN verfügbar

MSDN-Abonnenten können ab sofort das Service Pack 1 für Vista herunterladen. Im Angebot sind

  • Windows Vista Service Pack 1 (x86, x64) – DVD (English, French, German, Japanese, Spanish)
  • Windows Vista Service Pack 1 (x86) – EXE (English, French, German, Japanese, Spanish)
  • Windows Vista Service Pack 1 (x64) – EXE (English, French, German, Japanese, Spanish)

Die Links findet ihr in der Liste mit den Top Subscriber Downloads.

Zweitklassige Zertifikate

Meine eMail an Winqual wurde schnell beantwortet. Die Anmeldung sowie die Nutzung von Winqual ist nur mit einem von VeriSign ausgestellten Code Signing-Zertifikat möglich. Nur mit einem VeriSign-Zertifikat kann sichergestellt werden, dass die Dateien von mir stammen. Andere gleichwertige Zertikate von GlobalSign oder Thawte werden nicht akzeptiert.

Das heißt also, dass Microsoft nur von VeriSign ausgestellte Zertifikate als vertrauenswürdig erachtet. Ein Code Signing-Zertifikat kostet bei VeriSign $499, bei Verwendung eines Links auf der Winqual-Seite erhält man $100 Rabatt und zahlt nur $399. Ein von Thawte ausgestelltes Zertifikat kostet $299, bei GlobalSign zahlt man im Moment $229. Das ausgestellte Zertifikat ist ein Jahr gültig, nach Ablauf dieses Jahres muss es zu ähnlichen Preisen erneuert werden. Thawte wurde übrigens 2000 von VeriSign gekauft, läuft aber als eigene Marke weiter.

Diese exklusive Zusammenarbeit mit VeriSign ist vielleicht auch ein Grund dafür, dass beim Einsenden von Fehlerberichten an Microsoft meistens der Hinweis kommt, dass für das Problem keine Lösung bekannt ist. Schade eigentlich.

HTML wirkt

Kürzlich bin ich über die Windows Quality Online Services gestolpert. In Verbindung mit dem Windows Error Reporting (WER) kann ein Softwarehersteller Zugriff auf die von Anwendern eingeschickten Fehlerreports erhalten, diese analysieren und gegebenenfalls Lösungsvorschläge einstellen, die dann dem Anwender als Lösung präsentiert werden.

Meine Frage ließ sich leider nicht mit der FAQ lösen, also schrieb ich eine eMail an die empfohlene Adresse. Wenige Sekunden später kam eine Nichtzustellungsnachricht zurück, mit folgenden Zeilen:

This message was created automatically by mail delivery software.

A message that you sent could not be delivered to one or more of its
recipients. This is a permanent error. The following address(es) failed:

winqual@microsoft.com
SMTP error from remote mail server after end of data:
host mailc.microsoft.com [131.107.115.214]: 550 5.7.1 Your e-mail was rejected by an anti-spam content filter on gateway (131.107.115.214). Reasons for rejection may be:
obscene language, graphics, or spam-like characteristics. Removing these may let the e-mail through the filter.

Meine Anfrage enthielt weder obszöne Wörter noch Anhänge, zudem lese und verschicke ich alle eMails generell nur als Text. Aber das ist wohl ein Fehler. In einem zweiten Versuch habe ich die gleiche Anfrage noch einmal verschickt, diesmal als HTML verpackt. Statt dem Nichtzustellungshinweis kam diesmal eine eMail vom Autoresponder. Mal schauen, ob die eigentliche Antwort auch noch folgt.

Unwohl

Ich hätte ja nie geglaubt, dass es einmal so weit kommen würde. Gerade musste ich für ein paar Minuten wieder mit dem VC 6 arbeiten, weil ich einem Problem in SpeedCommander 11 auf den Grund gehen wollte. Die letzte Begegnung mit dem VC 6 liegt schon mehr als zwei paar Monate zurück.

Während der ganzen Zeit habe ich mich dabei ziemlich unwohl gefühlt und kam mir richtiggehend verloren vor. Also den VC 6 ganz schnell wieder schließen und zurück zum geliebten VS 2008.

Statische Codeanalyse zum Nulltarif

Die Windows-Programmierer unter euch werden sicher auch festgestellt haben, dass sich Funktionsdefinitionen in den Header-Dateien vom Platform Windows SDK in den letzten Versionen etwas verändert haben. Hieß es bei Windows XP noch

WINBASEAPI
UINT
WINAPI
GetTempFileNameW(
    IN LPCWSTR lpPathName,
    IN LPCWSTR lpPrefixString,
    IN UINT uUnique,
    OUT LPWSTR lpTempFileName
    );

so schaut die Definition im Windows SDK für Server 2008 so aus:

WINBASEAPI
UINT
WINAPI
GetTempFileNameW(
    __in LPCWSTR lpPathName,
    __in LPCWSTR lpPrefixString,
    __in UINT uUnique,
    __out_ecount(MAX_PATH) LPWSTR lpTempFileName
    );

An den Funktionsparametern selbst hat sich natürlich nichts verändert, aber die neuen Präfixe fallen doch ins Auge. Anfangs habe ich mir dabei nicht viel gedacht, aber mittlerweile hat sich mir der tiefere Sinn der Änderungen erschlossen.

Alles hängt mit der Standard Annotation Language (SAL) zusammen. In Verbindung mit einem statischen Codeanalyse-Tool lassen sich so mögliche Programmierfehler schon beim Kompilieren ermitteln. Auch wenn sich ein Projekt unter höchster Warnstufe ohne Warnungen kompilieren lässt, so heißt dies noch lange nicht, dass alles sauber ablaufen muss.

Leider ist das statischen Codeanalyse-Tool den höherpreisigen Visual Studio-Versionen Team System und Team Edition for Developers vorbehalten. Die Team Edition for Developers kostet aber locker 5000 Euro mehr als die Professional Edition, was für den normalen Entwickler ziemlich unerschwinglich sein dürfte.

Abhilfe schafft hier das Windows SDK für Vista sowie das für Server 2008. Beide enthalten die vollständige Compilersammlung von Visual Studio 2005 bzw. Visual Studio 2008 samt Codeanalyse-Tool. Für die Codeanalyse sind die Dateien c1ast.dll, c1xxast.dll, mspft80.dll und mspft80ui.dll zuständig. Die ersten drei Dateien befinden sich unter VC\bin, die letzte enthält die englischsprachigen Ressourcen und ist unter VC\bin\1033 zu Hause.

Nachdem man die vier Dateien an den entsprechenden Ort kopiert hat, muss die Codeanalyse nur noch aktiviert werden. In der Team Edition for Developers gibt es dafür eine Seite in den Projekteigenschaften, in der Professional Edition muss man den Kommandoschalter /analyze unter Configuration Properties – C/C++ – Command Line manuell eintragen.

Was macht die Codeanalyse nun so interessant? Nehmen wir einfach mal die oben angesprochene Funktion GetTempFileNameW. Die Verwendung könnte so aussehen:

29: WCHAR szTempFileName[240];
30: GetTempFileNameW(L”C:\\”, NULL, 1, szTempFileName);

Der Compiler hat hier nichts auszusetzen, selbst bei /W4 gibt es keine Warnungen. Aktiviert man aber die Codeanalyse, dann sieht man plötzlich folgende Warnhinweise:

: warning C6202: Buffer overrun for ‘szTempFileName’, which is possibly stack allocated, in call to ‘GetTempFileNameW’: length ’520′ exceeds buffer size ’480′
:warning C6309: Argument ’2′ is null: this does not adhere to function specification of ‘GetTempFileNameW’
: warning C6386: Buffer overrun: accessing ‘argument 4′, the writable size is ’480′ bytes, but ’520′ bytes might be written: Lines: 29, 30
: warning C6387: ‘argument 2′ might be ’0′: this does not adhere to the specification for the function ‘GetTempFileNameW’: Lines: 29, 30

Anhand der Definition von GetTempFileNameW erkennt der Compiler, dass die Funktion als vierten Parameter einen Puffer von mindestens 260 Zeichen erwartet, der Programmierer aber aus unerklärlichen Gründen nur einen Puffer von 240 Zeichen bereitgestellt hat. Ist der gewünschte temporäre Dateiname nun länger als die zur Verfügung stehenden 240 Zeichen, dann führt dies zu einem sicheren Pufferüberlauf.

Der Grund für die zweite Warnung ist der zweite Funktionsparameter. __in legt fest, dass lpPrefixString ein gültiger und initialisierter Zeiger sein muss. Der Compiler erkennt, dass NULL nicht in diese Kategorie passt und weist uns darauf hin. NULL wäre nur gültig, wenn lpPrefixString stattdessen mit __in_opt gekennzeichnet sein würde.

Insgesamt hat die statische Codeanalyse über 130 verschiedene Warnhinweise in petto. Sie erkennt z.B., wenn HRESULT-Werte in booleschen Vergleichen verwendet werden:

CAtlFile file;
if (!file.Create(L”C:\\test.txt”, GENERIC_READ, FILE_SHARE_READ, CREATE_ALWAYS))
{
//
}

oder wenn eine Funktion Variablen enthält, die unverhältnismäßig viel Platz auf dem Stack belegen:

WCHAR szTempFileName[32768];
GetTempFileNameW(L”C:\\”, L”123″, 1, szTempFileName);

Mich selbst haben die Möglichkeiten der statischen Codeanalyse mehr als begeistert. Wenn man sich die möglichen 138 Warnungen so anschaut, dann entdeckt man viele Sachen, die man gerne mal falsch macht und über die man auch schon das eine oder andere Mal gestolpert ist. In der nächsten Zeit werde ich daher meine Projekte Stück für Stück mit /analyze kompilieren und die angezeigten Warnungen abarbeiten. Im zweiten Schritt werden dann die eigenen Funktionen mit den SAL-Parametern versehen.

Vorsicht beim Windows SDK für Windows Server 2008

Ich musste gerade feststellen, dass sich das Windows SDK für Windows Server 2008 bei der Installation anders verhält als frühere Versionen und damit auch anders als erwartet. Bisher wurden die Compiler-Dateien immer in ein Verzeichnis unterhalb des SDK-Installationsordners installiert und das Visual Studio-Verzeichnis blieb unverändert.

Doch die Suche nach dem Compiler-Verzeichnis blieb diesmal erfolglos, obwohl ich die entsprechende Option beim Installationsdialog angekreuzt hatte. Auch eine Reparaturinstallation brachte das Verzeichnis nicht zum Erscheinen.

Aufklärung brachte ein Blick in das Visual Studio 2008-Verzeichnis. In diesem befanden sich plötzlich auch die IA64-Compiler, welche eigentlich kein Bestandteil von VS 2008 Professional sind. Ärgerlicherweise wurden aber auch alle von mir angepassten include- und lib-Dateien überschrieben, die für die angepasste Laufzeit benötigt werden. Zum Glück hatte ich noch eine Spiegelinstallation auf dem Laptop.

Also: Vorsicht bei der Installation des Windows SDK für Windows Server 2008, sofern man angepasste Dateien verwendet!

Windows XP SP4 in Planung?

Beim Stöbern durch die Headerdateien vom Windows SDK für Windows Server 2008 findet man wundersame Dinge:

#define NTDDI_WINXP              0x05010000
#define NTDDI_WINXPSP1           0x05010100
#define NTDDI_WINXPSP2           0x05010200
#define NTDDI_WINXPSP3           0x05010300
#define NTDDI_WINXPSP4           0x05010400
 
#define NTDDI_WS03               0x05020000
#define NTDDI_WS03SP1            0x05020100
#define NTDDI_WS03SP2            0x05020200
#define NTDDI_WS03SP3            0x05020300
#define NTDDI_WS03SP4            0x05020400
 
#define NTDDI_WIN6               0x06000000
#define NTDDI_WIN6SP1            0x06000100
#define NTDDI_WIN6SP2            0x06000200
#define NTDDI_WIN6SP3            0x06000300
#define NTDDI_WIN6SP4            0x06000400
 
#define NTDDI_VISTA              NTDDI_WIN6  
#define NTDDI_VISTASP1           NTDDI_WIN6SP1
#define NTDDI_VISTASP2           NTDDI_WIN6SP2
#define NTDDI_VISTASP3           NTDDI_WIN6SP3
#define NTDDI_VISTASP4           NTDDI_WIN6SP4
 
#define NTDDI_WS08               NTDDI_WIN6SP1
#define NTDDI_WS08SP2            NTDDI_WIN6SP2
#define NTDDI_WS08SP3            NTDDI_WIN6SP3
#define NTDDI_WS08SP4            NTDDI_WIN6SP4

Neben der neuen Konstante NTDDI_WINXPSP3 für das Windows XP Service Pack 3 taucht erstaunlicherweise auch NTDDI_WINXPSP4 auf, welche logischerweise nur für Windows XP Service Pack 4 stehen kann. Steckt da nun etwas Ernstes dahinter oder hatte der Autor der sdkddkver.h nur eine Vorliebe für schön formatierte Fünfergruppen?

SpeedCommander 12.10 verfügbar

Wer mag, der kann sich die finale Version 12.10.5270 herunterladen. Seit der Freigabe der öffentlichen Betaversion wurden nur noch kleinere Fehler beseitigt.

Bei einem Absturz erstellt SpeedCommander 12.10 ab sofort zusätzlich zur .rpt-Datei mit den Informationen zum Absturz auch ein Mini-Speicherabbild. Das Mini-Speicherabbild (.dmp) wird unter dem gleichen Dateinamen wie die .rpt-Datei abgespeichert. Ich bin mal gespannt, ob sich Abstürze damit leichter lokalisieren lassen. Erste Versuche verliefen recht vielversprechend.