| [82] | 1 | Unit FileUtilsUnit;
 | 
|---|
 | 2 | 
 | 
|---|
 | 3 | // NewView - a new OS/2 Help Viewer
 | 
|---|
 | 4 | // Copyright 2006/2007 Ronald Brill (rbri at rbri dot de)
 | 
|---|
 | 5 | // This software is released under the GNU Public License - see readme.txt
 | 
|---|
 | 6 | 
 | 
|---|
 | 7 | // Helper functions for file handling
 | 
|---|
 | 8 | 
 | 
|---|
 | 9 | Interface
 | 
|---|
 | 10 | 
 | 
|---|
 | 11 | uses
 | 
|---|
 | 12 |   Classes,
 | 
|---|
 | 13 |   ACLUtility;
 | 
|---|
 | 14 | 
 | 
|---|
 | 15 | 
 | 
|---|
 | 16 | const
 | 
|---|
| [187] | 17 |   DIRECTORY_SEPARATOR = '\';
 | 
|---|
| [82] | 18 |   PATH_SEPARATOR = ';';
 | 
|---|
 | 19 | 
 | 
|---|
| [187] | 20 |   // Drive numbers are one based
 | 
|---|
 | 21 |   MinDriveNumber = 1;
 | 
|---|
 | 22 |   MaxDriveNumber = 26;
 | 
|---|
 | 23 | 
 | 
|---|
 | 24 | 
 | 
|---|
| [82] | 25 |   // TODO
 | 
|---|
 | 26 |   HelpPathEnvironmentVar = 'HELP';
 | 
|---|
 | 27 |   BookshelfEnvironmentVar = 'BOOKSHELF';
 | 
|---|
 | 28 |   LanguageEnvironmentVar = 'LANG';
 | 
|---|
 | 29 |   DEFAULT_LANGUAGE = 'EN_US';
 | 
|---|
 | 30 |   HELP_FILE_EXTENSION = '.hlp';
 | 
|---|
 | 31 | 
 | 
|---|
 | 32 | 
 | 
|---|
| [187] | 33 | type
 | 
|---|
 | 34 |   TDriveType =
 | 
|---|
 | 35 |   (
 | 
|---|
 | 36 |     dtNone,
 | 
|---|
 | 37 |     dtFloppy,
 | 
|---|
 | 38 |     dtHard,
 | 
|---|
 | 39 |     dtCD,
 | 
|---|
 | 40 |     dtNetwork,
 | 
|---|
 | 41 |     dtRemovable
 | 
|---|
 | 42 |   );
 | 
|---|
 | 43 | 
 | 
|---|
 | 44 | 
 | 
|---|
| [82] | 45 |   // Adds a slash to the end of dir if not present
 | 
|---|
 | 46 |   // if aDir is empty this returns '\'
 | 
|---|
 | 47 |   Function AddDirectorySeparator(aDirectory : String) : String;
 | 
|---|
 | 48 | 
 | 
|---|
 | 49 |   // Adds a slash to the end of dir if not present
 | 
|---|
 | 50 |   // if aDir is empty this returns ''
 | 
|---|
 | 51 |   Function AddDirectorySeparatorIfNotEmpty(aDirectory: String) : String;
 | 
|---|
 | 52 | 
 | 
|---|
 | 53 |   // Removes a directory seperator from the end of aDirectory
 | 
|---|
 | 54 |   // (if present)
 | 
|---|
 | 55 |   Function RemoveRightDirectorySeparator(aDirectory : String) : String;
 | 
|---|
 | 56 | 
 | 
|---|
 | 57 |   // Expands the path given, relative to aBaseDirectory
 | 
|---|
 | 58 |   // Handles leading \ for root dir,
 | 
|---|
 | 59 |   // .. for parent, . (ignored),
 | 
|---|
 | 60 |   // drive spec at start,
 | 
|---|
 | 61 |   // ignores repeated \ e.g. \\
 | 
|---|
 | 62 |   Function ExpandPath(aBaseDirectory : String; aPath : String): String;
 | 
|---|
 | 63 | 
 | 
|---|
 | 64 |   Function GetLogFilesDir: String;
 | 
|---|
 | 65 | 
 | 
|---|
 | 66 |   Function SearchPath(const aPathEnvVar: String; const aFilename: String; var aResultFilename: String) : boolean;
 | 
|---|
 | 67 | 
 | 
|---|
 | 68 |   Function SearchHelpPaths(const aFilename: String; var aResultFilename: String; const anIncludeAppDir: boolean) : boolean;
 | 
|---|
 | 69 | 
 | 
|---|
 | 70 |   // Find the help file for the current app based on LANG
 | 
|---|
 | 71 |   Function FindDefaultLanguageHelpFile(const anApplicationName: String; const aLanguage : String) : String;
 | 
|---|
 | 72 | 
 | 
|---|
 | 73 |   // Breaks up specified Env var path
 | 
|---|
| [97] | 74 |   // this always clears the list at the beginning
 | 
|---|
| [82] | 75 |   Procedure GetDirsInPath(const aPathEnvVar: String; var aList: TStrings);
 | 
|---|
 | 76 | 
 | 
|---|
| [187] | 77 |   // Breaks up specified Env var path
 | 
|---|
 | 78 |   // then adds all matching files to the list
 | 
|---|
 | 79 |   Procedure GetFilesInPath(     const aPathEnvVar: String;
 | 
|---|
 | 80 |                                 const aFilter: String;
 | 
|---|
 | 81 |                                 var aList: TStrings );
 | 
|---|
 | 82 | 
 | 
|---|
| [82] | 83 |   // searches for all files in aDirectory matching aFilter and add
 | 
|---|
 | 84 |   // them to aList
 | 
|---|
 | 85 |   // it is possible to define different filter if you separate them by semicolon
 | 
|---|
| [97] | 86 |   Procedure ListFilesInDirectory(       const aDirectory : String;
 | 
|---|
 | 87 |                                         const aFilter : String;
 | 
|---|
 | 88 |                                         const aWithDirectoryFlag : boolean;
 | 
|---|
 | 89 |                                         var aList : TStrings);
 | 
|---|
| [82] | 90 | 
 | 
|---|
 | 91 |   // searches for all directories in aDirectory and add them to aList
 | 
|---|
 | 92 |   Procedure ListSubDirectories(const aDirectory: String; var aList: TStrings);
 | 
|---|
 | 93 | 
 | 
|---|
 | 94 |   Procedure ListFilesInDirectoryRecursiveWithTermination(const aDirectory : String;
 | 
|---|
 | 95 |                                                          const aFilter : String;
 | 
|---|
| [97] | 96 |                                                          const aWithDirectoryFlag : boolean;
 | 
|---|
| [82] | 97 |                                                          var aList : TStrings;
 | 
|---|
 | 98 |                                                          const aTerminateCheck : TTerminateCheck;
 | 
|---|
 | 99 |                                                          const aUseTerminateCheck : boolean);
 | 
|---|
 | 100 | 
 | 
|---|
 | 101 |   Function ParentDir(const aDirectory : String) : String;
 | 
|---|
 | 102 | 
 | 
|---|
| [187] | 103 |   // In the directory startpath, create directory and subdirectories
 | 
|---|
 | 104 |   // specified in DirsString
 | 
|---|
 | 105 |   // e.g. bob\bill\fred will make bob, then bill in bob, then fred in bob
 | 
|---|
 | 106 |   // returns path to lowest dir created
 | 
|---|
 | 107 |   Function MakeDirs(const aFullDirectoryPath: String) : String;
 | 
|---|
 | 108 | 
 | 
|---|
 | 109 | 
 | 
|---|
 | 110 | 
 | 
|---|
| [82] | 111 |   Function DirectoryExists(const aDirectory : String) : boolean;
 | 
|---|
 | 112 | 
 | 
|---|
| [187] | 113 |   Function DriveLetterToDriveNumber(const aDriveLetter : char) : longint;
 | 
|---|
 | 114 |   Function DriveNumberToDriveLetter(const aDriveNumber : longint) : char;
 | 
|---|
 | 115 | 
 | 
|---|
 | 116 |   Function GetVolumeLabel(aDrive: char) : String;
 | 
|---|
 | 117 | 
 | 
|---|
 | 118 |   Function GetBootDriveLetter: char;
 | 
|---|
 | 119 | 
 | 
|---|
 | 120 |   // Returns true if file exists and is read only
 | 
|---|
 | 121 |   Function FileIsReadOnly(const aFilename : String) : boolean;
 | 
|---|
 | 122 | 
 | 
|---|
 | 123 | 
 | 
|---|
 | 124 |   // TODO
 | 
|---|
 | 125 |   Function IsFloppyDrive( DriveNumber: longint ): Boolean;
 | 
|---|
 | 126 |   Function GetLocalDriveType( DriveNumber: longint ): TDriveType;
 | 
|---|
 | 127 |   Function GetDriveType( DriveNumber: longint ): TDriveType;
 | 
|---|
 | 128 |   Function GetNetworkDriveRemotePath( DriveNumber: longint ): String;
 | 
|---|
 | 129 | 
 | 
|---|
 | 130 | 
 | 
|---|
| [82] | 131 | Implementation
 | 
|---|
 | 132 | 
 | 
|---|
 | 133 | uses
 | 
|---|
 | 134 |   Dos,
 | 
|---|
 | 135 |   BseDos,
 | 
|---|
| [187] | 136 |   BseErr,
 | 
|---|
 | 137 |   BseDev,
 | 
|---|
| [82] | 138 |   Os2Def,
 | 
|---|
 | 139 |   SysUtils,
 | 
|---|
| [187] | 140 |   StringUtilsUnit,
 | 
|---|
 | 141 |   CharUtilsUnit;
 | 
|---|
| [82] | 142 | 
 | 
|---|
| [187] | 143 | imports
 | 
|---|
 | 144 |   FUNCTION _DosQueryFSAttach( VAR pszDeviceName: CSTRING;
 | 
|---|
 | 145 |                               ulOrdinal: ULONG;
 | 
|---|
 | 146 |                               ulFSAInfoLevel:ULONG;
 | 
|---|
 | 147 |                               pfsqb: PFSQBUFFER2;
 | 
|---|
 | 148 |                               VAR pcbBuffLength: ULONG ): APIRET; APIENTRY;
 | 
|---|
 | 149 |   'DOSCALLS' index 277;
 | 
|---|
 | 150 | end;
 | 
|---|
 | 151 | 
 | 
|---|
 | 152 | 
 | 
|---|
 | 153 | type
 | 
|---|
 | 154 |   TWord = Record                    // Bytes of a Word
 | 
|---|
 | 155 |     LoByte, HiByte : Byte;
 | 
|---|
 | 156 |   End;
 | 
|---|
 | 157 | 
 | 
|---|
 | 158 |   TBPB = Array[0..30] Of Byte;    // Puffer fuer BPB-Struktur
 | 
|---|
 | 159 | 
 | 
|---|
 | 160 |   TDeviceParameters = Record
 | 
|---|
 | 161 |     BPB: TBPB;
 | 
|---|
 | 162 |     Cylinders: word;
 | 
|---|
 | 163 |     DeviceType: Byte;
 | 
|---|
 | 164 |     Attributes: Word;
 | 
|---|
 | 165 |   End;
 | 
|---|
 | 166 | 
 | 
|---|
 | 167 | 
 | 
|---|
 | 168 | 
 | 
|---|
| [82] | 169 |   Function AddDirectorySeparator(aDirectory : String) : String;
 | 
|---|
 | 170 |   begin
 | 
|---|
 | 171 |     if aDirectory = '' then
 | 
|---|
 | 172 |     begin
 | 
|---|
| [187] | 173 |       Result:= DIRECTORY_SEPARATOR;
 | 
|---|
| [82] | 174 |       exit;
 | 
|---|
 | 175 |     end;
 | 
|---|
 | 176 | 
 | 
|---|
| [187] | 177 |     if aDirectory[length(aDirectory)] <> DIRECTORY_SEPARATOR then
 | 
|---|
| [82] | 178 |     begin
 | 
|---|
| [187] | 179 |       Result := aDirectory + DIRECTORY_SEPARATOR;
 | 
|---|
| [82] | 180 |       exit;
 | 
|---|
 | 181 |     end;
 | 
|---|
 | 182 | 
 | 
|---|
 | 183 |     Result := aDirectory;
 | 
|---|
 | 184 |   end;
 | 
|---|
 | 185 | 
 | 
|---|
 | 186 | 
 | 
|---|
 | 187 |   Function AddDirectorySeparatorIfNotEmpty(aDirectory: String): String;
 | 
|---|
 | 188 |   begin
 | 
|---|
 | 189 |     if aDirectory = '' then
 | 
|---|
 | 190 |     begin
 | 
|---|
 | 191 |       Result := '';
 | 
|---|
 | 192 |       exit;
 | 
|---|
 | 193 |     end;
 | 
|---|
 | 194 |     Result := AddDirectorySeparator(aDirectory);
 | 
|---|
 | 195 |   end;
 | 
|---|
 | 196 | 
 | 
|---|
 | 197 | 
 | 
|---|
 | 198 |   Function RemoveRightDirectorySeparator(aDirectory : String) : String;
 | 
|---|
 | 199 |   begin
 | 
|---|
| [187] | 200 |     Result := StrTrimRightChars(aDirectory, [DIRECTORY_SEPARATOR]);
 | 
|---|
| [82] | 201 |   end;
 | 
|---|
 | 202 | 
 | 
|---|
 | 203 | 
 | 
|---|
 | 204 |   Function ExpandPath(aBaseDirectory : String; aPath : String): String;
 | 
|---|
 | 205 |   var
 | 
|---|
 | 206 |     tmpDirectory: String;
 | 
|---|
 | 207 |     tmpDirectories : TStringList;
 | 
|---|
 | 208 |     i : integer;
 | 
|---|
 | 209 |   begin
 | 
|---|
 | 210 |     Result:= aBaseDirectory;
 | 
|---|
 | 211 | 
 | 
|---|
 | 212 |     if aPath = '' then
 | 
|---|
 | 213 |     begin
 | 
|---|
| [187] | 214 |       Result := StrTrimRightChars(Result, [DIRECTORY_SEPARATOR]);
 | 
|---|
| [82] | 215 |       exit;
 | 
|---|
 | 216 |     end;
 | 
|---|
 | 217 | 
 | 
|---|
 | 218 |     aPath := trim(aPath);
 | 
|---|
 | 219 |     if Length(aPath) > 1 then
 | 
|---|
 | 220 |     begin
 | 
|---|
 | 221 |       // check for drive spec
 | 
|---|
 | 222 |       if aPath[2] = ':' then
 | 
|---|
 | 223 |       begin
 | 
|---|
 | 224 |         Result := AddDirectorySeparator(aPath);
 | 
|---|
 | 225 |         if Length(aPath) > 3 then
 | 
|---|
 | 226 |         begin
 | 
|---|
| [187] | 227 |           Result := StrTrimRightChars(Result, [DIRECTORY_SEPARATOR]);
 | 
|---|
| [82] | 228 |         end;
 | 
|---|
 | 229 |         exit;
 | 
|---|
 | 230 |       end
 | 
|---|
 | 231 |     end;
 | 
|---|
 | 232 | 
 | 
|---|
 | 233 |     if Length(aPath) > 0 then
 | 
|---|
 | 234 |     begin
 | 
|---|
 | 235 |       // check for root dir spec
 | 
|---|
| [187] | 236 |       if aPath[1] = DIRECTORY_SEPARATOR then
 | 
|---|
| [82] | 237 |       begin
 | 
|---|
 | 238 |         // take just the drive from the basedir
 | 
|---|
 | 239 |         if aBaseDirectory[2] = ':' then
 | 
|---|
 | 240 |         begin
 | 
|---|
 | 241 |           Result := StrLeft(aBaseDirectory, 2);
 | 
|---|
 | 242 |         end
 | 
|---|
 | 243 |         else
 | 
|---|
 | 244 |         begin
 | 
|---|
| [187] | 245 |           Result := DIRECTORY_SEPARATOR;
 | 
|---|
| [82] | 246 |         end;
 | 
|---|
| [187] | 247 |           aPath := StrTrimLeftChars(aPath, [DIRECTORY_SEPARATOR]);
 | 
|---|
| [82] | 248 |       end;
 | 
|---|
 | 249 |     end;
 | 
|---|
 | 250 | 
 | 
|---|
 | 251 |     tmpDirectories := TStringList.Create;
 | 
|---|
| [187] | 252 |     StrExtractStringsIgnoreEmpty(tmpDirectories, aPath, [DIRECTORY_SEPARATOR], #0);
 | 
|---|
| [82] | 253 |     for i := 0 to tmpDirectories.count-1 do
 | 
|---|
 | 254 |     begin
 | 
|---|
 | 255 |       tmpDirectory := tmpDirectories[i];
 | 
|---|
 | 256 |       if tmpDirectory = '..' then
 | 
|---|
 | 257 |       begin
 | 
|---|
 | 258 |         if NOT ((Length(Result) = 2) AND (Result[2] = ':')) then
 | 
|---|
 | 259 |         begin
 | 
|---|
 | 260 |           Result := ParentDir(Result);
 | 
|---|
 | 261 |         end;
 | 
|---|
 | 262 |       end
 | 
|---|
 | 263 |       else if tmpDirectory = '.' then
 | 
|---|
 | 264 |       begin
 | 
|---|
 | 265 |         ; // nothing to do
 | 
|---|
 | 266 |       end
 | 
|---|
 | 267 |       else
 | 
|---|
 | 268 |       begin
 | 
|---|
 | 269 |         Result := AddDirectorySeparator(Result) + tmpDirectory;
 | 
|---|
 | 270 |       end;
 | 
|---|
 | 271 | 
 | 
|---|
 | 272 |       // strip any extra leading slashes
 | 
|---|
| [187] | 273 |       aPath := StrTrimLeftChars(aPath, [DIRECTORY_SEPARATOR]);
 | 
|---|
| [82] | 274 |     end;
 | 
|---|
 | 275 |     tmpDirectories.Destroy;
 | 
|---|
 | 276 | 
 | 
|---|
 | 277 |     if Length(Result) = 2 then
 | 
|---|
 | 278 |     begin
 | 
|---|
 | 279 |       if Result[2] = ':' then
 | 
|---|
 | 280 |       begin
 | 
|---|
 | 281 |         // just a drive spec X:, so add a slash
 | 
|---|
| [187] | 282 |         Result := Result + DIRECTORY_SEPARATOR;
 | 
|---|
| [82] | 283 |       end;
 | 
|---|
 | 284 |     end;
 | 
|---|
 | 285 |   end;
 | 
|---|
 | 286 | 
 | 
|---|
 | 287 |   Function GetLogFilesDir: String;
 | 
|---|
 | 288 |   begin
 | 
|---|
 | 289 |     // ecomstation 1.1 compat
 | 
|---|
 | 290 |     Result := GetEnv('LOGFILES');
 | 
|---|
 | 291 |     if Result <> '' then
 | 
|---|
 | 292 |     begin
 | 
|---|
 | 293 |       Result := AddDirectorySeparator(Result);
 | 
|---|
 | 294 |       exit;
 | 
|---|
 | 295 |     end;
 | 
|---|
 | 296 |     // TODO
 | 
|---|
 | 297 |     Result := AddDirectorySeparator(GetApplicationDir);
 | 
|---|
 | 298 |   end;
 | 
|---|
 | 299 | 
 | 
|---|
 | 300 | 
 | 
|---|
 | 301 |   Function SearchPath(const aPathEnvVar: String;
 | 
|---|
 | 302 |                       const aFilename: String;
 | 
|---|
 | 303 |                       var   aResultFilename: String) : boolean;
 | 
|---|
 | 304 |   var
 | 
|---|
 | 305 |     tmpSzEnvVar : CString;
 | 
|---|
 | 306 |     tmpSzFilename : CString;
 | 
|---|
 | 307 |     tmpSzFilenameFound : CString;
 | 
|---|
 | 308 |     tmpRC: APIRET;
 | 
|---|
 | 309 |   begin
 | 
|---|
 | 310 |     Result := false;
 | 
|---|
 | 311 |     aResultFilename := '';
 | 
|---|
 | 312 | 
 | 
|---|
 | 313 |     tmpSzEnvVar := aPathEnvVar;
 | 
|---|
 | 314 |     tmpSzFilename := aFilename;
 | 
|---|
 | 315 |     tmpRC := DosSearchPath( SEARCH_IGNORENETERRS
 | 
|---|
 | 316 |                             + SEARCH_ENVIRONMENT
 | 
|---|
 | 317 |                             + SEARCH_CUR_DIRECTORY,
 | 
|---|
 | 318 |                             tmpSzEnvVar,
 | 
|---|
 | 319 |                             tmpSzFilename,
 | 
|---|
 | 320 |                             tmpSzFilenameFound,
 | 
|---|
 | 321 |                             sizeof(tmpSzFilenameFound));
 | 
|---|
 | 322 |     if tmpRC = 0 then
 | 
|---|
 | 323 |     begin
 | 
|---|
 | 324 |       Result := true;
 | 
|---|
 | 325 |       aResultFilename := tmpSzFilenameFound;
 | 
|---|
 | 326 |     end;
 | 
|---|
 | 327 |   end;
 | 
|---|
 | 328 | 
 | 
|---|
 | 329 | 
 | 
|---|
 | 330 |   Function SearchHelpPaths(const aFilename: String;
 | 
|---|
 | 331 |                            var   aResultFilename: String;
 | 
|---|
 | 332 |                            const anIncludeAppDir: boolean) : boolean;
 | 
|---|
 | 333 |   begin
 | 
|---|
 | 334 |     Result := SearchPath(HelpPathEnvironmentVar, aFileName, aResultFilename);
 | 
|---|
 | 335 |     if not Result then
 | 
|---|
 | 336 |     begin
 | 
|---|
 | 337 |       Result := SearchPath(BookshelfEnvironmentVar, aFileName, aResultFilename);
 | 
|---|
 | 338 |     end;
 | 
|---|
 | 339 | 
 | 
|---|
 | 340 |     if (not Result) and anIncludeAppDir then
 | 
|---|
 | 341 |     begin
 | 
|---|
 | 342 |       aResultFilename := AddDirectorySeparator(GetApplicationDir) + aFilename;
 | 
|---|
 | 343 |       Result := FileExists(aResultFilename);
 | 
|---|
 | 344 |       if not Result then
 | 
|---|
 | 345 |       begin
 | 
|---|
 | 346 |         aResultFilename := '';
 | 
|---|
 | 347 |       end;
 | 
|---|
 | 348 |     end;
 | 
|---|
 | 349 |   end;
 | 
|---|
 | 350 | 
 | 
|---|
 | 351 | 
 | 
|---|
 | 352 |   Function FindDefaultLanguageHelpFile(const anApplicationName: String; const aLanguage : String) : String;
 | 
|---|
 | 353 |   var
 | 
|---|
 | 354 |     tmpLanguage : String;
 | 
|---|
 | 355 |     tmpLanguageParts : TStringList;
 | 
|---|
 | 356 |     tmpMajorLanguage : String;
 | 
|---|
 | 357 |     tmpMinorLanguage : String;
 | 
|---|
 | 358 |   begin
 | 
|---|
 | 359 |     Result := '';
 | 
|---|
 | 360 | 
 | 
|---|
 | 361 |     tmpLanguage := aLanguage;
 | 
|---|
 | 362 |     if aLanguage = '' then
 | 
|---|
 | 363 |     begin
 | 
|---|
 | 364 |       tmpLanguage := DEFAULT_LANGUAGE;
 | 
|---|
 | 365 |     end;
 | 
|---|
 | 366 | 
 | 
|---|
 | 367 |     tmpLanguageParts := TStringList.Create;
 | 
|---|
 | 368 |     StrExtractStrings(tmpLanguageParts, tmpLanguage, ['_'], #0);
 | 
|---|
 | 369 | 
 | 
|---|
 | 370 |     tmpMajorLanguage := '';
 | 
|---|
 | 371 |     if tmpLanguageParts.count > 0 then
 | 
|---|
 | 372 |     begin
 | 
|---|
 | 373 |       tmpMajorLanguage := tmpLanguageParts[0];
 | 
|---|
 | 374 |     end;
 | 
|---|
 | 375 | 
 | 
|---|
 | 376 |     tmpMinorLanguage := '';
 | 
|---|
 | 377 |     if tmpLanguageParts.count > 1 then
 | 
|---|
 | 378 |     begin
 | 
|---|
 | 379 |       tmpMinorLanguage := tmpMinorLanguage[1];
 | 
|---|
 | 380 |     end;
 | 
|---|
 | 381 | 
 | 
|---|
 | 382 |     tmpLanguageParts.Destroy;
 | 
|---|
 | 383 | 
 | 
|---|
 | 384 |     // note there might be some other stuff on the end of LANG
 | 
|---|
 | 385 |     // such as ES_ES_EURO...
 | 
|---|
 | 386 |     if tmpMinorLanguage <> '' then
 | 
|---|
 | 387 |     begin
 | 
|---|
 | 388 |       if SearchHelpPaths( anApplicationName
 | 
|---|
 | 389 |                           + '_' + tmpMajorLanguage
 | 
|---|
 | 390 |                           + '_' + tmpMinorLanguage
 | 
|---|
 | 391 |                           + HELP_FILE_EXTENSION,
 | 
|---|
 | 392 |                           Result,
 | 
|---|
 | 393 |                           true ) then
 | 
|---|
 | 394 |       begin
 | 
|---|
 | 395 |         // found a specifc language
 | 
|---|
 | 396 |         exit;
 | 
|---|
 | 397 |       end;
 | 
|---|
 | 398 |     end;
 | 
|---|
 | 399 | 
 | 
|---|
 | 400 |     // try generic language?
 | 
|---|
 | 401 |     if SearchHelpPaths( anApplicationName
 | 
|---|
 | 402 |                         + '_' + tmpMajorLanguage
 | 
|---|
 | 403 |                         + HELP_FILE_EXTENSION,
 | 
|---|
 | 404 |                         Result,
 | 
|---|
 | 405 |                         true ) then
 | 
|---|
 | 406 |     begin
 | 
|---|
 | 407 |       exit;
 | 
|---|
 | 408 |     end;
 | 
|---|
 | 409 | 
 | 
|---|
 | 410 |     // nothing specific, search for default
 | 
|---|
 | 411 |     SearchHelpPaths(anApplicationName + HELP_FILE_EXTENSION, Result, true);
 | 
|---|
 | 412 |   end;
 | 
|---|
 | 413 | 
 | 
|---|
 | 414 | 
 | 
|---|
 | 415 |   Procedure GetDirsInPath(const aPathEnvVar: String; var aList: TStrings);
 | 
|---|
 | 416 |   var
 | 
|---|
 | 417 |     tmpRC : APIRET;
 | 
|---|
 | 418 |     tmpPszPathEnvVar : PChar;
 | 
|---|
 | 419 |     tmpSzEnvVar : CString;
 | 
|---|
 | 420 |   begin
 | 
|---|
 | 421 |     // do this in any case also if there is an error
 | 
|---|
 | 422 |     // to garantie a defined behavior
 | 
|---|
 | 423 |     aList.Clear;
 | 
|---|
 | 424 | 
 | 
|---|
 | 425 |     tmpSzEnvVar := aPathEnvVar;
 | 
|---|
 | 426 |     tmpRC := DosScanEnv(tmpSzEnvVar, tmpPszPathEnvVar);
 | 
|---|
 | 427 | 
 | 
|---|
 | 428 |     if tmpRC <> 0 then
 | 
|---|
 | 429 |     begin
 | 
|---|
 | 430 |       exit;
 | 
|---|
 | 431 |     end;
 | 
|---|
 | 432 | 
 | 
|---|
 | 433 |     StrExtractStringsIgnoreEmpty(aList, StrPas(tmpPszPathEnvVar), [PATH_SEPARATOR], #0);
 | 
|---|
 | 434 |   end;
 | 
|---|
 | 435 | 
 | 
|---|
 | 436 | 
 | 
|---|
| [187] | 437 |   Procedure GetFilesInPath(     const aPathEnvVar: String;
 | 
|---|
 | 438 |                                 const aFilter: String;
 | 
|---|
 | 439 |                                 var aList: TStrings );
 | 
|---|
 | 440 |   var
 | 
|---|
 | 441 |     tmpDirectories : TStringList;
 | 
|---|
 | 442 |     i : integer;
 | 
|---|
 | 443 |   begin
 | 
|---|
 | 444 |     tmpDirectories := TStringList.Create;
 | 
|---|
 | 445 |     GetDirsInPath(aPathEnvVar, tmpDirectories);
 | 
|---|
 | 446 | 
 | 
|---|
 | 447 |     for i:=0 to tmpDirectories.count-1 do
 | 
|---|
 | 448 |     begin
 | 
|---|
 | 449 |       ListFilesInDirectory(tmpDirectories[i], aFilter, false, aList);
 | 
|---|
 | 450 |     end;
 | 
|---|
 | 451 | 
 | 
|---|
 | 452 |     tmpDirectories.Destroy;
 | 
|---|
 | 453 |   end;
 | 
|---|
 | 454 | 
 | 
|---|
 | 455 | 
 | 
|---|
| [97] | 456 |   Procedure ListFilesInDirectory(       const aDirectory: String;
 | 
|---|
 | 457 |                                         const aFilter: String;
 | 
|---|
 | 458 |                                         const aWithDirectoryFlag: boolean;
 | 
|---|
 | 459 |                                         var aList: TStrings);
 | 
|---|
| [82] | 460 |   var
 | 
|---|
 | 461 |     tmpRC : APIRET;
 | 
|---|
 | 462 |     tmpSearchResults: TSearchRec;
 | 
|---|
 | 463 |     tmpMask: String;
 | 
|---|
 | 464 |     tmpFilterParts : TStringList;
 | 
|---|
| [97] | 465 |     tmpDirectory : String;
 | 
|---|
| [82] | 466 |     i : integer;
 | 
|---|
 | 467 |   begin
 | 
|---|
 | 468 |     tmpFilterParts := TStringList.Create;
 | 
|---|
 | 469 |     StrExtractStrings(tmpFilterParts, aFilter, [PATH_SEPARATOR], #0);
 | 
|---|
 | 470 | 
 | 
|---|
 | 471 |     for i:=0 to tmpFilterParts.count-1 do
 | 
|---|
 | 472 |     begin
 | 
|---|
 | 473 |       tmpMask := tmpFilterParts[i];
 | 
|---|
| [97] | 474 |       tmpDirectory := AddDirectorySeparator(aDirectory);
 | 
|---|
 | 475 |       tmpRC := FindFirst(tmpDirectory + tmpMask, faAnyFile, tmpSearchResults);
 | 
|---|
| [82] | 476 | 
 | 
|---|
 | 477 |       while tmpRC = 0 do
 | 
|---|
 | 478 |       begin
 | 
|---|
 | 479 |         if tmpSearchResults.Attr And faDirectory = 0 then
 | 
|---|
 | 480 |         begin
 | 
|---|
| [97] | 481 |           if (aWithDirectoryFlag) then
 | 
|---|
 | 482 |           begin
 | 
|---|
 | 483 |             aList.Add(tmpDirectory + tmpSearchResults.Name);
 | 
|---|
 | 484 |           end
 | 
|---|
 | 485 |           else
 | 
|---|
 | 486 |           begin
 | 
|---|
 | 487 |             aList.Add(tmpSearchResults.Name);
 | 
|---|
 | 488 |           end;
 | 
|---|
| [82] | 489 |         end;
 | 
|---|
 | 490 | 
 | 
|---|
 | 491 |         tmpRC := FindNext(tmpSearchResults);
 | 
|---|
 | 492 |       end;
 | 
|---|
 | 493 | 
 | 
|---|
 | 494 |       FindClose(tmpSearchResults);
 | 
|---|
 | 495 |     end;
 | 
|---|
 | 496 |     tmpFilterParts.Destroy;
 | 
|---|
 | 497 |   end;
 | 
|---|
 | 498 | 
 | 
|---|
 | 499 | 
 | 
|---|
 | 500 |   Procedure ListSubDirectories(const aDirectory: String; var aList: TStrings);
 | 
|---|
 | 501 |   var
 | 
|---|
 | 502 |     tmpRC : APIRET;
 | 
|---|
 | 503 |     tmpSearchResults: TSearchRec;
 | 
|---|
 | 504 |     tmpName : String;
 | 
|---|
 | 505 |   begin
 | 
|---|
 | 506 | 
 | 
|---|
 | 507 |     tmpRC := FindFirst(AddDirectorySeparator(aDirectory) + '*', faDirectory or faMustDirectory, tmpSearchResults);
 | 
|---|
 | 508 |     if (tmpRC <> 0) then
 | 
|---|
 | 509 |     begin
 | 
|---|
 | 510 |       exit;
 | 
|---|
 | 511 |     end;
 | 
|---|
 | 512 | 
 | 
|---|
 | 513 |     while tmpRC = 0 do
 | 
|---|
 | 514 |     begin
 | 
|---|
 | 515 |       tmpName := tmpSearchResults.Name;
 | 
|---|
 | 516 |       if (tmpName <> '.') AND (tmpName <> '..') then
 | 
|---|
 | 517 |       begin
 | 
|---|
 | 518 |         aList.Add(AddDirectorySeparatorIfNotEmpty(aDirectory) + tmpSearchResults.Name );
 | 
|---|
 | 519 |       end;
 | 
|---|
 | 520 |       tmpRC := FindNext(tmpSearchResults);
 | 
|---|
 | 521 |     end;
 | 
|---|
 | 522 |     FindClose(tmpSearchResults);
 | 
|---|
 | 523 |   end;
 | 
|---|
 | 524 | 
 | 
|---|
 | 525 | 
 | 
|---|
 | 526 |   Procedure ListFilesInDirectoryRecursiveWithTermination(const aDirectory : String;
 | 
|---|
 | 527 |                                                          const aFilter : String;
 | 
|---|
| [97] | 528 |                                                          const aWithDirectoryFlag : boolean;
 | 
|---|
| [82] | 529 |                                                          var aList : TStrings;
 | 
|---|
 | 530 |                                                          const aTerminateCheck : TTerminateCheck;
 | 
|---|
 | 531 |                                                          const aUseTerminateCheck : boolean);
 | 
|---|
 | 532 |   var
 | 
|---|
 | 533 |     i : integer;
 | 
|---|
 | 534 |     tmpSubDirectories : TStringList;
 | 
|---|
 | 535 |     tmpSubDirectory : String;
 | 
|---|
 | 536 |   begin
 | 
|---|
 | 537 |     // at first add all files from the directory itself
 | 
|---|
| [97] | 538 |     ListFilesInDirectory(aDirectory, aFilter, aWithDirectoryFlag, aList);
 | 
|---|
| [82] | 539 | 
 | 
|---|
 | 540 |     // now determine all subdirectories
 | 
|---|
 | 541 |     tmpSubDirectories := TStringList.Create;
 | 
|---|
 | 542 |     ListSubDirectories(aDirectory, tmpSubDirectories);
 | 
|---|
 | 543 | 
 | 
|---|
 | 544 |     for i := 0 to tmpSubDirectories.Count - 1 do
 | 
|---|
 | 545 |     begin
 | 
|---|
 | 546 |       // if Assigned( TerminateCheck ) then - doesn't work in sibyl
 | 
|---|
 | 547 |       if aUseTerminateCheck then
 | 
|---|
 | 548 |         if aTerminateCheck then
 | 
|---|
 | 549 |           break;
 | 
|---|
 | 550 | 
 | 
|---|
 | 551 |       tmpSubDirectory := tmpSubDirectories[i];
 | 
|---|
 | 552 | 
 | 
|---|
| [97] | 553 |       ListFilesInDirectoryRecursiveWithTermination(tmpSubDirectory, aFilter, aWithDirectoryFlag, aList, aTerminateCheck, aUseTerminateCheck);
 | 
|---|
| [82] | 554 |     end;
 | 
|---|
 | 555 |     tmpSubDirectories.Destroy;
 | 
|---|
 | 556 |   end;
 | 
|---|
 | 557 | 
 | 
|---|
 | 558 | 
 | 
|---|
 | 559 |   Function ParentDir(const aDirectory : String) : String;
 | 
|---|
 | 560 |   var
 | 
|---|
 | 561 |     tmpPos: integer;
 | 
|---|
 | 562 |   begin
 | 
|---|
 | 563 |     tmpPos := Length(aDirectory);
 | 
|---|
 | 564 | 
 | 
|---|
 | 565 |     // ends with slash
 | 
|---|
| [187] | 566 |     while (aDirectory[tmpPos] = DIRECTORY_SEPARATOR) AND (tmpPos > 0) do
 | 
|---|
| [82] | 567 |     begin
 | 
|---|
 | 568 |       dec(tmpPos);
 | 
|---|
 | 569 |     end;
 | 
|---|
 | 570 | 
 | 
|---|
 | 571 |     // find slash
 | 
|---|
| [187] | 572 |     while (aDirectory[tmpPos] <> DIRECTORY_SEPARATOR) AND (tmpPos > 0) do
 | 
|---|
| [82] | 573 |     begin
 | 
|---|
 | 574 |       dec(tmpPos);
 | 
|---|
 | 575 |     end;
 | 
|---|
 | 576 | 
 | 
|---|
 | 577 |     result:= StrLeft(aDirectory, tmpPos-1);
 | 
|---|
 | 578 |   end;
 | 
|---|
 | 579 | 
 | 
|---|
 | 580 | 
 | 
|---|
| [187] | 581 |   Function MakeDirs(const aFullDirectoryPath: String) : String;
 | 
|---|
 | 582 |   Var
 | 
|---|
 | 583 |     tmpDirectoryParts : TStringList;
 | 
|---|
 | 584 |     tmpDirectoryPart : String;
 | 
|---|
 | 585 |     tmpCompletePart : String;
 | 
|---|
 | 586 |     i : integer;
 | 
|---|
 | 587 |   begin
 | 
|---|
 | 588 |     tmpDirectoryParts := TStringList.Create;
 | 
|---|
 | 589 |     StrExtractStringsIgnoreEmpty(tmpDirectoryParts, aFullDirectoryPath, [DIRECTORY_SEPARATOR], #0);
 | 
|---|
 | 590 | 
 | 
|---|
 | 591 |     tmpCompletePart := '';
 | 
|---|
 | 592 |     for i:=0 to tmpDirectoryParts.count-1 do
 | 
|---|
 | 593 |     begin
 | 
|---|
 | 594 |       tmpDirectoryPart := trim(tmpDirectoryParts[i]);
 | 
|---|
 | 595 | 
 | 
|---|
 | 596 |       if tmpDirectoryPart <> '' then
 | 
|---|
 | 597 |       begin
 | 
|---|
 | 598 |         tmpCompletePart := AddDirectorySeparatorIfNotEmpty(tmpCompletePart) + tmpDirectoryPart;
 | 
|---|
 | 599 | 
 | 
|---|
 | 600 |         if not DirectoryExists(tmpCompletePart) then
 | 
|---|
 | 601 |         begin
 | 
|---|
 | 602 |           MkDir(tmpCompletePart);
 | 
|---|
 | 603 |         end;
 | 
|---|
 | 604 |       end;
 | 
|---|
 | 605 |     end;
 | 
|---|
 | 606 | 
 | 
|---|
 | 607 |     Result := tmpCompletePart;
 | 
|---|
 | 608 |   end;
 | 
|---|
 | 609 | 
 | 
|---|
 | 610 | 
 | 
|---|
| [82] | 611 |   Function DirectoryExists(const aDirectory : String) : boolean;
 | 
|---|
 | 612 |   Var
 | 
|---|
 | 613 |     tmpRC : APIRET;
 | 
|---|
 | 614 |     tmpSearchResults : TSearchRec;
 | 
|---|
 | 615 |     tmpDriveMap : ULONG;
 | 
|---|
 | 616 |     tmpActualDrive : ULONG;
 | 
|---|
 | 617 |     tmpDrive : Char;
 | 
|---|
 | 618 |     tmpDriveNum : integer;
 | 
|---|
 | 619 |     tmpDriveBit : longword;
 | 
|---|
 | 620 |     tmpDirectory : String;
 | 
|---|
 | 621 |   Begin
 | 
|---|
 | 622 |     Result := false;
 | 
|---|
 | 623 |     tmpDirectory := RemoveRightDirectorySeparator(aDirectory);
 | 
|---|
 | 624 |     if tmpDirectory = '' then
 | 
|---|
 | 625 |     begin
 | 
|---|
 | 626 |       Result:= true;
 | 
|---|
 | 627 |       exit;
 | 
|---|
 | 628 |     end;
 | 
|---|
 | 629 | 
 | 
|---|
 | 630 |     if Length(tmpDirectory) = 2 then
 | 
|---|
 | 631 |     begin
 | 
|---|
 | 632 |       if tmpDirectory[2] = ':' then
 | 
|---|
 | 633 |       begin
 | 
|---|
 | 634 |         // a drive only has been specified
 | 
|---|
 | 635 |         tmpDrive:= UpCase(tmpDirectory[1] );
 | 
|---|
 | 636 |         if (tmpDrive < 'A') or (tmpDrive > 'Z') then
 | 
|---|
 | 637 |         begin
 | 
|---|
 | 638 |           // invalid drive; return false;
 | 
|---|
 | 639 |           exit;
 | 
|---|
 | 640 |         end;
 | 
|---|
 | 641 | 
 | 
|---|
 | 642 |         DosQueryCurrentDisk(tmpActualDrive, tmpDriveMap);
 | 
|---|
 | 643 |         tmpDriveNum := Ord(tmpDrive) - Ord('A') + 1; // A -> 1, B -> 2...
 | 
|---|
 | 644 |         tmpDriveBit := 1 shl (tmpDriveNum-1); // 2^DriveNum
 | 
|---|
 | 645 | 
 | 
|---|
 | 646 |         Result := tmpDriveMap and (tmpDriveBit) > 0;
 | 
|---|
 | 647 |         exit;
 | 
|---|
 | 648 |       end;
 | 
|---|
 | 649 |     end;
 | 
|---|
 | 650 | 
 | 
|---|
 | 651 |     tmpRC := FindFirst(tmpDirectory, faDirectory or faMustDirectory, tmpSearchResults);
 | 
|---|
 | 652 |     if tmpRC = 0 then
 | 
|---|
 | 653 |     begin
 | 
|---|
 | 654 |       Result:= true;
 | 
|---|
 | 655 |       FindClose(tmpSearchResults);
 | 
|---|
 | 656 |     end;
 | 
|---|
 | 657 |   end;
 | 
|---|
 | 658 | 
 | 
|---|
 | 659 | 
 | 
|---|
| [187] | 660 |   Function DriveLetterToDriveNumber(const aDriveLetter : char) : longint;
 | 
|---|
 | 661 |   begin
 | 
|---|
 | 662 |     if     (aDriveLetter >= 'a')
 | 
|---|
 | 663 |        and (aDriveLetter <= 'z') then
 | 
|---|
 | 664 |     begin
 | 
|---|
 | 665 |       Result := Ord(aDriveLetter) - Ord('a') + 1;
 | 
|---|
 | 666 |       exit;
 | 
|---|
 | 667 |     end;
 | 
|---|
 | 668 | 
 | 
|---|
 | 669 |     if     (aDriveLetter >= 'A')
 | 
|---|
 | 670 |        and (aDriveLetter <= 'Z') then
 | 
|---|
 | 671 |     begin
 | 
|---|
 | 672 |       Result := Ord(aDriveLetter) - Ord('A') + 1;
 | 
|---|
 | 673 |       exit;
 | 
|---|
 | 674 |     end;
 | 
|---|
 | 675 | 
 | 
|---|
 | 676 |     // not a valid drive letter
 | 
|---|
 | 677 |     Result := 0;
 | 
|---|
 | 678 |   end;
 | 
|---|
 | 679 | 
 | 
|---|
 | 680 | 
 | 
|---|
 | 681 |   Function DriveNumberToDriveLetter(const aDriveNumber: longint) : char;
 | 
|---|
 | 682 |   begin
 | 
|---|
 | 683 |     Result := Chr(aDriveNumber - 1 + Ord('A'));
 | 
|---|
 | 684 |   end;
 | 
|---|
 | 685 | 
 | 
|---|
 | 686 | 
 | 
|---|
 | 687 |   Function GetVolumeLabel(aDrive: char) : String;
 | 
|---|
 | 688 |   var
 | 
|---|
 | 689 |     tmpRC : APIRET;
 | 
|---|
 | 690 |     tmpFileSystemInfo : FSINFO;
 | 
|---|
 | 691 |     e : EInOutError;
 | 
|---|
 | 692 |   begin
 | 
|---|
 | 693 |     DosErrorAPI( FERR_DISABLEHARDERR );
 | 
|---|
 | 694 |     Result := '';
 | 
|---|
 | 695 |     tmpRC := DosQueryFSInfo( DriveLetterToDriveNumber(aDrive),
 | 
|---|
 | 696 |                              FSIL_VOLSER,
 | 
|---|
 | 697 |                              tmpFileSystemInfo,
 | 
|---|
 | 698 |                              sizeof(tmpFileSystemInfo));
 | 
|---|
 | 699 |     if tmpRC = 0 then
 | 
|---|
 | 700 |     begin
 | 
|---|
 | 701 |       Result := StrPasWithLength(Addr(tmpFileSystemInfo.vol.szVolLabel), tmpFileSystemInfo.vol.cch);
 | 
|---|
 | 702 |       Result := LowerCase(Result);
 | 
|---|
 | 703 |     end;
 | 
|---|
 | 704 |     DosErrorAPI( FERR_ENABLEHARDERR );
 | 
|---|
 | 705 | 
 | 
|---|
 | 706 |     if tmpRC <> 0 then
 | 
|---|
 | 707 |     begin
 | 
|---|
 | 708 |       e := EInOutError.Create( 'Cannot read drive ' + aDrive + ':');
 | 
|---|
 | 709 |       e.ErrorCode := tmpRC;
 | 
|---|
 | 710 |       raise e;
 | 
|---|
 | 711 |     end;
 | 
|---|
 | 712 |   end;
 | 
|---|
 | 713 | 
 | 
|---|
 | 714 | 
 | 
|---|
 | 715 |   Function GetBootDriveLetter: char;
 | 
|---|
 | 716 |   var
 | 
|---|
 | 717 |     tmpBuffer: longword;
 | 
|---|
 | 718 |   begin
 | 
|---|
 | 719 |     DosQuerySysInfo( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, tmpBuffer, sizeof(tmpBuffer));
 | 
|---|
 | 720 |     Result := Chr(ord('A') + tmpBuffer - 1);
 | 
|---|
 | 721 |   end;
 | 
|---|
 | 722 | 
 | 
|---|
 | 723 | 
 | 
|---|
 | 724 |   Function FileIsReadOnly(const aFilename : String ) : boolean;
 | 
|---|
 | 725 |   begin
 | 
|---|
 | 726 |     Result :=(FileGetAttr(aFilename) AND faReadonly) > 0;
 | 
|---|
 | 727 |   end;
 | 
|---|
 | 728 | 
 | 
|---|
 | 729 | 
 | 
|---|
 | 730 | 
 | 
|---|
 | 731 | 
 | 
|---|
 | 732 |   // TODO
 | 
|---|
 | 733 | 
 | 
|---|
 | 734 | 
 | 
|---|
 | 735 | Function IsFloppyDrive( DriveNumber: longint ): Boolean;
 | 
|---|
 | 736 | Var
 | 
|---|
 | 737 |   bResult : Byte;
 | 
|---|
 | 738 | Begin
 | 
|---|
 | 739 |   DosDevConfig( bResult, DEVINFO_FLOPPY );
 | 
|---|
 | 740 |   Result := ( Abs( DriveNumber ) <= bResult);
 | 
|---|
 | 741 | End;
 | 
|---|
 | 742 | 
 | 
|---|
 | 743 | // -------------------------------------------------------------------------
 | 
|---|
 | 744 | // Funktion/Function: QueryCDRoms()
 | 
|---|
 | 745 | //
 | 
|---|
 | 746 | // Beschreibung:
 | 
|---|
 | 747 | //   Die Funktion QueryCDRom ermittelt ueber eine nicht dokumentierte
 | 
|---|
 | 748 | //   Schnittstelle die Anzahl der CDRom-Laufwerke und den ersten, fuer
 | 
|---|
 | 749 | //   ein CDRom-Laufwerk, vergebenen UnitIdentifier.
 | 
|---|
 | 750 | //   Der Treiber OS2CDROM.DMD stellt dem System zwei Devices (CD-ROM1$
 | 
|---|
 | 751 | //   und CD-ROM2$) zur Verfuegung. Die beiden Devices unterscheiden sich
 | 
|---|
 | 752 | //   durch DeviceAttribute. Beide Devices unterstuetzen (zumindest unter
 | 
|---|
 | 753 | //   Warp) den undokumentierten Generic IOCtl 0x82/0x60, welcher Infor-
 | 
|---|
 | 754 | //   mationen ueber die angeschlossenen CDRom-Laufwerke liefert.
 | 
|---|
 | 755 | //
 | 
|---|
 | 756 | // Description:
 | 
|---|
 | 757 | //   This Functions finds out how many CD-Rom Drives are present in System
 | 
|---|
 | 758 | //   and which Drive Letter is the first occupied by a CD-Rom. It uses an
 | 
|---|
 | 759 | //   undocumented Interface to OS2CDROM.DMD.
 | 
|---|
 | 760 | //   OS2CDROM.DMD presents two Devices (CD-ROM1$ and CD-ROM2$). These De-
 | 
|---|
 | 761 | //   vices are distinguished by their Device-Attributes. Both Devices sup-
 | 
|---|
 | 762 | //   port (under Warp) the undocumented generic IOCtl-Call 0x82/0x60 which
 | 
|---|
 | 763 | //   deliver some Information about the connected CD-Rom Drives.
 | 
|---|
 | 764 | //
 | 
|---|
 | 765 | // Parameter:
 | 
|---|
 | 766 | //   Var ulCDRomCount        ULONG     Anzahl CD-Rom Laufwerke im System
 | 
|---|
 | 767 | //                                     Number of CD-Rom Drives in System
 | 
|---|
 | 768 | //
 | 
|---|
 | 769 | //   Var ulFirstCDRomDiskNo  ULONG     erste Laufwerksnummer, die an ein
 | 
|---|
 | 770 | //                                     CD-Rom vergeben ist
 | 
|---|
 | 771 | //                                     first Drive-Letter occupied by a
 | 
|---|
 | 772 | //                                     CD-Rom Drive
 | 
|---|
 | 773 | //
 | 
|---|
 | 774 | // Rueckgabe/Returnvalue:  keine/none
 | 
|---|
 | 775 | // -------------------------------------------------------------------------
 | 
|---|
 | 776 | Procedure QueryCDRoms(Var ulCDRomCount, ulFirstCDRomDiskNo: ULONG);
 | 
|---|
 | 777 |  
 | 
|---|
 | 778 | Const cszDriverName : CSTRING = 'CD-ROM?$';
 | 
|---|
 | 779 |  
 | 
|---|
 | 780 | Var cCurDriver : Char;                    // Indexvariable fuer aktuell bearbeites Device (1 oder 2)
 | 
|---|
 | 781 |                                           // Index for current Device (1 or 2)
 | 
|---|
 | 782 | 
 | 
|---|
 | 783 |     hDevHandle : HFILE;                   // Handle fuer Device
 | 
|---|
 | 784 |                                           // Device handle
 | 
|---|
 | 785 | 
 | 
|---|
 | 786 |     ulAction   : ULONG;                   // Aktionscode (DosOpen())
 | 
|---|
 | 787 |                                           // Actioncode (DosOpen())
 | 
|---|
 | 788 |                                           
 | 
|---|
 | 789 |     ulParams   : ULONG;                   // Anzahl Bytes von IOCtl gelieferter Parameterdaten
 | 
|---|
 | 790 |                                           // Number of Bytes for delivered Parameterdata
 | 
|---|
 | 791 |                                           
 | 
|---|
 | 792 |     ulData     : ULONG;                   // Anzahl Bytes von IOCtl gelieferter Daten
 | 
|---|
 | 793 |                                           // Number of Bytes delivered by IOCtl
 | 
|---|
 | 794 |                                           
 | 
|---|
 | 795 |     rCDInfo    : Record                   // Ergebnisstruktur der IOCtl-Funktion (s.o.)
 | 
|---|
 | 796 |                                           // Record for Results of IOCtl-Call (see above)
 | 
|---|
 | 797 |                    usCDRomCount : USHORT; // Anzahl CD-Roms                   / Number of CD-Rom Drives
 | 
|---|
 | 798 |                    usFirstUnitNo: USHORT; // erste vergebene Laufwerksnummer  / first Driver Letter
 | 
|---|
 | 799 |                  End;
 | 
|---|
 | 800 | 
 | 
|---|
 | 801 | Begin (* uQueryCDRom *)
 | 
|---|
 | 802 |                                        /************************************
 | 
|---|
 | 803 |                                         * Vorbelegungen
 | 
|---|
 | 804 |                                         *
 | 
|---|
 | 805 |                                         * initial assignments
 | 
|---|
 | 806 |                                         ************************************/
 | 
|---|
 | 807 |   ulCDRomCount := 0;
 | 
|---|
 | 808 |   ulFirstCDRomDiskNo := 0;
 | 
|---|
 | 809 | 
 | 
|---|
 | 810 |   ulParams := 0;
 | 
|---|
 | 811 | 
 | 
|---|
 | 812 |                                        /************************************
 | 
|---|
 | 813 |                                         * die beiden Devices abarbeiten
 | 
|---|
 | 814 |                                         *
 | 
|---|
 | 815 |                                         * accessing both Devices
 | 
|---|
 | 816 |                                         ************************************/
 | 
|---|
 | 817 |   For cCurDriver := '1' To '2' Do
 | 
|---|
 | 818 |     Begin
 | 
|---|
 | 819 |                                        /************************************
 | 
|---|
 | 820 |                                         * Device oeffnen
 | 
|---|
 | 821 |                                         *
 | 
|---|
 | 822 |                                         * open Device
 | 
|---|
 | 823 |                                         ************************************/
 | 
|---|
 | 824 |       cszDriverName[6] := cCurDriver;
 | 
|---|
 | 825 |       If (DosOpen(cszDriverName,              // Devicename
 | 
|---|
 | 826 |                   hDevHandle,                 // Handle
 | 
|---|
 | 827 |                   ulAction,                   // Aktionscode
 | 
|---|
 | 828 |                   0,                          // Dateigráe
 | 
|---|
 | 829 |                   FILE_NORMAL,                // Attribute: read/write
 | 
|---|
 | 830 |                   OPEN_ACTION_OPEN_IF_EXISTS, // OpenFlag: ffnen, wenn vorhanden
 | 
|---|
 | 831 |                   OPEN_FLAGS_FAIL_ON_ERROR Or // Modus: Fehlermeldung per Returncode
 | 
|---|
 | 832 |                     OPEN_SHARE_DENYNONE Or    //        keine Einschrnkungen fr Dritte
 | 
|---|
 | 833 |                     OPEN_ACCESS_READONLY,     //        nur lesender Zugriff
 | 
|---|
 | 834 |                   NIL)=NO_ERROR) Then         // keine EA
 | 
|---|
 | 835 |         Begin
 | 
|---|
 | 836 |                                        /************************************
 | 
|---|
 | 837 |                                         * IOCtl-Funktion aufrufen
 | 
|---|
 | 838 |                                         *
 | 
|---|
 | 839 |                                         * Call to IOCtl
 | 
|---|
 | 840 |                                         ************************************/
 | 
|---|
 | 841 |           If (DosDevIOCtl(hDevHandle,             // Handle                 / Handle
 | 
|---|
 | 842 |                           $82,                    // Kategorie              / Category
 | 
|---|
 | 843 |                           $60,                    // Funktion               / Function
 | 
|---|
 | 844 |                           NIL,                    // keine Parameterliste   / No Parameterlist
 | 
|---|
 | 845 |                           0,                      // Laenge Parameterliste  / Length of Parameterlist
 | 
|---|
 | 846 |                           ulParams,               // Groesse der gelieferten Parameterdaten
 | 
|---|
 | 847 |                                                   //                        / Number of Bytes for Parameterdata
 | 
|---|
 | 848 |                           rCDInfo,                // Puffer fuer gelieferte Daten
 | 
|---|
 | 849 |                                                   //                        / Buffer for returned Data
 | 
|---|
 | 850 |                           SizeOf(rCDInfo),        // Groesse des Datenpuffers
 | 
|---|
 | 851 |                                                   //                        / Size of Databuffer
 | 
|---|
 | 852 |                           ulData)=NO_ERROR) Then  // Groesse der gelieferten Daten
 | 
|---|
 | 853 |                                                   //                        / Number of Bytes for returned Data
 | 
|---|
 | 854 |             Begin
 | 
|---|
 | 855 |               ulCDRomCount := rCDInfo.usCDRomCount;
 | 
|---|
 | 856 |               ulFirstCDRomDiskNo := Succ(rCDInfo.usFirstUnitNo);
 | 
|---|
 | 857 |             End;
 | 
|---|
 | 858 | 
 | 
|---|
 | 859 |           DosClose(hDevHandle);
 | 
|---|
 | 860 |         End;
 | 
|---|
 | 861 | 
 | 
|---|
 | 862 |    End; (* For *)
 | 
|---|
 | 863 | 
 | 
|---|
 | 864 | End; (* uQueryCDRom *)
 | 
|---|
 | 865 | 
 | 
|---|
 | 866 | 
 | 
|---|
 | 867 | Function GetLocalDriveType( DriveNumber: longint ): TDriveType;
 | 
|---|
 | 868 | var
 | 
|---|
 | 869 |   IOCtlParameters: Word;
 | 
|---|
 | 870 |   rc: APIRET;
 | 
|---|
 | 871 |   ParameterLength: longWord;
 | 
|---|
 | 872 |   DataLength: longword;
 | 
|---|
 | 873 |   DeviceData: TDeviceParameters;
 | 
|---|
 | 874 |   Fixed: boolean;
 | 
|---|
 | 875 |   FirstCDDrive: ULONG;
 | 
|---|
 | 876 |   NumCDDrives: ULONG;
 | 
|---|
 | 877 | begin
 | 
|---|
 | 878 | 
 | 
|---|
 | 879 |   TWord( IOCtlParameters ).LoByte := 0;  // BPB of physical Device
 | 
|---|
 | 880 |   TWord( IOCtlParameters ).HiByte := DriveNumber - 1; // drive number, zero base
 | 
|---|
 | 881 | 
 | 
|---|
 | 882 |   ParameterLength := SizeOf( IOCtlParameters ); // input length of parameters
 | 
|---|
 | 883 |   DataLength := 0;                              // input length of data (none)
 | 
|---|
 | 884 | 
 | 
|---|
 | 885 |   rc := DosDevIOCTL( HFILE(-1),                 // Open Device (not a file)
 | 
|---|
 | 886 |                      IOCTL_DISK,                // Category
 | 
|---|
 | 887 |                      DSK_GETDEVICEPARAMS,       // Function
 | 
|---|
 | 888 |                      IOCtlParameters,           // Parameters
 | 
|---|
 | 889 |                      SizeOf( IOCtlParameters ), // (max) size of parameters
 | 
|---|
 | 890 |                      ParameterLength,           // parameters length
 | 
|---|
 | 891 |                      DeviceData,                // results
 | 
|---|
 | 892 |                      SizeOf( DeviceData ),      // (max) size of data block
 | 
|---|
 | 893 |                      DataLength );              // data block length
 | 
|---|
 | 894 | 
 | 
|---|
 | 895 |   Fixed := ( DeviceData.Attributes and 1 ) > 0;    // bit 0 indicates fixed (1) or removable (0)
 | 
|---|
 | 896 |   if not Fixed then
 | 
|---|
 | 897 |   begin
 | 
|---|
 | 898 |     result := dtRemovable;
 | 
|---|
 | 899 | 
 | 
|---|
 | 900 |     QueryCDRoms( FirstCDDrive,
 | 
|---|
 | 901 |                  NumCDDrives );
 | 
|---|
 | 902 | 
 | 
|---|
 | 903 |     if     ( DriveNumber >= FirstCDDrive )
 | 
|---|
 | 904 |        and ( DriveNumber < FirstCDDrive + NumCDDrives ) then
 | 
|---|
 | 905 |       result := dtCD;
 | 
|---|
 | 906 | 
 | 
|---|
 | 907 |     exit;
 | 
|---|
 | 908 |   end;
 | 
|---|
 | 909 | 
 | 
|---|
 | 910 |   result := dtHard;
 | 
|---|
 | 911 | end;
 | 
|---|
 | 912 | 
 | 
|---|
 | 913 | // Takes a one-based drive number
 | 
|---|
 | 914 | Function GetDriveType( DriveNumber: longint ): TDriveType;
 | 
|---|
 | 915 | var
 | 
|---|
 | 916 |   szDrive: CString;
 | 
|---|
 | 917 | 
 | 
|---|
 | 918 |   FSData: array[ 0..sizeof( FSQBuffer) + 3*_MAX_PATH ] of char;
 | 
|---|
 | 919 |   pBuffer: PFSQBUFFER2;
 | 
|---|
 | 920 |   FSDataLength: ULONG;
 | 
|---|
 | 921 | 
 | 
|---|
 | 922 |   rc: APIRET;
 | 
|---|
 | 923 | begin
 | 
|---|
 | 924 |   assert( DriveNumber >= 1 );
 | 
|---|
 | 925 |   assert( DriveNumber <= 26 );
 | 
|---|
 | 926 | 
 | 
|---|
 | 927 |   if ( DriveNumber >=1 ) and ( DriveNumber <= 2 ) then
 | 
|---|
 | 928 |   begin
 | 
|---|
 | 929 |     if IsFloppyDrive( DriveNumber ) then
 | 
|---|
 | 930 |     begin
 | 
|---|
 | 931 |       result := dtFloppy;
 | 
|---|
 | 932 |       exit;
 | 
|---|
 | 933 |     end;
 | 
|---|
 | 934 | 
 | 
|---|
 | 935 |     result := dtNone; // don't let OS/2 try a fake B: drive
 | 
|---|
 | 936 |     exit;
 | 
|---|
 | 937 |   end;
 | 
|---|
 | 938 | 
 | 
|---|
 | 939 |   DosErrorAPI( FERR_DISABLEHARDERR );
 | 
|---|
 | 940 | 
 | 
|---|
 | 941 |   szDrive := DriveNumberToDriveLetter( DriveNumber ) + ':';
 | 
|---|
 | 942 |   FSDataLength := sizeof( FSData );
 | 
|---|
 | 943 |   pBuffer := Addr( FSData );
 | 
|---|
 | 944 |   rc := _DosQueryFSAttach( szDrive,
 | 
|---|
 | 945 |                            0, // ignored
 | 
|---|
 | 946 |                            FSAIL_QUERYNAME,
 | 
|---|
 | 947 |                            pBuffer,
 | 
|---|
 | 948 |                            FSDataLength );
 | 
|---|
 | 949 | 
 | 
|---|
 | 950 |   if rc = 0 then
 | 
|---|
 | 951 |   begin
 | 
|---|
 | 952 |     case pBuffer^.iType of
 | 
|---|
 | 953 |       FSAT_REMOTEDRV:
 | 
|---|
 | 954 |         result := dtNetwork;
 | 
|---|
 | 955 | 
 | 
|---|
 | 956 |       FSAT_LOCALDRV:
 | 
|---|
 | 957 |         // Figure out what kind of local drive it is...
 | 
|---|
 | 958 |         result := GetLocalDriveType( DriveNumber );
 | 
|---|
 | 959 | 
 | 
|---|
 | 960 |       else
 | 
|---|
 | 961 |       begin
 | 
|---|
 | 962 |         // should never happen
 | 
|---|
 | 963 |         result := dtNone;
 | 
|---|
 | 964 |         exit;
 | 
|---|
 | 965 |       end;
 | 
|---|
 | 966 |     end;
 | 
|---|
 | 967 |   end
 | 
|---|
 | 968 |   else if rc = ERROR_NOT_READY then
 | 
|---|
 | 969 |   begin
 | 
|---|
 | 970 |     // No media?
 | 
|---|
 | 971 |     // Have a look for a local disk anyway.
 | 
|---|
 | 972 |     result := GetLocalDriveType( DriveNumber );
 | 
|---|
 | 973 |   end
 | 
|---|
 | 974 |   else
 | 
|---|
 | 975 |   begin
 | 
|---|
 | 976 |     result := dtNone;
 | 
|---|
 | 977 |   end;
 | 
|---|
 | 978 | 
 | 
|---|
 | 979 |   DosErrorAPI( FERR_ENABLEHARDERR );
 | 
|---|
 | 980 | end;
 | 
|---|
 | 981 | 
 | 
|---|
 | 982 | const
 | 
|---|
 | 983 |   DEVLEN = 8;
 | 
|---|
 | 984 |   CNLEN  = 15;               // Computer name length
 | 
|---|
 | 985 |   UNCLEN = (CNLEN+2);        // UNC computer name length
 | 
|---|
 | 986 |   NNLEN  = 12;               // 8.3 Net name length  (share name length)
 | 
|---|
 | 987 |   RMLEN  = (UNCLEN+1+NNLEN); // Maximum remote name length
 | 
|---|
 | 988 | 
 | 
|---|
 | 989 | type
 | 
|---|
 | 990 |   use_info_0 = record
 | 
|---|
 | 991 |     ui0_local: cstring[ DEVLEN ]; // note this is of size DEVLEN + 1
 | 
|---|
 | 992 |     ui0_pad_1: char;
 | 
|---|
 | 993 |     ui0_remote: pchar;
 | 
|---|
 | 994 |     space: array[ 0..RMLEN ] of char; // remote path is written to somewhere in here
 | 
|---|
 | 995 |   end;
 | 
|---|
 | 996 | 
 | 
|---|
 | 997 |   use_info_1 = record
 | 
|---|
 | 998 |     ui0_local: cstring[ DEVLEN ];
 | 
|---|
 | 999 |     ui0_pad_1: char;
 | 
|---|
 | 1000 |     ui0_remote: pchar; // address of a buffer to hold remote path
 | 
|---|
 | 1001 |     ui1_password: pchar; //
 | 
|---|
 | 1002 |     ui1_status: USHORT;
 | 
|---|
 | 1003 |     ui1_asg_type: SHORT;
 | 
|---|
 | 1004 |     ui1_refcount: USHORT;
 | 
|---|
 | 1005 |     ui1_usecount: USHORT;
 | 
|---|
 | 1006 |     space: array[ 0..RMLEN ] of char; // remote path is written to somewhere in here
 | 
|---|
 | 1007 |   end;
 | 
|---|
 | 1008 | 
 | 
|---|
 | 1009 |   TNet32UseGetInfo = Function( pszServer: pchar;
 | 
|---|
 | 1010 |                                pszUseName: pchar; // e.g. drive x:
 | 
|---|
 | 1011 |                                ulLevel: ULONG;
 | 
|---|
 | 1012 |                                pbBuffer: pointer; // pointer to output buffer
 | 
|---|
 | 1013 |                                ulBuffer: ULONG; // size of output in buffer
 | 
|---|
 | 1014 |                                Var pulTotalAvail: ULONG )
 | 
|---|
 | 1015 |                                : word; CDecl;
 | 
|---|
 | 1016 | 
 | 
|---|
 | 1017 | Var
 | 
|---|
 | 1018 |   Net32UseGetInfo: TNet32UseGetInfo;
 | 
|---|
 | 1019 |   hNetAPI32DLL: HMODULE;
 | 
|---|
 | 1020 |   TriedLoading: boolean;
 | 
|---|
 | 1021 | 
 | 
|---|
 | 1022 | //   129 Net32UseGetInfo
 | 
|---|
 | 1023 | Function GetNetworkDriveRemotePath( DriveNumber: longint ): string;
 | 
|---|
 | 1024 | var
 | 
|---|
 | 1025 |   ErrorName: array[ 0..255 ] of char;
 | 
|---|
 | 1026 |   dummy: cstring;
 | 
|---|
 | 1027 |   rc: word;
 | 
|---|
 | 1028 |   UseName: array[ 0..255 ] of char;
 | 
|---|
 | 1029 |   UseInfo: use_info_0;
 | 
|---|
 | 1030 |   pUseInfo: pointer;
 | 
|---|
 | 1031 |   TotalBytesNeeded: ULONG;
 | 
|---|
 | 1032 |   RemotePath: array[ 0..255 ] of char;
 | 
|---|
 | 1033 |   Dummy2: array[ 0..4096 ] of char; // try to fix stack probs
 | 
|---|
 | 1034 | begin
 | 
|---|
 | 1035 |   Result := '';
 | 
|---|
 | 1036 | 
 | 
|---|
 | 1037 |   if not TriedLoading then
 | 
|---|
 | 1038 |   begin
 | 
|---|
 | 1039 |     TriedLoading := true;
 | 
|---|
 | 1040 |     rc := DosLoadModule( ErrorName,
 | 
|---|
 | 1041 |                          sizeof( ErrorName ),
 | 
|---|
 | 1042 |                          'NETAPI32',
 | 
|---|
 | 1043 |                          hNetAPI32DLL );
 | 
|---|
 | 1044 |     if rc = NO_ERROR then
 | 
|---|
 | 1045 |     begin
 | 
|---|
 | 1046 |       // NetAPI32.DLL loaded OK
 | 
|---|
 | 1047 |       rc := DosQueryProcAddr( hNetAPI32DLL,
 | 
|---|
 | 1048 |                               129,
 | 
|---|
 | 1049 |                               dummy,
 | 
|---|
 | 1050 |                               pointer( Net32UseGetInfo ) );
 | 
|---|
 | 1051 |       if rc <> 0 then
 | 
|---|
 | 1052 |         Net32UseGetInfo := nil;
 | 
|---|
 | 1053 |     end;
 | 
|---|
 | 1054 |   end;
 | 
|---|
 | 1055 | 
 | 
|---|
 | 1056 |   if Assigned( Net32UseGetInfo ) then
 | 
|---|
 | 1057 |   begin
 | 
|---|
 | 1058 |     UseName[ 0 ] := DriveNumberToDriveLetter( DriveNumber );
 | 
|---|
 | 1059 |     UseName[ 1 ] := ':';
 | 
|---|
 | 1060 |     UseName[ 2 ] := #0;
 | 
|---|
 | 1061 | 
 | 
|---|
 | 1062 |     RemotePath[ 0 ] := #0;
 | 
|---|
 | 1063 | //    UseInfo.ui0_remote := Addr( RemotePath );
 | 
|---|
 | 1064 | 
 | 
|---|
 | 1065 |     pUseInfo := Addr( UseInfo );
 | 
|---|
 | 1066 |     rc := Net32UseGetInfo( nil, // server - always nil
 | 
|---|
 | 1067 |                            Addr( UseName ),
 | 
|---|
 | 1068 |                            0, // info level 0
 | 
|---|
 | 1069 |                            pUseInfo,
 | 
|---|
 | 1070 |                            sizeof( UseInfo ),
 | 
|---|
 | 1071 |                            TotalBytesNeeded );
 | 
|---|
 | 1072 | 
 | 
|---|
 | 1073 |     if rc = 0 then
 | 
|---|
 | 1074 |       Result := StrPas( UseInfo.ui0_remote );
 | 
|---|
 | 1075 | 
 | 
|---|
 | 1076 |   end;
 | 
|---|
 | 1077 | end;
 | 
|---|
 | 1078 | 
 | 
|---|
 | 1079 | 
 | 
|---|
| [82] | 1080 | Initialization
 | 
|---|
 | 1081 | End.
 | 
|---|