![]() |
Probleme mit PWideChar
Ich parse die MFT mittels eines USN-Records:
Delphi-Quellcode:
Dort ist FileName als PWChar deklariert, was über MarshaledString ein PWideChar ist.
USN_RECORD = record
... FileNameLength: Word; FileNameOffset: Word; FileName: PWChar; end; Die Zuweisung von FileName geschieht in
Delphi-Quellcode:
(P ist ein Pointer auf den Laufwerks-Char) mittels
function USNRecFromPointer(const P: Pointer): TUSNRecord;
Delphi-Quellcode:
Wenn ich mir nun innerhalb dieser Funktion den Wert von Result.FileName im Debugger anzeigen lasse, dann wird der korrekte Dateiname angezeigt. In der Prozedur, die USNRecFromPointer aufruft und den TUSNRecord zurück erhält, ist aber FileName plötzlich ein String der Länge FileNameLength voller kryptischer Unicode-Zeichen. Die Zuweisung an eine String-Variable ändert daran nichts.
Result.FileName := PWChar(Integer(P) + Result.FileNameOffset);
Die einzige funktionierende Lösung, die ich gefunden habe, ist
Delphi-Quellcode:
.
WideCharToString(PWChar(Integer(AUSN) + AUSN.FileNameOffset)
Hier fiel mir nun auf, dass der Dateiname in einigen Fällen um ein oder zwei Zeichen zu lang war. Ich dachte mir, dass der Record die FileNameLength vielleicht nicht umsonst mitliefert. Da ein WideChar 2 Bytes umfasst, musste ich die Länge halbieren und kam auf
Delphi-Quellcode:
, was auch endlich anstandslos funktioniert. Aber das kann es ja wohl nicht sein. Was geht da eigentlich vor? Und warum wird FileName im identischen Record einmal "richtig" und einmal als UTF-16-String angezeigt?
WideCharLenToString(PWChar(Integer(AUSN) + AUSN.FileNameOffset),Round(AUSN.FileNameLength / 2))
|
AW: Probleme mit PWideChar
Also, dies entspricht in etwa einem
![]() Der Inhalt dieser Strings muß nicht zwingend nullterminiert sein. Liegt hier vielleicht schon das Problem? Außerdem sind die beiden Längenangaben immer gerade Zahlen, da sie die Anzahl in Bytes und nicht etwa in WideChar angeben. Leider gibst du keinen relevanten Code, weshalb ich nur diese beiden Punkte als Denkanstoß liefern kann. Kannst du noch Code nachliefern (WideCharLenToString, WideCharToString ...)? |
AW: Probleme mit PWideChar
Ich dachte, ich hätte alles Wichtige an Code mitgeliefert. Was fehlt dir?
EDIT: Das sind ![]() |
AW: Probleme mit PWideChar
Zitat:
Das mit der Nullterminierung ist also schon ausgeschlossen? Kurzum: nach wiederholter Lektüre deines Beitrags eingangs, scheinst du dich über die Zählung in Bytes zu ärgern und über die Tatsache, daß die Strings nicht nullterminiert daherkommen, oder? Umgekehrt gefragt: woher die Annahme daß das nicht sein kann? Eigentlich ist das so ganz normal. Übrigens ist Round() falsch. Wenn du einen ungeraden Zahlwert in dem Feld siehst, darfst du getrost davon ausgehen, daß der Wert nicht stimmt. |
AW: Probleme mit PWideChar
Zitat:
Das Round ist notwendig, damit ein Integer rauskommt. Ich hätte auch Trunc() nehmen können. |
AW: Probleme mit PWideChar
Ja, der Debugger sieht den Typ "PWideChar" und nimmt das als Nullterminiert an,
was aber egal ist, so lange doe Werte in FileName und FileNameLength korrekt sind und zusammenpassen, gehen die entsprechenden Funktionen damit "richtig" um, welche diesen Typ dann auch korrekt via Längenangabe auswerten. Wie Assarbad schon sagte, wenn dieser Typ nicht nullterminiert ist (sein muß), dann muß man eben auch die Längenangabe verwenden, wenn man den String auslesen will. Neben WideCharLenToString gibt es auch noch ![]() aber diese brauchst du ja nur, wenn du selber diesen "String" auslesen und in einen Delphi-String umwandeln willst. Das, was du als Zeiger an USNRecFromPointer übergibst, das wird nicht zufällig zwischendurch freigegeben, nachdem du diese Funktion aufgerufen hattest? Der Dateiname bleibt weiterhin in der anderen Struktur und dieses USNRecFromPointer scheint nur einen Record zu erstellen, der darauf zeigt. (jedenfalls sieht die halbgezeigt Zeile Code danach aus) Würde dann in etwa so aussehn.
Delphi-Quellcode:
SetString(S, PWideChar(NativeInt(AUSN) + AUSN.FileNameOffset), AUSN.FileNameLength div SizeOf(WideChar)); // oder einfach nur "div 2"
PS: statt NativeInt bzw. NativeUInt verwende ich lieber einen Typ IntPtr (was im Prinzip auch nur ein NativeInt ist, aber so besser anzeigt, was er machen will). |
AW: Probleme mit PWideChar
Da bringt mich ja schon mal gut weiter.
Die aufrufende Routine heißt
Delphi-Quellcode:
, und sie ruft als Erstes
function TFrmMFT.MFTEnumCallback(AUSN: PUSNRecord; Extra: Pointer): Boolean;
Delphi-Quellcode:
auf. Dazwischen geschieht nichts.
USNRecFromPointer(AUSN);
Bei einem Beispiel-Dateinamen werden 41 Zeichen übergeben, das letzte ist nicht #0; die FileNameLength ist 22 und der Dateiname 11 Zeichen lang. EDIT: SetString funktioniert auch einwandfrei. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:40 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 by Thomas Breitkreuz