AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Von PChar nach UINT

Ein Thema von MathiasSimmack · begonnen am 26. Mai 2004 · letzter Beitrag vom 26. Mai 2004
Antwort Antwort
MathiasSimmack
(Gast)

n/a Beiträge
 
#1

Von PChar nach UINT

  Alt 26. Mai 2004, 10:50
Ich habe gerade ein kleines Problem. In einem C-Programm passiert folgendes:
Code:
// 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);
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.

Das geht IMHO in den binären Bereich, denn wenn ich in obigem C-Code folgendes mache:
Code:
memset(Result, 0, 15);
Result[1] = 1;
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".)

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:
val = *(unsigned int *)Result;
oder muss ich doch in einer Schleife durch die einzelnen Zeichen durch?
  Mit Zitat antworten Zitat
neolithos

Registriert seit: 31. Jul 2003
Ort: Dresden
1.386 Beiträge
 
Delphi 7 Architect
 
#2

Re: Von PChar nach UINT

  Alt 26. Mai 2004, 11:03
Sowas:
Delphi-Quellcode:
var cStr : PChar;
    dw : Cardinal;
begin
  cStr := #1#0#0#255; // müssen mindestens 4 Byte sein
  dw := PCardinal(cStr)^
- ciao neo -
Es gibt niemals dumme Fragen, sondern nur dumme Antworten!
  Mit Zitat antworten Zitat
nico42
(Gast)

n/a Beiträge
 
#3

Re: Von PChar nach UINT

  Alt 26. Mai 2004, 12:05
Zitat von MathiasSimmack:
printf("%u\n",val);
Kannste mal die Ausgabe von printf posten? Ich bezweifle eigentlich
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...
  Mit Zitat antworten Zitat
MathiasSimmack
(Gast)

n/a Beiträge
 
#4

Re: Von PChar nach UINT

  Alt 26. Mai 2004, 13:04
Nein, so wie neolithos das vorgeschlagen hat, ist das schon richtig.
@neolithos: Danke.
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#5

Re: Von PChar nach UINT

  Alt 26. Mai 2004, 13:49
Moin!

@nico42:
Code:
val = *(unsigned int *)Result;
(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).

@other:
Ansonsten eine Übersetzung des Codes:
Code:
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;
MfG
Muetze1
  Mit Zitat antworten Zitat
MathiasSimmack
(Gast)

n/a Beiträge
 
#6

Re: Von PChar nach UINT

  Alt 26. Mai 2004, 14:37
btw: Hier der Hintergrund der ganzen Geschichte. Auf www.licenturion.com/xp/ gibt es den Quellcode eines Tools, mit dem man u.a. aus dem Produktschlüssel von Windows XP die Produkt-ID (die in der Registry gespeichert ist) berechnen kann. Das heißt, das Programm zeigt den relevanten Teil dieser ID an, so dass man vergleichen kann. So sieht man auch sehr schön, wo dieser Schlüssel eigentlich steckt.
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:
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;
Aufzurufen:
Delphi-Quellcode:
var
  output : string;
begin
  DecodeProdKey(Edit1.Text { <-- WinXP-Schlüssel eingeben },output,15);
  ShowProdKey(pchar(output));
end;
Und hier zum Vergleich mal der Original-C-Code:
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;
}
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:45 Uhr.
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