-
Notifications
You must be signed in to change notification settings - Fork 23
/
unaUtils.pas
10384 lines (9235 loc) · 259 KB
/
unaUtils.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
(*
Copyright 2018 Alex Shamray
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*)
(*
----------------------------------------------
unaUtils.pas
----------------------------------------------
Copyright (c) 2001-2011 Lake of Soft
All rights reserved
http://lakeofsoft.com/
----------------------------------------------
created by:
Lake, 25 Aug 2001
modified by:
Lake, Aug-Dec 2001
Lake, Jan-Dec 2002
Lake, Jan-Dec 2003
Lake, Jan-Dec 2004
Lake, Jan-Dec 2005
Lake, Jan-Dec 2006
Lake, Jan-Dec 2007
Lake, Jan-Oct 2008
Lake, Jun-Dec 2009
Lake, Jan-Dec 2010
Lake, Jan-May 2011
----------------------------------------------
*)
{$I unaDef.inc }
{$IFDEF __AFTER_DE__ }
{$ELSE}
// Delphi 9.0 (2005) -- XE (2010)? has really buggy inline support, sorry. Get a better compiler.
{$UNDEF UNA_OK_INLINE }
{$ENDIF __AFTER_DE__ }
{x $DEFINE CONSOLE_IO } // defien to declare and initialize I/O handles: g_CONIN and g_CONOUT
{x $DEFINE UNAUTILS_NOSHELL } // Do not link to Shell/WinMM
{$DEFINE UNAUTILS_NOTIME } // Do not link to WinMM timers
{$IFDEF DEBUG }
//
{$DEFINE LOG_UNAUTILS_INFOS } // log informational messages
{$DEFINE LOG_UNAUTILS_ERRORS } // log fatal error messages
//
{$IFDEF __AFTER_D9__ }
//
{x $DEFINE UNAUTILS_DEBUG_MEM } // enable memory allocations calcualtions (g_allocMemSize will be valid)
// NOTE: If UNAUTILS_DEBUG_MEM is defined, ams() will return size of
// memory allocated by malloc()/mrealloc() routines only.
//
{x $DEFINE LOG_UNAUTILS_MALLOCS } // enable memory allocations logging
//
{$ENDIF __AFTER_D9__ }
{x $DEFINE UNAUTILS_MEM_USE_HEAP_ALLOCS } // define to use HeapAlloc()/HeapReAlloc() instead of Borland memory manager
{$DEFINE UNAUTILS_MEM_COLLECT_STATS } // define to collect some basic statistic of memory function usage
{x $DEFINE CHECK_MEMORY_LEAKS } // enable memory leaks checking routines
{$IFDEF CHECK_MEMORY_LEAKS }
{$DEFINE CHECK_MEMORY_LEAKS_UNA_ONLY } // enable memory leaks checking routines (do not override memory manager)
{$ENDIF CHECK_MEMORY_LEAKS }
{$ENDIF DEBUG }
{*
Contains useful routines used by other units and classes.
@Author Lake
Version 2.5.2008.10 + CodeGear RAD 2009 compatible;
Version 2.5.2008.07 + aware of BDS 2006's and later improved memory manager;
Version 2.5.2009.12 + removed variant stuff
Version 2.5.2010.01 + some cleanup
}
unit
unaUtils;
{$IFDEF CPU64 }
//
{$IFDEF CHECK_MEMORY_LEAKS }
Memory leak checks for x64 are not supported.
{$ENDIF CHECK_MEMORY_LEAKS }
//
{$IFDEF UNAUTILS_DEBUG_MEM }
Memory debug for x64 is not supported.
{$ENDIF UNAUTILS_DEBUG_MEM }
{$ENDIF CPU64 }
interface
uses
Windows, unaTypes
{$IFDEF FPC }
{$ELSE }
, TlHelp32
{$ENDIF FPC }
;
{
Note from Delphi Help.
( **** See below for CPU64 *** )
procedure Test(A: Integer; var B: Char; C: Double; const D: string; E: Pointer);
- a call to Test passes A in EAX as a 32-bit integer,
B in EDX as a pointer to a Char,
and D in ECX as a pointer to a long-string memory block;
C and E are pushed onto the stack as two double-words and a 32-bit pointer,
in that order.
Under the register convention, Self behaves as if it were declared before
all other parameters. It is therefore always passed in the EAX register.
For a string, dynamic array, method pointer, variant, or Int64 result,
the effects are the same as if the function result were declared as an additional
var parameter following the declared parameters. In other words, the caller passes
an additional 32-bit pointer that points to a variable in which to return the
function result.
Register saving conventions
Procedures and functions must preserve the EBX, ESI, EDI, and EBP registers,
but can modify the EAX, EDX, and ECX registers. When implementing a
constructor or destructor in assembler, be sure to preserve the DL register.
Procedures and functions are invoked with the assumption that the CPU’s direction
flag is cleared (corresponding to a CLD instruction) and must return with the
direction flag cleared.
**** For CPU64 ***
Unlike the x86, the C/C++ compiler only supports one calling convention on x64.
This calling convention takes advantage of the increased number of registers available on x64:
IN:
* The first four integer or pointer parameters are passed in the rcx, rdx, r8, and r9 registers.
* The first four floating-point parameters are passed in the first four SSE registers, xmm0-xmm3.
* The caller reserves space on the stack for arguments passed in registers.
The called function can use this space to spill the contents of registers to the stack.
* Any additional arguments are passed on the stack.
OUT:
* An integer or pointer return value is returned in the rax register, while a floating-point return value is returned in xmm0.
* rax, rcx, rdx, r8-r11 are volatile.
* rbx, rbp, rdi, rsi, r12-r15 are nonvolatile.
The calling convention for C++ is very similar: the this pointer is passed as an implicit first parameter.
The next three parameters are passed in registers, while the rest are passed on the stack.
}
// some MATH
{*
Returms minimal value of two signed integers.
@return A if A < B, or B otherwise.
}
function min(A, B: int): int; overload;{$IFDEF UNA_OK_INLINE }inline;{$ENDIF UNA_OK_INLINE }
{*
Returms minimal value of two unsigned integers.
@return A if A < B, or B otherwise.
}
function min(A, B: unsigned): unsigned; overload;{$IFDEF UNA_OK_INLINE }inline;{$ENDIF UNA_OK_INLINE }
{$IFNDEF CPU64 }
{*
Returms minimal value of two signed 64 bits integers.
@return A if A < B, B otherwise.
}
function min(A, B: int64): int64; overload;{$IFDEF UNA_OK_INLINE }inline;{$ENDIF UNA_OK_INLINE }
{*
Returns maximal value of two signed 64 bits integers.
@return A if A > B, B otherwise.
}
function max(A, B: int64): int64; overload;{$IFDEF UNA_OK_INLINE }inline;{$ENDIF UNA_OK_INLINE }
{$IFDEF __AFTER_D8__ }
function max(A, B: uint64): uint64; overload;{$IFDEF UNA_OK_INLINE }inline;{$ENDIF UNA_OK_INLINE }
{$ENDIF __AFTER_D8__ }
{$ENDIF CPU64 }
{*
Returns maximal value of two signed integers.
@return A if A > B, B otherwise.
}
function max(A, B: int): int; overload;{$IFDEF UNA_OK_INLINE }inline;{$ENDIF UNA_OK_INLINE }
{*
Returns maximal value of two unsigned integers.
@return A if A > B, B otherwise.
}
function max(A, B: unsigned): unsigned; overload;{$IFDEF UNA_OK_INLINE }inline;{$ENDIF UNA_OK_INLINE }
{*
Returns maximal value of two floating-point.
@return A if A > B, B otherwise.
}
function max(A, B: double): double; overload;{$IFDEF UNA_OK_INLINE }inline;{$ENDIF UNA_OK_INLINE }
{*
signed shift left
}
function sshl(v: int; c: int): int;{$IFDEF UNA_OK_INLINE }inline;{$ENDIF UNA_OK_INLINE }
{*
signed shift right
}
function sshr(v: int; c: int): int;{$IFDEF UNA_OK_INLINE }inline;{$ENDIF UNA_OK_INLINE }
// ENCODING
{*
Encodes data with base64 method.
@param data Data to be encoded.
@param len Size of buffer pointed by data.
@return Encoded value as string.
}
function base64encode(data: pointer; size: unsigned): aString; overload;
{*
Encodes string with base64 method.
@param data String of bytes to be encoded.
@return Encoded value as string.
}
function base64encode(const data: aString): aString; overload;
{*
Decodes string encoded with base64 method.
@param data String of bytes to be decoded.
@return Decoded value as string.
}
function base64decode(const data: aString): aString; overload;
{*
Decodes data encoded with base64 method.
@param data Data to be decoded.
@param len Size of buffer pointed by data.
@return Decoded value as string.
}
function base64decode(data: pointer; len: unsigned): aString; overload;
{*
Decodes string encoded with base64 method.
NOTE: buf will be allocated (not reallocated!).
@param data String of bytes to be decoded.
@param buf Output buffer. Use mrealloc() to deallocate memory pointed by buf.
@return Number of bytes in output buffer.
}
function base64decode(const data: aString; out buf: pointer): unsigned; overload;
{*
Calculates CRC32 checksum.
Based on Hagen Reddmann code.
NOTE: It is not fully compatible with standard CRC32!
@param data String of bytes to calculate CRC32 of.
@param crc Initial CRC value, do not change.
@return CRC32 value.
}
function crc32(const data: aString; crc: uint32 = $FFFFFFFF): uint32; overload;
{*
Calculates CRC32 checksum.
Based on Hagen Reddmann code.
NOTE: It is not fully compatible with standard CRC32!
@param data Pointer to array of bytes to calculate CRC32 of.
@param len Size of array pointed by data.
@param crc Initial CRC value, do not change.
@return CRC32 value.
}
function crc32(data: pointer; len: unsigned; crc: uint32 = $FFFFFFFF): uint32; overload;
{*
Calculates "CRC16" checksum. CRC16 is defined as "(crc shr 16) xor (crc and $FFFF)" where crc is standard CRC32 value.
@param data Pointer to array of bytes to calculate CRC16 of.
@param len Size of array pointed by data.
@return CRC16 value.
}
function crc16(data: pointer; len: unsigned): uint16;
{*
Calculates "CRC8" checksum.
@param data Pointer to array of bytes to calculate CRC8 of.
@param len Size of array pointed by data.
@return CRC8 value.
}
function crc8(data: pointer; len: unsigned): uint8;
{*
Calculates "CRC4" checksum.
@param data Pointer to array of bytes to calculate CRC4 of.
@param len Size of array pointed by data.
@return CRC4 value.
}
function crc4(data: pointer; len: unsigned): uint8;
// UTF8/UTF16/UNICODE functions
const
//
zeroWidthNonBreakingSpace = $FEFF;
zeroWidthNonBreakingSpaceW = wChar(zeroWidthNonBreakingSpace);
zeroWidthNonBreakingSpaceUTF8 = #$EF#$BB#$BF;
//
unicodeHighSurrogateStart = $D800;
unicodeHighSurrogateEnd = $DBFF;
unicodeLowSurrogateStart = $DC00;
unicodeLowSurrogateEnd = $DFFF;
function cp2UTF8(cp: uint32): aString;
function highSurrogate(cp: uint32): uint16;
function lowSurrogate(cp: uint32): uint16;
function isHighSurrogate(w: uint16): bool;
function isLowSurrogate(w: uint16): bool;
function surrogate2cp(highSurrogate, lowSurrogate: uint16): uint32;
{*
Converts UCS-2 to UTF-8 string.
@param w UTF16 string.
@return UTF8 string.
}
function UTF162UTF8(const w: wString): aString;
{*
Converts UTF-8 to low-endian UCS-2 string.
@param s UTF-8 string to be converted.
@return UCS-2 string.
}
function UTF82UTF16(const s: aString): wString;
{*
Converts multi-byte string into ANSI string using wCharToMultiByte().
@param w Multi-byte string to be converted.
@param cp code page to use for conversion, default is CP_ACP.
@return ANSI string (single-byte string).
}
function wide2ansi(const w: wString; cp: unsigned = CP_ACP): aString;
// FILES
//
// Borland had "misspelled" the declarations of the below functions a little,
// so we re-define them here.
//
{$EXTERNALSYM ReadFile }
function ReadFile(hFile: tHandle; buffer: pointer; nNumberOfBytesToRead: DWORD; lpNumberOfBytesRead: LPDWORD; lpOverlapped: POVERLAPPED): BOOL; stdcall;
{$EXTERNALSYM WriteFile }
function WriteFile(hFile: tHandle; buffer: pointer; nNumberOfBytesToWrite: DWORD; lpNumberOfBytesWritten: LPDWORD; lpOverlapped: POVERLAPPED): BOOL; stdcall;
{*
Returns nice string representing file size.
@param sz File size.
@return String representation of sz.
}
function fileSize2str(sz: int64): string;
{*
Checks if specified file exists.
@param name File name.
@return True if specified file exists.
}
function fileExists(const name: wString): bool;
{*
Creates a file. If file already exists, truncates it to zero-length file (if truncate is true).
@param name Name of file to be created (opened).
@param truncate True if existing file must be truncated afer opening (default is True).
@param leaveOpen Do not close file handle after creation (default is False).
@param flags Creation flags (refer to MSDN for details).
@return INVALID_HANDLE_VALUE if file creation has been failed for some reason;
@return 0 if file was created successfully, and leaveOpen was False;
@return file handle if file was created successfully, and leaveOpen was True.
}
function fileCreate(const name: wString; truncate: bool = true; leaveOpen: bool = false; flags: DWORD = 0): tHandle;
{*
Opens a file.
@param name Name of file to be opened.
@param wantWrites Try to open a file with WRITE access if True, or READONLY if False (default is False).
@param allowSharedWrites Allow others to write to opened file (default is True).
@param flags Any additional flags. For example, specify FILE_FLAG_BACKUP_SEMANTICS flag when opening directories.
@return INVALID_HANDLE_VALUE if file does not exist, or some other error occured, valid file handle otherwise.
}
function fileOpen(const name: wString; wantWrites: bool = false; allowSharedWrites: bool = true; flags: DWORD = FILE_ATTRIBUTE_NORMAL): tHandle;
{*
Closes file handle.
}
function fileClose(f: tHandle): bool;
{*
Truncates file at specified position.
@return False if truncation has been failed for some reason.
}
function fileTruncate(handle: tHandle; pos: unsigned = 0; posMode: unsigned = FILE_BEGIN): bool;
{*
Writes data into a file specified by name at specified position.
Creates the file if it does not exists.
@return 0 if operation has been completed successfully, or buf = nil, or size < 1;
@return -1 if no file name was given;
@return -2 if there was some error in opening the file;
@return -3 if operation has been failed for some reason;
@return -4 if number of bytes written does not equal to given size.
}
function writeToFile(const name: wString; buf: pointer; size: unsigned; pos: unsigned = 0; posMode: unsigned = FILE_END): int; overload;
{*
Writes data into a file specified by name at specified position.
Creates the file if it does not exists.
@return 0 if operation has been completed successfully, or buf = nil, or size < 1;
@return -1 if no file name was given;
@return -2 if there was some error in opening the file;
@return -3 if operation has been failed for some reason;
@return -4 if number of bytes written does not equal to given size.
}
function writeToFile(const name: wString; const buf: aString; pos: unsigned = 0; posMode: unsigned = FILE_END): int; overload;
{*
Writes data into a file specified by handle at specified position.
Creates the file if it does not exists.
@return 0 if operation has been completed successfully, or buf = nil, or size < 1;
@return -1 if no file name was given;
@return -2 if there was some error in opening the file;
@return -3 if operation has been failed for some reason;
@return -4 if number of bytes written does not equal to given size.
}
function writeToFile(handle: tHandle; buf: pointer; size: unsigned; pos: unsigned = 0; posMode: unsigned = FILE_CURRENT): int; overload;
{*
Writes data into a file specified by handle at specified position.
Creates the file if it does not exists.
@return 0 if operation has been completed successfully, or buf = nil, or size < 1;
@return -1 if no file name was given;
@return -2 if there was some error in opening the file;
@return -3 if operation has been failed for some reason;
@return -4 if number of bytes written does not equal to given size.
}
function writeToFile(handle: tHandle; const buf: aString; pos: unsigned = 0; posMode: unsigned = FILE_CURRENT): int; overload;
{$IFDEF VC25_OVERLAPPED }
// overlapped write
function write2file(handle: tHandle; var offset: int; buf: pointer; len: unsigned): bool;
{$ENDIF VC25_OVERLAPPED }
{*
Reads data from a file specified by name at specified position.
@param name File name.
@param buf Buffer to place data into.
@param size Number of bytes to read. Buffer must be at least of that size. This parameter will be set to number of bytes actually read from the file, or to 0 if some error has occured.
@param pos Offset in file to read data from (actual offset depends on posMode).
@param posMode How to calculate the real offset in the file (default is FILE_BEGIN, refer to MSDN for mode details).
@return 0 if operation has been completed successfully, or buf = nil, or size < 1
@return -1 if no file name was given;
@return -2 if there was an error in opening the file;
@return -3 if operation has been failed for some reason;
@return -4 if number of bytes read does not equal to given size (file is too short). Not a fatal error in most cases.
@return size parameter will be set to number of bytes actually read from the file, or to 0 if some error occured.
}
function readFromFile(const name: wString; buf: pointer; var size: unsigned; pos: unsigned = 0; posMode: unsigned = FILE_BEGIN): int; overload;
{*
Reads data from a file specified by name at specified position.
@param name File name.
@param pos Offset in file to read data from (actual offset depends on posMode).
@param posMode How to calculate the real offset in the file (default is FILE_BEGIN, refer to MSDN for mode details).
@param len How many bytes to read (default is 0, means read all the file).
@return Read data as string of bytes.
}
function readFromFile(const name: wString; pos: unsigned = 0; posMode: unsigned = FILE_BEGIN; len: int64 = 0): aString; overload;
{*
Reads data from a file specified by handle at specified position.
@param handle File handle.
@param buf Buffer to place data into.
@param size Number of bytes to read. Buffer must be at least of that size. Will be set to number of bytes actually read from the file, or to 0 if some error has occured.
@param pos Offset in file to read data from (actual offset depends on posMode).
@param posMode How to calculate the real offset in the file (default is FILE_CURRENT, refer to MSDN for mode details).
@return 0 if operation has been completed successfully, or buf = nil, or size < 1;
@return -1 if no file name was given;
@return -2 if there was an error in opening the file;
@return -3 if operation has been failed for some reason;
@return -4 if number of bytes read does not equal to given size (file is too short). Not a fatal error in most cases.
}
function readFromFile(handle: tHandle; buf: pointer; var size: unsigned; pos: unsigned = 0; posMode: unsigned = FILE_CURRENT): int; overload;
{*
@return file size in bytes, or -1 if file does not exists.
}
function fileSize(const name: wString): int64; overload;
{*
@return file size in bytes, or -1 if file does not exists.
}
function fileSize(handle: tHandle): int64; overload;
{*
Seeks the file to specified position.
@return Resulting file position or -1 if file handle is invalid.
}
function fileSeek(handle: tHandle; pos: int = 0; posMode: unsigned = FILE_BEGIN): int;
{*
Renames the file.
}
function fileMove(const oldName, newName: wString): bool;
{*
Copies the file content to a new file.
}
function fileCopy(const oldName, newName: wString; failIfExists: bool): bool;
{*
Removes the file.
}
function fileDelete(const fileName: wString): bool;
{*
Calculates CRC32 checksum of a file.
}
function fileChecksum(f: tHandle; crc: uint32 = $FFFFFFFF): uint32; overload;
{*
Calculates CRC32 checksum of a file.
}
function fileChecksum(const fileName: wString): uint32; overload;
{*
Returns file modification time.
}
function fileModificationDateTime(const fileName: wString; useLocalTime: bool = true): SYSTEMTIME; overload;
{*
Returns file modification time.
}
function fileModificationDateTime(f: tHandle; useLocalTime: bool = true): SYSTEMTIME; overload;
{*
Returns file creation time.
}
function fileCreationDateTime(const fileName: wString; useLocalTime: bool = true): SYSTEMTIME; overload;
{*
Returns file creation time.
}
function fileCreationDateTime(f: tHandle; useLocalTime: bool = true): SYSTEMTIME; overload;
{*
Returns True if specified directory exists.
}
function directoryExists(const name: wString): bool;
{*
Ensures that specified path exists. Recursively creates directories as required.
}
function forceDirectories(const path: wString): bool;
{*
Returns file path (without file name).
}
function extractFilePath(const fileName: wString): wString;
{*
Returns file name (without file path).
}
function extractFileName(const fileName: wString): wString;
{*
Replaces the file extension with given one.
}
function changeFileExt(const fileName: wString; const ext: wString = '.txt'): wString;
{*
Expands short file name to long one.
}
function getLongPathName(shortPathName: wString): wString;
const
{ Browsing for directory. }
{$EXTERNALSYM BIF_RETURNONLYFSDIRS}
BIF_RETURNONLYFSDIRS = $0001; /// For finding a folder to start document searching
{$EXTERNALSYM BIF_DONTGOBELOWDOMAIN}
BIF_DONTGOBELOWDOMAIN = $0002; /// For starting the Find Computer
{$EXTERNALSYM BIF_STATUSTEXT}
BIF_STATUSTEXT = $0004;
{$EXTERNALSYM BIF_RETURNFSANCESTORS}
BIF_RETURNFSANCESTORS = $0008;
{$EXTERNALSYM BIF_EDITBOX}
BIF_EDITBOX = $0010;
{$EXTERNALSYM BIF_VALIDATE}
BIF_VALIDATE = $0020; /// insist on valid result (or CANCEL)
{$EXTERNALSYM BIF_NEWDIALOGSTYLE}
BIF_NEWDIALOGSTYLE = $0040;
{$EXTERNALSYM BIF_BROWSEINCLUDEURLS}
BIF_BROWSEINCLUDEURLS = $0080;
{$EXTERNALSYM BIF_BROWSEFORCOMPUTER}
BIF_BROWSEFORCOMPUTER = $1000; /// Browsing for Computers
{$EXTERNALSYM BIF_BROWSEFORPRINTER}
BIF_BROWSEFORPRINTER = $2000; /// Browsing for Printers
{$EXTERNALSYM BIF_BROWSEINCLUDEFILES}
BIF_BROWSEINCLUDEFILES = $4000; /// Browsing for Everything
{$EXTERNALSYM BIF_SHAREABLE}
BIF_SHAREABLE = $8000;
{$EXTERNALSYM BIF_USENEWUI}
BIF_USENEWUI = BIF_NEWDIALOGSTYLE or BIF_EDITBOX;
{ message from browser }
{$EXTERNALSYM BFFM_INITIALIZED}
BFFM_INITIALIZED = 1;
{$EXTERNALSYM BFFM_SELCHANGED}
BFFM_SELCHANGED = 2;
{$EXTERNALSYM BFFM_VALIDATEFAILEDA}
BFFM_VALIDATEFAILEDA = 3; /// lParam:szPath ret:1(cont),0(EndDialog)
{$EXTERNALSYM BFFM_VALIDATEFAILEDW}
BFFM_VALIDATEFAILEDW = 4; /// lParam:wzPath ret:1(cont),0(EndDialog)
{ messages to browser }
{$EXTERNALSYM WM_USER}
WM_USER = $0400;
{$EXTERNALSYM BFFM_SETSTATUSTEXTA}
BFFM_SETSTATUSTEXTA = WM_USER + 100;
{$EXTERNALSYM BFFM_ENABLEOK}
BFFM_ENABLEOK = WM_USER + 101;
{$EXTERNALSYM BFFM_SETSELECTIONA}
BFFM_SETSELECTIONA = WM_USER + 102;
{$EXTERNALSYM BFFM_SETSELECTIONW}
BFFM_SETSELECTIONW = WM_USER + 103;
{$EXTERNALSYM BFFM_SETSTATUSTEXTW}
BFFM_SETSTATUSTEXTW = WM_USER + 104;
{$EXTERNALSYM BFFM_VALIDATEFAILED}
BFFM_VALIDATEFAILED = BFFM_VALIDATEFAILEDA;
{$EXTERNALSYM BFFM_SETSTATUSTEXT}
BFFM_SETSTATUSTEXT = BFFM_SETSTATUSTEXTA;
{$EXTERNALSYM BFFM_SETSELECTION}
BFFM_SETSELECTION = BFFM_SETSELECTIONA;
type
{$IFDEF FPC }
{$ELSE }
{*
TSHItemID -- Item ID
}
PSHItemID = ^TSHItemID;
{$EXTERNALSYM _SHITEMID}
_SHITEMID = record
cb: Word; /// Size of the ID (including cb itself)
abID: array[0..0] of Byte; /// The item ID (variable length)
end;
TSHItemID = _SHITEMID;
{$EXTERNALSYM SHITEMID}
SHITEMID = _SHITEMID;
{*
TItemIDList -- List if item IDs (combined with 0-terminator)
}
PItemIDList = ^TItemIDList;
{$EXTERNALSYM _ITEMIDLIST}
_ITEMIDLIST = record
mkid: TSHItemID;
end;
TItemIDList = _ITEMIDLIST;
{$EXTERNALSYM ITEMIDLIST}
ITEMIDLIST = _ITEMIDLIST;
{$EXTERNALSYM BFFCALLBACK}
BFFCALLBACK = function(wnd: HWND; uMsg: UINT; lParam, lpData: LPARAM): integer stdcall;
{$ENDIF FPC }
//
TFNBFFCallBack = type BFFCALLBACK;
//
PBrowseInfoA = ^TBrowseInfoA;
PBrowseInfoW = ^TBrowseInfoW;
{$IFDEF FPC }
{$ELSE }
PBrowseInfo = PBrowseInfoA;
{$ENDIF FPC }
{$EXTERNALSYM _browseinfoA}
_browseinfoA = record
hwndOwner: HWND;
pidlRoot: PItemIDList;
pszDisplayName: paChar; /// Return display name of item selected.
lpszTitle: paChar; /// text to go in the banner over the tree.
ulFlags: UINT; /// Flags that control the return stuff.
lpfn: TFNBFFCallBack;
lParam: LPARAM; /// extra info that's passed back in callbacks.
iImage: Integer; /// output var: where to return the Image index.
end;
{$EXTERNALSYM _browseinfoW}
_browseinfoW = record
hwndOwner: HWND;
pidlRoot: PItemIDList;
pszDisplayName: pwChar; /// Return display name of item selected.
lpszTitle: pwChar; /// text to go in the banner over the tree.
ulFlags: UINT; /// Flags that control the return stuff.
lpfn: TFNBFFCallBack;
lParam: LPARAM; /// extra info that's passed back in callbacks.
iImage: Integer; /// output var: where to return the Image index.
end;
TBrowseInfoA = _browseinfoA;
{$EXTERNALSYM BROWSEINFOA}
BROWSEINFOA = _browseinfoA;
TBrowseInfoW = _browseinfoW;
{$EXTERNALSYM BROWSEINFOW}
BROWSEINFOW = _browseinfoW;
{$IFDEF FPC }
{$ELSE }
{$EXTERNALSYM _browseinfo}
_browseinfo = _browseinfoA;
TBrowseInfo = TBrowseInfoA;
{$EXTERNALSYM BROWSEINFO}
BROWSEINFO = BROWSEINFOA;
{$ENDIF FPC }
{$IFNDEF UNAUTILS_NOSHELL }
{$IFDEF FPC }
{$ELSE }
{*
Record for returning strings from IShellFolder member functions.
}
PSTRRet = ^TStrRet;
{$EXTERNALSYM _STRRET}
_STRRET = record
uType: UINT; { One of the STRRET_* values }
case Integer of
0: (pOleStr: LPWSTR); { must be freed by caller of GetDisplayNameOf }
1: (pStr: LPSTR); { NOT USED }
2: (uOffset: UINT); { Offset into SHITEMID (ANSI) }
3: (cStr: array[0..MAX_PATH-1] of aChar); { Buffer to fill in }
end;
TStrRet = _STRRET;
{$EXTERNALSYM STRRET}
STRRET = _STRRET;
{$ENDIF FPC }
{$EXTERNALSYM IMalloc}
IMalloc = interface(IUnknown)
['{00000002-0000-0000-C000-000000000046}']
function Alloc(cb: Longint): Pointer; stdcall;
function Realloc(pv: Pointer; cb: Longint): Pointer; stdcall;
procedure Free(pv: Pointer); stdcall;
function GetSize(pv: Pointer): Longint; stdcall;
function DidAlloc(pv: Pointer): Integer; stdcall;
procedure HeapMinimize; stdcall;
end;
{$EXTERNALSYM IEnumIDList}
IEnumIDList = interface(IUnknown)
['{000214F2-0000-0000-C000-000000000046}']
function Next(celt: ULONG; out rgelt: PItemIDList; var pceltFetched: ULONG): HResult; stdcall;
function Skip(celt: ULONG): HResult; stdcall;
function Reset: HResult; stdcall;
function Clone(out ppenum: IEnumIDList): HResult; stdcall;
end;
{$EXTERNALSYM IShellFolder}
IShellFolder = interface(IUnknown)
['{000214E6-0000-0000-C000-000000000046}']
function ParseDisplayName(hwndOwner: HWND; pbcReserved: Pointer; lpszDisplayName: pwChar; out pchEaten: ULONG; out ppidl: PItemIDList; var dwAttributes: ULONG): HResult; stdcall;
function EnumObjects(hwndOwner: HWND; grfFlags: DWORD; out EnumIDList: IEnumIDList): HResult; stdcall;
function BindToObject(pidl: PItemIDList; pbcReserved: Pointer; const riid: TGUID; out ppvOut): HResult; stdcall;
function BindToStorage(pidl: PItemIDList; pbcReserved: Pointer; const riid: TGUID; out ppvObj): HResult; stdcall;
function CompareIDs(lParam: LPARAM; pidl1, pidl2: PItemIDList): HResult; stdcall;
function CreateViewObject(hwndOwner: HWND; const riid: TGUID; out ppvOut): HResult; stdcall;
function GetAttributesOf(cidl: UINT; var apidl: PItemIDList; var rgfInOut: UINT): HResult; stdcall;
function GetUIObjectOf(hwndOwner: HWND; cidl: UINT; var apidl: PItemIDList; const riid: TGUID; prgfInOut: Pointer; out ppvOut): HResult; stdcall;
function GetDisplayNameOf(pidl: PItemIDList; uFlags: DWORD; var lpName: TStrRet): HResult; stdcall;
function SetNameOf(hwndOwner: HWND; pidl: PItemIDList; lpszName: pwChar; uFlags: DWORD; var ppidlOut: PItemIDList): HResult; stdcall;
end;
{$EXTERNALSYM SHGetMalloc }
function SHGetMalloc(var ppMalloc: IMalloc): HResult; stdcall;
{$EXTERNALSYM SHGetDesktopFolder }
function SHGetDesktopFolder(var ppshf: IShellFolder): HResult; stdcall;
{$EXTERNALSYM SHBrowseForFolderA }
function SHBrowseForFolderA(var lpbi: TBrowseInfoA): PItemIDList; stdcall;
{$EXTERNALSYM SHBrowseForFolderW }
function SHBrowseForFolderW(var lpbi: TBrowseInfoW): PItemIDList; stdcall;
{$EXTERNALSYM SHGetPathFromIDListA}
function SHGetPathFromIDListA(pidl: PItemIDList; pszPath: paChar): BOOL; stdcall;
{$EXTERNALSYM SHGetPathFromIDListW}
function SHGetPathFromIDListW(pidl: PItemIDList; pszPath: pwChar): BOOL; stdcall;
{*
Opens directory selection dialog.
@param caption Dialog caption.
@param root Root folder to build tree from.
@param directory Start brofsing from this directory ('' = root). Returns selected directory if selection was successfull.
@param handle Handle of parent window.
@param flags Flags for the dialog.
@return @True if selection was successfull.
}
function guiSelectDirectory(const caption, root: wString; var directory: wString; handle: hWnd = 0; flags: uint = BIF_RETURNONLYFSDIRS): bool;
{$ENDIF UNAUTILS_NOSHELL }
{*
Ensures you can safely add a file name to the given path. Adds '\' character to the end of path as necessary.
Exaples:
C:\temp\ => C:\temp\
C:\temp => C:\temp\
C:\ => C:\
C: => C:
C:\temp/ => C:\temp/
}
function addBackSlash(const path: wString): wString;
{*
Returns temporary file name.
}
function getTemporaryFileName(const prefix: wString = 'una'): wString;
{$IFNDEF UNAUTILS_NOSHELL }
const
{$EXTERNALSYM REGSTR_PATH_EXPLORER}
REGSTR_PATH_EXPLORER = 'Software\Microsoft\Windows\CurrentVersion\Explorer';
{ registry entries for special paths are kept in : }
{$EXTERNALSYM REGSTR_PATH_SPECIAL_FOLDERS}
REGSTR_PATH_SPECIAL_FOLDERS = REGSTR_PATH_EXPLORER + '\Shell Folders';
{$EXTERNALSYM CSIDL_DESKTOP}
CSIDL_DESKTOP = $0000;
{$EXTERNALSYM CSIDL_INTERNET}
CSIDL_INTERNET = $0001;
{$EXTERNALSYM CSIDL_PROGRAMS}
CSIDL_PROGRAMS = $0002;
{$EXTERNALSYM CSIDL_CONTROLS}
CSIDL_CONTROLS = $0003;
{$EXTERNALSYM CSIDL_PRINTERS}
CSIDL_PRINTERS = $0004;
{$EXTERNALSYM CSIDL_PERSONAL}
CSIDL_PERSONAL = $0005;
{$EXTERNALSYM CSIDL_FAVORITES}
CSIDL_FAVORITES = $0006;
{$EXTERNALSYM CSIDL_STARTUP}
CSIDL_STARTUP = $0007;
{$EXTERNALSYM CSIDL_RECENT}
CSIDL_RECENT = $0008;
{$EXTERNALSYM CSIDL_SENDTO}
CSIDL_SENDTO = $0009;
{$EXTERNALSYM CSIDL_BITBUCKET}
CSIDL_BITBUCKET = $000a;
{$EXTERNALSYM CSIDL_STARTMENU}
CSIDL_STARTMENU = $000b;
{$EXTERNALSYM CSIDL_DESKTOPDIRECTORY}
CSIDL_DESKTOPDIRECTORY = $0010;
{$EXTERNALSYM CSIDL_DRIVES}
CSIDL_DRIVES = $0011;
{$EXTERNALSYM CSIDL_NETWORK}
CSIDL_NETWORK = $0012;
{$EXTERNALSYM CSIDL_NETHOOD}
CSIDL_NETHOOD = $0013;
{$EXTERNALSYM CSIDL_FONTS}
CSIDL_FONTS = $0014;
{$EXTERNALSYM CSIDL_TEMPLATES}
CSIDL_TEMPLATES = $0015;
{$EXTERNALSYM CSIDL_COMMON_STARTMENU}
CSIDL_COMMON_STARTMENU = $0016;
{$EXTERNALSYM CSIDL_COMMON_PROGRAMS}
CSIDL_COMMON_PROGRAMS = $0017;
{$EXTERNALSYM CSIDL_COMMON_STARTUP}
CSIDL_COMMON_STARTUP = $0018;
{$EXTERNALSYM CSIDL_COMMON_DESKTOPDIRECTORY}
CSIDL_COMMON_DESKTOPDIRECTORY = $0019;
{$EXTERNALSYM CSIDL_APPDATA}
CSIDL_APPDATA = $001a;
{$EXTERNALSYM CSIDL_PRINTHOOD}
CSIDL_PRINTHOOD = $001b;
{$EXTERNALSYM CSIDL_LOCAL_APPDATA}
CSIDL_LOCAL_APPDATA = $001c;
{$EXTERNALSYM CSIDL_ALTSTARTUP}
CSIDL_ALTSTARTUP = $001d; // DBCS
{$EXTERNALSYM CSIDL_COMMON_ALTSTARTUP}
CSIDL_COMMON_ALTSTARTUP = $001e; // DBCS
{$EXTERNALSYM CSIDL_COMMON_FAVORITES}
CSIDL_COMMON_FAVORITES = $001f;
{$EXTERNALSYM CSIDL_INTERNET_CACHE}
CSIDL_INTERNET_CACHE = $0020;
{$EXTERNALSYM CSIDL_COOKIES}
CSIDL_COOKIES = $0021;
{$EXTERNALSYM CSIDL_HISTORY}
CSIDL_HISTORY = $0022;
{$EXTERNALSYM CSIDL_PROFILE}
CSIDL_PROFILE = $0028; { USERPROFILE }
{$EXTERNALSYM CSIDL_CONNECTIONS}
CSIDL_CONNECTIONS = $0031; { Network and Dial-up Connections }
{$EXTERNALSYM CSIDL_COMMON_MUSIC}
CSIDL_COMMON_MUSIC = $0035; { All Users\My Music }
{$EXTERNALSYM CSIDL_COMMON_PICTURES}
CSIDL_COMMON_PICTURES = $0036; { All Users\My Pictures }
{$EXTERNALSYM CSIDL_COMMON_VIDEO}
CSIDL_COMMON_VIDEO = $0037; { All Users\My Video }
{$EXTERNALSYM CSIDL_CDBURN_AREA}
CSIDL_CDBURN_AREA = $003b; { USERPROFILE\Local Settings\Application Data\Microsoft\CD Burning }
{$EXTERNALSYM CSIDL_COMPUTERSNEARME}
CSIDL_COMPUTERSNEARME = $003d; { Computers Near Me (computered from Workgroup membership) }
{$EXTERNALSYM CSIDL_PROFILES}
CSIDL_PROFILES = $003e;
{$EXTERNALSYM CSIDL_COMMON_APPDATA}
{ All Users\Application Data }
CSIDL_COMMON_APPDATA = $0023;
{$EXTERNALSYM CSIDL_WINDOWS}
{ GetWindowsDirectory() }
CSIDL_WINDOWS = $0024;
{$EXTERNALSYM CSIDL_SYSTEM}
{ GetSystemDirectory() }
CSIDL_SYSTEM = $0025;
{$EXTERNALSYM CSIDL_PROGRAM_FILES}
{ C:\Program Files }
CSIDL_PROGRAM_FILES = $0026;
{$EXTERNALSYM CSIDL_MYPICTURES}
{ My Pictures, new for Win2K }
CSIDL_MYPICTURES = $0027;
{$EXTERNALSYM CSIDL_PROGRAM_FILES_COMMON}
{ C:\Program Files\Common }
CSIDL_PROGRAM_FILES_COMMON = $002b;
{$EXTERNALSYM CSIDL_COMMON_DOCUMENTS}
{ All Users\Documents }
CSIDL_COMMON_DOCUMENTS = $002e;
{$EXTERNALSYM CSIDL_FLAG_CREATE}
{ new for Win2K, or this in to force creation of folder }
CSIDL_FLAG_CREATE = $8000;
{$EXTERNALSYM CSIDL_COMMON_ADMINTOOLS}
{ All Users\Start Menu\Programs\Administrative Tools }
CSIDL_COMMON_ADMINTOOLS = $002f;
{$EXTERNALSYM CSIDL_ADMINTOOLS}
{ <user name>\Start Menu\Programs\Administrative Tools }
CSIDL_ADMINTOOLS = $0030;