CDFILE.CPP (24573B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 16 /* $Header: F:\projects\c&c\vcs\code\cdfile.cpv 2.18 16 Oct 1995 16:48:10 JOE_BOSTIC $ */ 17 /*********************************************************************************************** 18 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** 19 *********************************************************************************************** 20 * * 21 * Project Name : Westwood Library * 22 * * 23 * File Name : CDFILE.CPP * 24 * * 25 * Programmer : Joe L. Bostic * 26 * * 27 * Start Date : October 18, 1994 * 28 * * 29 * Last Update : October 18, 1994 [JLB] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Functions: * 33 * CDFileClass::Clear_Search_Drives -- Removes all record of a search path. * 34 * CDFileClass::Open -- Opens the file object -- with path search. * 35 * CDFileClass::Open -- Opens the file wherever it can be found. * 36 * CDFileClass::Set_Name -- Performs a multiple directory scan to set the filename. * 37 * CDFileClass::Set_Search_Drives -- Sets a list of search paths for file access. * 38 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 39 40 #include "function.h" 41 //#include "cdfile.h" 42 43 /* 44 ** Pointer to the first search path record. 45 */ 46 CDFileClass::SearchDriveType * CDFileClass::First = 0; 47 48 int CDFileClass::CurrentCDDrive = 0; 49 int CDFileClass::LastCDDrive = 0; 50 char CDFileClass::RawPath[512]; 51 52 53 54 int __cdecl Is_Disk_Inserted(int disk) 55 { 56 return true; 57 58 #if (0) // ST - 12/17/2018 5:31PM 59 struct find_t fb; 60 char scan[] = "?:\\*.*"; 61 62 scan[0] = 'A' + disk; 63 return(_dos_findfirst(scan, _A_SUBDIR, &fb) == 0); 64 #endif 65 } 66 67 68 CDFileClass::CDFileClass(char const *filename) : 69 IsDisabled(false) 70 { 71 Set_Name(filename); 72 memset (RawPath, 0, sizeof(RawPath)); 73 } 74 75 76 CDFileClass::CDFileClass(void) : 77 IsDisabled(false) 78 { 79 } 80 81 82 /*********************************************************************************************** 83 * CDFileClass::Open -- Opens the file object -- with path search. * 84 * * 85 * This will open the file object, but since the file object could have been constructed * 86 * with a pathname, this routine will try to find the file first. For files opened for * 87 * writing, then use the existing filename without performing a path search. * 88 * * 89 * INPUT: rights -- The access rights to use when opening the file * 90 * * 91 * OUTPUT: bool; Was the open successful? * 92 * * 93 * WARNINGS: none * 94 * * 95 * HISTORY: * 96 * 10/18/1994 JLB : Created. * 97 *=============================================================================================*/ 98 int CDFileClass::Open(int rights) 99 { 100 return(RawFileClass::Open(rights)); 101 } 102 103 104 /*********************************************************************************************** 105 * CDFC::Refresh_Search_Drives -- Updates the search path when a CD changes or is added * 106 * * 107 * * 108 * * 109 * INPUT: Nothing * 110 * * 111 * OUTPUT: Nothing * 112 * * 113 * WARNINGS: None * 114 * * 115 * HISTORY: * 116 * 5/22/96 9:01AM ST : Created * 117 *=============================================================================================*/ 118 void CDFileClass::Refresh_Search_Drives (void) 119 { 120 Clear_Search_Drives(); 121 Set_Search_Drives(RawPath); 122 } 123 124 125 126 127 128 /*********************************************************************************************** 129 * CDFileClass::Set_Search_Drives -- Sets a list of search paths for file access. * 130 * * 131 * This routine sets up a list of search paths to use when accessing files. The path list * 132 * is scanned if the file could not be found in the current directory. This is the primary * 133 * method of supporting CD-ROM drives, but is also useful for scanning network and other * 134 * directories. The pathlist as passed to this routine is of the same format as the path * 135 * list used by DOS -- paths are separated by semicolons and need not end in an antivirgule.* 136 * * 137 * If a path entry begins with "?:" then the question mark will be replaced with the first * 138 * CD-ROM drive letter available. If there is no CD-ROM driver detected, then this path * 139 * entry will be ignored. By using this feature, you can always pass the CD-ROM path * 140 * specification to this routine and it will not break if the CD-ROM is not loaded (as in * 141 * the case during development). * 142 * * 143 * Here is an example path specification: * 144 * * 145 * Set_Search_Drives("DATA;?:\DATA;F:\PROJECT\DATA"); * 146 * * 147 * In this example, the current directory will be searched first, followed by a the * 148 * subdirectory "DATA" located off of the current directory. If not found, then the CD-ROM * 149 * will be searched in a directory called "\DATA". If not found or the CD-ROM is not * 150 * present, then it will look to the hard coded path of "F:\PROJECTS\DATA" (maybe a * 151 * network?). If all of these searches fail, the file system will default to the current * 152 * directory and let the normal file error system take over. * 153 * * 154 * INPUT: pathlist -- Pointer to string of path specifications (separated by semicolons) * 155 * that will be used to search for files. * 156 * * 157 * OUTPUT: none * 158 * * 159 * WARNINGS: none * 160 * * 161 * HISTORY: * 162 * 10/18/1994 JLB : Created. * 163 * 05/21/1996 ST : Modified to recognise multiple CD drives * 164 *=============================================================================================*/ 165 int CDFileClass::Set_Search_Drives(char * pathlist) 166 { 167 int found = FALSE; 168 int empty = FALSE; 169 /* 170 ** If there is no pathlist to add, then just return. 171 */ 172 if (!pathlist) return(0); 173 174 /* 175 ** Save the path as it was passed in so we can parse it again later. 176 ** Check for the case where RawPath was passed in. 177 */ 178 if (pathlist != RawPath){ 179 strcat (RawPath, ";"); 180 strcat (RawPath, pathlist); 181 } 182 183 char const * ptr = strtok(pathlist, ";"); 184 while (ptr) { 185 if (strlen(ptr)){ 186 187 char path[MAX_PATH]; // Working path buffer. 188 189 /* 190 ** Fixup the path to be legal. Legal is defined as all that is necessary to 191 ** create a pathname is to append the actual filename submitted to the 192 ** file system. This means that it must have either a trailing ':' or '\' 193 ** character. 194 */ 195 strcpy(path, ptr); 196 switch (path[strlen(path)-1]) { 197 case ':': 198 case '\\': 199 break; 200 201 default: 202 strcat(path, "\\"); 203 break; 204 } 205 206 /* 207 ** If there is a drive letter specified, and this drive letter is '?', then it should 208 ** be substituted with the CD-ROM drive letter. In the case of no CD-ROM attached, then 209 ** merely ignore this path entry. 210 */ 211 if (strncmp(path, "?:", 2) == 0) { 212 if (CurrentCDDrive){ 213 found = TRUE; 214 /* 215 ** If the drive has a C&C CD in it then add it to the path 216 */ 217 if (Get_CD_Index(CurrentCDDrive, 2*60) >= 0){ 218 path[0] = CurrentCDDrive + 'A'; 219 Add_Search_Drive(path); 220 } 221 } 222 /* 223 ** Find the next path string and resubmit. 224 */ 225 ptr = strtok(NULL, ";"); 226 continue; 227 } 228 229 found = TRUE; 230 Add_Search_Drive(path); 231 } 232 233 /* 234 ** Find the next path string and resubmit. 235 */ 236 ptr = strtok(NULL, ";"); 237 } 238 if (!found) return(1); 239 if (empty) return(2); 240 return(0); 241 } 242 243 244 245 /*********************************************************************************************** 246 * CDFC::Set_CD_Drive -- sets the current CD drive letter * 247 * * 248 * * 249 * * 250 * INPUT: Nothing * 251 * * 252 * OUTPUT: Nothing * 253 * * 254 * WARNINGS: None * 255 * * 256 * HISTORY: * 257 * 5/22/96 9:39AM ST : Created * 258 *=============================================================================================*/ 259 260 void CDFileClass::Set_CD_Drive (int drive) 261 { 262 LastCDDrive = CurrentCDDrive; 263 CurrentCDDrive = drive; 264 } 265 266 267 268 /*********************************************************************************************** 269 * CDFC::Add_Search_Drive -- Add a new path to the search path list * 270 * * 271 * * 272 * * 273 * INPUT: path * 274 * * 275 * OUTPUT: Nothing * 276 * * 277 * WARNINGS: None * 278 * * 279 * HISTORY: * 280 * 5/22/96 10:12AM ST : Created * 281 *=============================================================================================*/ 282 283 void CDFileClass::Add_Search_Drive(char *path) 284 { 285 SearchDriveType *srch; // Working pointer to path object. 286 /* 287 ** Allocate a record structure. 288 */ 289 srch = new SearchDriveType; 290 291 /* 292 ** Attach the path to this structure. 293 */ 294 srch->Path = strdup(path); 295 srch->Next = NULL; 296 297 /* 298 ** Attach this path record to the end of the path chain. 299 */ 300 if (!First) { 301 First = srch; 302 } else { 303 SearchDriveType * chain = First; 304 305 while (chain->Next) { 306 chain = (SearchDriveType *)chain->Next; 307 } 308 chain->Next = srch; 309 } 310 } 311 312 313 314 315 /*********************************************************************************************** 316 * CDFileClass::Clear_Search_Drives -- Removes all record of a search path. * 317 * * 318 * Use this routine to clear out any previous path(s) set with Set_Search_Drives() * 319 * function. * 320 * * 321 * INPUT: none * 322 * * 323 * OUTPUT: none * 324 * * 325 * WARNINGS: none * 326 * * 327 * HISTORY: * 328 * 10/18/1994 JLB : Created. * 329 *=============================================================================================*/ 330 void CDFileClass::Clear_Search_Drives(void) 331 { 332 SearchDriveType * chain; // Working pointer to path chain. 333 334 chain = First; 335 while (chain) { 336 SearchDriveType *next; 337 338 next = (SearchDriveType *)chain->Next; 339 if (chain->Path) { 340 free((char *)chain->Path); 341 } 342 delete chain; 343 344 chain = next; 345 } 346 First = 0; 347 } 348 349 350 /*********************************************************************************************** 351 * CDFileClass::Set_Name -- Performs a multiple directory scan to set the filename. * 352 * * 353 * This routine will scan all the directories specified in the path list and if the file * 354 * was found in one of the directories, it will set the filename to a composite of the * 355 * correct directory and the filename. It is used to allow path searching when searching * 356 * for files. Typical use is to support CD-ROM drives. This routine examines the current * 357 * directory first before scanning through the path list. If after scanning the entire * 358 * path list, the file still could not be found, then the file object's name is set with * 359 * just the raw filename as passed to this routine. * 360 * * 361 * INPUT: filename -- Pointer to the filename to set as the name of this file object. * 362 * * 363 * OUTPUT: Returns a pointer to the final and complete filename of this file object. This * 364 * may have a path attached to the file. * 365 * * 366 * WARNINGS: none * 367 * * 368 * HISTORY: * 369 * 10/18/1994 JLB : Created. * 370 *=============================================================================================*/ 371 char const * CDFileClass::Set_Name(char const *filename) 372 { 373 /* 374 ** Try to find the file in the current directory first. If it can be found, then 375 ** just return with the normal file name setting process. Do the same if there is 376 ** no multi-drive search path. 377 */ 378 RawFileClass::Set_Name(filename); 379 if (IsDisabled || !First || RawFileClass::Is_Available()) { 380 return(File_Name()); 381 } 382 383 /* 384 ** Attempt to find the file first. Check the current directory. If not found there, then 385 ** search all the path specifications available. If it still can't be found, then just 386 ** fall into the normal raw file filename setting system. 387 */ 388 SearchDriveType * srch = First; 389 390 while (srch) { 391 char path[_MAX_PATH]; 392 393 /* 394 ** Build a pathname to search for. 395 */ 396 strcpy(path, srch->Path); 397 strcat(path, filename); 398 399 /* 400 ** Check to see if the file could be found. The low level Is_Available logic will 401 ** prompt if necessary when the CD-ROM drive has been removed. In all other cases, 402 ** it will return false and the search process will continue. 403 */ 404 RawFileClass::Set_Name(path); 405 if (RawFileClass::Is_Available()) { 406 return(File_Name()); 407 } 408 409 /* 410 ** It wasn't found, so try the next path entry. 411 */ 412 srch = (SearchDriveType *)srch->Next; 413 } 414 415 /* 416 ** At this point, all path searching has failed. Just set the file name to the 417 ** plain text passed to this routine and be done with it. 418 */ 419 RawFileClass::Set_Name(filename); 420 return(File_Name()); 421 } 422 423 424 /*********************************************************************************************** 425 * CDFileClass::Open -- Opens the file wherever it can be found. * 426 * * 427 * This routine is similar to the RawFileClass open except that if the file is being * 428 * opened only for READ access, it will search all specified directories looking for the * 429 * file. If after a complete search the file still couldn't be found, then it is opened * 430 * using the normal RawFileClass system -- resulting in normal error procedures. * 431 * * 432 * INPUT: filename -- Pointer to the override filename to supply for this file object. It * 433 * would be the base filename (sans any directory specification). * 434 * * 435 * rights -- The access rights to use when opening the file. * 436 * * 437 * OUTPUT: bool; Was the file opened successfully? If so then the filename may be different * 438 * than requested. The location of the file can be determined by examining the * 439 * filename of this file object. The filename will contain the complete * 440 * pathname used to open the file. * 441 * * 442 * WARNINGS: none * 443 * * 444 * HISTORY: * 445 * 10/18/1994 JLB : Created. * 446 *=============================================================================================*/ 447 int CDFileClass::Open(char const *filename, int rights) 448 { 449 Close(); 450 451 /* 452 ** Verify that there is a filename associated with this file object. If not, then this is a 453 ** big error condition. 454 */ 455 if (!filename) { 456 Error(ENOENT, false); 457 } 458 459 /* 460 ** If writing is requested, then multiple drive searching is not performed. 461 */ 462 if (IsDisabled || rights == WRITE) { 463 return(RawFileClass::Open(filename, rights)); 464 } 465 466 /* 467 ** Perform normal multiple drive searching for the filename and open 468 ** using the normal procedure. 469 */ 470 Set_Name(filename); 471 return(RawFileClass::Open(rights)); 472 } 473 474 475 #ifdef NEVER 476 /* Get the drive letters if the CD's online */ 477 WORD __cdecl GetCDDrive(VOID) 478 { 479 _ES = FP_SEG(&cdDrive[0]); 480 _BX = FP_OFF(&cdDrive[0]); 481 _AX = 0x150d; 482 geninterrupt(0x2F); 483 return((WORD)(*cdDrive)); 484 } 485 #endif 486 487 int Get_CD_Drive(void) 488 { 489 #ifdef NEVER 490 for (int index = 0; index < 26; index++) { 491 union REGS regs; 492 493 regs.w.ax = 0x150B; 494 regs.w.bx = 0; 495 regs.w.cx = index; 496 int386(0x2F, ®s, ®s); 497 if (regs.w.bx == 0xADAD) { 498 return(index); 499 } 500 } 501 return(0); 502 #else 503 504 // GetCDClass temp; 505 // return(temp.GetCDDrive()); 506 return (0); 507 #endif 508 509 } 510 511 512 513 const char *CDFileClass::Get_Search_Path(int index) 514 { 515 if (First == NULL) { 516 return NULL; 517 } 518 519 SearchDriveType *sd = First; 520 521 for (int i=0 ; i <= index ; i++) { // We want to loop once, even if index==0 522 523 if (i == index) { 524 return sd->Path; 525 } 526 527 sd = (SearchDriveType *) sd->Next; 528 if (sd == NULL) { 529 return NULL; 530 } 531 } 532 533 return NULL; 534 }