Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.166 Beiträge
 
Delphi 12 Athens
 

Re: Programmdatei auf "Fehler" prüfen

  Alt 24. Nov 2007, 16:45
Upps, bevor wer meckert,
ich verwende 'ne etwas andere (PSDK-äquivalente) Implementation von WriteFile, als die von Delphi

kann's oben nicht mehr Editieren, aber ihr müßt einfach nur die zwei @ entfernen:
WriteFile(H, MD5.digest, SizeOf(MD5.digest), W, nil);
@shmia:
Na ob sich das soviel auswirkt, aber du hast schon etwas Recht und vielleicht sieht es jetzt auch noch etwas netter aus

Aber die 2 Schleifen werden ja eh nur bei jedem (etwa) 256-ten Zeichen durchlaufen.
Tja, jetzt sind da 2 Funktionsaufrufe (inclusive einiger Parametertests) statt der 2 (etwas optimierten) Pascalschleifen.

Im Prinzip kann man das ganze eigentlich nur "großartig" optimieren, wenn man meinen ersten Code gegen eine Assemblerversion ersetzt, aber da diese eh nur ein einziges Mal bei Programmstart ausgeführt wird und nun doch nicht soooo langsam ist, hatte ich mir das gesparrt.

Was optimierenswert wäre, das wär eine binäre Pos-Version, womit man die Suche (IF+Schleife) ersetzen könnte.


extra für dich mit CompareMem,
aber immernoch mit der kleinen IF ((P + i)^ = SelfCheckData[0]),
wär ja blöd, wenn jetzt bei jedem Zeichen die Funktionen aufgerufen würden:
Delphi-Quellcode:
Type MD5_CTX = packed Record
    i: Array[0.. 1] of LongWord;
    buf: Array[0.. 3] of LongWord;
    input: Array[0..63] of Byte;
    digest: Array[0..15] of Byte;
  End;

Procedure MD5Init(Var Context: MD5_CTX); StdCall;
  External 'advapi32.dllName 'MD5Init';
Procedure MD5Update(Var Context: MD5_CTX; Input: Pointer; inLen: LongWord); StdCall;
  External 'advapi32.dllName 'MD5Update';
Procedure MD5Final(Var Context: MD5_CTX); StdCall;
  External 'advapi32.dllName 'MD5Final';

Function SelfCheck: Boolean;
  Const SelfCheckSigLen = 25;
    SelfCheckData: packed Array[0..44] of AnsiChar
      = 'S'#0'e'#1'l'#2'f'#3'C'#4'h'#5'e'#5'c'#4'k'#3'D'#2'a'#1't'#0'a'
      + '>>'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'<<';

  Var FileName: WideString;
    H, Hm: THandle;
    FileSize, i, i2: Integer;
    P: PChar;
    MD5: MD5_CTX;
    W: Cardinal;

  Begin
    Result := False;
    SetLength(FileName, MAX_PATH);
    SetLength(FileName, GetModuleFileNameW(0, PWideChar(FileName), MAX_PATH));
    H := CreateFileW(PWideChar(FileName), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE,
      nil, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
    FileSize := GetFileSize(H, nil);
    Hm := CreateFileMapping(H, nil, PAGE_READONLY, 0, 0, nil);
    P := MapViewOfFile(Hm, FILE_MAP_READ, 0, 0, 0);
    CloseHandle(H);
    Try
      If P = nil Then Exit;
      For i := 0 to FileSize - Length(SelfCheckData) do
        If ((P + i)^ = SelfCheckData[0])
          and CompareMem(P + i, @SelfCheckData[0], SelfCheckSigLen + 2)
          and CompareMem(P + i + SelfCheckSigLen + 2 + SizeOf(MD5.digest),
            @SelfCheckData[SelfCheckSigLen + 2 + SizeOf(MD5.digest)], 2) Then Begin
          MD5Init(MD5);
          MD5Update(MD5, P, i);
          MD5Update(MD5, P + i + Length(SelfCheckData), FileSize - i - Length(SelfCheckData));
          MD5Final(MD5);
          Result := True;
          For i2 := 0 to High(MD5.digest) do
            If PByte(P + i + SelfCheckSigLen + 2 + i2)^ <> 0 Then Begin
              Result := False;
              Break;
            End;
          If Result Then Begin
            DeleteFileW(PWideChar(FileName + '.old'));
            MoveFileW(PWideChar(FileName), PWideChar(FileName + '.old'));
            CopyFileW(PWideChar(FileName + '.old'), PWideChar(FileName), False);
            H := CreateFileW(PWideChar(FileName), GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE,
              nil, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0);
            If Integer(SetFilePointer(H, i + SelfCheckSigLen + 2, nil, FILE_BEGIN)) = i + SelfCheckSigLen + 2 Then
              WriteFile(H, MD5.digest, SizeOf(MD5.digest), W, nil);
            CloseHandle(H);
            //ShellExecuteW(0, 'open', PWideChar(FileName), GetCommandLineW, nil, SW_SHOW);
            //Halt;
            Exit;
          End;
          Result := True;
          For i2 := 0 to High(MD5.digest) do
            If PByte(P + i + SelfCheckSigLen + 2 + i2)^ <> MD5.digest[i2] Then Begin
              Result := False;
              Break;
            End;
          Exit;
        End;
    Finally
      UnmapViewOfFile(P);
      CloseHandle(Hm);
    End;
  End;



If not SelfCheck Then
  Error...



Zitat:
NonVCL-Freaks können ja die Routine kopieren.
neeeee, wir machen alles selber

PS: gerade die extrem aufblähende SysUtils hatte ich bei mir ja entfernt
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat