CDFILE.CPP 24 KB

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