Changeset 392 for trunk/Library/FileUtilsUnit.pas
- Timestamp:
- Apr 30, 2016, 8:19:42 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Library/FileUtilsUnit.pas
r388 r392 2 2 3 3 // NewView - a new OS/2 Help Viewer 4 // Copyright 2006/2007 Ronald Brill (rbri at rbri dot de) 4 // Copyright 2003-2006 Aaron Lawrence 5 // Copyright 2006-2009 Ronald Brill (rbri at rbri dot de) 5 6 // This software is released under the GNU Public License - see readme.txt 6 7 … … 15 16 16 17 const 17 D irectorySeparator= '\';18 DIRECTORY_SEPARATOR = '\'; 18 19 PATH_SEPARATOR = ';'; 20 CURRENT_DIRECTORY = '.'; 21 PARENT_DIRECTORY = '..'; 22 FILE_EXTENSION_DELIMITER = '.'; 23 24 // Drive numbers are one based 25 MinDriveNumber = 1; 26 MaxDriveNumber = 26; 27 19 28 20 29 // TODO … … 23 32 LanguageEnvironmentVar = 'LANG'; 24 33 DEFAULT_LANGUAGE = 'EN_US'; 25 HELP_FILE_EXTENSION = '.hlp'; 26 INF_FILE_EXTENSION = '.inf'; 34 HELP_FILE_DELIMITER = '+'; 35 HELP_FILE_EXTENSION = FILE_EXTENSION_DELIMITER + 'hlp'; 36 INF_FILE_EXTENSION = FILE_EXTENSION_DELIMITER + 'inf'; 37 38 39 type 40 TDriveType = 41 ( 42 dtNone, 43 dtFloppy, 44 dtHard, 45 dtCD, 46 dtNetwork, 47 dtRemovable 48 ); 27 49 28 50 … … 58 80 // this always clears the list at the beginning 59 81 Procedure GetDirsInPath(const aPathEnvVar: String; var aList: TStrings); 82 83 // Breaks up specified Env var path 84 // then adds all matching files to the list 85 Procedure GetFilesInPath( const aPathEnvVar: String; 86 const aFilter: String; 87 var aList: TStrings ); 60 88 61 89 // searches for all files in aDirectory matching aFilter and add … … 68 96 69 97 // searches for all directories in aDirectory and add them to aList 70 Procedure ListSubDirectories(const aDirectory: String; var aList: TStrings);98 Procedure ListSubDirectories(const aDirectory: String; const anIncludeSystemAndHiddenFlag: boolean; var aList: TStrings); 71 99 72 100 Procedure ListFilesInDirectoryRecursiveWithTermination(const aDirectory : String; 73 101 const aFilter : String; 74 102 const aWithDirectoryFlag : boolean; 103 const anIncludeSystemAndHiddenFlag: boolean; 75 104 var aList : TStrings; 76 105 const aTerminateCheck : TTerminateCheck; … … 79 108 Function ParentDir(const aDirectory : String) : String; 80 109 110 // In the directory startpath, create directory and subdirectories 111 // specified in DirsString 112 // e.g. bob\bill\fred will make bob, then bill in bob, then fred in bob 113 // returns path to lowest dir created 114 Function MakeDirs(const aFullDirectoryPath: String) : String; 115 116 117 // Checks if a directory exists 81 118 Function DirectoryExists(const aDirectory : String) : boolean; 119 120 Function DriveLetterToDriveNumber(const aDriveLetter : char) : longint; 121 Function DriveNumberToDriveLetter(const aDriveNumber : longint) : char; 122 123 Function GetVolumeLabel(aDrive: char) : String; 124 125 Function GetBootDriveLetter: char; 126 127 // Returns true if file exists and is read only 128 Function FileIsReadOnly(const aFilename : String) : boolean; 129 130 131 // TODO 132 Function IsFloppyDrive( DriveNumber: longint ): Boolean; 133 Function GetLocalDriveType( DriveNumber: longint ): TDriveType; 134 Function GetDriveType( DriveNumber: longint ): TDriveType; 135 Function GetNetworkDriveRemotePath( DriveNumber: longint ): String; 136 82 137 83 138 Implementation … … 86 141 Dos, 87 142 BseDos, 143 BseErr, 144 BseDev, 88 145 Os2Def, 89 146 SysUtils, 90 StringUtilsUnit; 147 StringUtilsUnit, 148 CharUtilsUnit; 149 150 imports 151 FUNCTION _DosQueryFSAttach( VAR pszDeviceName: CSTRING; 152 ulOrdinal: ULONG; 153 ulFSAInfoLevel:ULONG; 154 pfsqb: PFSQBUFFER2; 155 VAR pcbBuffLength: ULONG ): APIRET; APIENTRY; 156 'DOSCALLS' index 277; 157 end; 158 159 160 type 161 TWord = Record // Bytes of a Word 162 LoByte, HiByte : Byte; 163 End; 164 165 TBPB = Array[0..30] Of Byte; // Puffer fuer BPB-Struktur 166 167 TDeviceParameters = Record 168 BPB: TBPB; 169 Cylinders: word; 170 DeviceType: Byte; 171 Attributes: Word; 172 End; 173 174 91 175 92 176 Function AddDirectorySeparator(aDirectory : String) : String; … … 94 178 if aDirectory = '' then 95 179 begin 96 Result:= D irectorySeparator;180 Result:= DIRECTORY_SEPARATOR; 97 181 exit; 98 182 end; 99 183 100 if aDirectory[length(aDirectory)] <> D irectorySeparatorthen101 begin 102 Result := aDirectory + D irectorySeparator;184 if aDirectory[length(aDirectory)] <> DIRECTORY_SEPARATOR then 185 begin 186 Result := aDirectory + DIRECTORY_SEPARATOR; 103 187 exit; 104 188 end; … … 121 205 Function RemoveRightDirectorySeparator(aDirectory : String) : String; 122 206 begin 123 Result := StrTrimRightChars(aDirectory, [D irectorySeparator]);207 Result := StrTrimRightChars(aDirectory, [DIRECTORY_SEPARATOR]); 124 208 end; 125 209 … … 135 219 if aPath = '' then 136 220 begin 137 Result := StrTrimRightChars(Result, [D irectorySeparator]);221 Result := StrTrimRightChars(Result, [DIRECTORY_SEPARATOR]); 138 222 exit; 139 223 end; … … 148 232 if Length(aPath) > 3 then 149 233 begin 150 Result := StrTrimRightChars(Result, [D irectorySeparator]);234 Result := StrTrimRightChars(Result, [DIRECTORY_SEPARATOR]); 151 235 end; 152 236 exit; … … 157 241 begin 158 242 // check for root dir spec 159 if aPath[1] = D irectorySeparatorthen243 if aPath[1] = DIRECTORY_SEPARATOR then 160 244 begin 161 245 // take just the drive from the basedir … … 166 250 else 167 251 begin 168 Result := D irectorySeparator;252 Result := DIRECTORY_SEPARATOR; 169 253 end; 170 aPath := StrTrimLeftChars(aPath, [D irectorySeparator]);254 aPath := StrTrimLeftChars(aPath, [DIRECTORY_SEPARATOR]); 171 255 end; 172 256 end; 173 257 174 258 tmpDirectories := TStringList.Create; 175 StrExtractStringsIgnoreEmpty(tmpDirectories, aPath, [D irectorySeparator], #0);259 StrExtractStringsIgnoreEmpty(tmpDirectories, aPath, [DIRECTORY_SEPARATOR], #0); 176 260 for i := 0 to tmpDirectories.count-1 do 177 261 begin 178 262 tmpDirectory := tmpDirectories[i]; 179 if tmpDirectory = '..'then263 if tmpDirectory = PARENT_DIREcTORY then 180 264 begin 181 265 if NOT ((Length(Result) = 2) AND (Result[2] = ':')) then … … 184 268 end; 185 269 end 186 else if tmpDirectory = '.'then270 else if tmpDirectory = CURRENT_DIRECTORY then 187 271 begin 188 272 ; // nothing to do … … 194 278 195 279 // strip any extra leading slashes 196 aPath := StrTrimLeftChars(aPath, [D irectorySeparator]);280 aPath := StrTrimLeftChars(aPath, [DIRECTORY_SEPARATOR]); 197 281 end; 198 282 tmpDirectories.Destroy; … … 203 287 begin 204 288 // just a drive spec X:, so add a slash 205 Result := Result + D irectorySeparator;289 Result := Result + DIRECTORY_SEPARATOR; 206 290 end; 207 291 end; … … 355 439 356 440 StrExtractStringsIgnoreEmpty(aList, StrPas(tmpPszPathEnvVar), [PATH_SEPARATOR], #0); 441 end; 442 443 444 Procedure GetFilesInPath( const aPathEnvVar: String; 445 const aFilter: String; 446 var aList: TStrings ); 447 var 448 tmpDirectories : TStringList; 449 i : integer; 450 begin 451 tmpDirectories := TStringList.Create; 452 GetDirsInPath(aPathEnvVar, tmpDirectories); 453 454 for i:=0 to tmpDirectories.count-1 do 455 begin 456 ListFilesInDirectory(tmpDirectories[i], aFilter, false, aList); 457 end; 458 459 tmpDirectories.Destroy; 357 460 end; 358 461 … … 402 505 403 506 404 Procedure ListSubDirectories(const aDirectory: String; var aList: TStrings);507 Procedure ListSubDirectories(const aDirectory: String; const anIncludeSystemAndHiddenFlag: boolean; var aList: TStrings); 405 508 var 406 509 tmpRC : APIRET; 407 510 tmpSearchResults: TSearchRec; 408 511 tmpName : String; 409 begin 410 411 tmpRC := FindFirst(AddDirectorySeparator(aDirectory) + '*', faDirectory or faMustDirectory, tmpSearchResults); 512 tmpFileAttributes : ULONG; 513 begin 514 515 if anIncludeSystemAndHiddenFlag then 516 begin 517 tmpFileAttributes := faArchive or faReadonly or faHidden or faSysFile or faDirectory or faMustDirectory; 518 end 519 else 520 begin 521 tmpFileAttributes := faArchive or faReadonly or faDirectory or faMustDirectory; 522 end; 523 524 tmpRC := FindFirst(AddDirectorySeparator(aDirectory) + '*', tmpFileAttributes, tmpSearchResults); 412 525 if (tmpRC <> 0) then 413 526 begin … … 418 531 begin 419 532 tmpName := tmpSearchResults.Name; 420 if (tmpName <> '.') AND (tmpName <> '..') then533 if (tmpName <> CURRENT_DIRECTORY) AND (tmpName <> PARENT_DIRECTORY) then 421 534 begin 422 535 aList.Add(AddDirectorySeparatorIfNotEmpty(aDirectory) + tmpSearchResults.Name ); … … 431 544 const aFilter : String; 432 545 const aWithDirectoryFlag : boolean; 546 const anIncludeSystemAndHiddenFlag: boolean; 433 547 var aList : TStrings; 434 548 const aTerminateCheck : TTerminateCheck; … … 444 558 // now determine all subdirectories 445 559 tmpSubDirectories := TStringList.Create; 446 ListSubDirectories(aDirectory, tmpSubDirectories);560 ListSubDirectories(aDirectory, anIncludeSystemAndHiddenFlag, tmpSubDirectories); 447 561 448 562 for i := 0 to tmpSubDirectories.Count - 1 do … … 455 569 tmpSubDirectory := tmpSubDirectories[i]; 456 570 457 ListFilesInDirectoryRecursiveWithTermination(tmpSubDirectory, aFilter, aWithDirectoryFlag, aList, aTerminateCheck, aUseTerminateCheck); 571 ListFilesInDirectoryRecursiveWithTermination( tmpSubDirectory, 572 aFilter, 573 aWithDirectoryFlag, 574 anIncludeSystemAndHiddenFlag, 575 aList, 576 aTerminateCheck, 577 aUseTerminateCheck); 458 578 end; 459 579 tmpSubDirectories.Destroy; … … 468 588 469 589 // ends with slash 470 while (aDirectory[tmpPos] = D irectorySeparator) AND (tmpPos > 0) do590 while (aDirectory[tmpPos] = DIRECTORY_SEPARATOR) AND (tmpPos > 0) do 471 591 begin 472 592 dec(tmpPos); … … 474 594 475 595 // find slash 476 while (aDirectory[tmpPos] <> D irectorySeparator) AND (tmpPos > 0) do596 while (aDirectory[tmpPos] <> DIRECTORY_SEPARATOR) AND (tmpPos > 0) do 477 597 begin 478 598 dec(tmpPos); … … 480 600 481 601 result:= StrLeft(aDirectory, tmpPos-1); 602 end; 603 604 605 Function MakeDirs(const aFullDirectoryPath: String) : String; 606 Var 607 tmpDirectoryParts : TStringList; 608 tmpDirectoryPart : String; 609 tmpCompletePart : String; 610 i : integer; 611 begin 612 tmpDirectoryParts := TStringList.Create; 613 StrExtractStringsIgnoreEmpty(tmpDirectoryParts, aFullDirectoryPath, [DIRECTORY_SEPARATOR], #0); 614 615 tmpCompletePart := ''; 616 for i:=0 to tmpDirectoryParts.count-1 do 617 begin 618 tmpDirectoryPart := trim(tmpDirectoryParts[i]); 619 620 if tmpDirectoryPart <> '' then 621 begin 622 tmpCompletePart := AddDirectorySeparatorIfNotEmpty(tmpCompletePart) + tmpDirectoryPart; 623 624 if not DirectoryExists(tmpCompletePart) then 625 begin 626 MkDir(tmpCompletePart); 627 end; 628 end; 629 end; 630 631 Result := tmpCompletePart; 482 632 end; 483 633 … … 498 648 if tmpDirectory = '' then 499 649 begin 500 Result := true;650 Result := true; 501 651 exit; 502 652 end; … … 507 657 begin 508 658 // a drive only has been specified 509 tmpDrive := UpCase(tmpDirectory[1] );659 tmpDrive := UpCase(tmpDirectory[1] ); 510 660 if (tmpDrive < 'A') or (tmpDrive > 'Z') then 511 661 begin … … 523 673 end; 524 674 525 tmpRC := FindFirst(tmpDirectory, faDirectory or faMustDirectory, tmpSearchResults); 675 tmpRC := FindFirst( tmpDirectory, 676 faArchive or faReadonly or faHidden or faSysFile or faDirectory or faMustDirectory, 677 tmpSearchResults); 526 678 if tmpRC = 0 then 527 679 begin … … 532 684 533 685 686 Function DriveLetterToDriveNumber(const aDriveLetter : char) : longint; 687 begin 688 if (aDriveLetter >= 'a') 689 and (aDriveLetter <= 'z') then 690 begin 691 Result := Ord(aDriveLetter) - Ord('a') + 1; 692 exit; 693 end; 694 695 if (aDriveLetter >= 'A') 696 and (aDriveLetter <= 'Z') then 697 begin 698 Result := Ord(aDriveLetter) - Ord('A') + 1; 699 exit; 700 end; 701 702 // not a valid drive letter 703 Result := 0; 704 end; 705 706 707 Function DriveNumberToDriveLetter(const aDriveNumber: longint) : char; 708 begin 709 Result := Chr(aDriveNumber - 1 + Ord('A')); 710 end; 711 712 713 Function GetVolumeLabel(aDrive: char) : String; 714 var 715 tmpRC : APIRET; 716 tmpFileSystemInfo : FSINFO; 717 e : EInOutError; 718 begin 719 DosErrorAPI( FERR_DISABLEHARDERR ); 720 Result := ''; 721 tmpRC := DosQueryFSInfo( DriveLetterToDriveNumber(aDrive), 722 FSIL_VOLSER, 723 tmpFileSystemInfo, 724 sizeof(tmpFileSystemInfo)); 725 if tmpRC = 0 then 726 begin 727 Result := StrPasWithLength(Addr(tmpFileSystemInfo.vol.szVolLabel), tmpFileSystemInfo.vol.cch); 728 Result := LowerCase(Result); 729 end; 730 DosErrorAPI( FERR_ENABLEHARDERR ); 731 732 if tmpRC <> 0 then 733 begin 734 e := EInOutError.Create( 'Cannot read drive ' + aDrive + ':'); 735 e.ErrorCode := tmpRC; 736 raise e; 737 end; 738 end; 739 740 741 Function GetBootDriveLetter: char; 742 var 743 tmpBuffer: longword; 744 begin 745 DosQuerySysInfo( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, tmpBuffer, sizeof(tmpBuffer)); 746 Result := Chr(ord('A') + tmpBuffer - 1); 747 end; 748 749 750 Function FileIsReadOnly(const aFilename : String ) : boolean; 751 begin 752 Result :=(FileGetAttr(aFilename) AND faReadonly) > 0; 753 end; 754 755 756 757 758 // TODO 759 760 761 Function IsFloppyDrive( DriveNumber: longint ): Boolean; 762 Var 763 bResult : Byte; 764 Begin 765 DosDevConfig( bResult, DEVINFO_FLOPPY ); 766 Result := ( Abs( DriveNumber ) <= bResult); 767 End; 768 769 // ------------------------------------------------------------------------- 770 // Funktion/Function: QueryCDRoms() 771 // 772 // Beschreibung: 773 // Die Funktion QueryCDRom ermittelt ueber eine nicht dokumentierte 774 // Schnittstelle die Anzahl der CDRom-Laufwerke und den ersten, fuer 775 // ein CDRom-Laufwerk, vergebenen UnitIdentifier. 776 // Der Treiber OS2CDROM.DMD stellt dem System zwei Devices (CD-ROM1$ 777 // und CD-ROM2$) zur Verfuegung. Die beiden Devices unterscheiden sich 778 // durch DeviceAttribute. Beide Devices unterstuetzen (zumindest unter 779 // Warp) den undokumentierten Generic IOCtl 0x82/0x60, welcher Infor- 780 // mationen ueber die angeschlossenen CDRom-Laufwerke liefert. 781 // 782 // Description: 783 // This Functions finds out how many CD-Rom Drives are present in System 784 // and which Drive Letter is the first occupied by a CD-Rom. It uses an 785 // undocumented Interface to OS2CDROM.DMD. 786 // OS2CDROM.DMD presents two Devices (CD-ROM1$ and CD-ROM2$). These De- 787 // vices are distinguished by their Device-Attributes. Both Devices sup- 788 // port (under Warp) the undocumented generic IOCtl-Call 0x82/0x60 which 789 // deliver some Information about the connected CD-Rom Drives. 790 // 791 // Parameter: 792 // Var ulCDRomCount ULONG Anzahl CD-Rom Laufwerke im System 793 // Number of CD-Rom Drives in System 794 // 795 // Var ulFirstCDRomDiskNo ULONG erste Laufwerksnummer, die an ein 796 // CD-Rom vergeben ist 797 // first Drive-Letter occupied by a 798 // CD-Rom Drive 799 // 800 // Rueckgabe/Returnvalue: keine/none 801 // ------------------------------------------------------------------------- 802 Procedure QueryCDRoms(Var ulCDRomCount, ulFirstCDRomDiskNo: ULONG); 803 804 Const cszDriverName : CSTRING = 'CD-ROM?$'; 805 806 Var cCurDriver : Char; // Indexvariable fuer aktuell bearbeites Device (1 oder 2) 807 // Index for current Device (1 or 2) 808 809 hDevHandle : HFILE; // Handle fuer Device 810 // Device handle 811 812 ulAction : ULONG; // Aktionscode (DosOpen()) 813 // Actioncode (DosOpen()) 814 815 ulParams : ULONG; // Anzahl Bytes von IOCtl gelieferter Parameterdaten 816 // Number of Bytes for delivered Parameterdata 817 818 ulData : ULONG; // Anzahl Bytes von IOCtl gelieferter Daten 819 // Number of Bytes delivered by IOCtl 820 821 rCDInfo : Record // Ergebnisstruktur der IOCtl-Funktion (s.o.) 822 // Record for Results of IOCtl-Call (see above) 823 usCDRomCount : USHORT; // Anzahl CD-Roms / Number of CD-Rom Drives 824 usFirstUnitNo: USHORT; // erste vergebene Laufwerksnummer / first Driver Letter 825 End; 826 827 Begin (* uQueryCDRom *) 828 /************************************ 829 * Vorbelegungen 830 * 831 * initial assignments 832 ************************************/ 833 ulCDRomCount := 0; 834 ulFirstCDRomDiskNo := 0; 835 836 ulParams := 0; 837 838 /************************************ 839 * die beiden Devices abarbeiten 840 * 841 * accessing both Devices 842 ************************************/ 843 For cCurDriver := '1' To '2' Do 844 Begin 845 /************************************ 846 * Device oeffnen 847 * 848 * open Device 849 ************************************/ 850 cszDriverName[6] := cCurDriver; 851 If (DosOpen(cszDriverName, // Devicename 852 hDevHandle, // Handle 853 ulAction, // Aktionscode 854 0, // Dateigráe 855 FILE_NORMAL, // Attribute: read/write 856 OPEN_ACTION_OPEN_IF_EXISTS, // OpenFlag: ffnen, wenn vorhanden 857 OPEN_FLAGS_FAIL_ON_ERROR Or // Modus: Fehlermeldung per Returncode 858 OPEN_SHARE_DENYNONE Or // keine Einschrnkungen fr Dritte 859 OPEN_ACCESS_READONLY, // nur lesender Zugriff 860 NIL)=NO_ERROR) Then // keine EA 861 Begin 862 /************************************ 863 * IOCtl-Funktion aufrufen 864 * 865 * Call to IOCtl 866 ************************************/ 867 If (DosDevIOCtl(hDevHandle, // Handle / Handle 868 $82, // Kategorie / Category 869 $60, // Funktion / Function 870 NIL, // keine Parameterliste / No Parameterlist 871 0, // Laenge Parameterliste / Length of Parameterlist 872 ulParams, // Groesse der gelieferten Parameterdaten 873 // / Number of Bytes for Parameterdata 874 rCDInfo, // Puffer fuer gelieferte Daten 875 // / Buffer for returned Data 876 SizeOf(rCDInfo), // Groesse des Datenpuffers 877 // / Size of Databuffer 878 ulData)=NO_ERROR) Then // Groesse der gelieferten Daten 879 // / Number of Bytes for returned Data 880 Begin 881 ulCDRomCount := rCDInfo.usCDRomCount; 882 ulFirstCDRomDiskNo := Succ(rCDInfo.usFirstUnitNo); 883 End; 884 885 DosClose(hDevHandle); 886 End; 887 888 End; (* For *) 889 890 End; (* uQueryCDRom *) 891 892 893 Function GetLocalDriveType( DriveNumber: longint ): TDriveType; 894 var 895 IOCtlParameters: Word; 896 rc: APIRET; 897 ParameterLength: longWord; 898 DataLength: longword; 899 DeviceData: TDeviceParameters; 900 Fixed: boolean; 901 FirstCDDrive: ULONG; 902 NumCDDrives: ULONG; 903 begin 904 905 TWord( IOCtlParameters ).LoByte := 0; // BPB of physical Device 906 TWord( IOCtlParameters ).HiByte := DriveNumber - 1; // drive number, zero base 907 908 ParameterLength := SizeOf( IOCtlParameters ); // input length of parameters 909 DataLength := 0; // input length of data (none) 910 911 rc := DosDevIOCTL( HFILE(-1), // Open Device (not a file) 912 IOCTL_DISK, // Category 913 DSK_GETDEVICEPARAMS, // Function 914 IOCtlParameters, // Parameters 915 SizeOf( IOCtlParameters ), // (max) size of parameters 916 ParameterLength, // parameters length 917 DeviceData, // results 918 SizeOf( DeviceData ), // (max) size of data block 919 DataLength ); // data block length 920 921 Fixed := ( DeviceData.Attributes and 1 ) > 0; // bit 0 indicates fixed (1) or removable (0) 922 if not Fixed then 923 begin 924 result := dtRemovable; 925 926 QueryCDRoms( FirstCDDrive, 927 NumCDDrives ); 928 929 if ( DriveNumber >= FirstCDDrive ) 930 and ( DriveNumber < FirstCDDrive + NumCDDrives ) then 931 result := dtCD; 932 933 exit; 934 end; 935 936 result := dtHard; 937 end; 938 939 // Takes a one-based drive number 940 Function GetDriveType( DriveNumber: longint ): TDriveType; 941 var 942 szDrive: CString; 943 944 FSData: array[ 0..sizeof( FSQBuffer) + 3*_MAX_PATH ] of char; 945 pBuffer: PFSQBUFFER2; 946 FSDataLength: ULONG; 947 948 rc: APIRET; 949 begin 950 assert( DriveNumber >= 1 ); 951 assert( DriveNumber <= 26 ); 952 953 if ( DriveNumber >=1 ) and ( DriveNumber <= 2 ) then 954 begin 955 if IsFloppyDrive( DriveNumber ) then 956 begin 957 result := dtFloppy; 958 exit; 959 end; 960 961 result := dtNone; // don't let OS/2 try a fake B: drive 962 exit; 963 end; 964 965 DosErrorAPI( FERR_DISABLEHARDERR ); 966 967 szDrive := DriveNumberToDriveLetter( DriveNumber ) + ':'; 968 FSDataLength := sizeof( FSData ); 969 pBuffer := Addr( FSData ); 970 rc := _DosQueryFSAttach( szDrive, 971 0, // ignored 972 FSAIL_QUERYNAME, 973 pBuffer, 974 FSDataLength ); 975 976 if rc = 0 then 977 begin 978 case pBuffer^.iType of 979 FSAT_REMOTEDRV: 980 result := dtNetwork; 981 982 FSAT_LOCALDRV: 983 // Figure out what kind of local drive it is... 984 result := GetLocalDriveType( DriveNumber ); 985 986 else 987 begin 988 // should never happen 989 result := dtNone; 990 exit; 991 end; 992 end; 993 end 994 else if rc = ERROR_NOT_READY then 995 begin 996 // No media? 997 // Have a look for a local disk anyway. 998 result := GetLocalDriveType( DriveNumber ); 999 end 1000 else 1001 begin 1002 result := dtNone; 1003 end; 1004 1005 DosErrorAPI( FERR_ENABLEHARDERR ); 1006 end; 1007 1008 const 1009 DEVLEN = 8; 1010 CNLEN = 15; // Computer name length 1011 UNCLEN = (CNLEN+2); // UNC computer name length 1012 NNLEN = 12; // 8.3 Net name length (share name length) 1013 RMLEN = (UNCLEN+1+NNLEN); // Maximum remote name length 1014 1015 type 1016 use_info_0 = record 1017 ui0_local: cstring[ DEVLEN ]; // note this is of size DEVLEN + 1 1018 ui0_pad_1: char; 1019 ui0_remote: pchar; 1020 space: array[ 0..RMLEN ] of char; // remote path is written to somewhere in here 1021 end; 1022 1023 use_info_1 = record 1024 ui0_local: cstring[ DEVLEN ]; 1025 ui0_pad_1: char; 1026 ui0_remote: pchar; // address of a buffer to hold remote path 1027 ui1_password: pchar; // 1028 ui1_status: USHORT; 1029 ui1_asg_type: SHORT; 1030 ui1_refcount: USHORT; 1031 ui1_usecount: USHORT; 1032 space: array[ 0..RMLEN ] of char; // remote path is written to somewhere in here 1033 end; 1034 1035 TNet32UseGetInfo = Function( pszServer: pchar; 1036 pszUseName: pchar; // e.g. drive x: 1037 ulLevel: ULONG; 1038 pbBuffer: pointer; // pointer to output buffer 1039 ulBuffer: ULONG; // size of output in buffer 1040 Var pulTotalAvail: ULONG ) 1041 : word; CDecl; 1042 1043 Var 1044 Net32UseGetInfo: TNet32UseGetInfo; 1045 hNetAPI32DLL: HMODULE; 1046 TriedLoading: boolean; 1047 1048 // 129 Net32UseGetInfo 1049 Function GetNetworkDriveRemotePath( DriveNumber: longint ): string; 1050 var 1051 ErrorName: array[ 0..255 ] of char; 1052 dummy: cstring; 1053 rc: word; 1054 UseName: array[ 0..255 ] of char; 1055 UseInfo: use_info_0; 1056 pUseInfo: pointer; 1057 TotalBytesNeeded: ULONG; 1058 RemotePath: array[ 0..255 ] of char; 1059 Dummy2: array[ 0..4096 ] of char; // try to fix stack probs 1060 begin 1061 Result := ''; 1062 1063 if not TriedLoading then 1064 begin 1065 TriedLoading := true; 1066 rc := DosLoadModule( ErrorName, 1067 sizeof( ErrorName ), 1068 'NETAPI32', 1069 hNetAPI32DLL ); 1070 if rc = NO_ERROR then 1071 begin 1072 // NetAPI32.DLL loaded OK 1073 rc := DosQueryProcAddr( hNetAPI32DLL, 1074 129, 1075 dummy, 1076 pointer( Net32UseGetInfo ) ); 1077 if rc <> 0 then 1078 Net32UseGetInfo := nil; 1079 end; 1080 end; 1081 1082 if Assigned( Net32UseGetInfo ) then 1083 begin 1084 UseName[ 0 ] := DriveNumberToDriveLetter( DriveNumber ); 1085 UseName[ 1 ] := ':'; 1086 UseName[ 2 ] := #0; 1087 1088 RemotePath[ 0 ] := #0; 1089 // UseInfo.ui0_remote := Addr( RemotePath ); 1090 1091 pUseInfo := Addr( UseInfo ); 1092 rc := Net32UseGetInfo( nil, // server - always nil 1093 Addr( UseName ), 1094 0, // info level 0 1095 pUseInfo, 1096 sizeof( UseInfo ), 1097 TotalBytesNeeded ); 1098 1099 if rc = 0 then 1100 Result := StrPas( UseInfo.ui0_remote ); 1101 1102 end; 1103 end; 1104 1105 534 1106 Initialization 535 1107 End.
Note:
See TracChangeset
for help on using the changeset viewer.