Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Probleme mit RtlRunEncodeUnicodeString (https://www.delphipraxis.net/186682-probleme-mit-rtlrunencodeunicodestring.html)

uligerhardt 24. Sep 2015 08:39

AW: Probleme mit RtlRunEncodeUnicodeString
 
Zitat:

Zitat von Zacherl (Beitrag 1316814)
Auch gehen würde folgendes (normale Stringkonstanten landen nicht in der read-only Section bzw. werden bei Zuweisung vermutlich umkopiert):
Delphi-Quellcode:
var
  Source: WideString;
  UnicodeString: UNICODE_STRING;
  Hash: UCHAR;
begin
  Source := 'TestString'#0;
  RtlInitUnicodeString(@UnicodeString, @Source[1]);
  Hash := 0;
  RtlRunEncodeUnicodeString(@Hash, @UnicodeString);
Dann aber nicht vergessen vorher per Hand eine #0 an den Source String anzuhängen.

Die #0 fügt Delphi (AFAIK :mrgreen:) schon automatisch an verwaltete Strings an. Und statt @Source[1] lieber den passenden Cast nehmen:
Delphi-Quellcode:
var
  Source: WideString;
  UnicodeString: UNICODE_STRING;
  Hash: UCHAR;
begin
  Source := 'TestString';
  RtlInitUnicodeString(@UnicodeString, PWideChar(Source));
  Hash := 0;
  RtlRunEncodeUnicodeString(@Hash, @UnicodeString);
  RtlRunDecodeUniCodeString(Hash, @UnicodeString);
end.

Zacherl 24. Sep 2015 15:16

AW: Probleme mit RtlRunEncodeUnicodeString
 
Zitat:

Zitat von uligerhardt (Beitrag 1316819)
Die #0 fügt Delphi (AFAIK :mrgreen:) schon automatisch an verwaltete Strings an.

Wäre mir neu :D Würde ich mich, selbst wenn es so ist, aber auf keinen Fall drauf verlassen. "Normale" Strings sind in Delphi nicht nullterminiert, sondern enthalten ein vorangestelltes Längenbyte. Unter dem Gesichtspunkt ist für den Delphi Compiler ja keine Notwendigkeit gegeben noch irgendwelche Nullen hinzuzufügen.

Edit:
Zumindest bei neueren Delphi Versionen stehen auf den ersten Blick tatsächlich zwei Nullbytes hinter dem String.

Zitat:

Zitat von uligerhardt (Beitrag 1316819)
Und statt @Source[1] lieber den passenden Cast nehmen

Macht keinen Unterschied:
Code:
Unit1.pas.63: RtlInitUnicodeString(@UnicodeString, @Source[1]);
005C7383 8B45F8           mov eax,[ebp-$08]
005C7386 E8252DE4FF      call @WStrToPWChar
005C738B 50               push eax
005C738C 8D45F0           lea eax,[ebp-$10]
005C738F 50               push eax
005C7390 E8B7FFFFFF      call RtlInitUnicodeString
Unit1.pas.64: RtlInitUnicodeString(@UnicodeString, PWideChar(Source));
005C7395 8B45F8           mov eax,[ebp-$08]
005C7398 E8132DE4FF      call @WStrToPWChar
005C739D 50               push eax
005C739E 8D45F0           lea eax,[ebp-$10]
005C73A1 50               push eax
005C73A2 E8A5FFFFFF      call RtlInitUnicodeString

uligerhardt 24. Sep 2015 15:29

AW: Probleme mit RtlRunEncodeUnicodeString
 
Zitat:

Zitat von Zacherl (Beitrag 1316869)
Zitat:

Zitat von uligerhardt (Beitrag 1316819)
Die #0 fügt Delphi (AFAIK :mrgreen:) schon automatisch an verwaltete Strings an.

Wäre mir neu :D Würde ich mich, selbst wenn es so ist, aber auf keinen Fall drauf verlassen. "Normale" Strings sind in Delphi nicht nullterminiert, sondern enthalten ein vorangestelltes Längenbyte. Unter dem Gesichtspunkt ist für den Delphi Compiler ja keine Notwendigkeit gegeben noch irgendwelche Nullen hinzuzufügen.

Aus reiner Delphi-Sicht nicht. Aber eben genau, um einfache Interaktion mit der API zu ermöglichen, wird m.W. die Null drangehängt. Das müsste dokumentiertes Verhalten sein. Ich bin aber zu faul, das jetzt rauszusuchen. :oops:

Zitat:

Zitat von Zacherl (Beitrag 1316869)
Zitat:

Zitat von uligerhardt (Beitrag 1316819)
Und statt @Source[1] lieber den passenden Cast nehmen

Macht keinen Unterschied:
Code:
Unit1.pas.63: RtlInitUnicodeString(@UnicodeString, @Source[1]);
005C7383 8B45F8           mov eax,[ebp-$08]
005C7386 E8252DE4FF      call @WStrToPWChar
005C738B 50               push eax
005C738C 8D45F0           lea eax,[ebp-$10]
005C738F 50               push eax
005C7390 E8B7FFFFFF      call RtlInitUnicodeString
Unit1.pas.64: RtlInitUnicodeString(@UnicodeString, PWideChar(Source));
005C7395 8B45F8           mov eax,[ebp-$08]
005C7398 E8132DE4FF      call @WStrToPWChar
005C739D 50               push eax
005C739E 8D45F0           lea eax,[ebp-$10]
005C73A1 50               push eax
005C73A2 E8A5FFFFFF      call RtlInitUnicodeString

WIMRE macht es einen Unterschied, wenn Source = '' ist. Vielleicht erkennt der Compiler, dass das in dem Beispiel nicht der Fall ist und lässt deshalb die Prüfung weg. Vermutlich taucht ein Unterschied auf, wenn man das ganze z.B. in eine Prozedur mit Source als Argument steckt.

SMO 24. Sep 2015 15:30

AW: Probleme mit RtlRunEncodeUnicodeString
 
Zitat:

Zitat von Zacherl (Beitrag 1316869)
Wäre mir neu :D Würde ich mich, selbst wenn es so ist, aber auf keinen Fall drauf verlassen. "Normale" Strings sind in Delphi nicht nullterminiert, sondern enthalten ein vorangestelltes Längenbyte. Unter dem Gesichtspunkt ist für den Delphi Compiler ja keine Notwendigkeit gegeben noch irgendwelche Nullen hinzuzufügen.

Doch, das macht Delphi schon immer (?) so, wie uligerhardt sagte. Nur auf diese Weise können Delphi-Strings, egal ob Ansi oder Unicode, schnell und einfach für die Verwendung mit der Windows-API auf PChar gecastet werden.
Delphi-Strings haben auch schon seit Delphi 2 kein vorangestelltes Längenbyte mehr, sondern einen 32 Bit Integer. Der String mit Längenbyte ist der alte ShortString.
Aktuell steht vor Ansi/UnicodeStrings eine ganze Menge mehr, insgesamt 12 Bytes.

Zacherl 24. Sep 2015 15:36

AW: Probleme mit RtlRunEncodeUnicodeString
 
Zitat:

Zitat von SMO (Beitrag 1316871)
Doch, das macht Delphi schon immer (?) so, wie uligerhardt sagte. Nur auf diese Weise können Delphi-Strings, egal ob Ansi oder Unicode, schnell und einfach für die Verwendung mit der Windows-API auf PChar gecastet werden.

Ja, konnte das grade bei mir auch beobachten. Da wurde wohl tatsächlich einmal mitgedacht.

Zitat:

Zitat von SMO (Beitrag 1316871)
Delphi-Strings haben auch schon seit Delphi 2 kein vorangestelltes Längenbyte mehr, sondern einen 32 Bit Integer. Der String mit Längenbyte ist der alte ShortString.
Aktuell steht vor Ansi/UnicodeStrings eine ganze Menge mehr, insgesamt 12 Bytes.

Ich weiß ich weiß :P Ist hier nur nicht wirklich von Relevanz. Ging mir eher um die zwei verschiedenen Techniken Längenprefix vs. Nullterminierung.

Zitat:

Zitat von uligerhardt (Beitrag 1316870)
WIMRE macht es einen Unterschied, wenn Source = '' ist. Vielleicht erkennt der Compiler, dass das in dem Beispiel nicht der Fall ist und lässt deshalb die Prüfung weg. Vermutlich taucht ein Unterschied auf, wenn man das ganze z.B. in eine Prozedur mit Source als Argument steckt.

Konnte auch mit leerem Source und Source als Funktionsargument keinen Unterschied im Assembly ausmachen, aber kann natürlich sein, dass es irgendwelche Edge-cases gibt.

Glaube aber wir bewegen uns grade etwas vom Thema weg.

mkinzler 24. Sep 2015 15:42

AW: Probleme mit RtlRunEncodeUnicodeString
 
Zitat:

Ich weiß ich weiß Ist hier nur nicht wirklich von Relevanz. Ging mir eher um die zwei verschiedenen Techniken Längenprefix vs. Nullterminierung.
Und wäre Delphi 1 noch die aktuelle Version hättest Du auch Recht.

slemke76 27. Sep 2015 11:41

AW: Probleme mit RtlRunEncodeUnicodeString
 
Hallo zusammen,

da habe ich ja was los getreten ;-)

*** Vielen Dank an alle, die geholfen haben :thumb::thumb::thumb::thumb:..! ***

Inzwischen habe ich das ganze integriert und es funktioniert alles wie es soll. Auch über Pointer, CopyMemory, etc. habe ich einiges gelernt - ich hoffe, ich vergesse es nicht wieder so schnell ;-)

Grüße & schönen Sonntag,
Sebastian


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:09 Uhr.
Seite 2 von 2     12   

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