Subversion Repositories decoder

Rev

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

Rev Author Line No. Line
2 daniel-mar 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
5 daniel-mar 30
  Binary         = AnsiString;  // LongString with Binary Contents
2 daniel-mar 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';
4 daniel-mar 116
  sWrongIdentity      = 'Another class "%s" with same identity as "%s" are already registered.';
2 daniel-mar 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
4 daniel-mar 236
  Signature: AnsiString;
2 daniel-mar 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
5 daniel-mar 374
  UniqueString(AnsiString(Value));
2 daniel-mar 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}
4 daniel-mar 738
procedure ModuleUnload(Instance: NativeInt);
2 daniel-mar 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
4 daniel-mar 744
      if NativeInt(FindClassHInstance(TClass(FClasses[I]))) = Instance then
2 daniel-mar 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