1 { Version 050625. Copyright � Alexey A.Chernobaev, 2000-5 }
2 
3 unit VFileSys;
4 
5 interface
6 
7 {$I VCheck.inc}
8 
9 uses
10   {$IFNDEF V_WIN}{$IFNDEF UNIX}{$DEFINE V_WIN}{$ENDIF}{$ENDIF}
11   {$IFDEF V_WIN}Windows,{$ENDIF}
12   SysUtils, ExtType, ExtSys, VectStr, VectErr;
13 
14 //{$IFNDEF V_WIN}{$IFNDEF UNIX}Error!{$ENDIF}{$ENDIF}
15 
16 const
17   InvalidWinFileNameChars = ['"', '*', '?', '/', ':', '<', '>', '\', '|'];
18   {$IFDEF UNIX}
19   InvalidFileNameChars = ['*', '?', '/'];
20   {$ELSE}
21   InvalidFileNameChars = InvalidWinFileNameChars;
22   {$ENDIF}
23   InvalidFileMaskChars = InvalidFileNameChars - ['*', '?'];
24 
25   MaxFileLen = 1023;
26 
27 {$IFNDEF V_D4} // Delphi 3 or Free Pascal
IsPathDelimiternull28 function IsPathDelimiter(const S: String; Index: Integer): Boolean;
29 {$ENDIF} {V_D4}
30 
31 {$IFNDEF V_D5}
32 // Delphi 3 or Delphi 4 or Free Pascal
IncludeTrailingBackslashnull33 function IncludeTrailingBackslash(const S: String): String;
ExcludeTrailingBackslashnull34 function ExcludeTrailingBackslash(const S: String): String;
35 
36 {$IFDEF V_WIN}
SafeLoadLibrarynull37 function SafeLoadLibrary(const FileName: String;
38   ErrorMode: UINT{$IFDEF V_DEFAULTS} = SEM_NOOPENFILEERRORBOX{$ENDIF}): HMODULE;
39 {$ENDIF} {V_WIN}
40 
41 {$ENDIF} {V_D5}
42 
43 {$IFNDEF V_D6}
IncludeTrailingPathDelimiternull44 function IncludeTrailingPathDelimiter(const S: String): String;
ExcludeTrailingPathDelimiternull45 function ExcludeTrailingPathDelimiter(const S: String): String;
46 {$ENDIF} {V_D6}
47 
48 {$IFDEF V_WIN}
SafeLoadLibraryWnull49 function SafeLoadLibraryW(const FileName: WideString;
50   ErrorMode: UINT{$IFDEF V_DEFAULTS} = SEM_NOOPENFILEERRORBOX{$ENDIF}): HMODULE;
51 {$ENDIF}
52 
53 type
54   TFileBuf = array [0..MaxFileLen] of AnsiChar;
55   TFileBufW = array [0..MaxFileLen] of WideChar;
56 
GetCurrentDirWnull57 function GetCurrentDirW: WideString;
SetCurrentDirWnull58 function SetCurrentDirW(const Dir: WideString): Boolean;
LastDelimiterWnull59 function LastDelimiterW(const Delimiters, W: WideString): Integer;
ChangeFileExtWnull60 function ChangeFileExtW(const FileName, Extension: WideString): WideString;
ExtractFilePathWnull61 function ExtractFilePathW(const FileName: WideString): WideString;
ExtractFileExtWnull62 function ExtractFileExtW(const FileName: WideString): WideString;
ExtractFileNameWnull63 function ExtractFileNameW(const FileName: WideString): WideString;
ExpandFileNameWnull64 function ExpandFileNameW(const FileName: WideString): WideString;
IncludePathDelimiterWnull65 function IncludePathDelimiterW(const S: WideString): WideString;
ExcludePathDelimiterWnull66 function ExcludePathDelimiterW(const S: WideString): WideString;
67 
68 { why use pLastOSError: GetLastError will be altered by WideString cleaning
69   code (under Windows) }
70 {$IFDEF V_WIN}
71 {$ENDIF}
72 
73 {$IFDEF UNIX}
74 
UserNamenull75 //function UserName(uid: __uid_t): WideString;
76 
77 //function GroupName(gid: __gid_t): WideString;
78 {$ENDIF}
79 
80 function ValidateFileName(const FileName: String; MaxLen: Integer): String;
81 
IsFileNameSyntaxValidnull82 function IsFileNameSyntaxValid(const FileName: WideString): Boolean;
83 
IsAbsolutePathSyntaxValidnull84 function IsAbsolutePathSyntaxValid(const Path: WideString): Boolean;
85 
GetTempDirnull86 function GetTempDir: String;
87 
88 type
89   TFileLock = {$IFDEF UNIX}Integer{$ELSE}THandle{$ENDIF};
90 
91 { ��������� ���� �� ������; � ������ ������ ���������� ���������� �����, �����
92   ���������� INVALID_HANDLE_VALUE (Linux: -1) }
93 { write-locks the given file; returns a file handle if successful or
94   INVALID_HANDLE_VALUE (Linux: -1) if failed }
95 
96 {$IFDEF V_WIN}
GetTempDirWnull97 function GetTempDirW: WideString;
98 
GetWindowsDirnull99 function GetWindowsDir: String;
GetWindowsDirWnull100 function GetWindowsDirW: WideString;
101 
GetSystemDirnull102 function GetSystemDir: String;
GetSystemDirWnull103 function GetSystemDirW: WideString;
104 
LockFileReadnull105 function LockFileRead(const FileName: String): THandle;
106 
GetLongFileNamenull107 function GetLongFileName(const Name: String): String;
108   {$IFDEF V_D6}platform;{$ENDIF}
109 { ���������� "�������" ���, ��������������� ��������� "���������" ����� �����
110   ��� ���������� ���� ������ ������, ���� ���� ��� ���������� �� �������; �
111   ������� ����� ���������� "�������" ����� }
112 { returns the long name corresponding to the specified short file or directory
113   name or the empty string if the file or directory were not found; it's legal
114   to pass long names to the function }
115 
116 
117 {$ENDIF} {V_WIN}
118 
119 {$IFDEF V_DELPHI}{$IFNDEF V_D6}
DirectoryExistsnull120 function DirectoryExists(const Name: String): Boolean;
121 {$ENDIF}{$ENDIF}
122 
123 {$IFDEF V_DELPHI}{$IFNDEF V_D6}
ForceDirectoriesnull124 function ForceDirectories(Dir: String): Boolean;
125 {$ENDIF}{$ENDIF}
126 
ExcludeFileExtnull127 function ExcludeFileExt(const Name: String): String;
ExcludeFileExtWnull128 function ExcludeFileExtW(const Name: WideString): WideString;
129 { ���������� ��� ����� ��� ���������� }
130 { excludes an extension from the given file name }
131 
ShortenFileNamenull132 function ShortenFileName(const FileName: String; MaxLen: Integer;
133   DelimitChars: TCharSet{$IFDEF V_DEFAULTS} = []{$ENDIF}): String;
ShortenFileNameWnull134 function ShortenFileNameW(const FileName: WideString; MaxLen: Integer;
135   DelimitChars: TCharSet{$IFDEF V_DEFAULTS} = []{$ENDIF}): WideString;
136 
GetModuleNameWnull137 function GetModuleNameW(Module: HMODULE): WideString;
138 { returns a name of a file which contains the specified module }
139 
140 procedure ParseFileName(const FileName: String; var Path, Name: String);
141 procedure ParseFileNameW(const FileName: WideString; var Path, Name: WideString);
142 
FirstItemDelimiterWnull143 function FirstItemDelimiterW(const Path: WideString): Integer;
144 { returns an index of the first PathDelim or '|' character (0 if not found) }
145 
LastItemDelimiterWnull146 function LastItemDelimiterW(const Path: WideString): Integer;
147 { returns an index of the last PathDelim or '|' character (0 if not found) }
148 
149 procedure ParseItemName(const FullItemName: String; var Path, Name: String);
150 procedure ParseItemNameW(const FullItemName: WideString; var Path,
151   Name: WideString);
152 
GetItemNameWnull153 function GetItemNameW(const FullItemName: WideString): WideString;
GetItemPathWnull154 function GetItemPathW(const FullItemName: WideString): WideString;
155 
CorrectFileNamenull156 function CorrectFileName(const Name: String;
157   DefaultChar: AnsiChar{$IFDEF V_DEFAULTS} = '_'{$ENDIF}): String;
CorrectFileNameWnull158 function CorrectFileNameW(const Name: WideString;
159   DefaultChar: WideChar{$IFDEF V_DEFAULTS} = '_'{$ENDIF}): WideString;
160 
CorrectPathNamenull161 function CorrectPathName(const Name: String;
162   DefaultChar: AnsiChar{$IFDEF V_DEFAULTS} = '_'{$ENDIF}): String;
CorrectPathNameWnull163 function CorrectPathNameW(const Name: WideString;
164   DefaultChar: WideChar{$IFDEF V_DEFAULTS} = '_'{$ENDIF}): WideString;
165 
GetStdFileExtnull166 function GetStdFileExt(const FileName: String): String;
167 { ���������� ���������� ����� ��� ��������� �����, ������ � ������ �������� }
168 { returns an extension portion of the given file name without a leading dot,
169   always in lowercase }
170 
171 {$IFDEF V_DEFAULTS}
172 
173 {$IFDEF V_WIN}
GetFilePropsnull174 function GetFileProps(const FileName: String; pSize: PInt64;
175   pModifyTime: PDateTime = nil; pCreationTime: PDateTime = nil;
176   pLastAccessTime: PDateTime = nil; pAttributes: PDWORD = nil;
177   pLastOSError: PDWORD = nil): Boolean;
178 
GetFilePropsWnull179 function GetFilePropsW(const FileName: WideString; pSize: PInt64;
180   pModifyTime: PDateTime = nil; pCreationTime: PDateTime = nil;
181   pLastAccessTime: PDateTime = nil; pAttributes: PDWORD = nil;
182   pLastOSError: PDWORD = nil): Boolean;
183 {$ENDIF}
184 
185 {$IFDEF UNIX}
GetFilePropsnull186 function GetFileProps(const FileName: String; pSize: PInt64;
187   pModifyTime: PDateTime = nil; pLastStatusChangeTime: PDateTime = nil;
188   pLastAccessTime: PDateTime = nil; pAttributes: PUInt32 = nil;
189   pUser: PUInt32  = nil; pGroup: PUInt32  = nil): Boolean;
190 
GetFilePropsWnull191 function GetFilePropsW(const FileName: WideString; pSize: PInt64;
192   pModifyTime: PDateTime = nil; pLastStatusChangeTime: PDateTime = nil;
193   pLastAccessTime: PDateTime = nil; pAttributes: PUInt32 = nil;
194   pUser: PUInt32  = nil; pGroup: PUInt32  = nil): Boolean;
195 
GetLinkTargetnull196 function GetLinkTarget(const PathOnly: String): String;
197 {$ENDIF} {LINUX}
198 
199 {$ELSE}
200 
201 {$ENDIF} {V_DEFAULTS}
202 
IsRelativePathnull203 function IsRelativePath(const FileName: String): Boolean;
204 
205 implementation
206 
207 {$IFNDEF V_D4}
IsPathDelimiternull208 function IsPathDelimiter(const S: String; Index: Integer): Boolean;
209 begin
210   Result:=(Index > 0) and (Index <= Length(S)) and (S[Index] = PathDelim) and
211     (ByteType(S, Index) = mbSingleByte);
212 end;
213 {$ENDIF}
214 
215 {$IFNDEF V_D5}
IncludeTrailingBackslashnull216 function IncludeTrailingBackslash(const S: String): String;
217 begin
218   Result:=S;
219   if not IsPathDelimiter(Result, Length(Result)) then
220     Result:=Result + PathDelim;
221 end;
222 
ExcludeTrailingBackslashnull223 function ExcludeTrailingBackslash(const S: String): String;
224 begin
225   Result:=S;
226   if IsPathDelimiter(Result, Length(Result)) then
227     SetLength(Result, Length(Result) - 1);
228 end;
229 
230 {$IFDEF V_WIN}
SafeLoadLibrarynull231 function SafeLoadLibrary(const FileName: String; ErrorMode: UINT): HMODULE;
232 var
233   OldMode: UINT;
234   FPUControlWord: Word;
235 begin
236   OldMode:=SetErrorMode(ErrorMode);
237   try
238     asm
239       FNSTCW  FPUControlWord
240     end;
241     try
242       Result:=LoadLibrary(PChar(FileName));
243     finally
244       asm
245         FNCLEX
246         FLDCW FPUControlWord
247       end;
248     end;
249   finally
250     SetErrorMode(OldMode);
251   end;
252 end;
253 {$ENDIF} {V_WIN}
254 
255 {$ENDIF} {V_D5}
256 
257 {$IFNDEF V_D6}
IncludeTrailingPathDelimiternull258 function IncludeTrailingPathDelimiter(const S: String): String;
259 begin
260   Result:=IncludeTrailingBackslash(S);
261 end;
262 
ExcludeTrailingPathDelimiternull263 function ExcludeTrailingPathDelimiter(const S: String): String;
264 begin
265   Result:=ExcludeTrailingBackslash(S);
266 end;
267 {$ENDIF} {V_D6}
268 
269 {$IFDEF V_WIN}
SafeLoadLibraryWnull270 function SafeLoadLibraryW(const FileName: WideString; ErrorMode: UINT): HMODULE;
271 var
272   OldMode: UINT;
273   FPUControlWord: Word;
274 begin
275   if Win32Platform = VER_PLATFORM_WIN32_NT then begin
276     OldMode:=SetErrorMode(ErrorMode);
277     try
278       asm
279         FNSTCW  FPUControlWord
280       end;
281       try
282         Result:=LoadLibraryW(PWideChar(FileName));
283       finally
284         asm
285           FNCLEX
286           FLDCW FPUControlWord
287         end;
288       end;
289     finally
290       SetErrorMode(OldMode);
291     end;
292   end
293   else
294     Result:=SafeLoadLibrary(FileName, ErrorMode);
295 end;
296 {$ENDIF}
297 
GetCurrentDirWnull298 function GetCurrentDirW: WideString;
299 {$IFDEF V_WIN}
300 var
301   Sz: DWORD;
302   Buf: TFileBufW;
303 {$ENDIF}
304 begin
305   {$IFDEF V_WIN}
306   if Win32Platform = VER_PLATFORM_WIN32_NT then begin
307     Sz:=GetCurrentDirectoryW(SizeOf(Buf) div 2, Buf);
308     if (Sz > 0) and (Sz < SizeOf(Buf) div 2) then begin
309       SetWideString(Result, Buf, Sz);
310       Exit;
311     end;
312   end;
313   {$ENDIF}
314   Result:=GetCurrentDir;
315 end;
316 
SetCurrentDirWnull317 function SetCurrentDirW(const Dir: WideString): Boolean;
318 begin
319   {$IFDEF V_WIN}
320   if Win32Platform = VER_PLATFORM_WIN32_NT then
321     Result:=SetCurrentDirectoryW(PWideChar(Dir))
322   else
323   {$ENDIF}
324     Result:=SetCurrentDir(Dir);
325 end;
326 
LastDelimiterWnull327 function LastDelimiterW(const Delimiters, W: WideString): Integer;
328 var
329   L: Integer;
330   P: PWideChar;
331 begin
332   Result:=Length(W);
333   L:=Length(Delimiters);
334   P:=PWideChar(Delimiters);
335   while Result > 0 do begin
336     if (W[Result] <> #0) and (IndexOfValue16(P^, Smallint(W[Result]), L) >= 0) then
337       Exit;
338     Dec(Result);
339   end;
340 end;
341 
ChangeFileExtWnull342 function ChangeFileExtW(const FileName, Extension: WideString): WideString;
343 var
344   I: Integer;
345 begin
346   I:=LastDelimiterW('.' + PathDelim + DriveDelim, FileName);
347   if (I = 0) or (FileName[I] <> '.') then
348     I:=MaxInt;
349   Result:=Copy(FileName, 1, I - 1) + Extension;
350 end;
351 
ExtractFilePathWnull352 function ExtractFilePathW(const FileName: WideString): WideString;
353 var
354   I: Integer;
355 begin
356   I:=LastDelimiterW(PathDelim + DriveDelim, FileName);
357   Result:=Copy(FileName, 1, I);
358 end;
359 
ExtractFileExtWnull360 function ExtractFileExtW(const FileName: WideString): WideString;
361 var
362   I: Integer;
363 begin
364   I:=LastDelimiterW('.' + PathDelim + DriveDelim, FileName);
365   if (I > 0) and (FileName[I] = '.') then
366     Result:=Copy(FileName, I, MaxInt)
367   else
368     Result:='';
369 end;
370 
ExtractFileNameWnull371 function ExtractFileNameW(const FileName: WideString): WideString;
372 var
373   I: Integer;
374 begin
375   I:=LastDelimiterW(PathDelim + DriveDelim, FileName);
376   Result:=Copy(FileName, I + 1, MaxInt);
377 end;
378 
ExpandFileNameWnull379 function ExpandFileNameW(const FileName: WideString): WideString;
380 {$IFDEF V_WIN}
381 var
382   L: DWORD;
383   LastDot: Boolean;
384   PW: PWideChar;
385   P: PChar;
386   BufW: TFileBufW;
387   Buf: TFileBuf absolute BufW;
388 begin
389   if FileName = '' then begin
390     {$IFNDEF V_AUTOINITSTRINGS}
391     Result:='';
392     {$ENDIF}
393     Exit;
394   end;
395   BufW[0]:=#0;
396   LastDot:=FileName[Length(FileName)] = '.';
397   if Win32Platform = VER_PLATFORM_WIN32_NT then begin
398     L:=GetFullPathNameW(Pointer(FileName), SizeOf(BufW) div 2, BufW, PW);
399     if (L = 0) or (L >= SizeOf(BufW) div 2) then begin
400       Result:=FileName;
401       Exit;
402     end;
403     Result:=LWideString(@BufW, L);
404   end
405   else begin
406     L:=GetFullPathName(PChar(String(FileName)), SizeOf(Buf), @Buf, P);
407     if (L = 0) or (L >= SizeOf(Buf)) then begin
408       Result:=FileName;
409       Exit;
410     end;
411     Result:=WideString(LString(@Buf, L));
412   end;
413   if LastDot then
414     Result:=Result + '.';
415 end;
416 {$ENDIF}
417 {$IFDEF UNIX}
418 begin
419   Result:=ExpandFileName(FileName);
420 end;
421 {$ENDIF}
422 
IncludePathDelimiterWnull423 function IncludePathDelimiterW(const S: WideString): WideString;
424 begin
425   Result:=S;
426   if (Result = '') or (Result[Length(Result)] <> PathDelim) then
427     Result:=Result + PathDelim;
428 end;
429 
ExcludePathDelimiterWnull430 function ExcludePathDelimiterW(const S: WideString): WideString;
431 var
432   L: Integer;
433 begin
434   Result:=S;
435   L:=Length(Result);
436   if (L > 0) and (Result[L] = PathDelim) then
437     SetLength(Result, L - 1);
438 end;
439 
440 
441 
442 {$IFDEF V_WIN}
443 
444 {$ENDIF}
445 
ValidateFileNamenull446 function ValidateFileName(const FileName: String; MaxLen: Integer): String;
447 var
448   I: Integer;
449 begin
450   Result:=Copy(FileName, 1, MaxLen);
451   for I:=1 to Length(Result) do
452     if Result[I] in InvalidFileNameChars then
453       Result[I]:='_';
454 end;
455 
456 {$IFDEF UNIX}
457 
458 {$ENDIF} {LINUX}
459 
IsFileNameSyntaxValidnull460 function IsFileNameSyntaxValid(const FileName: WideString): Boolean;
461 var
462   I: Integer;
463   {$IFDEF V_WIN}
464   Path: WideString;
465   {$ENDIF}
466 begin
467   Result:=False;
468   if FileName = '' then
469     Exit;
470   I:=LastDelimiterW(PathDelim + DriveDelim, FileName);
471   if WideContainsChars(Copy(FileName, I + 1, MaxInt), InvalidFileNameChars) then
472     Exit;
473   if I <= 0 then begin
474     Result:=True;
475     Exit;
476   end;
477   {$IFDEF V_WIN}
478   Path:=Copy(FileName, 1, I - 1);
479   if (FileName[I] = DriveDelim) and not IsAbsolutePathSyntaxValid(Path) then
480     Exit;
481   Result:=not WideContainsChars(Path, InvalidFileNameChars - [PathDelim, DriveDelim]);
482   {$ENDIF}
483   {$IFDEF UNIX}
484   Result:=not WideContainsChars(Copy(FileName, 1, I - 1), InvalidFileNameChars -
485     [PathDelim]);
486   {$ENDIF}
487 end;
488 
IsAbsolutePathSyntaxValidnull489 function IsAbsolutePathSyntaxValid(const Path: WideString): Boolean;
490 begin
491   {$IFDEF V_WIN}
492   Result:=(Length(Path) >= 2) and
493     (
494       WideCharIn(Path[1], ASCIIAlpha) and (Path[2] = ':') or
495       (Path[1] = '\') and (Path[2] = '\')
496     ) and
497     (WideCharPos(':', Path, 3) = 0);
498   {$ENDIF}
499   {$IFDEF UNIX}
500   Result:=(Path <> '') and (Path[1] = '/');
501   {$ENDIF}
502 end;
503 
504 
GetTempDirnull505 function GetTempDir: String;
506 {$IFDEF V_WIN}
507 var
508   L: DWORD;
509   Buf: array [0..MAX_PATH] of AnsiChar;
510 {$ENDIF}
511 begin
512   {$IFDEF V_WIN}
513   L:=GetTempPath(SizeOf(Buf), Buf);
514   OSCheck((L > 0) and (L <= High(Buf)));
515   SetString(Result, Buf, L);
516   {$ENDIF}
517   {$IFDEF UNIX}
518   Result:=GetTempDir;
519   if Result = '' then
520     Result:='/tmp/'
521   else
522     if Result[Length(Result)] <> '/' then
523       Result:=Result + '/';
524   {$ENDIF}
525 end;
526 
527 
528 {$IFDEF V_WIN}
GetTempDirWnull529 function GetTempDirW: WideString;
530 var
531   L: DWORD;
532   Buf: array [0..MAX_PATH] of WideChar;
533 begin
534   if Win32Platform = VER_PLATFORM_WIN32_NT then begin
535     L:=GetTempPathW(SizeOf(Buf) div 2, Buf);
536     OSCheck((L > 0) and (L <= High(Buf)));
537     Result:=WideString(Buf);
538   end
539   else
540     Result:=GetTempDir;
541 end;
542 
GetWindowsDirnull543 function GetWindowsDir: String;
544 var
545   L: UINT;
546   Buf: array [0..MAX_PATH] of AnsiChar;
547 begin
548   L:=GetWindowsDirectory(Buf, SizeOf(Buf));
549   OSCheck((L > 0) and (L <= High(Buf)));
550   SetString(Result, Buf, L);
551 end;
552 
GetWindowsDirWnull553 function GetWindowsDirW: WideString;
554 var
555   L: UINT;
556   Buf: array [0..MAX_PATH] of WideChar;
557 begin
558   if Win32Platform = VER_PLATFORM_WIN32_NT then begin
559     L:=GetWindowsDirectoryW(Buf, SizeOf(Buf) div 2);
560     OSCheck((L > 0) and (L <= High(Buf)));
561     Result:=WideString(Buf);
562   end
563   else
564     Result:=GetWindowsDir;
565 end;
566 
GetSystemDirnull567 function GetSystemDir: String;
568 var
569   L: UINT;
570   Buf: array [0..MAX_PATH] of AnsiChar;
571 begin
572   L:=GetSystemDirectory(Buf, SizeOf(Buf));
573   OSCheck((L > 0) and (L <= High(Buf)));
574   SetString(Result, Buf, L);
575 end;
576 
GetSystemDirWnull577 function GetSystemDirW: WideString;
578 var
579   L: UINT;
580   Buf: array [0..MAX_PATH] of WideChar;
581 begin
582   if Win32Platform = VER_PLATFORM_WIN32_NT then begin
583     L:=GetSystemDirectoryW(Buf, SizeOf(Buf) div 2);
584     OSCheck((L > 0) and (L <= High(Buf)));
585     Result:=WideString(Buf);
586   end
587   else
588     Result:=GetSystemDir;
589 end;
590 
LockFileReadnull591 function LockFileRead(const FileName: String): THandle;
592 begin
593   Result:=CreateFile(PChar(FileName), GENERIC_READ, 0, nil, OPEN_EXISTING,
594     FILE_FLAG_NO_BUFFERING, 0);
595 end;
596 
GetLongFileNamenull597 function GetLongFileName(const Name: String): String;
598 
ProcessExpandednull599   function ProcessExpanded(const ExpName: String): String;
600   var
601     I: Integer;
602     S, Path: String;
603     SR: TSearchRec;
604   begin
605     Result:=ExpName;
606     I:=Length(Result);
607     if I > 0 then begin
608       if Result[I] = '\' then begin
609         Dec(I);
610         if (I > 0) and (Result[I] = ':') then
611           Exit;
612         SetLength(Result, I);
613       end
614       else
615         if Result[I] = ':' then
616           Exit;
617       ParseFileName(Result, Path, S);
618       if (CharPos('*', S, 1) = 0) and (CharPos('?', S, 1) = 0) then begin
619         if SysUtils.FindFirst(Result, faAnyFile and not faVolumeID, SR) = 0 then
620           SysUtils.FindClose(SR)
621         else
622           Exit;
623         if SR.Name = '.' then // ������... can happen...
624           Exit;
625         if SysUtils.FindFirst(Path + SR.Name, faAnyFile and not faVolumeID, SR) = 0 then
626           SysUtils.FindClose(SR)
627         else // ���� ������... can happen too...
628           SR.Name:=S;
629       end
630       else
631         SR.Name:=S;
632       if Length(Path) < I then begin
633         if CharPos('~', Path, 1) > 0 then begin
634           Path:=ProcessExpanded(Path);
635           I:=Length(Path);
636           if (I > 0) and (Path[I] <> '\') then
637             Path:=Path + '\';
638         end;
639         Result:=Path + SR.Name;
640       end;
641     end;
642   end;
643 
644 begin
645   Result:=Name;
646   if Result <> '' then begin
647     if Result[Length(Result)] = ':' then
648       Result:=Result + '\';
649     Result:=ExpandFileName(Result);
650     if CharPos('~', Result, 1) > 0 then
651       Result:=ProcessExpanded(Result);
652   end;
653 end;
654 
655 {$ENDIF}
656 
657 {$IFDEF V_DELPHI}{$IFNDEF V_D6}
DirectoryExistsnull658 function DirectoryExists(const Name: String): Boolean;
659 var
660   Code: DWORD;
661 begin
662   Code:=GetFileAttributes(PChar(Name));
663   Result:=(Code <> DWORD(-1)) and (Code and FILE_ATTRIBUTE_DIRECTORY <> 0);
664 end;
665 {$ENDIF}{$ENDIF}
666 
667 {$IFDEF V_DELPHI}{$IFNDEF V_D6}
ForceDirectoriesnull668 function ForceDirectories(Dir: String): Boolean;
669 var
670   L: Integer;
671   E: EInOutError;
672 begin
673   Result:=True;
674   if Dir = '' then begin
675     E:=EInOutError.Create(SCreateDirError);
676     E.ErrorCode:=3;
677     raise E;
678   end;
679   L:=Length(Dir);
680   if IsPathDelimiter(Dir, L) then
681     SetLength(Dir, L - 1);
682   {$IFDEF V_WIN}
683   if (Length(Dir) < 3) or DirectoryExists(Dir) or (ExtractFilePath(Dir) = Dir) then
684     Exit; // avoid 'xyz:\' problem.
685   {$ENDIF}
686   {$IFDEF UNIX}
687   if (Dir = '') or DirectoryExists(Dir) then
688     Exit;
689   {$ENDIF}
690   Result:=ForceDirectories(ExtractFilePath(Dir)) and CreateDir(Dir);
691 end;
692 {$ENDIF}{$ENDIF}
693 
ExcludeFileExtnull694 function ExcludeFileExt(const Name: String): String;
695 begin
696   Result:=Name;
697   SetLength(Result, Length(Result) - Length(ExtractFileExt(Name)));
698 end;
699 
ExcludeFileExtWnull700 function ExcludeFileExtW(const Name: WideString): WideString;
701 begin
702   Result:=Name;
703   SetLength(Result, Length(Result) - Length(ExtractFileExtW(Name)));
704 end;
705 
ShortenFileNamenull706 function ShortenFileName(const FileName: String; MaxLen: Integer;
707   DelimitChars: TCharSet): String;
708 
709   procedure SetDots(FromIndex: Integer);
710   begin
711     Result[FromIndex]:='.';
712     Result[FromIndex - 1]:='.';
713     Result[FromIndex - 2]:='.';
714   end;
715 
716 var
717   I, J, K, L, Len: Integer;
718   B: Boolean;
719 begin
720   Result:=FileName;
721   Len:=Length(Result);
722   if MaxLen < 4 then
723     MaxLen:=4;
724   L:=Len - MaxLen;
725   if L > 0 then begin
726     if DelimitChars = [] then
727       DelimitChars:=[PathDelim];
728     I:=CharInSetPos(DelimitChars, Result, 1);
729     if I > 0 then begin
730       J:=Len;
731       while (J > I) and not (Result[J] in DelimitChars) do Dec(J);
732       K:=J - I - 5; { how many chars in the "middle" can we delete }
733       if K > 0 then begin
734         if K >= L then begin
735           K:=L;
736           B:=True;
737         end
738         else
739           B:=False;
740         Dec(J, K);
741         Delete(Result, J, K);
742         SetDots(J - 1);
743         if B then
744           Exit;
745       end;
746     end;
747     SetLength(Result, MaxLen);
748     SetDots(MaxLen);
749   end;
750 end;
751 
ShortenFileNameWnull752 function ShortenFileNameW(const FileName: WideString; MaxLen: Integer;
753   DelimitChars: TCharSet): WideString;
754 
755   procedure SetDots(FromIndex: Integer);
756   begin
757     Result[FromIndex]:='.';
758     Result[FromIndex - 1]:='.';
759     Result[FromIndex - 2]:='.';
760   end;
761 
762 var
763   I, J, K, L, Len: Integer;
764   B: Boolean;
765 begin
766   Result:=FileName;
767   Len:=Length(Result);
768   if MaxLen < 4 then
769     MaxLen:=4;
770   L:=Len - MaxLen;
771   if L > 0 then begin
772     if DelimitChars = [] then
773       DelimitChars:=[PathDelim];
774     I:=WideCharInSetPos(DelimitChars, Result, 1);
775     if I > 0 then begin
776       J:=Len;
777       while (J > I) and (Result[J] < #256) and
778         not (AnsiChar(Result[J]) in DelimitChars)
779       do
780         Dec(J);
781       K:=J - I - 5; { how many chars in the "middle" can we delete }
782       if K > 0 then begin
783         if K >= L then begin
784           K:=L;
785           B:=True;
786         end
787         else
788           B:=False;
789         Dec(J, K);
790         Delete(Result, J, K);
791         SetDots(J - 1);
792         if B then
793           Exit;
794       end;
795     end;
796     SetLength(Result, MaxLen);
797     SetDots(MaxLen);
798   end;
799 end;
800 
GetModuleNameWnull801 function GetModuleNameW(Module: HMODULE): WideString;
802 begin
803   {$IFDEF V_WIN}
804   if Win32Platform = VER_PLATFORM_WIN32_NT then begin
805     SetLength(Result, MAX_PATH);
806     SetLength(Result, GetModuleFileNameW(Module, Pointer(Result), MAX_PATH));
807   end
808   else
809   {$ENDIF}
810     Result:=GetModuleName(Module);
811 end;
812 
813 procedure ParseFileName(const FileName: String; var Path, Name: String);
814 var
815   I: Integer;
816 begin
817   I:=LastDelimiter(PathDelim + DriveDelim, FileName);
818   Path:=Copy(FileName, 1, I);
819   Name:=Copy(FileName, I + 1, MaxInt);
820 end;
821 
822 procedure ParseFileNameW(const FileName: WideString; var Path, Name: WideString);
823 var
824   I: Integer;
825 begin
826   I:=LastDelimiterW(PathDelim + DriveDelim, FileName);
827   Path:=Copy(FileName, 1, I);
828   Name:=Copy(FileName, I + 1, MaxInt);
829 end;
830 
FirstItemDelimiterWnull831 function FirstItemDelimiterW(const Path: WideString): Integer;
832 var
833   I: Integer;
834 begin
835   for I:=1 to Length(Path) do
836     if (Path[I] = PathDelim) or (Path[I] = '|') then begin
837       Result:=I;
838       Exit;
839     end;
840   Result:=0;
841 end;
842 
LastItemDelimiterWnull843 function LastItemDelimiterW(const Path: WideString): Integer;
844 var
845   I: Integer;
846 begin
847   for I:=Length(Path) downto 1 do
848     if (Path[I] = PathDelim) or (Path[I] = '|') then begin
849       Result:=I;
850       Exit;
851     end;
852   Result:=0;
853 end;
854 
855 const
856   ItemDelimiters = '|' + PathDelim + DriveDelim;
857 
858 procedure ParseItemName(const FullItemName: String; var Path, Name: String);
859 var
860   I: Integer;
861 begin
862   I:=LastDelimiter(ItemDelimiters, FullItemName);
863   Path:=Copy(FullItemName, 1, I - 1);
864   Name:=Copy(FullItemName, I + 1, MaxInt);
865 end;
866 
867 procedure ParseItemNameW(const FullItemName: WideString; var Path, Name: WideString);
868 var
869   I: Integer;
870 begin
871   I:=LastDelimiterW(ItemDelimiters, FullItemName);
872   Path:=Copy(FullItemName, 1, I - 1);
873   Name:=Copy(FullItemName, I + 1, MaxInt);
874 end;
875 
GetItemNameWnull876 function GetItemNameW(const FullItemName: WideString): WideString;
877 begin
878   Result:=Copy(FullItemName, LastDelimiterW(ItemDelimiters, FullItemName) + 1, MaxInt);
879 end;
880 
GetItemPathWnull881 function GetItemPathW(const FullItemName: WideString): WideString;
882 begin
883   Result:=Copy(FullItemName, 1, LastDelimiterW(ItemDelimiters, FullItemName) - 1);
884 end;
885 
CorrectFilePathNamenull886 function CorrectFilePathName(const Name: String; DefaultChar: AnsiChar;
887   ProhibitedChars: TCharSet): String;
888 var
889   I: Integer;
890   C: AnsiChar;
891 begin
892   Result:=Name;
893   for I:=1 to Length(Name) do begin
894     C:=Name[I];
895     if C < #32 then
896       Result[I]:=DefaultChar
897     else if C in ProhibitedChars then begin
898       {$IFDEF V_WIN}
899       Case C of
900         '"': C:='''';
901         '<': C:=#$AB;
902         '>': C:=#$BB;
903         '|': C:=#$A6;
904       Else
905         C:=DefaultChar;
906       End;
907       Result[I]:=C;
908       {$ENDIF}
909       {$IFDEF UNIX}
910       Result[I]:=DefaultChar;
911       {$ENDIF}
912     end;
913   end; {for}
914 end;
915 
CorrectFilePathNameWnull916 function CorrectFilePathNameW(const Name: WideString; DefaultChar: WideChar;
917   ProhibitedChars: TCharSet): WideString;
918 var
919   I: Integer;
920   W: WideChar;
921 begin
922   Result:=Name;
923   for I:=1 to Length(Name) do begin
924     W:=Name[I];
925     if W < #32 then
926       Result[I]:=DefaultChar
927     else if (W < #256) and (AnsiChar(W) in ProhibitedChars) then begin
928       {$IFDEF V_WIN}
929       Case AnsiChar(W) of
930         '"': W:='''';
931         '<': W:=#$AB;
932         '>': W:=#$BB;
933         '|': W:=#$A6;
934       Else
935         W:=DefaultChar;
936       End;
937       Result[I]:=W;
938       {$ENDIF}
939       {$IFDEF UNIX}
940       Result[I]:=DefaultChar;
941       {$ENDIF}
942     end;
943   end; {for}
944 end;
945 
CorrectFileNamenull946 function CorrectFileName(const Name: String; DefaultChar: AnsiChar): String;
947 begin
948   Result:=CorrectFilePathName(Name, DefaultChar, InvalidFileNameChars);
949 end;
950 
CorrectFileNameWnull951 function CorrectFileNameW(const Name: WideString; DefaultChar: WideChar): WideString;
952 begin
953   Result:=CorrectFilePathNameW(Name, DefaultChar, InvalidFileNameChars);
954 end;
955 
CorrectPathNamenull956 function CorrectPathName(const Name: String; DefaultChar: AnsiChar): String;
957 begin
958   Result:=CorrectFilePathName(Name, DefaultChar, InvalidFileNameChars - [PathDelim]);
959 end;
960 
CorrectPathNameWnull961 function CorrectPathNameW(const Name: WideString; DefaultChar: WideChar): WideString;
962 begin
963   Result:=CorrectFilePathNameW(Name, DefaultChar, InvalidFileNameChars - [PathDelim]);
964 end;
965 
GetStdFileExtnull966 function GetStdFileExt(const FileName: String): String;
967 begin
968   Result:=AnsiLowerCase(Copy(ExtractFileExt(FileName), 2, MaxInt));
969 end;
970 
971 {$IFDEF V_WIN}
972 
973 {$ENDIF}
974 
975 {$IFDEF UNIX}
976 
977 {$ENDIF} {LINUX}
978 
979 {$IFDEF V_WIN}
980 type
981   TReadFileSize =
982     {$IFDEF V_D3}{$IFNDEF V_D4}Integer{$ELSE}DWORD{$ENDIF}{$ELSE}DWORD{$ENDIF};
983 {$ENDIF}
984 
985 
IsRelativePathnull986 function IsRelativePath(const FileName: String): Boolean;
987 begin
988   {$IFDEF V_WIN}
989   Result:=(Length(FileName) > 1) and (FileName[2] <> ':');
990   {$ENDIF}
991   {$IFDEF UNIX}
992   Result:=(FileName <> '') and not (FileName[1] in [PathDelim, '~', '$']);
993   {$ENDIF}
994 end;
995 
996 end.
997