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 |