![]() |
Von PChar nach UINT
Ich habe gerade ein kleines Problem. In einem C-Programm passiert folgendes:
Code:
Wie mache ich das in Delphi? "StrToInt" geht nicht, weil die Null ja nicht der '0' mit dem ASCII-Code #48 entspricht, sondern es handelt sich ja wirklich um das 1. Zeichen mit dem ASCII-Code #0.
// hier wird ein pchar-Array mit 15 Zeichen
// erzeugt und komplett auf Null gesetzt unsigned char* Result; memset(Result, 0, 15); // hier ist ein "Typecasting" (?) vom // PChar nach UINT unsigned int val; val = *(unsigned int *)Result; // das angezeigte Ergebnis ist Null, // weil der Inhalt des PChar irgendwie (aber wie?) // als Zahl interpretiert wird printf("%u\n",val); Das geht IMHO in den binären Bereich, denn wenn ich in obigem C-Code folgendes mache:
Code:
dann wäre das Ergebnis nicht mehr Null sondern 256. Und das PChar besteht ja aus 15 Zeichen, quasi "010000000000000". (Nennt man diese Art der Schreibweise nicht little endian, weil der kleinste Wert links steht? Im Normalfall würde man diese Binärzahl doch eher so darstellen: "000000000000010".)
memset(Result, 0, 15);
Result[1] = 1; Wie gesagt, ich denke gerade an alles Mögliche. Aber die Frage ist: Gibt es, ähnlich wie im C-Beispiel, in Delphi eine elegante Art, aus dem PChar den gewünschten UINT-Wert zu ermitteln? Eben so wie
Code:
oder muss ich doch in einer Schleife durch die einzelnen Zeichen durch?
val = *(unsigned int *)Result;
|
Re: Von PChar nach UINT
Sowas:
Delphi-Quellcode:
var cStr : PChar;
dw : Cardinal; begin cStr := #1#0#0#255; // müssen mindestens 4 Byte sein dw := PCardinal(cStr)^ |
Re: Von PChar nach UINT
Zitat:
das hier der Inhalt von Result ausgegeben wird, ich würde eher vermuten das es sich um die Adresse handelt. Das könntest Du in Delphi dann ganz einfach mit Integer(Result) haben... |
Re: Von PChar nach UINT
Nein, so wie neolithos das vorgeschlagen hat, ist das schon richtig.
@neolithos: Danke. :) |
Re: Von PChar nach UINT
Moin!
@nico42:
Code:
(unsigned int *) ist ein Zeiger typecast und mit dem * vor diesem greift er auf den Inhalt zu und nicht auf die Adresse des Zeigers (was er ohne * ganz vorne machen würde).
val = *(unsigned int *)Result;
@other: Ansonsten eine Übersetzung des Codes:
Code:
MfG
Var
Result : PChar; value : Cardinal; Begin // hier wird ein pchar-Array mit 15 Zeichen // erzeugt und komplett auf Null gesetzt Result := StrAlloc(15); FillChar(Result^, 0, 15); // hier ist ein "Typecasting" (?) vom // PChar nach UINT value := Cardinal(Result^); // bzw.: := Cardinal(Pointer(Result)^); // das angezeigte Ergebnis ist Null, // weil der Inhalt des PChar irgendwie (aber wie?) // als Zahl interpretiert wird Ausgabe(value); End; Muetze1 |
Re: Von PChar nach UINT
btw: Hier der Hintergrund der ganzen Geschichte. Auf
![]() Der Nutzwert hält sich damit zwar in Grenzen, aber man könnte ja mal versuchen, das Verfahren umzukehren. Sprich: aus der ID wieder den Schlüssel generieren. Das würde mich noch interessieren. Evtl. gibt es aber auch eine einfachere Möglichkeit, den Schlüssel zu ermitteln. Wie dem auch sei, hier wäre also das Ergebnis in Delphi, wobei ich gleich noch die Produkt-ID aus der Registry auslese und ebenfalls anzeige.
Delphi-Quellcode:
Aufzurufen:
procedure ShowProdKey(const ProdKey: pchar);
function CheckDigit(const uVal: UINT): UINT; var uSum, uCopy : UINT; begin uSum := 0; uCopy := uVal; while(uCopy <> 0) do begin uSum := uSum + (uCopy mod 10); uCopy := uCopy div 10; end; Result := uVal * 10 + 7 - (uSum mod 7); end; var s : string; reg : TRegistry; uVal1, uVal2 : UINT; begin // die Produkt-ID aus der Registry ermitteln s := ''; reg := TRegistry.Create(KEY_READ); if(reg <> nil) then try reg.RootKey := HKEY_LOCAL_MACHINE; if(reg.OpenKey('SOFTWARE\Microsoft\Windows NT\CurrentVersion', false)) then try s := reg.ReadString('ProductId'); finally reg.CloseKey; end; finally reg.Free; end; // den berechneten Wert holen, ... uVal1 := PUINT(ProdKey)^; // ... & umrechnen uVal1 := uVal1 and $7fffffff; uVal1 := uVal1 shr 1; uVal2 := CheckDigit(uVal1 mod 1000000); uVal1 := uVal1 div 1000000; // die tatsächlich gespeicherte und die errechnete // Produkt-ID anzeigen MessageBox(0,pchar(Format( 'Your product ID should be XXXXX-%.3u-%.7u-XXXXX.' + #13#10 + 'Your reported product ID is %s', [uVal1,uVal2,s])),'ShowProdKey',MB_OK or MB_ICONINFORMATION); end; function DecodeProdKey(ProdKey: string; var pResult: string; iResLen: integer): integer; const ValidDigits = 'BCDFGHJKMPQRTVWXY2346789'; var k, m, Aux, NumDigits : integer; begin Result := -1; if(length(ProdKey) <> 29) then begin Writeln('Warning: Product key has non-standard length.'); exit; end; if(length(ProdKey) mod 6 < 1) then begin Writeln('Product key has invalid length.'); exit; end; SetLength(pResult,iResLen); ZeroMemory(@pResult[1],length(pResult)); NumDigits := length(ValidDigits); // Bindestriche entfernen, & in Großbuchstaben konvertieren ProdKey := StringReplace(ProdKey,'-','',[rfReplaceAll]); ProdKey := UpperCase(ProdKey); for k := 1 to length(ProdKey) do if(ProdKey[k] <> '') then begin // Position des aktuellen Zeichens ermitteln, ... Aux := pos(ProdKey[k],ValidDigits); if(Aux = 0) then begin Writeln('Invalid character in group'); exit; end; // ... aber um Eins verringern, weil sonst die // Berechnung nicht stimmt (das liegt daran, // dass das Zeichen-Array "ValidDigits" im // C-Programm ja auch ein PChar ist und daher // bei Null beginnt) dec(Aux); // und das ist die Berechnung ... furchtbar! ;o) for m := 1 to length(pResult) do begin Aux := Aux + BYTE(pResult[m]) * NumDigits; pResult[m] := CHR(Aux and 255); Aux := Aux shr 8; end; end; Result := 0; end;
Delphi-Quellcode:
Und hier zum Vergleich mal der Original-C-Code:
var
output : string; begin DecodeProdKey(Edit1.Text { <-- WinXP-Schlüssel eingeben },output,15); ShowProdKey(pchar(output)); end;
Code:
unsigned int CheckDigit(unsigned int Val)
{ unsigned int Sum, Copy; Sum = 0; Copy = Val; while (Copy != 0) { Sum += Copy % 10; Copy /= 10; } return Val * 10 + 7 - (Sum % 7); } void ShowProdKey(unsigned char *ProdKey) { unsigned int Val1, Val2; Val1 = *(unsigned int *)ProdKey; Val1 &= 0x7fffffff; Val1 >>= 1; Val2 = CheckDigit(Val1 % 1000000); Val1 /= 1000000; printf("Your product ID should be XXXXX-%.3u-%.7u-XXXXX.\n", Val1, Val2); } int DecodeProdKey(char *ProdKey, unsigned char *Result, int ResLen) { static char *ValidDigits = "BCDFGHJKMPQRTVWXY2346789"; int i, k, m, Groups; int Aux, NumDigits; if (strlen(ProdKey) != 29) fprintf(stderr, "Warning: Product key has non-standard length.\n"); if (strlen(ProdKey) % 6 < 1) { fprintf(stderr, "Product key has invalid length.\n"); return -1; } memset(Result, 0, ResLen); NumDigits = strlen(ValidDigits); Groups = (strlen(ProdKey) + 5) / 6; for (i = 0; i < Groups * 6; i += 6) { for (k = 0; k < 5 && ProdKey[i + k] != 0; k++) { if (ProdKey[i + k] >= 'a' && ProdKey[i + k] <= 'z') ProdKey[i + k] -= 32; for (m = 0; ValidDigits[m] != 0; m++) if (ProdKey[i + k] == ValidDigits[m]) break; if (ValidDigits[m] == 0) { fprintf(stderr, "Invalid character in group '"); for (k = 0; k < 5 && ProdKey[i + k] != 0; k++) fprintf(stderr, "%c", ProdKey[i + k]); fprintf(stderr, "'.\n"); return -1; } Aux = m; m = 0; do { Aux += Result[m] * NumDigits; Result[m++] = (unsigned char)(Aux & 255); Aux >>= 8; } while (m < ResLen); } if (ProdKey[i + k] != '-' && ProdKey[i + k] != 0) { fprintf(stderr, "Expected '-' character after group '"); for (k = 0; k < 5 && ProdKey[i + k] != 0; k++) fprintf(stderr, "%c", ProdKey[i + k]); fprintf(stderr, "'.\n"); return -1; } } return 0; } |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:03 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