...someplace, where there isn't any trouble? Do you suppose there is such a place, Toto?

Dialoge aus credui.dll benutzen...

So, der ist jetzt für den Löselic, wie versprochen.

Irgendwie gewinne ich den Eindruck, als hätte sich noch nicht überall rumgesprochen, daß unter XP und seinen Nachfolgern die Möglichkeit besteht, die Authentifizierungsdialoge des Systems, ähnlich den "Common Dialogs" aus comdlg32.dll, auch für das UI der eigenen Programme zu benutzen.

Aussehen kann das dann etwa so:

Credui Beispiel

Und der Code, der dazu erforderlich ist (ein VC6-Projekt kann man hier runterladen), ist wirklich trivial:

#include <windows.h>
#include <wincred.h>
#include <tchar.h>
#include <stdio.h>

#ifndef dimof
#define dimof(a) (sizeof(a)/sizeof(a[0]))
#endif // dimof


int _tmain(int /*argc*/, LPCTSTR * /*argv*/ [])
{

    TCHAR szUser[CREDUI_MAX_USERNAME_LENGTH+1];
    ULONG ulUserMaxChars = dimof(szUser);
    TCHAR szPwd[CREDUI_MAX_PASSWORD_LENGTH+1];
    ULONG ulPwdMaxChars = dimof(szPwd);
    BOOL bSaveState = FALSE;
    DWORD dwFlags = CREDUI_FLAGS_DO_NOT_PERSIST|
                    CREDUI_FLAGS_GENERIC_CREDENTIALS|
                    CREDUI_FLAGS_ALWAYS_SHOW_UI;
    szUser[0] = szPwd[0] = _T('\0');


    if (NO_ERROR == CredUIPromptForCredentials
        (NULL, _T("this bloody Computer!"), NULL, ERROR_SUCCESS, 
         szUser, ulUserMaxChars, szPwd, 
         ulPwdMaxChars, &bSaveState, dwFlags))
        _tprintf(_T("You typed:\nuser: %s\npassword:%s\n"), 
                     szUser, szPwd);
    else
        _tprintf(_T("You idiot, you cancelled this dialog!\n"));


    return 0;
}

...und voila, man hat einen richtig amtlichen Windows-Authentifizierungsdialog. Wenn man jetzt noch total TSUnami-mäßig drauf ist, kann man den Dialog sogar noch a bissal pimpen und ihm im Header ein mehr oder minder hübsches Bitmap unterjubeln, um so das eigene CD auch noch zu verbreiten. Ich glaube allerdings, daß damit der Effekt des offiziell amtlichen Authentifizierungsdialogs doch ein wenig verloren geht. YMMV.

Das einzige, worauf man wirklich achtgeben muß, ist, daß das so nur unter XP und höher funktioniert. Wenn der Code auch unter Windows 2000 und NT4 funktionieren muß, muß man folgendes ergänzen:

  • Alternativcode mit einem eigenen Dialogtemplate, das verwendet wird, wenn die credui.dll nicht geladen werden kann
  • Delayload von credui.dll

Das Codebeispiel hier benutzt das CredUIPromptForCredentials API natürlich nur in einer äußerst generischen Form. Man kann mit diesem API aber auch einen Credentials Store des Betriebssystems benutzen und noch andere Gimmicks und Spielereien, aber ich hatte ehrlich gesagt noch nie das gesteigerte Bedürfnis, da näher nachzuforschen. Und ja, mit VC6 "out-of-the-box" geht das alles natürlich auch nicht, man braucht mindestens das Windows XP PlatSDK von 2001.

This news just in...

Es gibt ein paar bemerkenswerte Neuigkeiten aus επτ€σ Mission Control. Zum einen haben wir jetzt ein absolut hochoffizielles Türschild mit "Mission Control" drauf, unseren Namen, und unseren Dienstgraden, nämlich für mich den EMCSC und für meinen treuen Deputy den EMCSCD. Die Abkürzungen stehen natürlich für επτ€σ Mission Control Supreme Commander und επτ€σ Mission Control Supreme Commander Deputy. Und so schaugt das Türschild aus, für den Fall, daß uns das 'mal wieder keiner abnimmt:


Tausend Dank für dieses tolle Türschild schuldet Mission Control dem unermüdlichen Darth Ännchen. Ännchen ist einfach Supersonderextraklasse, auch wenn sie manchmal unter Apostrophenkatastropheritis leidet. Schade nur, daß ich irgendwie so ein komisches Gefühl im Urin habe, als ob es Mission Control in seiner jetzigen Form nimmer lang geben wird. Aber dazu mehr wenn irgendwas spruchreif wird.

Als nächstes hätten wir eine echte Innovation in Mission Control. Das bisherige Laserschwert, nunmehr ziemlich genau drei Jahre alt, hat einen kleinen, schicken Bruder bekommen. Genauer gesagt, haben wir jetzt ein Original Star Wars Merchandising Light Saber vom Typ "Obi Wan". Das macht erotisierende Lichteffekte und hat den Original Star Wars Light Saber Sound wie in den Filmen. Und wenn man jemanden mit dem Laserschwert trifft, geht ein kleiner Vibrator (huestel) in dem Laserschwert los. Da Mission Control ja eigentlich aus zwei gestandenen Elektrotechnikingenieuren besteht, könnte vielleicht sein, daß wir das Ganze noch a bissal pimpen und zusätzlich ein Elektroschockfeature einbauen. Aber dieses Feature müssen wir erst noch "schneiden" und dann einen "Domain Walkthrough" machen (oder andersrum? Ach egal...).

Auf jeden Fall, without any further ado, hier mein treuer Deputy mit dem alten Laserschwert:


... und hier mit dem neuen Laserschwert:


Schließen möchte ich dieses Blogposting mit den weisen Worten eines der gegenwärtig ca. 300 hochbegeisterten Lesern dieses Blogs, der mir in einer Email zu meiner 10.000€-Frage Folgendes ins Stammbuch schrieb:

"Wahrscheinlich kann man das auch nur verstehen, wenn man sich wie ein kleines Kind freuen kann, wenn EMCSC auf seinem Türschildchen steht."

 

Und das trifft die Sache so ziemlich haargenau ins Schwarze.

Auflösung der 10.000?-Frage

Der Ansturm von Antworten war ja geradezu überwältigend, die Spekulationen sind ins Kraut geschossen und so manch einer hat sogar noch mit einer möglichen Antwort gezögert, weil er/sie nicht so recht wußte, wie man eine politisch korrekte Antwort findet auf das Problem mit den 10.000€. Aber ich will Euch nicht länger auf den Volker spannen und gebe jetzt hier die Antwort:

Es kann nur der schlechte Projektleiter sein, der die 10.000€ gewinnt und man kommt mit etwas gesundem Menschenverstand und systematischem Ausschließen eigentlich recht einfach auf die Gründe, warum es nur der schlechte Projektleiter sein kann und nicht der gute Projektleiter und auch nicht der Testingenieur und auch nicht der Systemarchitekt:

  • Es gibt keine guten Projektleiter
  • Dem Testingenieur waren die Spielregeln zu kompliziert
  • Für läppische 10.000€ macht doch ein Systemarchitekt keinen Finger krumm

Wer gewinnt die 10.000??

Heute 'mal 'n Joke in Abwandlung eines Medizinerwitzes (Danke Caro, credits, where credits are due):

Wir sind auf einem Fussballplatz, der SGL hat 10.000€ gestiftet und bei jeder Eckfahne steht eine der folgenden Personen: Ein Testingenieur, ein guter Projektleiter, ein schlechter Projektleiter und ein Systemarchitekt. Die 10.000€ sind am Anstoßpunkt deponiert und auf Kommando müssen alle vier loslaufen. Wer zuerst am Anstoßpunkt ist, bekommt die 10.000€. Wer gewinnt die Knete und warum?

Zuschriften als Email werden nicht akzeptiert, nur Postings hier in diesem Blog. Und TDE ist außer Konkurrenz und darf nicht mitraten.

64 bit Windows - Teil 7

Auweia - es sind schon dreieinhalb Wochen her seit meinem letzten Blogposting zum Thema 64 bit Windows her. Höchste Eisenbahn also, wieder was Erhellendes zum Thema beizutragen. Diesesmal geht's um die Größen von Datentypen. Das ist dann nämlich die perfekte Überleitung zum Thema "Beliebte Fehler beim Portieren auf x64". Um das Thema näher zu illustrieren, habe ich, wie es so meine Art ist, eine kleine Kommandozeilenapplikation geschrieben, die man sich hier mit Sourcen und x86 und x64 Targets runterladen kann. Der Code für das Ganze sieht so aus:

#include <windows.h>
#include <stdio.h>
#include <conio.h>

typedef struct _TYPE_SIZE
{
    size_t m_stSize;
    LPCSTR m_szType;
}
TYPE_SIZE, *PTYPE_SIZE;

#define CRT_ENTRY(a) {sizeof(a), #a}
#define dimof(a) (sizeof(a)/sizeof(a[0]))

const TYPE_SIZE g_typesize[] = 
{
    CRT_ENTRY(size_t),
    CRT_ENTRY(LPBYTE),
    CRT_ENTRY(int),
    CRT_ENTRY(long),
    CRT_ENTRY(short),
    CRT_ENTRY(char),
    CRT_ENTRY(DWORD),
    CRT_ENTRY(WORD),
    CRT_ENTRY(LPARAM),
    CRT_ENTRY(WPARAM),
    CRT_ENTRY(LRESULT),
    CRT_ENTRY(INT_PTR),
    CRT_ENTRY(UINT_PTR),
    CRT_ENTRY(LONG_PTR),
    CRT_ENTRY(LONGLONG),
    CRT_ENTRY(ULONG_PTR),
};

int main(int /*argc*/, char* /*argv*/[])
{
    for (int i = 0; i<dimof(g_typesize); i++)
        printf("%s\t%ld bit\n", g_typesize[i].m_szType, 
            g_typesize[i].m_stSize*8);

    printf ("\nINVALID_HANDLE_VALUE is 0x%I64x\n", INVALID_HANDLE_VALUE);
	return 0;
}

Der geneigte Leser erkennt sofort, daß der Code über ein konstantes Array einer Struktur iteriert, die in einem member die Größe eines Elements und im anderen einen konstanten String mit dem Namen des Typs beinhaltet. Und ganz zum Schluß wird nochmal der Wert der Konstanten INVALID_HANDLE_VALUE ausgegeben.

Auf dem nächten Bild sieht man den Output des Programms, wenn es für Win32 auf x86 gebuildet wurde:

Dieses Ergebnis dürfte eigentlich niemanden verwundern. Aber das Ergebnis desselben Programms, wenn es für x64 gebuildet wurde, hätte mich vor gut einem Jahr noch ziemlich verdutzt:

Daß ein Pointer nun 64 bit breit ist, war ja nun wirklich zu erwarten, denn das ist es ja schließlich, was wir wollen, einen 64-bit breiten Adreßraum. Aber daß ein int und ein long immer noch die Größe eines DWORD haben, nämlich 32 bit, das hat mich dann doch extrem verwirrt, denn traditionell geht man ja davon aus, daß ein int immer so groß ist wie ein Register des Mikroprozessors. So war beispielsweise unter Win16 und MS-DOS als Targets, ein int so groß wie ein short, nämlich 16 bits. MS-DOS lief minimal auf dem Intel 8088/8086 Prozessor und Win16 minimal als Windows 3.x im Standard Mode auf einem Intel 80286 im 80286-Protected Mode, und beidesmal waren die Register 16 bit breit. Daher der int als 16 bit großer Typ. Win32 unter x86 nutzte dann die volle Registerbreite des 80386 Prozessors im 80386 protected mode und hatte daher den int native als 32 bit breiten Typ. Also sollte man doch nun annehmen, daß auf einem x64 Rechner die volle Registerbreite von 64 bits für einen int ausgenutzt wird. Pustekuchen!

Ja aber warum denn nun das? Raymond Chen,"who is, by the way, the best programmer in the world" (so Joel Spolsky) hat die Antwort. Es zerstört die Kompatibilität und viele Aplikationen würden einfach nicht mehr korrekt laufen nach dem Portieren, wenn ein int oder ein long plötzlich 64 bit breit sind. Dazu kommt, daß viele Applikationen den int in einer Weise verwenden, wo sie die 2^32 möglichen Werte gar nie ausnutzen und so auch erst recht nicht von nun 2^64 Werten profitieren würden, wenn der int nun 64 bits groß wäre. Der einzige Seiteneffekt der in diesem Fall bliebe, wäre eine lächerliche Aufblähung von Daten auf unnötig großen Speicherbedarf. Das Ganze ist auch in keinster Weise ein Verstoß gegen irgendwelche Standards, obwohl man das ja nun MS unterstellen könnte, denn auf 64-bittigen Unices ist der int tatsächlich 64 bits breit. Aber der C Standard sieht wirklich nur vor, daß ein int mindestens 16 bit breit sein muß und das war's dann.

Sodele, wahrscheinlich schreibe ich dann das nächste Mal was über diese komischen Typen im Code oben namens INT_PTR, LONG_PTR und ULONG_PTR, oder ich schreibe was über die Top Ten meiner Fehler beim Portieren von x86 binaries auf x64 binaries.

<< 1 ... 35 36 37 38 39 40 41 42 43 44 45 46 >>