Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Unicode Eingabe einlesen (https://www.delphipraxis.net/85408-unicode-eingabe-einlesen.html)

Luckie 30. Jan 2007 13:41


Unicode Eingabe einlesen
 
Ich versuche gerade eine Eingabe von der Konsole zu lesen:
Code:
#include "stdafx.h"
#include <windows.h>

#define INFO _T("Ausgabe der SIDs zu einem principal\n")
#define PRINCIPAL _T("Principal (z.B. Benutzername): ")

int _tmain(int argc, _TCHAR* argv[])
{
   PWSTR principal;
   wprintf(INFO);
   wprintf(PRINCIPAL);
   wscanf(L"%s", &principal);
   wprintf(L"%s\n", principal);
   getchar();
   return 0;
}
Aber wenn er die Eingabe ausgeben soll, kommt es zu einer Zugriffsverletzung. Was mache ich da falsch? Die Eingabe soll spätermal an eine Funktion übergeben werden.

bigg 30. Jan 2007 13:53

Re: Unicode Eingabe einlesen
 
Zeile12: Welche Adresse liefert &principal?
Oben arbeitest du mit #define, vermute mal das es dadurch knallt. (ungetestet)

shmia 30. Jan 2007 13:54

Re: Unicode Eingabe einlesen
 
Ha! ein Abtrüniger C-Programmierer.
Die Strafe folgt sogleich:
Code:
   PWSTR principal; // das ist nur ein Zeiger, für den niemand einen Speicherplatz reserviert hat
Mit Delphi wäre das nicht passiert. :-)

Luckie 30. Jan 2007 14:25

Re: Unicode Eingabe einlesen
 
Auch wenn ich das ändere geht es nicht. Aber so geht es:
Code:
   wchar_t principal[80];
   wprintf(INFO);
   wprintf(QUERYINPUT);
   wscanf(L"%s", &principal);
   wprintf(L"%s\n", principal);
   getchar();
   return 0;
Das ganze muss ich jetzt aber an eine Funktion übergeben: LookupAccountName die ich in einer Funktion kapseln will:

Das soll dann so aussehen:
Code:
DWORD GetStrSID(LPTSTR server, LPTSTR principal, wchar_t *StrSID)
{
   wprintf(principal);
   // SID ermitteln und in lesbare Form umwandeln
   // in StrSID zurückgeben
   return GetLastError();
}

int _tmain(int argc, _TCHAR* argv[])
{
   wchar_t principal[80];
   wchar_t *StrSID;
   int LastError;
   wprintf(INFO);
   wprintf(QUERYINPUT);
   wscanf(L"%s", &principal);
   wprintf(L"%s\n", principal);
   LastError = GetStrSID(NULL, principal, StrSID);
   if (LastError == 0)
   {
      wprintf(L"%s", StrSID);
   }
   else
   {
      wprintf("%i", LastError);
   }
   getchar();
   return 0;
}
Bekomme aber noch zwei Fehlermeldungen:
Zitat:

Run-Time Check Failure #3 - The variable 'StrSID' is being used without being defined.
Und
Zitat:

'wprintf': Konvertierung des Parameters 1 von 'const char [3]' in 'const wchar_t *' nicht möglich
bei dem wprintf im else Abschnitt.

Olli 31. Jan 2007 07:47

Re: Unicode Eingabe einlesen
 
Dass DWORD und int einen Unterschied machen und warum, erklaere ich jetzt nicht nochmal.

Bei
Code:
wprintf("%i", LastError);
fehlt mir irgendwie der Unicode-Literal als erster Parameter. Wie waere es mit
Code:
wprintf(L"%i", LastError);
...?

... warum du echtes Unicode mit der gemischten Form (LPTSTR) zusammen benutzt, erschliesst sich mir auch nach mehrmaligem Hingucken noch nicht ganz, aber vielleicht kannst du es erklaeren. Genau wie den Sinn gemischt Typen aus den Windows-Headern und native C++-Typen zu benutzen ... :gruebel:

Wenn man _UNICODE/UNICODE nicht definiert hat, warum sollte dann bspw. die Zeile
Code:
wprintf(principal);
funktionieren, wenn doch principal vom Typ LPTSTR (schon an die konstante Variante LPCTSTR gedacht?) ist und damit zu LPSTR (sprich PChar) wird?! Stattdessen solltest du eben LPWSTR oder besser LPCWSTR benutzen. Und ueberhaupt mal weniger Windowstypen und C++-Typen mischen (sprich: disziplinierter programmieren), damit es zu solchen Fehlern erst garnicht kommen kann.

Wenn man die Adresse eines Zeichenarrays haben will, muss man auch keinen Adressoperator voranstellen.

Hier meine leicht korrigierte Variante. WinDiff wirste ja haben ...

Code:
DWORD GetStrSID(LPCWSTR server, LPCWSTR principal, LPWSTR &StrSID)

   wprintf(principal);
   // SID ermitteln und in lesbare Form umwandeln
   // in StrSID zurückgeben
   return GetLastError();


int __cdecl _tmain(int argc, _TCHAR *argv[])
{
    WCHAR principal[80], *StrSID = principal;
    DWORD LastError;

//     wprintf(INFO);
//     wprintf(QUERYINPUT); <--- warum die auskommentiert sind sollte klar sein
    wscanf(L"%s", principal);
    wprintf(L"%s\n", principal);
    LastError = GetStrSID(NULL, principal, StrSID);
    if (LastError == 0)
    { 
       wprintf(L"%s", StrSID);
    } 
    else
    { 
       wprintf(L"%i", LastError);
    } 
    getchar();
    return 0;
}
Uebrigens empfiehlt sich beim Arbeiten mit nullterminierten Strings auch das Ausnullen des Puffers (principal).

Last but not least: da du Arrays equivalent zu Pointern benutzen kannst, ist die Trennung zwischen principal und StrSID komplett hinfaellig. Beide koennen equivalent benutzt werden.

Noch'n Nachtrag: Warum _tmain wenn du ohnehin komplett in Unicode arbeiten willst? Es hilft dem Compiler ungemein, wenn du ihm erklaerst was du willst :zwinker:

Luckie 31. Jan 2007 09:16

Re: Unicode Eingabe einlesen
 
Genau mit diesem Unicode Mischmasch und mit Zeichenketten unter C/C++ habe ich ja so meine Probleme, deswegen wollte ich mir das mal genauer angucken und endlich mal verstehen.

Zum Programm: Unicode ist in den Projektoptionen eingestellt, deswegen dachte ich, ich müsste es nicht noch mal im Code definieren.

Zitat:

warum du echtes Unicode mit der gemischten Form (LPTSTR) zusammen benutzt, erschliesst sich mir auch nach mehrmaligem Hingucken noch nicht ganz, aber vielleicht kannst du es erklaeren.
Ich wusste nicht, dass ich es gemischt hatte. Ich würde gerne echtes Unicode verwenden oder was wäre, deiner Meinung nach, zu empfehlen?

Zitat:

Und ueberhaupt mal weniger Windowstypen und C++-Typen mischen (sprich: disziplinierter programmieren),
Was hast du den njetzt benutzt? WCHAR istz doch ein C++ Typ aber die Typen der Parameter von der Funktion sind doch wieder Windows Typen oder?

Delphi-Quellcode:
//     wprintf(INFO);
//     wprintf(QUERYINPUT); <--- warum die auskommentiert sind sollte klar sein
Nicht wirklich. :gruebel:

Zitat:

Uebrigens empfiehlt sich beim Arbeiten mit nullterminierten Strings auch das Ausnullen des Puffers (principal).
Das geht mit ZeroMemory?

Zitat:

Warum _tmain wenn du ohnehin komplett in Unicode arbeiten willst?
Ist das nicht der Einsprungspunkt für Unicode Konsolenprogramme?

Olli 31. Jan 2007 09:58

Re: Unicode Eingabe einlesen
 
Zitat:

Zitat von Luckie
Zum Programm: Unicode ist in den Projektoptionen eingestellt, deswegen dachte ich, ich müsste es nicht noch mal im Code definieren.

Das ist auch richtig. Alelrdings benutzt du explizit Unicode (wchar_t) gemischt mit TCHAR-Typen (LPTSTR). Das ist es, was ich meinte.

Zitat:

Zitat von Luckie
Ich wusste nicht, dass ich es gemischt hatte. Ich würde gerne echtes Unicode verwenden oder was wäre, deiner Meinung nach, zu empfehlen?

Wie gesagt, konsequente Typisierung, wenn du ohnehin nur Unicode verwenden willst.

Zitat:

Zitat von Luckie
Was hast du den njetzt benutzt? WCHAR istz doch ein C++ Typ aber die Typen der Parameter von der Funktion sind doch wieder Windows Typen oder?

wchar_t ist ein intrinsischer C++Typ. WCHAR ist, je nach System und Compiler ein define oder eine Umtypisierung.

Zitat:

Zitat von Luckie
Nicht wirklich. :gruebel:

Weil ich die Konstanten nicht gefunden habe ;)

Spaeter habe ich gesehen, dass zumindest INFO oben schon deklariert war. Aber eben nicht in dem Beitrag den ich zitiert habe.

Zitat:

Zitat von Luckie
Das geht mit ZeroMemory?

Japp. Oder eben memset(). Aber MS' Compiler definieren ZeroMemory() glaube ich sogar als Alias von memset(..., 0, ...).

Zitat:

Zitat von Luckie
Ist das nicht der Einsprungspunkt für Unicode Konsolenprogramme?

Nein, das ist der fuer jene die man mit TCHAR als ANSI oder Unicode-Zeichen kompilieren kann/will/darf.

Luckie 31. Jan 2007 10:13

Re: Unicode Eingabe einlesen
 
Zitat:

Zitat von Olli
Alelrdings benutzt du explizit Unicode (wchar_t) gemischt mit TCHAR-Typen (LPTSTR). Das ist es, was ich meinte.

Ach so. Und der C Datentyp WCHAR gehört zu den Windows Datentypen LPCWSTR und LPWSTR?

Zitat:

Weil ich die Konstanten nicht gefunden habe ;)
Hmpf und ich habe mir den Kopf zerbrochen, was an den Zeilen falsch sein könnte und überlegt, was du mir damit sagen wolltest. :wall:

Zitat:

Zitat:

Zitat von Luckie
Ist das nicht der Einsprungspunkt für Unicode Konsolenprogramme?

Nein, das ist der fuer jene die man mit TCHAR als ANSI oder Unicode-Zeichen kompilieren kann/will/darf.
Wie wäre denn der richtige wenn man mit WCHAR und "echtem" Unicode arbeitet?

Olli 31. Jan 2007 10:50

Re: Unicode Eingabe einlesen
 
Zitat:

Zitat von Luckie
Ach so. Und der C Datentyp WCHAR gehört zu den Windows Datentypen LPCWSTR und LPWSTR?

Genaugenommen gibt es kein WCHAR in C (und C++). Die sind entweder Preprocessor-Defines oder Umtypisierungen intrinsischer Typen. Und ja, die entsprechenden Pointertypen sind korrekt. S.o.

Zitat:

Zitat von Luckie
Hmpf und ich habe mir den Kopf zerbrochen, was an den Zeilen falsch sein könnte und überlegt, was du mir damit sagen wolltest. :wall:

:lol:

Zitat:

Zitat von Luckie
Wie wäre denn der richtige wenn man mit WCHAR und "echtem" Unicode arbeitet?

Hast du doch selber schon zurueckgefragt und ich oben auch genannt. LPWSTR und LPCWSTR ;)

Luckie 31. Jan 2007 10:54

Re: Unicode Eingabe einlesen
 
Zum letzten Punkt: Ich meinte wie main "aussehen" muss. Bei _tmain hast du ja gesagt es "gehöre" zu TCHAR. Aber wie sieht der Einsprungspunkt aus, wen ich WCHAR verwende? Oder hab eich da jetzt einfach nur was übersehen oder falsch verstanden?

Olli 31. Jan 2007 10:58

Re: Unicode Eingabe einlesen
 
Ich glaube das war dann wmain. Muesstest du dir mal die Definition fuer _tmain anschauen.

Luckie 31. Jan 2007 11:34

Re: Unicode Eingabe einlesen
 
So. So sieht es bisher aus:
Code:
#include "stdafx.h"
#include <windows.h>
#include <Sddl.h>

#define INFO _T("Ausgabe der SIDs zu einem Principal\n")
#define QUERYINPUT _T("Principal (z.B. Benutzername): ")

DWORD GetStrSID(LPCWSTR server, LPCWSTR principal, LPWSTR &StrSID)
{
   // SID ermitteln und in lesbare Form umwandeln
   // in StrSID zurückgeben
   PSID Sid;
   DWORD cbSize = 0;   
   if (LookupAccountNameW(NULL, principal, NULL, &cbSize, NULL, NULL, NULL))
   {
      Sid = (PSID) new BYTE[256];
      LookupAccountNameW(NULL, principal, Sid, &cbSize, NULL, NULL, NULL);
      //ConvertSidToStringSidW(Sid, StrSID);
      delete Sid;
   }
   return GetLastError();
}

int wmain(int argc, _TCHAR* argv[])
{
   WCHAR principal[80], *StrSID = principal;
    DWORD LastError;

   wprintf(INFO);
   wprintf(QUERYINPUT);
   wscanf(L"%s", &principal);
   wprintf(L"%s\n", principal);
   LastError = GetStrSID(NULL, principal, StrSID);
   if (LastError == 0)
   {
      wprintf(L"%s", StrSID);
   }
   else
   {
      wprintf(L"%i", LastError);
   }
   getchar();
   return 0;
}
Allerdings kennt er die API-Funktion ConvertSidToStringSidW nicht, obwohl ich die Sddl.h eingebunden und die Advapi32.lib mit gelinkt wird. Benutzen tue ich das Visual Studio 2005.

Ich habe die Funktion erstmal auskommentiert, aber trotzdem kommt es noch zu einer AV beim Aufruf von if (LookupAccountNameW(NULL, principal, NULL, &cbSize, NULL, NULL, NULL)).

pitti platsch 31. Jan 2007 12:03

Re: Unicode Eingabe einlesen
 
Es muss wscanf(L"%S", &principal); und nicht wscanf(L"%s", &principal); heißen also ein "%S" statt "%s".
Mit "%s" ließt man char* ein. Mit "%S" wchar_t*

Luckie 31. Jan 2007 12:27

Re: Unicode Eingabe einlesen
 
Wenn ich das grosse S nehme, dann kommt in der Funktion GetStrSID nur Mist an.

Ich habe jetzt mal die standard Aufrufkonvention in den Projekteigenschaften von __cdecl auf __stdcall umgestellt, aber das hilft leider auch nicht.

Olli 31. Jan 2007 12:40

Re: Unicode Eingabe einlesen
 
Zitat:

Zitat von pitti platsch
Es muss wscanf(L"%S", &principal); und nicht wscanf(L"%s", &principal); heißen also ein "%S" statt "%s".
Mit "%s" ließt man char* ein. Mit "%S" wchar_t*

Stimmt, habe ich uebersehen. Allerdings muss der Adressoperator da garnicht stehen. Hatte ich oben schonmal erwaehnt.

Zitat:

Zitat von Luckie
Wenn ich das grosse S nehme, dann kommt in der Funktion GetStrSID nur Mist an.

Ich habe jetzt mal die standard Aufrufkonvention in den Projekteigenschaften von __cdecl auf __stdcall umgestellt, aber das hilft leider auch nicht.

Das sollte nichts aendern. Ich schaue mal eben kurz drueber.

Code:
#if(_WIN32_WINNT >= 0x0500)
in der sddl.h hattest du aber gesehen?

Luckie 31. Jan 2007 12:50

Re: Unicode Eingabe einlesen
 
Den Adressoperator hatte ich noch übersehen. Mit %S und ohne Adressoperator geht es jetzt. Und ich bekomme auch keine AV mehr. Allerdings ist cbSize immer null:
Code:
DWORD GetStrSID(LPCWSTR server, LPCWSTR principal, LPWSTR &StrSID)
{
   // SID ermitteln und in lesbare Form umwandeln
   // in StrSID zurückgeben
   PSID Sid;
   DWORD cbSize = 0;   
   LookupAccountNameW(NULL, principal, NULL, &cbSize, NULL, 0, NULL);
   if (cbSize > 0)
   {
      Sid = (PSID) new BYTE[256];
      LookupAccountNameW(NULL, principal, Sid, &cbSize, NULL, 0, NULL);
      wprintf(L"%i", cbSize);
      //ConvertSidToStringSidW(Sid, StrSID);
      delete Sid;
   }
   return GetLastError();
}
Zitat:

Zitat von Olli
Code:
#if(_WIN32_WINNT >= 0x0500)
in der sddl.h hattest du aber gesehen?

Nein, was bedeutet das für mich? Muss ich da noch irgendwas definieren?

Mann ist das kompliziert. :roll:

Olli 31. Jan 2007 13:02

Re: Unicode Eingabe einlesen
 
Liste der Anhänge anzeigen (Anzahl: 1)
... bla bla bla ...

Code:
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>

#ifndef ConvertSidToStringSid
#ifdef __cplusplus
extern "C" {
#endif
BOOL
WINAPI
ConvertSidToStringSidA(
    IN PSID    Sid,
    OUT LPSTR *StringSid
    );
BOOL
WINAPI
ConvertSidToStringSidW(
    IN PSID    Sid,
    OUT LPWSTR *StringSid
    );
#ifdef UNICODE
#define ConvertSidToStringSid ConvertSidToStringSidW
#else
#define ConvertSidToStringSid ConvertSidToStringSidA
#endif // !UNICODE
#ifdef __cplusplus
};
#endif
#endif // ConvertSidToStringSid


#define INFO L"Ausgabe der SIDs zu einem Principal\n"
#define QUERYINPUT L"Principal (z.B. Benutzername): "

DWORD GetStrSID(LPCWSTR server, LPCWSTR principal, WCHAR StrSID[80])
{
   PSID Sid = NULL;
   DWORD cbSize = 0;
   if (LookupAccountNameW(NULL, principal, NULL, &cbSize, NULL, NULL, NULL))
   {
      if(Sid = PSID(new BYTE[cbSize]))
      {
          LPWSTR lpwszTemp = NULL;
          if(LookupAccountNameW(NULL, principal, Sid, &cbSize, NULL, NULL, NULL))
          {
              if(ConvertSidToStringSidW(Sid, &lpwszTemp))
              {
                  // Fill with zeros
                  memset(StrSID, 0, sizeof(StrSID));
                  // Copy string into buffer
                  memcpy(StrSID, lpwszTemp, sizeof(StrSID) - sizeof(WCHAR));
                  // Free the string allocated by ConvertSidToStringSidW
                  LocalFree(HLOCAL(lpwszTemp));
                  SetLastError(ERROR_SUCCESS);
              }
          }
          delete Sid;
      }
      else
      {
          SetLastError(ERROR_NOT_ENOUGH_MEMORY);
      }

   }
   return GetLastError();


int __cdecl _tmain(int argc, _TCHAR* argv[])

   WCHAR principal[80] = {0};
   DWORD LastError;

   wprintf(INFO);
   wprintf(QUERYINPUT);
   wscanf(L"%S", principal);
   wprintf(L"%S\n", principal);
   if (ERROR_SUCCESS == (LastError = GetStrSID(NULL, principal, principal)))
   { 
      wprintf(L"%s", principal);
   } 
   else
   { 
      wprintf(L"Error %d", LastError);
   } 
   getchar();
   return 0;
}
Den ersten Teil kannste weglassen wenn du die korrekte Zielplatform (mind. W2K waehlst). ConvertSidToStringSid, das steht auch in der Doku (PSDK) alloziert den String selber, was du gemacht hast, war also gelinde gesagt Mist.

In einer Domaene funzt dein Ansatz logischerweise so nicht. Wer GetLastError() auswertet sollte im Erfolgsfall auch explizit den Erfolg signalisieren. "new BYTE[256]" war wohl Quark, wenn du offenbar zuvor die exakte Groesse zu ermitteln versuchtest. Also warum nicht auch diese benutzen?

Olli 31. Jan 2007 13:03

Re: Unicode Eingabe einlesen
 
Stoer dich nicht am _tmain, liegt an bestimmten Projekteinstellungen meines Testprojektes (hab's mit dem DDK getestet).

Luckie 31. Jan 2007 13:14

Re: Unicode Eingabe einlesen
 
Welche Zielplatform muss ich denn wie, wo einstellen, damit er ConvertSidToStringSidW kennt?

Ansonsten danke erstmal. Da ist ja nicht all zuviel von meinem Code übrig geblieben, da werde ich mich erstmal durchwühlen müssen.

Olli 31. Jan 2007 13:17

Re: Unicode Eingabe einlesen
 
Zitat:

Zitat von Luckie
Welche Zielplatform muss ich denn wie, wo einstellen, damit er ConvertSidToStringSidW kennt?

W2K, wie schon gesagt. Deswegen der Hinweis mit dem Define siehe oben.

Alternativ uebernimmst du den Teil zwischen "#ifndef ConvertSidToStringSid" und "#endif // ConvertSidToStringSid" in deinen Code. Selbst wenn es dann schon woanders deklariert wurde, wird das nicht stoeren und du brauchst Sddl.h nicht mehr explizit einbinden. Statt der ersten beiden Includes waere es bei dir dann wohl nur stdafx.h ...

Zitat:

Zitat von Luckie
Ansonsten danke erstmal. Da ist ja nicht all zuviel von meinem Code übrig geblieben, da werde ich mich erstmal durchwühlen müssen.

:gruebel: ... das ist, bis auf minimale Aenderungen und Sanity-Checks, dein Code. Noch immer nicht ganz sattelfest in C/C++, Luckie? :zwinker:

Luckie 31. Jan 2007 13:30

Re: Unicode Eingabe einlesen
 
Zitat:

Zitat von Olli
Noch immer nicht ganz sattelfest in C/C++, Luckie? :zwinker:

Und wenn das so wieter geht, werde ich das auch nie werden:
Code:
int wmain(int argc, _CHAR* argv[])
{
   WCHAR principal[80] = {0};
    DWORD LastError;

    wprintf(INFO);
    wprintf(QUERYINPUT);
    wscanf(L"%S", principal);
    if (ERROR_SUCCESS == (LastError = GetStrSID(NULL, principal, principal)))
    {
       wprintf(L"%s", principal);
    }
    else
    {
       wprintf(L"Error %d", LastError);
    }
    getchar();
    return 0;
}
Jetzt steht in principal wieder nur ein eckiges Kästchen drinne, anstatt der eingegebenen Zeichenkette. :wall:

PS: Ich bin hier in einer Domäne. Aber wenn ich einen lokalen Account angebe, sollte es doch funktionieren oder?

PPS: Wo kann ich beim VS die Zielplattfiorm angegeben? Ich finde da nichts in den Projektoptionen. :gruebel:

Olli 31. Jan 2007 13:34

Re: Unicode Eingabe einlesen
 
Zitat:

Zitat von Luckie
Jetzt steht in principal wieder nur ein eckiges Kästchen drinne, anstatt der eingegebenen Zeichenkette. :wall:

Also der von mir gepostete Code funktionierte tadellos auf der Konsole (das wscanf).

Zitat:

Zitat von Luckie
PS: Ich bin hier in einer Domäne. Aber wenn ich einen lokalen Account angebe, sollte es doch funktionieren oder?

Jupp.

Zitat:

Zitat von Luckie
PPS: Wo kann ich beim VS die Zielplattfiorm angegeben? Ich finde da nichts in den Projektoptionen. :gruebel:

Bei den Praeprozessor-Defines. Als WINNT=0x0500 z.B. ...

Ich schaue nochmal ueber den Code und teste aus an einem lokalen Account. Paar Minuetchen. Muss ja wohl in GetStrSID() haengen.

Luckie 31. Jan 2007 13:43

Re: Unicode Eingabe einlesen
 
Glaube ich nicht. Es hängt an der Eingabe, dass er da die Eingabe nicht richtig liest, warum auch immer.

Code:
#include "stdafx.h"
#include <windows.h>

#define WINNT 0x0500

#define INFO L"Ausgabe der SIDs zu einem Principal\n"
#define QUERYINPUT L"Principal (z.B. Benutzername): "

DWORD GetStrSID(LPCWSTR server, LPCWSTR principal, WCHAR StrSID[80])
{
   PSID Sid = NULL;
   DWORD cbSize = 0;
   if (LookupAccountNameW(NULL, principal, NULL, &cbSize, NULL, NULL, NULL))
   {
      if(Sid = PSID(new BYTE[cbSize]))
      {
          LPWSTR lpwszTemp = NULL;
          if(LookupAccountNameW(NULL, principal, Sid, &cbSize, NULL, NULL, NULL))
          {
           if(ConvertSidToStringSidW(Sid, &lpwszTemp))
              {
                  // Fill with zeros
                  memset(StrSID, 0, sizeof(StrSID));
                  // Copy string into buffer
                  memcpy(StrSID, lpwszTemp, sizeof(StrSID) - sizeof(WCHAR));
                  // Free the string allocated by ConvertSidToStringSidW
                  LocalFree(HLOCAL(lpwszTemp));
                  SetLastError(ERROR_SUCCESS);
              }
           wprintf(L"%i", cbSize);
          }
          delete Sid;
      }
      else
      {
          SetLastError(ERROR_NOT_ENOUGH_MEMORY);
      }

   }
   return GetLastError();


int wmain(int argc, _TCHAR* argv[])
{
   WCHAR principal[80] = {0};
    DWORD LastError;

    wprintf(INFO);
    wprintf(QUERYINPUT);
    wscanf(L"%S", principal);
    if (ERROR_SUCCESS == (LastError = GetStrSID(NULL, principal, principal)))
    {
       wprintf(L"%s", principal);
    }
    else
    {
       wprintf(L"Error %d", LastError);
    }
    getchar();
    return 0;
}
Ich hatte auch schon WINNT=0x0500 bei den Präprozessiranweisungen hinzugefügt, das hat aber auch nicht geholfen. Und mit #define WINNT 0x0500 geht es auch nicht. Das kann doch einfach nicht so schwer sein. :wall:

Olli 31. Jan 2007 14:00

Re: Unicode Eingabe einlesen
 
"#define _WIN32_WINNT 0x0500" (bzw. _WIN32_WINNT=0x0500)

Ich habe noch zwei subtile Dinge bei deinem Code uebersehen.
1. new fuer Arrays erfordert delete[], niemals delete!
2. new kann eine Exception werfen. Solltest du also danach noch im Zweifelsfall handeln.

Uebrigens, wenn wir schon bei C++ sind, solltest du eventuell lieber I/O Streams benutzen und bei den Formatstrings sollte natuerlich die Puffergroesse Beachtung finden ... also 79 in unserem Fall.



Bei mir liest er die Eingabe voellig korrekt. Also duerftest du nur wieder irgendwelche eigenen Aenderungen gemacht haben. Ich kapier nicht, wieso du nicht einfach meine Aenderungen 1:1 uebernimmst und dann als Ausgangspunkt nimmst. Aber ich mache ohnehin gerade noch ein paar Aenderungen. PSDK lesen hilft uebrigens ... die Funktionsaufrufe sind zT hanebuechen ...

Luckie 31. Jan 2007 14:10

Re: Unicode Eingabe einlesen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Olli
Bei mir liest er die Eingabe voellig korrekt. Also duerftest du nur wieder irgendwelche eigenen Aenderungen gemacht haben. Ich kapier nicht, wieso du nicht einfach meine Aenderungen 1:1 uebernimmst und dann als Ausgangspunkt nimmst.

Ich habe sie 1:1 übernommen. Ich habe nur das _tmain in wmain geändert. Ich hänge mal das Projekt, wie ich es zur Zeit habe hier an.

Olli 31. Jan 2007 14:30

Re: Unicode Eingabe einlesen
 
Siehe Anhang mit EXE-Datei. Bitte mal testen ob er einen Fehler bringt. Bei mir kommt leider immer Fehler 1332 (ERROR_NONE_MAPPED), weshalb ich nicht weiter als bis zum ersten LookupAccountName komme :(

Olli 31. Jan 2007 14:54

Re: Unicode Eingabe einlesen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Autsch. Der letzte Fehler ging auf mich - dank pitti platsch - auf den ich ungeprueft gehoert hatte. Es muss naemlich nicht %S (was bei printf Unicode und bei wprintf ANSI bedeutet), sondern %ws heissen. (%S ist sozusagen immer der "entgegengesetzte" Stringtyp)

Danach funzt der Input und der Rest. Auf die Spur dessen bin ich dann auch erst gekommen, nachdem ich mal ein Literal uebergeben habe.

Siehe Anhang mit EXE und Source. Ausser der Behandlung der Exceptions welche von new() geworfen werden koennten, wird eigentlich alles gecheckt.

Luckie 31. Jan 2007 15:17

Re: Unicode Eingabe einlesen
 
Puh jetzt geht es endlich. Mann war das eine schwere Geburt. :? Jetzt muss ich mir nur noch angucken, was da genau passiert, um es zu verstehen.

Allerdings verstehe ich nicht, warum du da solche Probleme hattest, ich dachte so was machst du Tag täglich. :gruebel:

Olli 31. Jan 2007 15:26

Re: Unicode Eingabe einlesen
 
Zitat:

Zitat von Luckie
Puh jetzt geht es endlich. Mann war das eine schwere Geburt. :? Jetzt muss ich mir nur noch angucken, was da genau passiert, um es zu verstehen.

Verstehe ich noch immer nicht. Soll ich es nochmal schnell durchkommentieren?

Zitat:

Zitat von Luckie
Allerdings verstehe ich nicht, warum du da solche Probleme hattest, ich dachte so was machst du Tag täglich. :gruebel:

Was? Einen kranken Mix aus C und C++? Nö, ich schreibe entweder richtig C oder richtig C++ ... normalerweise aber C++. Und da benutzt man (siehe meine Kommentare zu Streams) keine bekloppten Formatstrings, sondern verläßt sich auf die Typsicherheit des Compilers.

Ein Teil der Probleme ergab sich allerdings daraus, daß ich den Fehler eben an einer anderen Stelle vermutet hatte (nämlich beim Lookup). Aber durch deinen Hinweis bzgl. der Eingabe habe ich mich dann auf den anderen Teil gestürzt und prompt den Fehler gefunden. Übrigens gibt's im Kernelmode auch relativ selten Eingabeaufforderungen ... soviel zum tagtäglichen ... :zwinker:

Luckie 31. Jan 2007 15:40

Re: Unicode Eingabe einlesen
 
OK, ich versuche dass dann noch mal mit Streams hinzubekommen, damit es ein sauberes C++ wird. Und dann poste ich es nochmal hier.

Irgendwann muss ich das doch mit den Zeichenketten und C/C++ in den Kopf bekommen. :wall:

Luckie 31. Jan 2007 23:31

Re: Unicode Eingabe einlesen
 
Ich versuche gerade die Ein- und Ausgabe mit Streams zu realisieren:
Code:
   cout << INFO << endl;
   cout << QUERYINPUT << endl;
    cin >> principal;
Die Ausgabe funktioniert, die Eingabe jedoch nicht:
Zitat:

Binaerer Operator '>>' : Kein Operator definiert, der einen rechtsseitigen Operator vom Typ 'unsigned short [80]' akzeptiert (oder keine geeignete Konvertierung moeglich)
Was mache ich da falsch? Ich habe schon gegoogelt, aber nichts brauchbares gefunden. :(

Olli 1. Feb 2007 00:49

Re: Unicode Eingabe einlesen
 
Am besten schreibst du dir einen eigenen Operator dafür. Alternativ benutzt du gleich die STL std::string-Klasse für Ein/Ausgaben. Natürlich mit wchar_t spezialisiert.

Luckie 1. Feb 2007 09:24

Re: Unicode Eingabe einlesen
 
Zitat:

Zitat von Olli
Am besten schreibst du dir einen eigenen Operator dafür.

Das übersteigt meine momentanen C/C++ Kenntnisse nun doch um einiges. Und damit will ich auch erst gar nicht anfangen nicht bevor ich mit den Grundlagen zurecht komme.

Zitat:

Alternativ benutzt du gleich die STL std::string-Klasse für Ein/Ausgaben. Natürlich mit wchar_t spezialisiert.
Das klingt doch schön besser. Kannst du mir ein Beispiel geben, wie das mit der String-Klasse funktioniert? Es muss natürlich dann auch mit dem Windows Datentyp LP(C)WSTR irgendwie kompatible sein, damit man die Eingabe an die Funktion übergeben kann.

PS: Sollten wir uns auf den Delphi Tagen 2007 in Paderborn treffen oder sollte ich mal nach Island kommen, gebe ich dir einen aus. ;)

Olli 1. Feb 2007 10:41

Re: Unicode Eingabe einlesen
 
Zitat:

Zitat von Luckie
Das klingt doch schön besser. Kannst du mir ein Beispiel geben, wie das mit der String-Klasse funktioniert? Es muss natürlich dann auch mit dem Windows Datentyp LP(C)WSTR irgendwie kompatible sein, damit man die Eingabe an die Funktion übergeben kann.

Komme ich erst am Abend dazu. Du kannst dich aber in der MSDN-Doku ueber die verschiedenen STL-Klassen schlaulesen. Der Header war IMO "<string>". Aber ich wuerde es an deiner Stelle bei dem C/C++-Mischmasch belassen. Wenn du dich noch nicht sicher mit C++ fuehlst, findest du wohl mehr Stolperfallen als Freude wenn du konsequent C++ benutzt ;)

Zitat:

Zitat von Luckie
PS: Sollten wir uns auf den Delphi Tagen 2007 in Paderborn treffen oder sollte ich mal nach Island kommen, gebe ich dir einen aus. ;)

Das wird fuer dich auf den Delphitagen aber deutlich billiger ... wuesstest du die Alkpreise hier in Island, wuerdest du vermutlich nichtmal das Angebot machen :)


Ehrlich gesagt habe ich ueberlegt zu den diesjaehrigen Delphitagen mal zu kommen.

Luckie 1. Feb 2007 10:54

Re: Unicode Eingabe einlesen
 
OK, dann belasse ich es dabei. Dann kann man das Thema jetzt als Abgeschlossen betrachten.

Und was die Delphitage angeht: Überleg nicht lange, sondern komm einfach. Nico habe ich schon per Mail gefragt, aber noch keine Antwort erhalten.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:23 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz