Subversion Repositories decoder

Rev

Rev 4 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. {Copyright:      Hagen Reddmann  HaReddmann at T-Online dot de
  2.  Author:         Hagen Reddmann
  3.  Remarks:        freeware, but this Copyright must be included
  4.  known Problems: none
  5.  Version:        5.1, Delphi Encryption Compendium
  6.                  Delphi 2-4, BCB 3-4, designed and testet under D3-5
  7.  Description:    Utilitys for the DEC Packages
  8.  
  9.  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
  10.  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  11.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  12.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
  13.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  14.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  15.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  16.  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  17.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  18.  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  19.  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  20. }
  21.  
  22. unit DECUtil;
  23. {$I VER.INC}
  24.  
  25. interface
  26.  
  27. uses Windows, SysUtils, Classes, CRC;
  28.  
  29. type
  30.   Binary         = String;  // LongString with Binary Contens
  31. {$IFNDEF VER_D4H}
  32.   LongWord       = type Integer;
  33. {$ENDIF}
  34.   PLongWord      = ^LongWord;
  35.   PByte          = ^Byte;
  36.   PInteger       = ^Integer;
  37.   PWord          = ^Word;
  38.   PLongArray     = ^TLongArray;
  39.   TLongArray     = array[0..1023] of LongWord;
  40.  
  41. // basicaly DEC Exceptionclass ALL-exception in DEC-Classes/methods should be use this or descends
  42.   EDECException  = class(Exception);
  43.  
  44. // basicaly Class for all DEC classes that needed a RefCounter and
  45. // Registration Support
  46.   TDECClass = class of TDECObject;
  47.  
  48.   TDECObject = class(TPersistent)
  49.   public
  50.     constructor Create; virtual;
  51.     class function Identity: LongWord;
  52.     class procedure Register;
  53.     procedure FreeInstance; override;
  54.   end;
  55.  
  56.   IDECProgress = interface
  57.     ['{64366E77-82FE-4B86-951E-79389729A493}']
  58.     procedure Process(const Min,Max,Pos: Int64); stdcall;
  59.   end;
  60.  
  61. // DEC Classes Registration
  62. type
  63.   TDECEnumClassesCallback = function(UserData: Pointer; ClassType: TClass): Boolean; register;
  64.  
  65. // Register DEC Classes to make it streamable
  66. procedure RegisterDECClasses(const Classes: array of TClass);
  67. // Unregister DEC Classes
  68. procedure UnregisterDECClasses(const Classes: array of TClass);
  69. // fillout a StringList with registered DEC Classes
  70. procedure DECClasses(List: TStrings; Include: TClass = nil; Exclude: TClass = nil);
  71. // find a registered DEC Class by Identity
  72. function DECClassByIdentity(Identity: LongWord; ClassType: TClass): TDECClass;
  73. // find DEC Class by Name, can be as Example: TCipher_Blowfish, Blowfish or registered Name override
  74. function  DECClassByName(const Name: String; ClassType: TClass): TDECClass;
  75. // returns correted short Classname of any registered DEC Class
  76. function  DECClassName(ClassType: TClass): String;
  77. // enumerate by callback over registered DEC classes
  78. function  DECEnumClasses(Callback: TDECEnumClassesCallback; UserData: Pointer; Include: TClass = nil; Exclude: TClass = nil): TDECClass;
  79.  
  80. procedure ProtectBuffer(var Buffer; Size: Integer);
  81. procedure ProtectBinary(var Value: Binary);
  82. procedure ProtectStream(Stream: TStream; Size: Integer = 0);
  83. // test iff Buffer contains BufferSize values
  84. function  IsFilledWith(var Buffer; Size: Integer; Value: Char): Boolean;
  85. procedure FoldBuf(var Dest; DestSize: Integer; const Source; SourceSize: Integer);
  86. procedure FoldStr(var Dest; DestSize: Integer; const Source: String);
  87. // Random Buffer/Binary, ATENTION! standard Random Function are'nt crytographicaly secure,
  88. // please include DECRandom to install secure PRNG
  89. function  RandomBinary(Size: Integer): Binary;
  90. procedure RandomBuffer(var Buffer; Size: Integer);
  91. function  RandomLong: LongWord;
  92. procedure RandomSeed(const Buffer; Size: Integer); overload;
  93. procedure RandomSeed; overload;
  94. function  RandomSystemTime: Cardinal;
  95. // reverse Byte order from Buffer
  96. procedure SwapBytes(var Buffer; BufferSize: Integer);
  97. function  SwapLong(Value: LongWord): LongWord;
  98. procedure SwapLongBuffer(const Source; var Dest; Count: Integer);
  99. function  SwapInt64(const Value: Int64): Int64;
  100. procedure SwapInt64Buffer(const Source; var Dest; Count: Integer);
  101. function  SwapBits(Value, Bits: LongWord): LongWord;
  102. procedure XORBuffers(const Source1, Source2; Size: Integer; var Dest);
  103. // saver Test iff AObject valid
  104. function IsObject(AObject: Pointer; AClass: TClass): Boolean;
  105.  
  106. var
  107.   IdentityBase : LongWord = $25844852; // used as base in classmethod Identity
  108.  
  109.   DoRandomBuffer: procedure(var Buffer; Size: Integer); register = nil;
  110.   DoRandomSeed: procedure(const Buffer; Size: Integer); register = nil;
  111.  
  112. implementation
  113.  
  114. resourcestring
  115.   sClassNotRegistered = 'Class %s not registered';
  116.   sWrongIdentity      = 'Another class "%s" with same identity as "%s" are allready registered.';
  117.  
  118. var
  119.   FClasses: TList = nil;
  120.  
  121. function GetShortClassName(const Value: String): String;
  122. var
  123.   I: Integer;
  124. begin
  125.   Result := Value;
  126.   I := Pos('_', Result);
  127.   if I > 0 then Delete(Result, 1, I);
  128. end;
  129.  
  130. procedure RegisterDECClasses(const Classes: array of TClass);
  131. var
  132.   I: Integer;
  133. begin
  134.   for I := Low(Classes) to High(Classes) do
  135.     if (Classes[I] <> nil) and Classes[I].InheritsFrom(TDECObject) then
  136.       TDECClass(Classes[I]).Register;
  137. end;
  138.  
  139. procedure UnregisterDECClasses(const Classes: array of TClass);
  140. var
  141.   I,J: Integer;
  142. begin
  143.   if IsObject(FClasses, TList) then
  144.     for I := Low(Classes) to High(Classes) do
  145.     begin
  146.       J := FClasses.IndexOf(Classes[I]);
  147.       if J >= 0 then FClasses.Delete(J);
  148.     end;
  149. end;
  150.  
  151. procedure DECClasses(List: TStrings; Include: TClass = nil; Exclude: TClass = nil);
  152.  
  153.   function DoAdd(List: TStrings; ClassType: TClass): Boolean;
  154.   begin
  155.     Result := False;
  156.     List.AddObject(ClassType.ClassName, Pointer(ClassType));
  157.   end;
  158.  
  159. begin
  160.   if IsObject(List, TStrings) then
  161.   try
  162.     List.BeginUpdate;
  163.     List.Clear;
  164.     DECEnumClasses(@DoAdd, List, Include, Exclude);
  165.   finally
  166.     List.EndUpdate;
  167.   end;
  168. end;
  169.  
  170. function DECClassByIdentity(Identity: LongWord; ClassType: TClass): TDECClass;
  171.  
  172.   function DoFind(Identity: LongWord; ClassType: TDECClass): Boolean;
  173.   begin
  174.     Result := ClassType.Identity = Identity;
  175.   end;
  176.  
  177. begin
  178.   Result := DECEnumClasses(@DoFind, Pointer(Identity), ClassType);
  179.   if Result = nil then
  180.     raise EDECException.CreateFmt(sClassNotRegistered, [IntToHEX(Identity, 8)]);
  181. end;
  182.  
  183. function DECClassByName(const Name: String; ClassType: TClass): TDECClass;
  184.  
  185.   function DoFindShort(const Name: String; ClassType: TClass): Boolean;
  186.   begin
  187.     Result := AnsiCompareText(DECClassName(ClassType), Name) = 0;
  188.   end;
  189.  
  190.   function DoFindLong(const Name: String; ClassType: TClass): Boolean;
  191.   begin
  192.     Result := AnsiCompareText(ClassType.ClassName, Name) = 0;
  193.   end;
  194.  
  195. begin
  196.   Result := nil;
  197.   if Name <> '' then
  198.     if GetShortClassName(Name) = Name then
  199.       Result := DECEnumClasses(@DoFindShort, Pointer(Name), ClassType)
  200.     else
  201.       Result := DECEnumClasses(@DoFindLong, Pointer(Name), ClassType);
  202.   if Result = nil then
  203.     raise EDECException.CreateFmt(sClassNotRegistered, [Name]);
  204. end;
  205.  
  206. function DECClassName(ClassType: TClass): String;
  207. begin
  208.   if ClassType = nil then Result := ''
  209.     else Result := GetShortClassName(ClassType.ClassName);
  210. end;
  211.  
  212. function DECEnumClasses(Callback: TDECEnumClassesCallback; UserData: Pointer;
  213.             Include: TClass = nil; Exclude: TClass = nil): TDECClass;
  214. var
  215.   I: Integer;
  216. begin
  217.   Result := nil;
  218.   if Assigned(Callback) and IsObject(FClasses, TList) then
  219.     for I := 0 to FClasses.Count -1 do
  220.       if ((Include = nil) or     TClass(FClasses[I]).InheritsFrom(Include)) and
  221.          ((Exclude = nil) or not TClass(FClasses[I]).InheritsFrom(Exclude)) and
  222.           Callback(UserData, FClasses[I]) then
  223.       begin
  224.         Result := FClasses[I];
  225.         Break;
  226.       end;
  227. end;
  228.  
  229. constructor TDECObject.Create;
  230. begin
  231.   inherited Create;
  232. end;
  233.  
  234. class function TDECObject.Identity: LongWord;
  235. var
  236.   Signature: String;
  237. begin
  238.   Signature := StringOfChar(#$5A, 256 - Length(Classname)) + AnsiUpperCase(ClassName);
  239.   Result := CRC32(IdentityBase, Signature[1], Length(Signature));
  240. end;
  241.  
  242. class procedure TDECObject.Register;
  243. var
  244.   I: Integer;
  245.   Found: Boolean;
  246.   ID: LongWord;
  247. begin
  248.   if IsObject(FClasses, TList) then
  249.   begin
  250.     Found := False;
  251.     ID := Identity;
  252.     for I := 0 to FClasses.Count-1 do
  253.       if FClasses[I] = Self then Found := True else
  254.         if ID = TDECClass(FClasses[I]).Identity then
  255.           raise EDECException.CreateFmt(sWrongIdentity, [TDECClass(FClasses[I]).ClassName, ClassName]);
  256.     if not Found then FClasses.Add(Self);
  257.   end;
  258. end;
  259.  
  260. // override FreeInstance to fillout allocated Object with Zeros
  261. // that is safer for any access to invalid Pointers of any released Object
  262. // WE WANT SECURITY !!!
  263. procedure TDECObject.FreeInstance;
  264. asm
  265.       PUSH    EBX
  266.       PUSH    EDI
  267.       MOV     EBX,EAX
  268.       CALL    TObject.CleanupInstance
  269.       MOV     EAX,[EBX]
  270.       CALL    TObject.InstanceSize
  271.       MOV     ECX,EAX
  272.       MOV     EDI,EBX
  273.       XOR     EAX,EAX
  274.       REP     STOSB
  275.       MOV     EAX,EBX
  276.       CALL    System.@FreeMem
  277.       POP     EDI
  278.       POP     EBX
  279. end;
  280.  
  281.  
  282. function IsObject(AObject: Pointer; AClass: TClass): Boolean;
  283. // Relacement of "is" Operator for safer access/check iff AObject is AClass
  284.  
  285.   function IsClass(AObject: Pointer; AClass: TClass): Boolean;
  286.   asm  // safer replacement for Borland's "is" operator
  287.   @@1:    TEST    EAX,EAX
  288.           JE      @@3
  289.           MOV     EAX,[EAX]
  290.           TEST    EAX,EAX
  291.           JE      @@3
  292.           CMP     EAX,EDX
  293.           JE      @@2
  294.           MOV     EAX,[EAX].vmtParent
  295.           JMP     @@1
  296.   @@2:    MOV     EAX,1
  297.   @@3:
  298.   end;
  299.  
  300. begin
  301.   Result := False;
  302.   if AObject <> nil then
  303.   try
  304.     Result := IsClass(AObject, AClass);
  305.   except
  306.   end;
  307. end;
  308.  
  309. function MemCompare(P1, P2: Pointer; Size: Integer): Integer;
  310. asm //equal to StrLComp(P1, P2, Size), but allways Size Bytes are checked
  311.        PUSH    ESI
  312.        PUSH    EDI
  313.        MOV     ESI,P1
  314.        MOV     EDI,P2
  315.        XOR     EAX,EAX
  316.        REPE    CMPSB
  317.        JE      @@1
  318.        MOVZX   EAX,BYTE PTR [ESI-1]
  319.        MOVZX   EDX,BYTE PTR [EDI-1]
  320.        SUB     EAX,EDX
  321. @@1:   POP     EDI
  322.        POP     ESI
  323. end;
  324.  
  325. procedure XORBuffers(const Source1, Source2; Size: Integer; var Dest);
  326. asm // Dest^ =  Source1^ xor Source2^ , Size bytes
  327.        AND   ECX,ECX
  328.        JZ    @@5
  329.        PUSH  ESI
  330.        PUSH  EDI
  331.        MOV   ESI,EAX
  332.        MOV   EDI,Dest
  333. @@1:   TEST  ECX,3
  334.        JNZ   @@3
  335. @@2:   SUB   ECX,4
  336.        JL    @@4
  337.        MOV   EAX,[ESI + ECX]
  338.        XOR   EAX,[EDX + ECX]
  339.        MOV   [EDI + ECX],EAX
  340.        JMP   @@2
  341. @@3:   DEC   ECX
  342.        MOV   AL,[ESI + ECX]
  343.        XOR   AL,[EDX + ECX]
  344.        MOV   [EDI + ECX],AL
  345.        JMP   @@1
  346. @@4:   POP   EDI
  347.        POP   ESI
  348. @@5:                          
  349. end;
  350.  
  351. // wipe
  352. const
  353.   WipeCount = 4;
  354.   WipeBytes : array[0..WipeCount -1] of Byte = ($55, $AA, $FF, $00);
  355.  
  356. procedure ProtectBuffer(var Buffer; Size: Integer);
  357. var
  358.   Count: Integer;
  359. begin
  360.   if Size > 0 then
  361.     for Count := 0 to WipeCount -1 do
  362.       FillChar(Buffer, Size, WipeBytes[Count]);
  363. end;
  364.  
  365. procedure ProtectString(var Value: String);
  366. begin
  367.   UniqueString(Value);
  368.   ProtectBuffer(Pointer(Value)^, Length(Value));
  369.   Value := '';
  370. end;
  371.  
  372. procedure ProtectBinary(var Value: Binary);
  373. begin
  374.   UniqueString(String(Value));
  375.   ProtectBuffer(Pointer(Value)^, Length(Value));
  376.   Value := '';
  377. end;
  378.  
  379. procedure ProtectStream(Stream: TStream; Size: Integer = 0);
  380. const
  381.   BufferSize = 512;
  382. var
  383.   Buffer: String;
  384.   Count,Bytes,DataSize: Integer;
  385.   Position: Integer;
  386. begin
  387.   if IsObject(Stream, TStream) then
  388.   begin
  389.     Position := Stream.Position;
  390.     DataSize := Stream.Size;
  391.     if Size <= 0 then
  392.     begin
  393.       Size := DataSize;
  394.       Position := 0;
  395.     end else
  396.     begin
  397.       Dec(DataSize, Position);
  398.       if Size > DataSize then Size := DataSize;
  399.     end;
  400.     SetLength(Buffer, BufferSize);
  401.     for Count := 0 to WipeCount -1 do
  402.     begin
  403.       Stream.Position := Position;
  404.       DataSize := Size;
  405.       FillChar(Buffer[1], BufferSize, WipeBytes[Count]);
  406.       while DataSize > 0 do
  407.       begin
  408.         Bytes := DataSize;
  409.         if Bytes > BufferSize then Bytes := BufferSize;
  410.         Stream.Write(Buffer[1], Bytes);
  411.         Dec(DataSize, Bytes);
  412.       end;
  413.     end;
  414.   end;
  415. end;
  416.  
  417. function IsFilledWith(var Buffer; Size: Integer; Value: Char): Boolean;
  418. asm // check iff Buffer is filled Size of bytes with Value
  419.        TEST   EAX,EAX
  420.        JZ     @@1
  421.        PUSH   EDI
  422.        MOV    EDI,EAX
  423.        MOV    EAX,ECX
  424.        MOV    ECX,EDX
  425.        REPE   SCASB
  426.        SETE   AL
  427.        POP    EDI
  428. @@1:
  429. end;
  430.  
  431. procedure FoldBuf(var Dest; DestSize: Integer; const Source; SourceSize: Integer);
  432. var
  433.   I: Integer;
  434.   S,D: PByteArray;
  435. begin
  436.   if (DestSize <= 0) or (SourceSize <= 0) then Exit;
  437.   S := PByteArray(@Source);
  438.   D := PByteArray(@Dest);
  439.   if SourceSize > DestSize then
  440.   begin
  441.     FillChar(D^, DestSize, 0);
  442.     for I := 0 to SourceSize-1 do
  443.       D[I mod DestSize] := D[I mod DestSize] + S[I];
  444.   end else
  445.   begin
  446.     while DestSize > SourceSize do
  447.     begin
  448.       Move(S^, D^, SourceSize);
  449.       Dec(DestSize, SourceSize);
  450.       Inc(PChar(D), SourceSize);
  451.     end;
  452.     Move(S^, D^, DestSize);
  453.   end;
  454. end;
  455.  
  456. procedure FoldStr(var Dest; DestSize: Integer; const Source: String);
  457. begin
  458.   FoldBuf(Dest, DestSize, PChar(Source)^, Length(Source));
  459. end;
  460. // random
  461.  
  462. var
  463.   FRndSeed: Cardinal = 0;
  464.  
  465. function DoRndBuffer(Seed: Cardinal; var Buffer; Size: Integer): Cardinal;
  466. // nothing others as Borlands Random
  467. asm
  468.       AND     EDX,EDX
  469.       JZ      @@2
  470.       AND     ECX,ECX
  471.       JLE     @@2
  472.       PUSH    EBX
  473. @@1:  IMUL    EAX,EAX,134775813
  474.       INC     EAX
  475.       MOV     EBX,EAX
  476.       SHR     EBX,24
  477.       MOV     [EDX],BL
  478.       INC     EDX
  479.       DEC     ECX
  480.       JNZ     @@1
  481.       POP     EBX
  482. @@2:
  483. end;
  484.  
  485. function RandomSystemTime: Cardinal;
  486. // create Seed from Systemtime and performancecounter
  487. var
  488.   SysTime: record
  489.              Year: Word;
  490.              Month: Word;
  491.              DayOfWeek: Word;
  492.              Day: Word;
  493.              Hour: Word;
  494.              Minute: Word;
  495.              Second: Word;
  496.              MilliSeconds: Word;
  497.              Reserved: array [0..7] of Byte;
  498.            end;
  499.   Counter: record
  500.              Lo,Hi: Integer;
  501.            end;
  502. asm
  503.          LEA    EAX,SysTime
  504.          PUSH   EAX
  505.          CALL   GetSystemTime
  506.          MOVZX  EAX,Word Ptr SysTime.Hour
  507.          IMUL   EAX,60
  508.          ADD    AX,SysTime.Minute
  509.          IMUL   EAX,60
  510.          MOVZX  ECX,Word Ptr SysTime.Second
  511.          ADD    EAX,ECX
  512.          IMUL   EAX,1000
  513.          MOV    CX,SysTime.MilliSeconds
  514.          ADD    EAX,ECX
  515.          PUSH   EAX
  516.          LEA    EAX,Counter
  517.          PUSH   EAX
  518.          CALL   QueryPerformanceCounter
  519.          POP    EAX
  520.          ADD    EAX,Counter.Hi
  521.          ADC    EAX,Counter.Lo
  522. end;
  523.  
  524. function RandomBinary(Size: Integer): Binary;
  525. begin
  526.   SetLength(Result, Size);
  527.   RandomBuffer(Result[1], Size);
  528. end;
  529.  
  530. procedure RandomBuffer(var Buffer; Size: Integer);
  531. begin
  532.   if Assigned(DoRandomBuffer) then DoRandomBuffer(Buffer, Size)
  533.     else FRndSeed := DoRndBuffer(FRndSeed, Buffer, Size);
  534. end;
  535.  
  536. function RandomLong: LongWord;
  537. begin
  538.   RandomBuffer(Result, SizeOf(Result));
  539. end;
  540.  
  541. procedure RandomSeed(const Buffer; Size: Integer);
  542. begin
  543.   if Assigned(DoRandomSeed) then DoRandomSeed(Buffer, Size) else
  544.     if Size >= 0 then
  545.     begin
  546.       FRndSeed := 0;
  547.       while Size > 0 do
  548.       begin
  549.         Dec(Size);
  550.         FRndSeed := (FRndSeed shl 8 + FRndSeed shr 24) xor TByteArray(Buffer)[Size]
  551.       end;
  552.     end else FRndSeed := RandomSystemTime;
  553. end;
  554.  
  555. procedure RandomSeed;
  556. begin
  557.   RandomSeed('', -1);
  558. end;
  559.  
  560. procedure SwapBytes(var Buffer; BufferSize: Integer);
  561. asm
  562.        CMP    EDX,1
  563.        JLE    @@3
  564.        AND    EAX,EAX
  565.        JZ     @@3
  566.        PUSH   EBX
  567.        MOV    ECX,EDX
  568.        LEA    EDX,[EAX + ECX -1]
  569.        SHR    ECX,1
  570. @@1:   MOV    BL,[EAX]
  571.        XCHG   BL,[EDX]
  572.        DEC    EDX
  573.        MOV    [EAX],BL
  574.        INC    EAX
  575.        DEC    ECX
  576.        JNZ    @@1
  577. @@2:   POP    EBX
  578. @@3:
  579. end;
  580.  
  581. function SwapLong(Value: LongWord): LongWord;
  582. {$IFDEF UseASM}
  583.   {$IFDEF 486GE}
  584.     {$DEFINE SwapLong_asm}
  585.   {$ENDIF}
  586. {$ENDIF}
  587. {$IFDEF SwapLong_asm}
  588. asm
  589.        BSWAP  EAX
  590. end;
  591. {$ELSE}
  592. begin
  593.   Result := Value shl 24 or Value shr 24 or Value shl 8 and $00FF0000 or Value shr 8 and $0000FF00;
  594. end;
  595. {$ENDIF}
  596.  
  597. procedure SwapLongBuffer(const Source; var Dest; Count: Integer);
  598. {$IFDEF UseASM}
  599.   {$IFDEF 486GE}
  600.     {$DEFINE SwapLongBuffer_asm}
  601.   {$ENDIF}
  602. {$ENDIF}
  603. {$IFDEF SwapLongBuffer_asm}
  604. asm
  605.        TEST   ECX,ECX
  606.        JLE    @Exit
  607.        PUSH   EDI
  608.        SUB    EAX,4
  609.        SUB    EDX,4
  610. @@1:   MOV    EDI,[EAX + ECX * 4]
  611.        BSWAP  EDI
  612.        MOV    [EDX + ECX * 4],EDI
  613.        DEC    ECX
  614.        JNZ    @@1
  615.        POP    EDI
  616. @Exit:
  617. end;
  618. {$ELSE}
  619. var
  620.   I: Integer;
  621.   T: LongWord;
  622. begin
  623.   for I := 0 to Count -1 do
  624.   begin
  625.     T := TLongArray(Source)[I];
  626.     TLongArray(Dest)[I] := (T shl 24) or (T shr 24) or ((T shl 8) and $00FF0000) or ((T shr 8) and $0000FF00);
  627.   end;
  628. end;
  629. {$ENDIF}
  630.  
  631. function SwapInt64(const Value: Int64): Int64;
  632. {$IFDEF UseASM}
  633.   {$IFDEF 486GE}
  634.     {$DEFINE SwapInt64_asm}
  635.   {$ENDIF}
  636. {$ENDIF}
  637. {$IFDEF SwapInt64_asm}
  638. asm
  639.        MOV    EDX,Value.DWord[0]
  640.        MOV    EAX,Value.DWord[4]
  641.        BSWAP  EDX
  642.        BSWAP  EAX
  643. end;
  644. {$ELSE}
  645. var
  646.   L,H: LongWord;
  647. begin
  648.   L := Int64Rec(Value).Lo;
  649.   H := Int64Rec(Value).Hi;
  650.   L := L shl 24 or L shr 24 or L shl 8 and $00FF0000 or L shr 8 and $0000FF00;
  651.   H := H shl 24 or H shr 24 or H shl 8 and $00FF0000 or H shr 8 and $0000FF00;
  652.   Int64Rec(Result).Hi := L;
  653.   Int64Rec(Result).Lo := H;
  654. end;
  655. {$ENDIF}
  656.  
  657. procedure SwapInt64Buffer(const Source; var Dest; Count: Integer);
  658. {$IFDEF UseASM}
  659.   {$IFDEF 486GE}
  660.     {$DEFINE SwapInt64Buffer_asm}
  661.   {$ENDIF}
  662. {$ENDIF}
  663. {$IFDEF SwapInt64Buffer_asm}
  664. asm
  665.        TEST   ECX,ECX
  666.        JLE    @Exit
  667.        PUSH   ESI
  668.        PUSH   EDI
  669.        LEA    ESI,[EAX + ECX * 8]
  670.        LEA    EDI,[EDX + ECX * 8]
  671.        NEG    ECX
  672. @@1:   MOV    EAX,[ESI + ECX * 8]
  673.        MOV    EDX,[ESI + ECX * 8 + 4]
  674.        BSWAP  EAX
  675.        BSWAP  EDX
  676.        MOV    [EDI + ECX * 8 + 4],EAX
  677.        MOV    [EDI + ECX * 8],EDX
  678.        INC    ECX
  679.        JNZ    @@1
  680.        POP    EDI
  681.        POP    ESI
  682. @Exit:
  683. end;
  684. {$ELSE}
  685. var
  686.   I: Integer;
  687.   H,L: LongWord;
  688. begin
  689.   for I := 0 to Count -1 do
  690.   begin
  691.    H := TLongArray(Source)[I * 2    ];
  692.    L := TLongArray(Source)[I * 2 + 1];
  693.    TLongArray(Dest)[I * 2    ] := L shl 24 or L shr 24 or L shl 8 and $00FF0000 or L shr 8 and $0000FF00;
  694.    TLongArray(Dest)[I * 2 + 1] := H shl 24 or H shr 24 or H shl 8 and $00FF0000 or H shr 8 and $0000FF00;
  695.   end;
  696. end;
  697. {$ENDIF}
  698.  
  699. {reverse the bit order from a integer}
  700. function SwapBits(Value, Bits: LongWord): LongWord;
  701. {$IFDEF UseASM}
  702.   {$IFDEF 486GE}
  703.     {$DEFINE SwapBits_asm}
  704.   {$ENDIF}
  705. {$ENDIF}
  706. {$IFDEF SwapBits_asm}
  707. asm
  708.        BSWAP  EAX
  709.        MOV    ECX,EAX
  710.        AND    EAX,0AAAAAAAAh
  711.        SHR    EAX,1
  712.        AND    ECX,055555555h
  713.        SHL    ECX,1
  714.        OR     EAX,ECX
  715.        MOV    ECX,EAX
  716.        AND    EAX,0CCCCCCCCh
  717.        SHR    EAX,2
  718.        AND    ECX,033333333h
  719.        SHL    ECX,2
  720.        OR     EAX,ECX
  721.        MOV    ECX,EAX
  722.        AND    EAX,0F0F0F0F0h
  723.        SHR    EAX,4
  724.        AND    ECX,00F0F0F0Fh
  725.        SHL    ECX,4
  726.        OR     EAX,ECX
  727.        AND    EDX,01Fh
  728.        JZ     @@1
  729.        MOV    ECX,32
  730.        SUB    ECX,EDX
  731.        SHR    EAX,CL
  732. @@1:
  733. end;
  734. {$ELSE}
  735. {$ENDIF}
  736.  
  737. {$IFDEF VER_D3H}
  738. procedure ModuleUnload(Instance: Integer);
  739. var // automaticaly deregistration/releasing
  740.   I: Integer;
  741. begin
  742.   if IsObject(FClasses, TList) then
  743.     for I := FClasses.Count -1 downto 0 do
  744.       if Integer(FindClassHInstance(TClass(FClasses[I]))) = Instance then
  745.         FClasses.Delete(I);
  746. end;
  747.  
  748. initialization
  749.   AddModuleUnloadProc(ModuleUnload);
  750. {$ELSE}
  751. initialization
  752. {$ENDIF}
  753.   FClasses := TList.Create;
  754. finalization
  755. {$IFDEF VER_D3H}
  756.   RemoveModuleUnloadProc(ModuleUnload);
  757. {$ENDIF}
  758.   FClasses.Free;
  759.   FClasses := nil;
  760. end.
  761.  
  762.  
  763.