Thema: Delphi Zwei Hexwerte tauschen

Einzelnen Beitrag anzeigen

Benutzerbild von nTE
nTE

Registriert seit: 8. Sep 2003
60 Beiträge
 
#4

Re: Zwei Hexwerte tauschen

  Alt 15. Apr 2004, 14:16
Da ich glaube, dass du Patchen meinst, bringe ich mal ein wenig alten Code von mir.
Allerdings habe ich das mit API-Calls gelöst:

Delphi-Quellcode:
const
  sPatchFile = 'ToPatch.bla';
  NumBytesToWrite = 1;
  WhereToWrite : Array[1..NumBytesToWrite] of Longint = ($4B9A0, $4B9A1);

var
  i : Integer;
  NumWritten : DWORD;
  hFile : THandle;
  BytesToWrite : Array[1..NumBytesToWrite] of Byte = ($00,$00);


begin
  hFile := CreateFile(sPatchFile, GENERIC_WRITE, 0, nil, 3, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL);
  if hFile = DWORD(-1) then
    // Fehler, Datei nicht gefunden
  else
    begin
      for i := 1 to NumBytesToWrite do
        begin
          if SetFilePointer(hFile, WhereToWrite[i], nil, FILE_BEGIN) <> WhereToWrite[i] then
            begin
              NumWritten := 0;
              break;
            end;
          WriteFile(hFile, BytesToWrite[i], 1, NumWritten, nil);
          if NumWritten = 0 then
            // etwas ging schief beim Schreiben, NumWritten müsste immer 1 sein
            break;
        end;
          if NumWritten = 1 then
            // Patchen war erfolgreich
          else
            // Patchen ist fehlgeschlagen
        end;
    end;
  CloseHandle(hFile);
end;
Erklärung:

hFile := CreateFile(sPatchFile, GENERIC_WRITE, 0, nil, 3, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL);
CreateFile liefert ein FileHandle zurück, welches hFile zugewiesen wird (zur weiteren Arbeit mit der Datei bei SetFilePointer und WriteFile).

Der 1. Parameter ist der Name der Datei, der 2. die Zugriffsmethode (GENERIC_WRITE, weil ja nur geschrieben werden soll), der 3. Parameter gibt den Freigabemodus an (d.h. ob andere Programme zur gleichen Zeit auf die Datei zugreifen dürfen) und ist auf nicht freigeben (also exklusiven Zugriff) gestellt.
Der 4. Parameter steht für einen Zeiger auf eine Struktur vom Typ SECURITY_ATTRIBUTES, welcher verwendet werden kann um einem Kindprozess das Filehandle zu übergeben, aber da das nicht benötigt wird ist der Wert "nil". Der 5. Parameter sagt was gemacht werden soll, wenn die Datei schon existiert/noch nicht existiert, ich verwende OPEN_EXISTING, weil ja nur dann gepatcht werden soll, wenn die Datei existiert.
Der 6. Parameter ist FILE_ATTRIBUTE_NORMAL, weil das für diese Zwecke ausreichen sollte. *g*


SetFilePointer(hFile, WhereToWrite[i], nil, FILE_BEGIN);
hFile steht für das Filehandle, an 2. Stelle die Position in der Datei an die der Datei-Zeiger gesetzt werden soll (damit WriteFile nicht einfach nur an den Anfang der Datei schreibt).
Der 3. Parameter ist ein Zeiger auf das mögliche High-DWORD um Dateien mit Grössen über 4 GB zu unterstützen. Das ist hier nicht der Fall, daher ist der Parameter "nil", aber wenn man es benutzen wollte, dann müsste man eben einen Pointer auf eine DWORD (Cardinal)-Variable übergeben, da in diese dann auch das High-DWORD der neuen Position in der Datei geschrieben wird.
Der 4. Parameter ist auf FILE_BEGIN, weil ja vom Anfang der Datei aus "losgegangen" werden soll.

Zurückgegeben wird die neue Position in der Datei, welche mit WhereToWrite[i] verglichen wird um festzustellen ob alles geklappt hat. (Wenn ich sage "Setze an Position x vom Anfang der Datei aus gesehen", dann sollte die neue Position ja auch Position x sein. ;)


WriteFile(hFile, BytesToWrite[i], 1, NumWritten, nil);
hFile ist mal wieder das Filehandle, BytesToWrite[i] ist das Array mit den Byte-Werten die geschrieben werden sollen, der 3. Parameter steht für die Anzahl der Bytes die geschrieben werden sollen (also 1). Der 4. Parameter ist die Variable die Aufnehmen soll wieviele Bytes geschrieben wurden. (Sollte in diesem Falle immer 1 sein, außer es ging was schief.)
Der 5. Parameter ist nur dann in Verwendung, wenn FILE_FLAG_OVERLAPPED genommen wird wo ich bei CreateFile FILE_ATTRIBUTE_NORMAL habe.

Dass das jetzt die beste Lösung, wage ich zu bezweifeln, aber funktionieren tut es. :P

Vielleicht habe ich dich aber auch nur falsch verstanden in dem was du bezwecken willst. Für diesen Fall würde ich dir an's Herz legen, dein Problem näher zu beschreiben, vielleicht auch mit Beispielen, da du sicher weißt was du willst, andere aber nicht immer. ^^
  Mit Zitat antworten Zitat