ISO9660_API.c
上传用户:super_houu
上传日期:2008-09-21
资源大小:4099k
文件大小:70k
源码类别:

DVD

开发平台:

Others

  1. /****************************************************************************************
  2.  *  Copyright (c) 2002 ZORAN Corporation, All Rights Reserved
  3.  *  THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ZORAN CORPORATION
  4.  *
  5.  *  File: $Workfile: ISO9660_API.c $             
  6.  *
  7.  * Description:
  8.  * ============
  9.  * 
  10.  * 
  11.  * Log:
  12.  * ====
  13.  * $Revision: 22 $
  14.  * Last Modified by $Author: Mikex $ at $Modtime: 04-03-20 20:36 $ 
  15.  ****************************************************************************************
  16.  * Updates:
  17.  ****************************************************************************************
  18.  * $Log: /I76/I76_Common/I76_Reference/Playcore/FileSys/ISO9660/ISO9660_API.c $
  19.  * 
  20.  * 22    04-03-20 21:00 Mikex
  21.  * Cut the file name longer than 128 bytes.
  22.  * example: if the file name length is 130
  23.  * origenal: abc...xyz.mp3
  24.  * before:   abc...xyz.m
  25.  * now:       abc...x.mp3
  26.  * 
  27.  * 21    11/19/03 10:25a Leslie
  28.  * 
  29.  * 20    03-07-17 17:11 Jerryc
  30.  * support finding files with name length of 63 and 64. 
  31.  * 
  32.  * 19    03-07-15 18:57 Jerryc
  33.  * ISO9660_checkValid will not return FLASE if some pathTable records are
  34.  * empty.
  35.  * 
  36.  * 18    7/08/03 3:39p Mikex
  37.  * delete the CHECK_ISO9660_PATHTABLE define switch
  38.  * 
  39.  * 17    7/08/03 3:14p Mikex
  40.  * change function ISO9660_checkValid for having several iso9660 PVD disc.
  41.  * 
  42.  * 16    03-07-06 1:55 Leslie
  43.  * Add CHECK_ISO9660_PATHTABLE
  44.  * 
  45.  * 15    7/03/03 7:37p Mikex
  46.  * 
  47.  * 14    7/03/03 2:16p Mikex
  48.  * add a function ISO9660_checkValid to check whether the ISO9660 file
  49.  * system was ok or not. the function was transferred by
  50.  * ISO9660_initialize function.
  51.  * 
  52.  * 13    7/01/03 6:28p Mikex
  53.  * add ISO9660_getFilesFirst, ISO9660_getFilesNext and
  54.  * ISO9660_getFilesClose function to get all files in one directory
  55.  * 
  56.  * 12    2/07/03 10:41p Tomasp
  57.  * - changed SW feature selection to compilation switch
  58.  * 
  59.  * 11    03-01-30 23:12 Leslie
  60.  * Add functions ISO9660_GetcurrentDirICB and ISO9660_SetcurrentDirICB
  61.  * 
  62.  * 10    03-01-10 12:20 Leslie
  63.  * Add builtin unicode support
  64.  * 
  65.  * 9     10/31/02 17:22 Hamadk
  66.  * Check of the parameter in filesystem intializing
  67.  * 
  68.  * 10    23/04/02 9:30 Nirm
  69.  * - Added dependency in "Config.h".
  70.  * 
  71.  * 9     13/03/02 21:25 Nirm
  72.  * Fixed an endless-loop problem in _findNextFileRecord(): If a directory
  73.  * padding spans beyond a sector-boundary (due to authoring error), the
  74.  * sector-boundary wouldn't be crossed. This is a result of the caching
  75.  * mechanism.
  76.  * A special check was added to assure correct sector-boundary crossing.
  77.  * 
  78.  * 8     4/02/02 10:54 Nirm
  79.  * Unused External-Memory is freed, to reduce memory consumption.
  80.  * 
  81.  * 7     30/01/02 18:16 Nirm
  82.  * Updated debugging-messages.
  83.  * 
  84.  * 6     27/01/02 17:47 Nirm
  85.  * - Added ISO9660_construct() and ISO9660_destruct(), to allow proper
  86.  * allocation and deallocation of system resources;
  87.  * - Modifications and optimizations to memory consumption.
  88.  * 
  89.  * 5     16/01/02 11:46 Atai
  90.  * Change Debug printing
  91.  * 
  92.  * 4     1/10/02 18:08 Idan
  93.  * added optimization - avoid memory allocation when wild card search is
  94.  * requested.
  95.  * 
  96.  * 3     1/10/02 15:32 Idan
  97.  * FindFirstFile, FindNextFile, GoUp, ChangeDirectory, GetFileAttributes
  98.  * and all memory allocatations are working properly.
  99.  * 
  100.  * 2     12/31/01 19:46 Idan
  101.  * initializing the ISO9660 FS is working.
  102.  * 
  103.  * 1     12/27/01 14:19 Idan
  104.  * 
  105.  ****************************************************************************************/
  106. /////////////////////////////////////////////////////////////////////////////
  107. // ISO9660_API.c - Implementation of the ISO-9660 File-System For DVD/S-VCD
  108. //    Players.
  109. //
  110. // Author: Nir Milstein
  111. #include "Config.h" // Global Configuration - do not remove!
  112. #ifdef _DEBUG
  113. #undef IFTRACE
  114. #define IFTRACE if (gTraceFileSys)
  115. #include "DebugDbgMain.h"
  116. #endif //_DEBUG
  117. #include "Includemath-macro.h"
  118. #include "Includestring_ex.h"
  119. #include "PlaycoreFileSysFileSystem_Impl.h"
  120. #include "PlaycoreFileSysIso9660ISO9660_API.h"
  121. #include "PlaycoreFileSysIso9660ECMA119.h"
  122. #include "PlaycoreDataStructuresArray.h"
  123. #include "PlaycoreAuxCacheAuxCache.h"
  124. #include "PlaycoreScPadscmgr.h"
  125. #include "PlaycoreCoremaincoregdef.h"
  126. #include "PlaycoreFileSysFileSystem.h"
  127. #ifdef MACESTROLINK_SUPPORT
  128. #include "drivefe_manager.h"
  129. #endif
  130. /////////////////////////////////////////////////////////////////////////////
  131. // Constants
  132. #define DIRECTORY_RECLIST_SZ (5 * (sizeof(struct DirFileRecord) + MAX_ID_LENGTH))
  133. /////////////////////////////////////////////////////////////////////////////
  134. // Macros
  135. #ifdef MOTOROLA
  136. #define BB_WORD(wBothBytes) (WORD)(wBothBytes ## .wBE16)
  137. #define BB_DWORD(dwBothBytes) (DWORD)(dwBothBytes ## .dwBE32)
  138. #else
  139. #define BB_WORD(wBothBytes) (WORD)(wBothBytes ## .wLE16)
  140. #define BB_DWORD(dwBothBytes) (DWORD)(dwBothBytes ## .dwLE32)
  141. #endif //MOTOROLA
  142. /////////////////////////////////////////////////////////////////////////////
  143. // Globals and Singletons
  144. /*
  145. //static struct ISO9660_TAG {
  146. typedef struct {
  147. // Session information
  148. DWORD dwSessionStartLBN;
  149. // Unicode support
  150. BOOL  bIsUsingUnicode;
  151. // Volume information
  152. DWORD dwRootDirICB;
  153. DWORD dwCurrDirICB;
  154. // Current Working-Directory storage
  155. BOOL  bCWDStored;
  156. DWORD dwCWDStorage;
  157. // Directory Hierarchy Tree
  158. UINT16 uDirectoryCnt;
  159. UINT32 hDirTree;
  160. } ISO9660_TAG;//g_ISO9660Info;
  161. */
  162. ISO9660_TAG * g_pISO9660Info;
  163. /////////////////////////////////////////////////////////////////////////////
  164. // Internal Structures / Types
  165. typedef struct ISO9660_DirectorySearchInfo_TAG {
  166. // Directory Location and Size related
  167. DWORD  dwDirICB; // Location of the Directory
  168. UINT16 uDirNumber; // Serial Number
  169. DWORD  dwDirectorySize; // In Bytes
  170. // Search Criteria related
  171. LPWSTR pszFileID; // The Pattern/Name to search for
  172. UINT8  uFileFlagsMask; // A Mask to apply to File-Flags
  173. UINT8  uFileFlags; // The required File-Flags
  174. // Search Status/Position related
  175. WORD   hDirFileRecordList;
  176. UINT32 cbRecListOffset; // In Bytes from the Directory's start
  177. UINT16 cbCurrRecOffset; // In Bytes from the Record-List start
  178. } DirectorySearchInfo;
  179. typedef struct DirectoryNode_TAG {
  180. UINT16 uParentDirNumber;
  181. DWORD  dwDirICB;
  182. } DirectoryNode;
  183. #define MAX_FILEREC_SIZE (sizeof(struct DirFileRecord) + MAX_ID_LENGTH + 2)
  184. /////////////////////////////////////////////////////////////////////////////
  185. // Forward-Declarations of Private-Services
  186. static BOOL _buildDirectoryTree(DWORD dwPathTableAddress, DWORD dwPathTableSize);
  187. static UINT16 _findFirstFileRecord(LPCWSTR i_pszFileID, UINT8 uFileFlagsMask, 
  188.    UINT8 uFileFlags, 
  189.    struct DirFileRecord **o_pFileRecordPtr);
  190. static BOOL _findNextFileRecord(UINT16 uSearchID, struct DirFileRecord **o_pFileRecordPtr);
  191. static BOOL _findClose(UINT16 uSearchID);
  192. static void _getFileAttributes(const struct DirFileRecord *i_pFileRec, FindData *o_pFindData);
  193. /////////////////////////////////////////////////////////////////////////////
  194. // Detection
  195. /////////////////////////////////////////////////////////////////////////////
  196. // ISO9660_isResident()
  197. //
  198. // Description: Tests a given LBN to detect whether or not an instance of
  199. // ISO-9660 is resident on the Medium at that location.
  200. //
  201. // Input: dwCandidateLBN - The candidate LBN to test.
  202. // Output: None
  203. // In/Out: None
  204. // Return: TRUE if an ISO-9660 instance was found at the specified LBN;
  205. // FALSE otherwise.
  206. //
  207. // Remarks:
  208. // The method assumes that the given LBN is the beginning of a
  209. // Volume-Recognition Sequence, and searches for the Standard-ID associated
  210. // with ISO-9660.
  211. BOOL ISO9660_isResident(DWORD dwCandidateLBN)
  212. {
  213. struct GenericVolumeStructureDesc_Base gvsdVolumeDesc;
  214. dbg_printf(("ISO9660_isResident(0x%08x) calling.n", dwCandidateLBN));
  215. // Load the first Volume-Structure Descriptor within the Volume-Recognition-Sequence
  216. if (! AuxCache_GetBytes((dwCandidateLBN + VOLUME_RECOGNITION_SEQUENCE_START_LSN), 0, 
  217.    sizeof(gvsdVolumeDesc), (BYTE*)&gvsdVolumeDesc))
  218. {
  219. dbg_printf(("WARNING: ISO9660_isResident() Failed [1]n"));
  220. return FALSE;
  221. }
  222. // Check for an ISO-9660 Standard-ID
  223. if (0 == strncmp((LPCSTR)gvsdVolumeDesc.aStandardID, STANDARD_ID_CD001, STANDARD_ID_LEN))
  224. return TRUE;
  225. return FALSE;
  226. }
  227. /////////////////////////////////////////////////////////////////////////////
  228. // Construction / Destruction
  229. /////////////////////////////////////////////////////////////////////////////
  230. // ISO9660_construct()
  231. //
  232. // Description: Constructs the File-System, and allocates system resources
  233. // needed for correct operation.
  234. //
  235. // Input: dwSessionStartLBN - The Start-LBN of the current Session.
  236. // Output: None
  237. // In/Out: None
  238. // Return: None
  239. //
  240. // Remarks:
  241. // This method must be called prior to initialization of the File-System.
  242. void ISO9660_construct(DWORD dwSessionStartLBN)
  243. {
  244. dbg_printf(("ISO9660_construct(0x%08x) calling.n", dwSessionStartLBN));
  245. if( g_pISO9660Info != NULL)
  246. {
  247. free(g_pISO9660Info);
  248. }
  249. g_pISO9660Info = (FileInfo *)malloc(sizeof(FileInfo));
  250. if(NULL == g_pISO9660Info)
  251. {
  252. tr_printf(("ISO9660_construct() failed--alloc memory for g_pISO9660Info failed.n"));
  253. return;
  254. }
  255. // Record the Session-Start Address
  256. g_pISO9660Info->dwSessionStartLBN= dwSessionStartLBN;
  257. // Initialize the Directory-Tree Handle
  258. g_pISO9660Info->hDirTree= NULL;
  259. // Reset the Search-Info Pool
  260. if (! _FileSys_resetSearchInfoPool(sizeof(DirectorySearchInfo))) {
  261. tr_printf(("FATAL: ISO9660_construct() Failed [1]n"));
  262. }
  263. return;
  264. }
  265. /////////////////////////////////////////////////////////////////////////////
  266. // ISO9660_destruct()
  267. //
  268. // Description: Destructs the File-System, and frees system resources
  269. // allocated during the operation.
  270. //
  271. // Input: None
  272. // Output: None
  273. // In/Out: None
  274. // Return: None
  275. //
  276. // Remarks:
  277. // This method should be called when the File-System is no longer needed.
  278. void ISO9660_destruct(void)
  279. {
  280. dbg_printf(("ISO9660_destruct() callingn"));
  281. // Free the Directory-Tree
  282. if (NULL != g_pISO9660Info->hDirTree) {
  283. Array_destruct(g_pISO9660Info->hDirTree);
  284. g_pISO9660Info->hDirTree= NULL;
  285. }
  286. if(NULL != g_pISO9660Info)
  287. {
  288. free(g_pISO9660Info);
  289. g_pISO9660Info = NULL;
  290. }
  291. return;
  292. }
  293. /////////////////////////////////////////////////////////////////////////////
  294. // Initialization
  295. /////////////////////////////////////////////////////////////////////////////
  296. // ISO9660_initialize()
  297. //
  298. // Description: Initializes the File-System and switches to the Root 
  299. // directory.
  300. //
  301. // Input: bLongFilenameSupport - Determines whether or not Long-Filenames
  302. //    Support is enabled.
  303. // Output: None
  304. // In/Out: None
  305. // Return: TRUE if the File-System was successfully initialized; FALSE
  306. // otherwise.
  307. //
  308. // Remarks:
  309. // 1. In case of failure, none of the Navigation or Queries methods may
  310. //    be used.
  311. // 2. Supplying a value of FALSE in bLongFilenameSupport forces use
  312. //    of Filenames in 8.3 format, even if the Medium carries a Joliet
  313. //    extension for Long-Filenames.
  314. // 3. The File-System information is taken from the last Closed-Session on 
  315. //    the Medium.
  316. BOOL ISO9660_initialize(BOOL bLongFilenameSupport)
  317. {
  318. BOOL bRootDirEstablished= FALSE;
  319. DWORD dwCurrDescLBN;
  320. struct GenericVolumeStructureDesc_Base *pCurrDescHdr;
  321. struct VolumeDesc_Partial *pPartialVolDesc;
  322. dbg_printf(("ISO9660_initialize() calling.n"));
  323. if(!ISO9660_checkValid())
  324. return FALSE;
  325. // Allocate space for a generic Descriptor base
  326. pCurrDescHdr= (struct GenericVolumeStructureDesc_Base*)malloc(sizeof(struct GenericVolumeStructureDesc_Base));
  327. if (NULL == pCurrDescHdr) {
  328. tr_printf(("FATAL: ISO9660_initialize() Failed [1]: Low system resourcesn"));
  329. return FALSE;
  330. }
  331. // Allocate space for a Partial Volume Descriptor (will be used for Primary or Supplemantary 
  332. // Volume descriptors).
  333. pPartialVolDesc = (struct VolumeDesc_Partial*)malloc(sizeof(struct VolumeDesc_Partial));
  334. if (NULL == pPartialVolDesc) {
  335. tr_printf(("FATAL: ISO9660_initialize() Failed [2]: Low system resourcesn"));
  336. free(pCurrDescHdr);
  337. return FALSE;
  338. }
  339. g_pISO9660Info->bIsUsingUnicode= FALSE;
  340. // Start searching for the Primary or Supplementary Volume Descriptor, while verifying the 
  341. // integrity of the Volume-Recognition Sequence.
  342. dwCurrDescLBN= (g_pISO9660Info->dwSessionStartLBN + VOLUME_RECOGNITION_SEQUENCE_START_LSN);
  343. while (TRUE) 
  344. {
  345. // Read the first few bytes in order to determine the type of the descriptor
  346. if (! AuxCache_GetBytes(dwCurrDescLBN, 0, sizeof(struct GenericVolumeStructureDesc_Base),
  347.    (BYTE *)pCurrDescHdr)) 
  348. {
  349. dbg_printf(("WARNING: ISO9660_initialize() Failed [3]n"));
  350. break;
  351. }
  352. // Check for a Primary-Volume
  353. if (DESC_TYPE_PRIMARY_VOLUME == pCurrDescHdr->uVolumeDescType) 
  354. {
  355. // Read the essential part of the descriptor
  356. if (! AuxCache_GetBytes(dwCurrDescLBN, PARTIAL_VOLUME_DESC_OFFSET, 
  357.    sizeof(struct VolumeDesc_Partial), (BYTE *)pPartialVolDesc))
  358. {
  359. dbg_printf(("WARNING: ISO9660_initialize() Failed [4]n"));
  360. break;
  361. }
  362. #ifdef HW_POWER_ON_RESUME
  363. {
  364. // Calculate checksum here for poweron resume
  365. // Calculating checksum using simple mechanism of adding each byte of the 
  366.           int i;
  367. BYTE * pTmp = 0;
  368. pTmp = (BYTE*)&pPartialVolDesc->dwVolumeSpaceSize;
  369. NewChecksum = 0;
  370. for (i=0;i<32;i++)
  371. NewChecksum+=pPartialVolDesc->sVolumeID[i];
  372. for (i=0;i<8;i++)
  373. NewChecksum += *pTmp++; //Add 8 bytes of volume space size.
  374. }
  375. #endif//HW_POWER_ON_RESUME
  376. // Collect information of the Root-Directory
  377. g_pISO9660Info->dwRootDirICB= BB_DWORD(pPartialVolDesc->rdrRootDir.dwExtentLocation);
  378. bRootDirEstablished= TRUE;
  379. dbg_printf(("Primary Volume Descriptor found.n"));
  380. // Copy the Primary-Volume Name
  381. pPartialVolDesc->sVolumeID[SHORT_ID_LENGTH]= 0;
  382. sc_SetBytes(SC_VOLUME_ID_ADDR, 0, FILESYSTEM_MAX_VOLUME_NAME*sizeof(WCHAR), pPartialVolDesc->sVolumeID);
  383. dbg_printf(("Volume-ID: '%s'n", (LPCSTR)pPartialVolDesc->sVolumeID));
  384. // Build the Directory-Hierarchy Tree, based on the M-Type Path-Table or the L-Type Path-Table
  385. #ifdef MOTOROLA
  386. if (! _buildDirectoryTree(pPartialVolDesc->dwLoactionOfMPathTable, BB_DWORD(pPartialVolDesc->dwPathTableSize))) {
  387. dbg_printf(("Failed to build the Directory-Hierarchy Tree.n"));
  388. }
  389. #else
  390. if (! _buildDirectoryTree(pPartialVolDesc->dwLocationOfLPathTable, BB_DWORD(pPartialVolDesc->dwPathTableSize))) {
  391. dbg_printf(("Failed to build the Directory-Hierarchy Tree.n"));
  392. }
  393. #endif //MOTOROLA
  394. dwCurrDescLBN++; // Move to the next Descriptor
  395. continue;
  396. }
  397. // Check for a Supplementary Volume
  398. if (DESC_TYPE_SUPPL_VOLUME == pCurrDescHdr->uVolumeDescType) 
  399. {
  400. if (! AuxCache_GetBytes(dwCurrDescLBN, PARTIAL_VOLUME_DESC_OFFSET, 
  401.    sizeof(struct VolumeDesc_Partial), (BYTE *)pPartialVolDesc))
  402. {
  403. dbg_printf(("WARNING: ISO9660_initialize() Failed [5]n"));
  404. break;
  405. }
  406. // Check if the Supplementary Volume describes a Joliet extension to ISO-9660
  407. if ((0x25 == pPartialVolDesc->aEscapeSequences[0]) && 
  408. (0x2F == pPartialVolDesc->aEscapeSequences[1])) 
  409. {
  410. BYTE ucJolietLevel= pPartialVolDesc->aEscapeSequences[2];
  411. if ((0x40 == ucJolietLevel) || (0x43 == ucJolietLevel) || (0x45 == ucJolietLevel)) {
  412. dbg_printf(("Joliet Extension Level-%d detected.n",
  413.    ((0x40 == ucJolietLevel) ? 1 : ((0x43 == ucJolietLevel) ? 2 : 3))));
  414. // Collect information of the Supplementary Root-Directory
  415. if (bLongFilenameSupport)
  416. {
  417. g_pISO9660Info->dwRootDirICB= BB_DWORD(pPartialVolDesc->rdrRootDir.dwExtentLocation);
  418. g_pISO9660Info->bIsUsingUnicode= TRUE;
  419. bRootDirEstablished= TRUE;
  420. // Collect the Directory-Hierarchy Tree, based on the M/L-Type Path-Table
  421. #ifdef MOTOROLA
  422. if (! _buildDirectoryTree(pPartialVolDesc->dwLoactionOfMPathTable, BB_DWORD(pPartialVolDesc->dwPathTableSize))) {
  423. dbg_printf(("Failed to build the Directory-Hierarchy Tree.n"));
  424. }
  425. #else
  426. if (! _buildDirectoryTree(pPartialVolDesc->dwLocationOfLPathTable, BB_DWORD(pPartialVolDesc->dwPathTableSize))) {
  427. dbg_printf(("Failed to build the Directory-Hierarchy Tree.n"));
  428. }
  429. #endif //MOTOROLA
  430. }
  431. }
  432. else {
  433. dbg_printf(("Unexpected Joliet Extension Level found. Ignored.n"));
  434. }
  435. }
  436. dwCurrDescLBN++; // Skip to the next Descriptor
  437. continue;
  438. }
  439. // Check for a Terminator
  440. if (( (DESC_TYPE_BOOT != pCurrDescHdr->uVolumeDescType) &&
  441.   (DESC_TYPE_PRIMARY_VOLUME != pCurrDescHdr->uVolumeDescType) &&
  442.   (DESC_TYPE_SUPPL_VOLUME != pCurrDescHdr->uVolumeDescType) &&
  443.   (DESC_TYPE_VOLUME_PARTITION != pCurrDescHdr->uVolumeDescType) ) ||
  444. ((dwCurrDescLBN - g_pISO9660Info->dwSessionStartLBN) >= 20))
  445. {
  446. dbg_printf(("Volume-Recognition-Sequence Termination found.n"));
  447. break;
  448. }
  449. #ifdef _DEBUG
  450. // Check for a Boot-Record
  451. if (DESC_TYPE_BOOT == pCurrDescHdr->uVolumeDescType) {
  452. dbg_printf(("Boot Descriptor found.n"));
  453. dwCurrDescLBN++; // Skip to the next Descriptor
  454. continue;
  455. }
  456. // Check for a Volume-Partition
  457. if (DESC_TYPE_VOLUME_PARTITION == pCurrDescHdr->uVolumeDescType) {
  458. dbg_printf(("Volume-Partition Descriptor found.n"));
  459. dwCurrDescLBN++; // Skip to the next Descriptor
  460. continue;
  461. }
  462. #endif //_DEBUG
  463. // Any other type -- skip
  464. dbg_printf(("Skipping Volume-Descriptor of type: 0x%02x.n", pCurrDescHdr->uVolumeDescType));
  465. dwCurrDescLBN++;
  466. } //endof while()
  467. // When this point is reached, the entire File-Set Descriptor Sequence has been
  468. // scanned, and the Root-Directory's ICB possibly established.
  469. free(pCurrDescHdr);
  470. free(pPartialVolDesc);
  471. // Set the Current Directory to the Root-Directory, if it was established.
  472. if (bRootDirEstablished)
  473. g_pISO9660Info->dwCurrDirICB= g_pISO9660Info->dwRootDirICB;
  474. // Currently, no CWD is stored
  475. g_pISO9660Info->bCWDStored= FALSE;
  476. return bRootDirEstablished;
  477. }
  478. /////////////////////////////////////////////////////////////////////////////
  479. // Navigation
  480. /////////////////////////////////////////////////////////////////////////////
  481. // ISO9660_goToRootDir()
  482. //
  483. // Description: Sets the current working-directory to the Root directory.
  484. //
  485. // Input: None
  486. // Output: None
  487. // In/Out: None
  488. // Return: TRUE if the current working-directory was successfully switched
  489. // to the Root; FALSE otherwise.
  490. //
  491. // Remarks: None
  492. BOOL ISO9660_goToRootDir(void)
  493. {
  494. dbg_printf(("ISO9660_goToRootDir() calling.n"));
  495. g_pISO9660Info->dwCurrDirICB= g_pISO9660Info->dwRootDirICB;
  496. return TRUE;
  497. }
  498. DWORD ISO9660_GetcurrentDirICB(void)
  499. {
  500. return g_pISO9660Info->dwCurrDirICB;
  501. }
  502. void ISO9660_SetCurrentDirICB(DWORD CurrentDirICB)
  503. {
  504. g_pISO9660Info->dwCurrDirICB = CurrentDirICB;
  505. }
  506. /////////////////////////////////////////////////////////////////////////////
  507. // ISO9660_changeDir()
  508. //
  509. // Description: Changes the current working-directory to a desired directory.
  510. //
  511. // Input: i_pszDestDirName - A string holding the name of the destination
  512. //    Directory.
  513. // Output: None
  514. // In/Out: None
  515. // Return: TRUE if the current working-directory was successfully changed;
  516. // FALSE otherwise.
  517. //
  518. // Remarks:
  519. // 1. The destination Directory must be a direct descendant of the current
  520. //    working-directory.
  521. // 2. Only a single directory may be specified inside i_pszDestDirName.
  522. //    I.e., i_pszDestDirName is treated as a name of a single directory
  523. //    (directory hierarchy cannot be specified).
  524. BOOL ISO9660_changeDir(LPCWSTR i_pszDestDirName)
  525. {
  526. UINT16 hFileRecFind;
  527. struct DirFileRecord *pDestDirRec;
  528. dbg_printf(("ISO9660_changeDir() calling.n"));
  529. // Try to locate a Directory/File Record corresponding to the required Directory
  530. hFileRecFind= _findFirstFileRecord(i_pszDestDirName, FILE_FLAGS_DIRECTORY, 
  531.    FILE_FLAGS_DIRECTORY, &pDestDirRec);
  532. if (NULL == hFileRecFind)
  533. return FALSE;
  534. // The appropriate Directory was found: record the location of its ICB for
  535. // future use.
  536. g_pISO9660Info->dwCurrDirICB= BB_DWORD(pDestDirRec->dwExtentLocation);
  537. // Free the file record and terminate the search
  538. free(pDestDirRec);
  539. _findClose(hFileRecFind);
  540. return TRUE;
  541. }
  542. /////////////////////////////////////////////////////////////////////////////
  543. // ISO9660_goUp()
  544. //
  545. // Description: Moves up one level in the Directories hierarchy.
  546. //
  547. // Input: None
  548. // Output: None
  549. // In/Out: None
  550. // Return: TRUE if the current working-directory was successfully changed;
  551. // FALSE otherwise.
  552. //
  553. // Remarks:
  554. // This method changes the current working-directory to its direct parent
  555. // in the Directories hierarchy. If the current working-directory is already
  556. // the Root when this method is called, no change is made.
  557. BOOL ISO9660_goUp(void)
  558. {
  559. WCHAR szParentDirname[2];
  560. UINT16 hFileRecFind;
  561. struct DirFileRecord *pParentDirRec;
  562. dbg_printf(("ISO9660_goUp() calling.n"));
  563. // Prohibit climbing up from the Root Directory
  564. if (g_pISO9660Info->dwRootDirICB == g_pISO9660Info->dwCurrDirICB)
  565. return TRUE;
  566. // Locate the Parent-Directory of the Current Directory
  567. _str2wcs(FILE_FILEID_PARENT, szParentDirname, sizeof(szParentDirname));
  568. hFileRecFind= _findFirstFileRecord((LPCWSTR)szParentDirname, FILE_FLAGS_DIRECTORY, 
  569.    FILE_FLAGS_DIRECTORY, &pParentDirRec);
  570. if (NULL == hFileRecFind)
  571. return FALSE;
  572. // Record the location of the Parent-Directory
  573. g_pISO9660Info->dwCurrDirICB= BB_DWORD(pParentDirRec->dwExtentLocation);
  574. // Free the file record and terminate the search
  575. free(pParentDirRec);
  576. _findClose(hFileRecFind);
  577. return TRUE;
  578. }
  579. /////////////////////////////////////////////////////////////////////////////
  580. // ISO9660_storeWorkingDirectory()
  581. //
  582. // Description: Stores the position of the Current Working Directory.
  583. //
  584. // Input: None
  585. // Output: None
  586. // In/Out: None
  587. // Return: None
  588. //
  589. // Remarks:
  590. // The position of the Current Directory is unconditionally stored, and may
  591. // be later recalled via ISO0660_recallWorkingDirectory().
  592. // This method is useful for peeking into different directories, and then
  593. // restoring the original Working-Directory.
  594. void ISO9660_storeWorkingDirectory(void)
  595. {
  596. // Store the Working-Directory and set the Storage indicator
  597. g_pISO9660Info->dwCWDStorage= g_pISO9660Info->dwCurrDirICB;
  598. g_pISO9660Info->bCWDStored= TRUE;
  599. return;
  600. }
  601. /////////////////////////////////////////////////////////////////////////////
  602. // ISO0660_recallWorkingDirectory()
  603. //
  604. // Description: Recalls the position of the Current Working Directory.
  605. //
  606. // Input: None
  607. // Output: None
  608. // In/Out: None
  609. // Return: None
  610. //
  611. // Remarks:
  612. // The position of the Current Directory is stored only if it has been
  613. // previously stored via ISO9660_storeWorkingDirectory().
  614. void ISO9660_recallWorkingDirectory(void)
  615. {
  616. // Restore the Working-Directory
  617. if (g_pISO9660Info->bCWDStored)
  618. g_pISO9660Info->dwCurrDirICB= g_pISO9660Info->dwCWDStorage;
  619. // Clear the Storage indicator
  620. g_pISO9660Info->bCWDStored= FALSE;
  621. return;
  622. }
  623. /////////////////////////////////////////////////////////////////////////////
  624. // Queries
  625. /////////////////////////////////////////////////////////////////////////////
  626. // ISO9660_getVolumeName()
  627. //
  628. // Description: Retrieves the Name of the Primary-Volume on the Medium.
  629. //
  630. // Input: None
  631. // Output: None
  632. // In/Out: None
  633. // Return: A pointer to a constant String, containing the Volume-Name.
  634. //
  635. // Remarks:
  636. // The returned String must not be modified or freed by the caller.
  637. void ISO9660_getVolumeName(LPCWSTR volumeName)
  638. {
  639. sc_GetBytes(SC_VOLUME_ID_ADDR, 0, FILESYSTEM_MAX_VOLUME_NAME*sizeof(WCHAR), (BYTE*)volumeName);
  640. return;
  641. }
  642. /////////////////////////////////////////////////////////////////////////////
  643. // ISO9660_fileExists()
  644. //
  645. // Description: Tests whether a certain file exists in the current working-
  646. // directory, or not.
  647. //
  648. // Input: i_pszFilename - A string holding the name of the File to test.
  649. // Output: None
  650. // In/Out: None
  651. // Return: TRUE if the requested File exists in the current working-directory;
  652. // FALSE otherwise.
  653. //
  654. // Remarks:
  655. // A return value of FALSE may also indicate that the currently-selected
  656. // File-System is unknown. The user is responsible for verifying correctness
  657. // by assuring that the File-System type was selected and the File-System 
  658. // successfully initialized.
  659. BOOL ISO9660_fileExists(LPCWSTR i_pszFilename)
  660. {
  661. UINT16 hFileRecFind;
  662. struct DirFileRecord *pDestDirRec;
  663. dbg_printf(("ISO9660_fileExists() calling.n"));
  664. // Try to locate a File-ID Descriptor corresponding to the required File; Specify
  665. // that the required file must be non-directory, not hidden, not a Parent, and undeleted.
  666. hFileRecFind= _findFirstFileRecord(i_pszFilename, 
  667.    (FILE_FLAGS_DIRECTORY | FILE_FLAGS_HIDDEN),
  668.    0x0, &pDestDirRec);
  669. if (NULL == hFileRecFind)
  670. return FALSE;
  671. // Free the file record and terminate the search
  672. free(pDestDirRec);
  673. _findClose(hFileRecFind);
  674. return TRUE;
  675. }
  676. /////////////////////////////////////////////////////////////////////////////
  677. // ISO9660_fileLocation()
  678. //
  679. // Description: Retrieves the location of a certain file (its start address).
  680. //
  681. // Input: i_pszFilename - A string holding the name of the requested File.
  682. // Output: o_pFileLocation - Points to a DWORD to receive the File's start
  683. //   address.
  684. // In/Out: None
  685. // Return: TRUE if the requested File was located and its address retrieved;
  686. // FALSE otherwise.
  687. //
  688. // Remarks:
  689. // 1. A return value of FALSE indicates that the requested File does not
  690. //    exist in the current working-directory.
  691. // 2. The File's start-address is given in terms of the Medium's native
  692. //    addressing system. E.g., for Optical-Storage Media, the returned
  693. //    address is expressed in terms of Logical-Block-Number (LBN).
  694. BOOL ISO9660_fileLocation(LPCWSTR i_pszFilename, DWORD *o_pFileLocation)
  695. {
  696. UINT16 hFileRecFind;
  697. struct DirFileRecord *pFileRec;
  698. dbg_printf(("ISO9660_fileLocation() calling.n"));
  699. // Try to locate a Directory/File Record corresponding to the required File; Specify
  700. // that the required file must be non-directory and not hidden.
  701. hFileRecFind= _findFirstFileRecord(i_pszFilename,
  702.    (FILE_FLAGS_DIRECTORY | FILE_FLAGS_HIDDEN),
  703.    0x0, &pFileRec);
  704. if (NULL == hFileRecFind)
  705. return FALSE;
  706. *o_pFileLocation= BB_DWORD(pFileRec->dwExtentLocation);
  707. // Free the file record and terminate the search
  708. free(pFileRec);
  709. _findClose(hFileRecFind);
  710. return TRUE;
  711. }
  712. /////////////////////////////////////////////////////////////////////////////
  713. // ISO9660_findFirstFile()
  714. //
  715. // Description: Initiates a search for a certain file, or collection of
  716. // files.
  717. //
  718. // Input: i_pszFilename - A string holding the name of the requested File,
  719. // or a pattern to match.
  720. // Output: o_pFindData - Points to a FindData structure, to receive the File's
  721. //   details upon successful completion of the search.
  722. // In/Out: None
  723. // Return: A UINT16 which serves as the Handle to this search. This value
  724. // must be saved for later use with other find-related methods.
  725. // NULL is returned if the search fails.
  726. //
  727. // Remarks:
  728. // 1. The user must save the returned Handle in order to supply it to future
  729. //    calls to any of the other find-related methods.
  730. // 2. If the returned Handle is NULL, then no File matching the supplied
  731. //    name/pattern could be located in the current working-directory.
  732. // 3. The search is limited to the current working-directory only.
  733. // 4. The following patterns may be supplied in i_pszFilename:
  734. // - An empty string ("") - matches any File/Sub-Directory;
  735. // - Some non-empty string: treated as a Filename/Sub-Directory prefix.
  736. //   For a string of length N, only the first N characters are used
  737. //   for matching.
  738. //   For example: supplying a value of i_pszFilename="A" would retrieve
  739. //   the first File/Sub-Directory whose name begins with a Captial 'A',
  740. //   if such a File/Sub-Directory exists.
  741. // 5. The search is Case-Sensitive.
  742. // 6. ISO9660_findClose() must be called when no additional searches are needed.
  743. UINT16 ISO9660_findFirstFile(LPCWSTR i_pszPattern, FindData *o_pFindData)
  744. {
  745. UINT16 hFileRecFind;
  746. struct DirFileRecord *pFileRec;
  747. dbg_printf(("ISO9660_findFirstFile() calling.n"));
  748. // Try to locate a Directory/File Record corresponding to the required File.
  749. // There are no restrictions over the file's Attributes (find any File/Directory).
  750. hFileRecFind= _findFirstFileRecord(i_pszPattern, 0x0, 0x0, &pFileRec);
  751. if (NULL == hFileRecFind)
  752. return NULL;
  753. // Acquire the found item's Attributes
  754. _getFileAttributes((const struct DirFileRecord *)pFileRec, o_pFindData);
  755. // Free the found record
  756.    free(pFileRec);
  757. return hFileRecFind;
  758. }
  759. /////////////////////////////////////////////////////////////////////////////
  760. // ISO9660_findNextFile()
  761. //
  762. // Description: Continues a search that was previously initiated using a call
  763. // to ISO9660_findFirstFile().
  764. //
  765. // Input: hFindFile - A Handle to a file-search, that was returned from 
  766. // a previous call to ISO9660_findFirstFile().
  767. // Output: o_pFindData - Points to a FindData structure, to receive the File's
  768. //   details upon successful completion of the search.
  769. // In/Out: None
  770. // Return: TRUE if the search succeeded, and an additional File matching
  771. // the Filename/pattern was found. In this case, the supplied
  772. // o_pFindData contains updated information of the found File.
  773. // FALSE is returned if no more Files/Sub-Directories matching the
  774. // supplied Filename/pattern could be found. In this case, the
  775. // supplied o_pFindData is invalid.
  776. //
  777. // Remarks:
  778. // 1. This method continues a previous search from the point it left off.
  779. // 2. The search relates to the Directory that was the current working-
  780. //    directory at the time the search was initiated via ISO9660_findFirstFile().
  781. // 3. The search uses the same Filename/pattern as was originally supplied
  782. //    to ISO9660_findFirstFile().
  783. // 4. ISO9660_findClose() must be called when no additional searches are needed.
  784. BOOL ISO9660_findNextFile(UINT16 hFindFile, FindData *o_pFindData)
  785. {
  786. struct DirFileRecord *pFileRec;
  787. dbg_printf(("ISO9660_findNextFile() calling.n"));
  788. // Continue the Search
  789. if (! _findNextFileRecord((WORD)hFindFile, &pFileRec))
  790. return FALSE;
  791. // Acquire the found item's Attributes
  792. _getFileAttributes((const struct DirFileRecord *)pFileRec, o_pFindData);
  793. // Free the found record
  794. free(pFileRec);
  795. return TRUE;
  796. }
  797. /////////////////////////////////////////////////////////////////////////////
  798. // ISO9660_findClose()
  799. //
  800. // Description: Terminates a file-search.
  801. //
  802. // Input: hFindFile - A Handle to a file-search, that was returned from 
  803. // a previous call to ISO9660_findFirstFile().
  804. // Output: None
  805. // In/Out: None
  806. // Return: TRUE if the search was successfully terminated; FALSE othewise.
  807. //
  808. // Remarks:
  809. // Any search that is initiated via ISO9660_findFirstFile() must be terminated
  810. // using a call to this method, in order to allow for proper release of
  811. // resources that were allocated for that search.
  812. BOOL ISO9660_findClose(UINT16 hFileFind)
  813. {
  814. dbg_printf(("ISO9660_findClose() calling.n"));
  815. return _findClose((WORD)hFileFind);
  816. }
  817. /////////////////////////////////////////////////////////////////////////////
  818. // ISO9660_getFilesFirst()
  819. //
  820. // Description: Get all files in the indicated directory.
  821. //
  822. // Input: LPCWSTR i_pszFilename: The directory name which want to get from
  823. // UINT16 uGetFileCount: The files count which want get
  824. //
  825. // Output: UINT16 *o_uGetFileNum: The files count which has been get
  826. // FindData *o_pGetData: Points to a FindData structure, to receive the File's
  827. //   details upon successful completion of the search.
  828. //
  829. // In/Out: None
  830. // Return: A UINT16, which is the ID of the search, and should be passed
  831. // to future calls to any of the search-related methods.
  832. // NULL is returned if no File matching the requested criteria could
  833. // be found.
  834. //
  835. // Remarks:
  836. // Any search that is initiated via ISO9660_getFilesFirst() must be terminated
  837. // using a call to this method, in order to allow for proper release of
  838. // resources that were allocated for that search. 
  839. //  If the call to ISO9660_getFilesFirst() returned NULL, it is prohibited 
  840. // to call ISO9660_getFilesClose().
  841. // If you want to get current directory, you can give the i_pszFilename with L""
  842. // If you want to get parent directory, you can give the i_pszFilename with L"1"
  843. // If you want to get root directory, you can give the i_pszFilename with L"\"
  844. UINT16 ISO9660_getFilesFirst(LPCWSTR i_pszFilename, UINT16 uGetFileCount, UINT16 *o_uGetFileNum, FindData *o_pGetData)
  845. {
  846. BOOL bSuccess;
  847. UINT16 hFileRecFind;
  848. struct DirFileRecord *pFileRec;
  849. DirectorySearchInfo dsiInfo;
  850. UINT16 uSearchID;
  851. dbg_printf(("ISO9660_getFilesFirst() calling.n"));
  852. if( (i_pszFilename[0]==(WCHAR)'\' || i_pszFilename[0]==(WCHAR)'')
  853. && i_pszFilename[1]==0)
  854. {
  855. if(i_pszFilename[0]==(WCHAR)'\' && i_pszFilename[1]==0)
  856. dsiInfo.dwDirICB=g_pISO9660Info->dwRootDirICB;
  857. else
  858. dsiInfo.dwDirICB=g_pISO9660Info->dwCurrDirICB;
  859. pFileRec=(struct DirFileRecord*)malloc(sizeof(struct DirFileRecord)+1);
  860. if (NULL == pFileRec)
  861. {
  862. dbg_printf(("WARNING: ISO9660_getFilesFirst() Failed [1]:n"));
  863. *o_uGetFileNum=0;
  864. return NULL;
  865. }
  866. if(!AuxCache_GetBytes(dsiInfo.dwDirICB, 0, sizeof(struct DirFileRecord)+1, (BYTE*)pFileRec))
  867. {
  868. dbg_printf(("WARNING: ISO9660_getFilesFirst() Failed [2]:n"));
  869. free(pFileRec);
  870. *o_uGetFileNum=0;
  871. return NULL;
  872. }
  873. if(1 == pFileRec->cbLengthOfFileID && 0 == pFileRec->sFileID[0])
  874. dsiInfo.dwDirectorySize = BB_DWORD( pFileRec->dwDataLength );
  875. else
  876. {
  877. dbg_printf(("WARNING: ISO9660_getFilesFirst() Failed [3]: Directory record was error.n"));
  878. free(pFileRec);
  879. *o_uGetFileNum=0;
  880. return NULL;
  881. }
  882. free(pFileRec);
  883. }
  884. else
  885. {
  886. hFileRecFind= _findFirstFileRecord(i_pszFilename,FILE_FLAGS_DIRECTORY,
  887.    FILE_FLAGS_DIRECTORY, &pFileRec);
  888. if (NULL == hFileRecFind)
  889. {
  890. dbg_printf(("WARNING: ISO9660_getFilesFirst() Failed [4]: Directory no found.n"));
  891. *o_uGetFileNum=0;
  892. return NULL;
  893. }
  894. dsiInfo.dwDirICB = BB_DWORD( pFileRec->dwExtentLocation );
  895. dsiInfo.dwDirectorySize = BB_DWORD( pFileRec->dwDataLength );
  896. // Free the file record and terminate the search
  897. free(pFileRec);
  898. _findClose(hFileRecFind);
  899. }
  900. dsiInfo.uDirNumber = 0;
  901. dsiInfo.pszFileID = NULL;
  902. dsiInfo.uFileFlagsMask = 0;
  903. dsiInfo.uFileFlags = 0;
  904. dsiInfo.hDirFileRecordList = 0;
  905. dsiInfo.cbRecListOffset = 0;
  906. dsiInfo.cbCurrRecOffset = 0;
  907. // Allocate a Search-Info
  908. uSearchID= _FileSys_allocateSearchInfo();
  909. if (NULL == uSearchID) {
  910. dbg_printf(("WARNING: ISO9660_getFilesFirst() Failed [5]: No available Search-Info IDn"));
  911. *o_uGetFileNum=0;
  912. return NULL;
  913. }
  914. // Register the Directory-Search Info in the Search-Info Pool
  915. bSuccess= _FileSys_setSearchInfo(uSearchID, (const BYTE*)&dsiInfo);
  916. if (! bSuccess) {
  917. dbg_printf(("FATAL: ISO9660_getFilesFirst() Failed [6]: Cannot register new Searchn"));
  918. }
  919. // Now, the information in dsiInfo is stable and complete: perform the search
  920. if (bSuccess)
  921. if(!(*o_uGetFileNum = ISO9660_getFilesNext(uSearchID, uGetFileCount, o_pGetData)))
  922. {
  923. dbg_printf(("WARNING: ISO9660_getFilesFirst() Failed [7]: Could not find a matchn"));
  924. bSuccess= FALSE;
  925. }
  926. if (! bSuccess) {
  927. _FileSys_freeSearchInfo(uSearchID);
  928. *o_uGetFileNum=0;
  929. return NULL;
  930. }
  931. return uSearchID;
  932. }
  933. /////////////////////////////////////////////////////////////////////////////
  934. // ISO9660_getFilesNext()
  935. //
  936. // Description: Continues to get the files that was previously initiated using a call
  937. // to ISO9660_getFilesFirst().
  938. //
  939. // Input: UINT16 hFindFile: A Handle to a file-search, that was returned from 
  940. // a previous call to ISO9660_getFilesFirst().
  941. // UINT16 uGetFileCount: 
  942. // Output: FindData *o_pGetData: Points to a FindData structure, to receive the File's
  943. //   details upon successful completion of the search.
  944. // In/Out: None
  945. // Return: >0 if the search succeeded, and return the get files count.
  946. // and the o_pGetData is valid.
  947. // 0 is returned if no more Files could be get. In this case, the
  948. // supplied o_pGetData is invalid.
  949. //
  950. // Remarks:
  951. // 1. This method continues a previous search from the point it left off.
  952. // 2. The search relates to the Directory that was the current working-
  953. //    directory at the time the search was initiated via ISO9660_getFilesFirst().
  954. // 3. The search uses the same Filename/pattern as was originally supplied
  955. //    to ISO9660_findFirstFile().
  956. // 4. ISO9660_findClose() must be called when no additional searches are needed.
  957. UINT16 ISO9660_getFilesNext(UINT16 uSearchID,UINT16 uGetFileCount, FindData *o_pGetData)
  958. {
  959. UINT16 uGetNum=0;
  960. struct DirFileRecord *pRec;
  961. DirectorySearchInfo dsiInfo;
  962. LPWSTR pszSeparator2;
  963. dbg_printf(("ISO9660_getFilesNext() calling.n"));
  964. // Retrieve the Directory-Search Info from the Search-Pool
  965. if ((NULL == uSearchID) ||
  966. ! _FileSys_getSearchInfo(uSearchID, (BYTE*)&dsiInfo))
  967. {
  968. dbg_printf(("WARNING: ISO9660_getFilesNext() Failed [1]: Directory no found.n"));
  969. return FALSE;
  970. }
  971. if(dsiInfo.cbRecListOffset >= dsiInfo.dwDirectorySize)
  972. {
  973. dbg_printf(("WARNING: ISO9660_getFilesNext() Failed [2]: This directory has already get all files.n"));
  974. return 0;
  975. }
  976. pRec= (struct DirFileRecord *)malloc(MAX_FILEREC_SIZE);
  977. if (NULL == pRec) {
  978. tr_printf(("FATAL: ISO9660_getFilesNext() Failed [3]: Low system resourcesn"));
  979. return NULL;
  980. }
  981. for(uGetNum=0;( uGetNum<uGetFileCount ) && ( dsiInfo.cbRecListOffset < dsiInfo.dwDirectorySize );
  982. uGetNum++)
  983. {
  984. if (! AuxCache_GetBytes(dsiInfo.dwDirICB+dsiInfo.cbRecListOffset/2048, dsiInfo.cbRecListOffset%2048, 
  985. MAX_FILEREC_SIZE, (BYTE*)pRec))
  986. {
  987. dbg_printf(("WARNING: ISO9660_getFilesNext() Failed [4]n"));
  988. free(pRec);
  989. return NULL;
  990. }
  991. if( 0 == pRec->cbLengthOfDirRecord )
  992. {
  993. dsiInfo.cbRecListOffset = (dsiInfo.cbRecListOffset/2048 + 1) * 2048;
  994. uGetNum--;
  995. continue;
  996. }
  997. else
  998. dsiInfo.cbRecListOffset += pRec->cbLengthOfDirRecord;
  999. _getFileAttributes(pRec,&(o_pGetData[uGetNum]));
  1000. }
  1001. free(pRec);
  1002. // Update the Directory-Search Info in the Search-Pool
  1003. if (! _FileSys_setSearchInfo(uSearchID, (const BYTE*)&dsiInfo)) {
  1004. dbg_printf(("WARNING: ISO9660_getFilesNext() Failed [5]n"));
  1005. }
  1006. return uGetNum;
  1007. }
  1008. /////////////////////////////////////////////////////////////////////////////
  1009. // ISO9660_getFilesClose()
  1010. //
  1011. // Description: Terminates a file-get.
  1012. //
  1013. // Input: hFindFile - A Handle to a file-search, that was returned from 
  1014. // a previous call to ISO9660_getFilesFirst().
  1015. // Output: None
  1016. // In/Out: None
  1017. // Return: TRUE if the search was successfully terminated; FALSE othewise.
  1018. //
  1019. // Remarks:
  1020. // Any search that is initiated via ISO9660_getFilesFirst() must be terminated
  1021. // using a call to this method, in order to allow for proper release of
  1022. // resources that were allocated for that search.
  1023. BOOL ISO9660_getFilesClose(UINT16 uSearchID)
  1024. {
  1025. DirectorySearchInfo dsiInfo;
  1026. dbg_printf(("ISO9660_getFilesClose() calling.n"));
  1027. // Retrieve the Directory-Search Info from the Search-Pool
  1028. if ((NULL == uSearchID) ||
  1029. ! _FileSys_getSearchInfo(uSearchID, (BYTE*)&dsiInfo))
  1030. {
  1031. return FALSE;
  1032. }
  1033. _FileSys_freeSearchInfo(uSearchID);
  1034. return TRUE;
  1035. }
  1036. /////////////////////////////////////////////////////////////////////////////
  1037. // ISO9660_checkValid()
  1038. //
  1039. // Description: Check whether the ISO9660 file system was valid or not
  1040. //
  1041. // Input: None
  1042. // Output: None
  1043. // In/Out: None
  1044. // Return: TRUE if the ISO9660 File-System was valid; FALSE otherwise.
  1045. //
  1046. // Remarks:
  1047. // 1. Check whether the ISO9660 path table was empty or not
  1048. //
  1049. BOOL ISO9660_checkValid()
  1050. {
  1051. BOOL iso9660_valid=TRUE;
  1052. DWORD dwCurrDescLBN;
  1053. DWORD dwRootDirICB,dwPathTableICB,dwPathTableSize;
  1054. DWORD dwTemp;
  1055. DWORD dwOffset=0;
  1056. struct PathTableRecord *pCurrRec;
  1057. struct GenericVolumeStructureDesc_Base *pCurrDescHdr;
  1058. struct VolumeDesc_Partial *pPartialVolDesc;
  1059. dbg_printf(("ISO9660_checkValid() calling.n"));
  1060. // Allocate space for a generic Descriptor base
  1061. pCurrDescHdr= (struct GenericVolumeStructureDesc_Base*)malloc(sizeof(struct GenericVolumeStructureDesc_Base));
  1062. if (NULL == pCurrDescHdr) {
  1063. tr_printf(("FATAL: ISO9660_checkValid() Failed [1]: Low system resourcesn"));
  1064. return FALSE;
  1065. }
  1066. // Allocate space for a Partial Volume Descriptor (will be used for Primary or Supplemantary 
  1067. // Volume descriptors).
  1068. pPartialVolDesc = (struct VolumeDesc_Partial*)malloc(sizeof(struct VolumeDesc_Partial));
  1069. if (NULL == pPartialVolDesc) {
  1070. tr_printf(("FATAL: ISO9660_checkValid() Failed [2]: Low system resourcesn"));
  1071. free(pCurrDescHdr);
  1072. return FALSE;
  1073. }
  1074. // Start searching for the Primary or Supplementary Volume Descriptor, while verifying the 
  1075. // integrity of the Volume-Recognition Sequence.
  1076. dwCurrDescLBN= (g_pISO9660Info->dwSessionStartLBN + VOLUME_RECOGNITION_SEQUENCE_START_LSN);
  1077. while (TRUE) 
  1078. {
  1079. // Read the first few bytes in order to determine the type of the descriptor
  1080. if (! AuxCache_GetBytes(dwCurrDescLBN, 0, sizeof(struct GenericVolumeStructureDesc_Base),
  1081.    (BYTE *)pCurrDescHdr)) 
  1082. {
  1083. dbg_printf(("WARNING: ISO9660_checkValid() Failed [3]n"));
  1084. break;
  1085. }
  1086. // Check for a Primary-Volume
  1087. if (DESC_TYPE_PRIMARY_VOLUME == pCurrDescHdr->uVolumeDescType) 
  1088. {
  1089. // Read the essential part of the descriptor
  1090. if (! AuxCache_GetBytes(dwCurrDescLBN, PARTIAL_VOLUME_DESC_OFFSET, 
  1091.    sizeof(struct VolumeDesc_Partial), (BYTE *)pPartialVolDesc))
  1092. {
  1093. dbg_printf(("WARNING: ISO9660_checkValid() Failed [4]n"));
  1094. iso9660_valid=FALSE;
  1095. break;
  1096. }
  1097. // Collect information of the Root-Directory
  1098. dwRootDirICB = BB_DWORD(pPartialVolDesc->rdrRootDir.dwExtentLocation);
  1099. // Build the Directory-Hierarchy Tree, based on the M-Type Path-Table or the L-Type Path-Table
  1100. #ifdef MOTOROLA
  1101. dwPathTableICB = pPartialVolDesc->dwLoactionOfMPathTable;
  1102. #else
  1103. dwPathTableICB = pPartialVolDesc->dwLocationOfLPathTable;
  1104. #endif //MOTOROLA
  1105. dwPathTableSize = BB_DWORD(pPartialVolDesc->dwPathTableSize);
  1106. dwOffset=0;
  1107. while(TRUE)
  1108. {
  1109. // Allocate room for a single Path-Table Record, used for iteration
  1110. pCurrRec= (struct PathTableRecord *)malloc(sizeof(struct PathTableRecord));
  1111. if (NULL == pCurrRec) {
  1112. dbg_printf(("WARNING: ISO9660_checkValid() Failed [5]n"));
  1113. break;
  1114. }
  1115. if (! AuxCache_GetBytes(dwPathTableICB, dwOffset, 
  1116.    sizeof(struct PathTableRecord), (BYTE *)pCurrRec))
  1117. {
  1118. dbg_printf(("WARNING: ISO9660_checkValid() Failed [6]n"));
  1119. free(pCurrRec);
  1120. iso9660_valid=FALSE;
  1121. break;
  1122. }
  1123. if (0 == pCurrRec->cbLengthOfDirID && 0 == pCurrRec->dwExtentLocation && 0 == pCurrRec->uParentDirNumber)
  1124. {
  1125. dbg_printf(("WARNING: ISO9660_checkValid() Failed [7]: The Path Table is Empty!n"));
  1126. free(pCurrRec);
  1127.                if(0 == dwOffset) //jerry cai, only if the first record is invalid, the file system is invalid.
  1128. iso9660_valid=FALSE;
  1129. break;
  1130. }
  1131. dwOffset += (sizeof(struct PathTableRecord) + pCurrRec->cbLengthOfDirID);
  1132. if (pCurrRec->cbLengthOfDirID & 0x1)
  1133. dwOffset++;
  1134. free(pCurrRec);
  1135. if(dwOffset>=dwPathTableSize)
  1136. break;
  1137. }
  1138. dwCurrDescLBN++; // Move to the next Descriptor
  1139. continue;
  1140. }
  1141. // Check for a Terminator
  1142. if (( (DESC_TYPE_BOOT != pCurrDescHdr->uVolumeDescType) &&
  1143.   (DESC_TYPE_PRIMARY_VOLUME != pCurrDescHdr->uVolumeDescType) &&
  1144.   (DESC_TYPE_SUPPL_VOLUME != pCurrDescHdr->uVolumeDescType) &&
  1145.   (DESC_TYPE_VOLUME_PARTITION != pCurrDescHdr->uVolumeDescType) ) ||
  1146. ((dwCurrDescLBN - g_pISO9660Info->dwSessionStartLBN) >= 20))
  1147. {
  1148. dbg_printf(("Volume-Recognition-Sequence Termination found.n"));
  1149. break;
  1150. }
  1151. // Any other type -- skip
  1152. dbg_printf(("Skipping Volume-Descriptor of type: 0x%02x.n", pCurrDescHdr->uVolumeDescType));
  1153. dwCurrDescLBN++;
  1154. } //endof while()
  1155. // When this point is reached, the entire File-Set Descriptor Sequence has been
  1156. // scanned, and the Root-Directory's ICB possibly established.
  1157. free(pCurrDescHdr);
  1158. free(pPartialVolDesc);
  1159. return iso9660_valid;
  1160. }
  1161. /////////////////////////////////////////////////////////////////////////////
  1162. // Private Services
  1163. /////////////////////////////////////////////////////////////////////////////
  1164. // _buildDirectoryTree()
  1165. //
  1166. // Description: Builds an Array describing the Directories, based on the
  1167. // Volume Descriptor's Path-Table.
  1168. //
  1169. // Input: dwPathTableAddress - Holds the starting address of the Path-Table.
  1170. // dwPathTableSize - Holds the size of the Path-Table.
  1171. // Output: None
  1172. // In/Out: None
  1173. // Return: TRUE if the entire Path Table was extracted; FALSE otherwise.
  1174. //
  1175. // Remarks: None
  1176. static BOOL _buildDirectoryTree(DWORD dwPathTableAddress, DWORD dwPathTableSize)
  1177. {
  1178. UINT16 uDirsCnt= 0;
  1179. UINT16 uMaxDirsCnt= (UINT16)(dwPathTableSize / sizeof(struct PathTableRecord));
  1180. DWORD  cbCurrRecOffset= 0;
  1181. BOOL   bSuccess= TRUE;
  1182. struct PathTableRecord *pCurrRec;
  1183. // Allocate room for a single Path-Table Record, used for iteration
  1184. pCurrRec= (struct PathTableRecord *)malloc(sizeof(struct PathTableRecord));
  1185. if (NULL == pCurrRec) {
  1186. dbg_printf(("WARNING: _buildDirectoryTree() Failed [1]n"));
  1187. return FALSE;
  1188. }
  1189. // If the Directories Tree was previously allocated, free that allocation
  1190. if (NULL != g_pISO9660Info->hDirTree)
  1191. Array_destruct(g_pISO9660Info->hDirTree);
  1192. // Allocate the Array that will hold the Directories-Tree
  1193. g_pISO9660Info->hDirTree= Array_construct(uMaxDirsCnt, sizeof(DirectoryNode), NULL);
  1194. if (NULL == g_pISO9660Info->hDirTree) {
  1195. dbg_printf(("WARNING: _buildDirectoryTree() Failed [2]: Low system resources.n"));
  1196. free(pCurrRec);
  1197. return FALSE;
  1198. }
  1199. // Start scanning the Path-Table, adding new Directories Nodes to the array along the way
  1200. while (cbCurrRecOffset < dwPathTableSize) {
  1201. DirectoryNode dnCurrDir;
  1202. // Read Path-Table's base contents
  1203. if (! AuxCache_GetBytes(dwPathTableAddress, cbCurrRecOffset, sizeof(struct PathTableRecord),
  1204.    (BYTE*)pCurrRec)) 
  1205. {
  1206. dbg_printf(("WARNING: _buildDirectoryTree() Failed [3]n"));
  1207. bSuccess= FALSE;
  1208. break;
  1209. }
  1210. // Copy the Parent-Directory Number and the Extent-Location
  1211. dnCurrDir.uParentDirNumber= pCurrRec->uParentDirNumber;
  1212. dnCurrDir.dwDirICB= pCurrRec->dwExtentLocation;
  1213. // Set the new Directory-Node
  1214. if (! Array_setAt(g_pISO9660Info->hDirTree, uDirsCnt++, (BYTE*)&dnCurrDir)) {
  1215. dbg_printf(("WARNING: _buildDirectoryTree() Failed [4]n"));
  1216. bSuccess= FALSE;
  1217. break;
  1218. }
  1219. // Move to the next Record
  1220. cbCurrRecOffset += (sizeof(struct PathTableRecord) + pCurrRec->cbLengthOfDirID);
  1221. if (pCurrRec->cbLengthOfDirID & 0x1)
  1222. cbCurrRecOffset++;
  1223. }
  1224. free(pCurrRec);
  1225. // Get rid of any Extra-Memory, that was not actually used
  1226. Array_freeExtra(g_pISO9660Info->hDirTree);
  1227. if (bSuccess) {
  1228. // Record the total number of Directories
  1229. g_pISO9660Info->uDirectoryCnt= uDirsCnt;
  1230. }
  1231. else {
  1232. Array_destruct(g_pISO9660Info->hDirTree);
  1233. g_pISO9660Info->hDirTree= NULL;
  1234. }
  1235. return TRUE;
  1236. }
  1237. /////////////////////////////////////////////////////////////////////////////
  1238. // _findFirstFileRecord()
  1239. //
  1240. // Description: Initiates a search for the first occurrence of a File-Record
  1241. // structure describing a File/Sub-Directory that meets the 
  1242. // supplied criteria.
  1243. //
  1244. // Input: i_pszFileID - A string holding the requested Filename/pattern.
  1245. // uFileFlagsMask - A Mask to apply to the File's Flags.
  1246. // uFileFlags - A combination of Flags, that should match.
  1247. // Output: o_pFileRecordPtr - Points to a DirFileRecord Pointer, to receive
  1248. //    the File-Record of a matching File/Sub-Directory.
  1249. // In/Out: None
  1250. // Return: A UINT16, which is the ID of the search, and should be passed
  1251. // to future calls to any of the search-related methods.
  1252. // NULL is returned if no File matching the requested criteria could
  1253. // be found.
  1254. //
  1255. // Remarks:
  1256. // 1. The supplied i_pszFileID can be a Filename or a pattern, as described
  1257. //    in the documentation for ISO9660_findFirstFile().
  1258. // 2. uFileFlagsMask is a Mask that is applied to any File-Record whose 
  1259. //    File-ID mathces the supplied Filename/pattern. This mask is applied
  1260. //    to that item's Flags.
  1261. // 3. uFileFlags is compared against the Masked Flags of a matching item.
  1262. //    If there is a match, then the whole item is considered to match the
  1263. //    requested criteria.
  1264. // 4. The returned ID should be saved for future use with search-related
  1265. //    methods.
  1266. // 5. A return value of NULL indicates that no File/Sub-Directory matching
  1267. //    the requested criteria could be found. That might happen also because there
  1268. //    isn't enough memory in the system.
  1269. // 6. The search is limited to the current working-directory.
  1270. // 7. The search is Case-Sensitive.
  1271. // 8. The returned File-Record Pointer should be considered persistant
  1272. //    across calls. The caller has to make sure that o_pFileRecordPtr 
  1273. //    is freed when it is no longer needed.
  1274. // 9. _findClose() must be called when no additional searches are needed.
  1275. static UINT16 _findFirstFileRecord(LPCWSTR i_pszFileID, UINT8 uFileFlagsMask, 
  1276.    UINT8 uFileFlags, 
  1277.    struct DirFileRecord **o_pFileRecordPtr)
  1278. {
  1279. BOOL bSuccess;
  1280. BOOL bWildcardSearch;
  1281. UINT8  cbFirstRecordSize;
  1282. UINT16 uDirFileRecListSizeInCont;
  1283. UINT16 uDirNodePos;
  1284. UINT16 uSearchID;
  1285. DWORD dwCurrDirSize;
  1286. struct ReservedDirRecord *pRec;
  1287. DirectorySearchInfo dsiInfo;
  1288. // Find the size of the first record and the size of the entire directory.
  1289. // Load only the self descriptor and then save both sizes in local variables.
  1290. // After that there is no need to keep the self descriptor anymore.
  1291. pRec= (struct ReservedDirRecord *)malloc(sizeof(struct ReservedDirRecord));
  1292. if (NULL == pRec) {
  1293. tr_printf(("FATAL: _findFirstFileRecord() Failed [1]: Low system resourcesn"));
  1294. return NULL;
  1295. }
  1296. if (! AuxCache_GetBytes(g_pISO9660Info->dwCurrDirICB, 0, sizeof(struct ReservedDirRecord), 
  1297. (BYTE*)pRec))
  1298. {
  1299. dbg_printf(("WARNING: _findFirstFileRecord() Failed [2]n"));
  1300. free(pRec);
  1301. return NULL;
  1302. }
  1303. // Collect the Directory's Size and the size of the first record
  1304. dwCurrDirSize= BB_DWORD(pRec->dwDataLength);
  1305. cbFirstRecordSize= pRec->cbLengthOfDirRecord;
  1306. free(pRec);
  1307. // Check if the Directory has anything in it. I.e., if its size is larger
  1308. // than the length of the first Record (which is the self-descriptor).
  1309. if (dwCurrDirSize == (DWORD)cbFirstRecordSize) {
  1310. // If the Current Directory is Empty, there's no point in continuing the search
  1311. dbg_printf(("Empty Directory found.n"));
  1312. return NULL;
  1313. }
  1314. // Allocate space for the Records List Cache
  1315. uDirFileRecListSizeInCont= CONTAINER_COUNT(DIRECTORY_RECLIST_SZ);
  1316. dsiInfo.hDirFileRecordList= sc_Malloc(uDirFileRecListSizeInCont);
  1317. if (NULL_HANDLE == dsiInfo.hDirFileRecordList) {
  1318. tr_printf(("FATAL: _findFirstFileRecord() Failed [3]: Low system resourcesn"));
  1319. return NULL;
  1320. }
  1321. // Cache the beginning of the Directory's contents (Record-List)
  1322. if (! sc_CopyFromDisc(g_pISO9660Info->dwCurrDirICB, cbFirstRecordSize, DIRECTORY_RECLIST_SZ, 
  1323.   dsiInfo.hDirFileRecordList))
  1324. {
  1325. dbg_printf(("WARNING: _findFirstFileRecord() Failed [4]n"));
  1326. sc_Free(dsiInfo.hDirFileRecordList, uDirFileRecListSizeInCont);
  1327. return NULL;
  1328. }
  1329. // Copy the necessary information into the DirSearchInfo, and initialize it
  1330. dsiInfo.dwDirICB= g_pISO9660Info->dwCurrDirICB;
  1331. dsiInfo.dwDirectorySize= dwCurrDirSize;
  1332. // In case of a Wildcard search, use a static string for File-ID, instead of allocating
  1333. // memory.
  1334. bWildcardSearch= ((0 == i_pszFileID[0]) ? TRUE : FALSE);
  1335. if (bWildcardSearch) {
  1336. dsiInfo.pszFileID= (LPWSTR)g_pszWildcardSearch;
  1337. }
  1338. else {
  1339. dsiInfo.pszFileID= (LPWSTR)malloc((1 + wcslen(i_pszFileID)) * sizeof(WCHAR));
  1340. if (NULL == dsiInfo.pszFileID) {
  1341. tr_printf(("FATAL: _findFirstFileRecord() Failed [5]: Low system resourcesn"));
  1342. sc_Free(dsiInfo.hDirFileRecordList, uDirFileRecListSizeInCont);
  1343. return NULL;
  1344. }
  1345. wcscpy(dsiInfo.pszFileID, i_pszFileID);
  1346. }
  1347. // Continue to copy necessary information into the DirSearchInfo, and initialize it.
  1348. dsiInfo.uFileFlagsMask= uFileFlagsMask;
  1349. dsiInfo.uFileFlags= uFileFlags;
  1350. // Locate the Directory-Node corresponding to the Current Directory within 
  1351. // the Directory-Hierarchy Tree.
  1352. for (uDirNodePos=0; uDirNodePos < g_pISO9660Info->uDirectoryCnt; uDirNodePos++) {
  1353. DirectoryNode dnCurrDir;
  1354. // Retrieve the Current Directory-Node
  1355. if (! Array_getAt(g_pISO9660Info->hDirTree, uDirNodePos, (BYTE*)&dnCurrDir)) {
  1356. dbg_printf(("WARNING: _findFirstFileRecord() Failed [6]n"));
  1357. break;
  1358. }
  1359. if (g_pISO9660Info->dwCurrDirICB == dnCurrDir.dwDirICB) {
  1360. dsiInfo.uDirNumber= uDirNodePos;
  1361. break;
  1362. }
  1363. }
  1364. // Calculate the first Record to examine. This record is the Second record
  1365. // on the Record-List, since the first Record always describes the Current Directory
  1366. // and is not of interest.
  1367. dsiInfo.cbRecListOffset= cbFirstRecordSize;
  1368. dsiInfo.cbCurrRecOffset= 0;
  1369. // Allocate a Search-Info
  1370. uSearchID= _FileSys_allocateSearchInfo();
  1371. if (NULL == uSearchID) {
  1372. dbg_printf(("WARNING: _findFirstFileRecord() Failed [7]: No available Search-Info IDn"));
  1373. if (! bWildcardSearch)
  1374. free(dsiInfo.pszFileID);
  1375. sc_Free(dsiInfo.hDirFileRecordList, uDirFileRecListSizeInCont);
  1376. return NULL;
  1377. }
  1378. // Register the Directory-Search Info in the Search-Info Pool
  1379. bSuccess= _FileSys_setSearchInfo(uSearchID, (const BYTE*)&dsiInfo);
  1380. if (! bSuccess) {
  1381. dbg_printf(("FATAL: _findFirstFileRecord() Failed [8]: Cannot register new Searchn"));
  1382. }
  1383. // Now, the information in dsiInfo is stable and complete: perform the search
  1384. if (bSuccess && ! _findNextFileRecord(uSearchID, o_pFileRecordPtr)) {
  1385. dbg_printf(("WARNING: _findFirstFileRecord() Failed [9]: Could not find a matchn"));
  1386. bSuccess= FALSE;
  1387. }
  1388. if (! bSuccess) {
  1389. if (! bWildcardSearch)
  1390. free(dsiInfo.pszFileID);
  1391. sc_Free(dsiInfo.hDirFileRecordList, uDirFileRecListSizeInCont);
  1392. _FileSys_freeSearchInfo(uSearchID);
  1393. return NULL;
  1394. }
  1395. return uSearchID;
  1396. }
  1397. /////////////////////////////////////////////////////////////////////////////
  1398. // _findNextFileRecord()
  1399. //
  1400. // Description: Continues a search that was previously initiated via a call
  1401. // to _findFirstFileRecord().
  1402. //
  1403. // Input: uSearchID - The ID of a search, that was returned from a
  1404. // previous call to _findFirstFileRecord().
  1405. // Output: o_pFileRecordPtr - Points to a DirFileRecord Pointer, to receive
  1406. //    the File-Record of a matching File/Sub-Directory.
  1407. // In/Out: None
  1408. // Return: TRUE if the search succeeded, and an additional File-Record matching
  1409. // the criteria was found. In this case, the supplied o_pFileRecordPtr
  1410. // contains a valid pointer.
  1411. // FALSE is returned if no more Files/Sub-Directories matching the
  1412. // supplied criteria could be found. In this case, the supplied 
  1413. // o_pFileRecordPtr is invalid.
  1414. //
  1415. // Remarks:
  1416. // 1. This method continues a previous search from the point it left off.
  1417. // 2. The search relates to the Directory that was the current working-
  1418. //    directory at the time the search was initiated via _findFirstFileRecord().
  1419. // 3. The search uses the same criteria as were originally supplied  to 
  1420. //    _findFirstFileRecord().
  1421. // 4. The returned File-Record Pointer should be considered persistant
  1422. //    across calls. The caller has to make sure that o_pFileRecordPtr 
  1423. //    is freed when it is no longer needed.
  1424. // 5. _findClose() must be called when no additional searches are needed. 
  1425. static BOOL _findNextFileRecord(UINT16 uSearchID, struct DirFileRecord **o_pFileRecordPtr)
  1426. {
  1427. UINT8 uFileIDLength;
  1428. BOOL bFileRecFound;
  1429. BOOL bSearchIncludesDirs;
  1430. WCHAR szUnicodeFileID[(MAX_ID_LENGTH / sizeof(WCHAR)) + 1];
  1431. LPCWSTR pszFileID;
  1432. struct DirFileRecord *pCurrFileRec;
  1433. DirectorySearchInfo dsiInfo;
  1434. //<<<MikeX_1213_2004_A:compare the files' length when searching files.
  1435. UINT8 uFoundFileIDLength;
  1436. WCHAR* pwcFoundFileVersionChar;
  1437. BOOL bBlurredlySearch = FALSE;
  1438. //MikeX_1213_2004_A>>>
  1439. // Retrieve the Directory-Search Info from the Search-Pool
  1440. if ((NULL == uSearchID) ||
  1441. ! _FileSys_getSearchInfo(uSearchID, (BYTE*)&dsiInfo))
  1442. {
  1443. return FALSE;
  1444. }
  1445. uFileIDLength= wcslen(dsiInfo.pszFileID);
  1446. // MikeX_1213_2004_A: support blurred searching
  1447. if( FILESYS_BLURRED_SEARCH == dsiInfo.pszFileID[uFileIDLength-1] )
  1448. {
  1449. bBlurredlySearch = TRUE;
  1450. uFileIDLength --;
  1451. }
  1452. bSearchIncludesDirs= (dsiInfo.uFileFlags == (FILE_FLAGS_DIRECTORY & dsiInfo.uFileFlagsMask));
  1453. // Reset the result
  1454. *o_pFileRecordPtr= NULL;
  1455. // Prepare a descriptor-container
  1456. pCurrFileRec= (struct DirFileRecord *)malloc(MAX_FILEREC_SIZE);
  1457. if (NULL == pCurrFileRec) {
  1458. tr_printf(("FATAL: _findNextFileRecord() Failed [1]: Low system resourcesn"));
  1459. return FALSE;
  1460. }
  1461. // Scan the Directory, as long as it is not exhausted, and there is no match
  1462. bFileRecFound= FALSE;
  1463. while ( ((dsiInfo.cbRecListOffset + dsiInfo.cbCurrRecOffset) < dsiInfo.dwDirectorySize) &&
  1464. (! bFileRecFound) )
  1465. {
  1466. UINT8 cbRequiredDataSize;
  1467. // Extract the Length of the Current Record, which is the first Byte of the Record
  1468. sc_GetBytes(dsiInfo.hDirFileRecordList, dsiInfo.cbCurrRecOffset, 1, &cbRequiredDataSize);
  1469. // If the Length of the Current Record is Zero, then the required data is One Byte long
  1470. if (0 == cbRequiredDataSize)
  1471. cbRequiredDataSize++;
  1472. // Check if the remaining space until the end of the Record-List Cache is large enough
  1473. // to accomodate for the Current Record. If not, cache an additional Record-List chunk.
  1474. if ((DIRECTORY_RECLIST_SZ - dsiInfo.cbCurrRecOffset) < cbRequiredDataSize) {
  1475. dsiInfo.cbRecListOffset += dsiInfo.cbCurrRecOffset;
  1476. dsiInfo.cbCurrRecOffset= 0;
  1477. if (! sc_CopyFromDisc(dsiInfo.dwDirICB, dsiInfo.cbRecListOffset,
  1478.   DIRECTORY_RECLIST_SZ, dsiInfo.hDirFileRecordList))
  1479. {
  1480. dbg_printf(("WARNING: _findNextFileRecord() Failed [2]n"));
  1481. break;
  1482. }
  1483. // Set the Required Data Size to the Maximum Record size, in order to avoid
  1484. // having to read this size again from the Record-List Cache.
  1485. cbRequiredDataSize= MAX_FILEREC_SIZE;
  1486. }
  1487. // Collect the next DirFileRecord
  1488. sc_GetBytes(dsiInfo.hDirFileRecordList, dsiInfo.cbCurrRecOffset,
  1489. MIN(cbRequiredDataSize, MAX_FILEREC_SIZE), (BYTE*)pCurrFileRec);
  1490. // Check the Length of the current Record: if it is Zero, then either the End-Of-Directory
  1491. // was encountered, or a Sector-Boundary needs to be crossed.
  1492. if (0 == pCurrFileRec->cbLengthOfDirRecord) {
  1493. // ECMA-119 guarantees, that each Record shall end in the same Sector in which it was
  1494. // started. If there isn't enough space, the Record will be moved to the succeeding
  1495. // Sector, and the current Sector will be Zero-padded.
  1496. DWORD dwCurrSectorBoundary= 
  1497. ( ((dsiInfo.cbRecListOffset + dsiInfo.cbCurrRecOffset + LOGICAL_BLOCK_SIZE - 1) / 
  1498.    LOGICAL_BLOCK_SIZE) * LOGICAL_BLOCK_SIZE );
  1499. // If the Current Record-Offest is Zero, then move to the next closest Sector
  1500. if (0 == dsiInfo.cbCurrRecOffset)
  1501. dwCurrSectorBoundary += LOGICAL_BLOCK_SIZE;
  1502. // If the current Sector boundary exceeds the Directory's size, then End-Of-Directory
  1503. // was encountered.
  1504. if (dwCurrSectorBoundary >= dsiInfo.dwDirectorySize)
  1505. break;
  1506. // The Sector boundary must be crossed:
  1507. // Set cbCurrRecOffset to DIRECTORY_RECLIST_SZ, thus forcing caching of a Record-List
  1508. // chunk; adjust cbRecListOffset such, that the next caching will occur
  1509. // at the beginning of the succeeding Sector.
  1510. dsiInfo.cbRecListOffset= (dwCurrSectorBoundary - DIRECTORY_RECLIST_SZ);
  1511. dsiInfo.cbCurrRecOffset= DIRECTORY_RECLIST_SZ;
  1512. // Force collection of the next DirFileRecord from the freshly-loaded cache
  1513. continue;
  1514. }
  1515. // If the search includes Sub-Directories, and provided that the Current Directory-
  1516. // File Record is not reported as a Directory, cross-check this against the
  1517. // information from the Directory-Hierarchy Tree (Path table).
  1518. // This is a precaution required to overcome authoring-errors in the File-Flags field
  1519. // (which is the only criterion for determining the Type of this Record).
  1520. if (bSearchIncludesDirs && (0 == (pCurrFileRec->uFlags & FILE_FLAGS_DIRECTORY))) {
  1521. UINT16 uDirNodePos;
  1522. // Iterate over all the Directory-Tree, and try to locate this Record in it.
  1523. for (uDirNodePos=0; uDirNodePos < g_pISO9660Info->uDirectoryCnt; uDirNodePos++) {
  1524. DirectoryNode dnCurrDir;
  1525. // Retrieve the Current Directory-Node
  1526. if (! Array_getAt(g_pISO9660Info->hDirTree, uDirNodePos, (BYTE*)&dnCurrDir)) {
  1527. dbg_printf(("WARNING: _findNextFileRecord() Failed [3]n"));
  1528. break;
  1529. }
  1530. // Check if the Directory has the same location as this Record, and if
  1531. // its Parent is the current Directory.
  1532. if ( (BB_DWORD(pCurrFileRec->dwExtentLocation) == dnCurrDir.dwDirICB) &&
  1533.  (dsiInfo.uDirNumber == (dnCurrDir.uParentDirNumber - 1)) )
  1534. {
  1535. // A misreported directory was found: force this Record's Flags field to
  1536. // identify a Directory.
  1537. pCurrFileRec->uFlags= FILE_FLAGS_DIRECTORY;
  1538. }
  1539. }
  1540. }
  1541. // Collect the current File-ID
  1542. pszFileID= (LPCWSTR)szUnicodeFileID;
  1543. //<<<Hannah_0524_2005 Cut the file length properly according to the different system.
  1544. {
  1545. extern BOOL _fileID_Cut(UINT8 i_fileID_len, BYTE* i_pSourceBuffer, UINT8 o_fileID_len, BYTE* o_pDestBuffer);
  1546. if(!g_pISO9660Info->bIsUsingUnicode)  //ROMEO
  1547. {
  1548. if( pCurrFileRec->cbLengthOfFileID > MAX_ID_LENGTH/sizeof(WCHAR) )
  1549. {
  1550. BYTE* buff = NULL;
  1551. BYTE len = pCurrFileRec->cbLengthOfFileID+1;
  1552. buff=(BYTE*)malloc(len +1);
  1553. if(buff == NULL)
  1554. {
  1555. dbg_printf(("WARNING: _findNextFileRecord() Failed [5]:Low system resourcesn"));
  1556. break;
  1557. }
  1558. buff[0] = 0x08; //UNICODE_COMPRESSIONID_DOUBLE_BYTE 
  1559. sc_GetBytes(dsiInfo.hDirFileRecordList, dsiInfo.cbCurrRecOffset + sizeof(struct DirFileRecord),
  1560. len-1, buff+1);
  1561. _fileID_Cut(len, buff, MAX_ID_LENGTH/sizeof(WCHAR)+1, pCurrFileRec->sFileID-1);
  1562. pCurrFileRec->cbLengthOfFileID = MAX_ID_LENGTH/sizeof(WCHAR);
  1563. free(buff);
  1564. }
  1565. }
  1566. else
  1567. {
  1568. if( pCurrFileRec->cbLengthOfFileID > MAX_ID_LENGTH )
  1569. {
  1570. BYTE* buff = NULL;
  1571. BYTE len = pCurrFileRec->cbLengthOfFileID+1;
  1572. buff=(BYTE*)malloc(len + 2);
  1573. if(buff == NULL)
  1574. {
  1575. dbg_printf(("WARNING: _findNextFileRecord() Failed [6]:Low system resourcesn"));
  1576. break;
  1577. }
  1578. buff[0] = 0x10; //UNICODE_COMPRESSIONID_DOUBLE_BYTE 
  1579. sc_GetBytes(dsiInfo.hDirFileRecordList, dsiInfo.cbCurrRecOffset + sizeof(struct DirFileRecord),
  1580. len-1, buff+1);
  1581. _fileID_Cut(len, buff, MAX_ID_LENGTH+1, pCurrFileRec->sFileID-1);
  1582. pCurrFileRec->cbLengthOfFileID = MAX_ID_LENGTH;
  1583. free(buff);
  1584. }
  1585. }
  1586. }
  1587. //Hannah_0524_2005>>>
  1588.       //ZCH JC2003-7-17, limit pCurrFileRec->cbLengthOfFileID within MAX_ID_LENGTH, pCurrFileRec->cbLengthOfFileID is sometimes beyond MAX_ID_LENGTH because the addition of ";1"
  1589.       //if(pCurrFileRec->cbLengthOfFileID > MAX_ID_LENGTH)
  1590.         //pCurrFileRec->cbLengthOfFileID = MAX_ID_LENGTH;
  1591. // Convert the File-ID into UNICODE, if UNICODE is not in use or the current File-ID is
  1592. // one character long.
  1593. if (!g_pISO9660Info->bIsUsingUnicode || (1 == pCurrFileRec->cbLengthOfFileID)) {
  1594. // The File-ID is given in ANSI-ASCII: convert it into UNICODE
  1595. _str2wcs((LPCSTR)pCurrFileRec->sFileID, szUnicodeFileID,
  1596.  ((pCurrFileRec->cbLengthOfFileID + 1) * sizeof(WCHAR)));
  1597. }
  1598. else {
  1599. // The File-ID is given in UNICODE: manipulate as required
  1600. pCurrFileRec->sFileID[pCurrFileRec->cbLengthOfFileID]= 0;
  1601. pCurrFileRec->sFileID[pCurrFileRec->cbLengthOfFileID+1]= 0;
  1602. #ifdef MOTOROLA
  1603. pszFileID= (LPCWSTR)pCurrFileRec->sFileID;
  1604. #else
  1605. swab((LPSTR)pCurrFileRec->sFileID, (LPSTR)szUnicodeFileID,
  1606.  (pCurrFileRec->cbLengthOfFileID + 2));
  1607. #endif //MOTOROLA
  1608. }
  1609. // Check if an appropriate Directory-File Record was found, according to
  1610. // both the (UNICODE-normalized) File-ID and the File-Flags.
  1611. #if 0 // Robin_1112_2004, "*" mean any char/string, RB_TBD
  1612. if (dsiInfo.uFileFlags == (pCurrFileRec->uFlags & dsiInfo.uFileFlagsMask))
  1613. {
  1614. if ((0 != uFileIDLength && dsiInfo.pszFileID[uFileIDLength-1] == '*') && (0 == _wcsnicmp(dsiInfo.pszFileID, pszFileID, uFileIDLength-1)) )
  1615. bFileRecFound= TRUE;
  1616. else if ((uFileIDLength == wcslen(pszFileID) || 0 == uFileIDLength) && (0 == _wcsnicmp(dsiInfo.pszFileID, pszFileID, uFileIDLength)) )
  1617. bFileRecFound= TRUE;
  1618. }
  1619. #else
  1620. //<<<MikeX_1213_2004_A:compare the files' length when searching files.
  1621. if( g_pISO9660Info->bIsUsingUnicode )
  1622. uFoundFileIDLength = pCurrFileRec->cbLengthOfFileID/sizeof(WCHAR);
  1623. else
  1624. uFoundFileIDLength = pCurrFileRec->cbLengthOfFileID;
  1625. pwcFoundFileVersionChar = wcsrchr(pszFileID, L';');
  1626. if( 0 != pwcFoundFileVersionChar )
  1627. uFoundFileIDLength = (UINT8)(pwcFoundFileVersionChar - pszFileID);
  1628. if( 0 == uFoundFileIDLength || 0 == uFileIDLength )
  1629. uFoundFileIDLength = uFileIDLength;
  1630. //MikeX_1213_2004_A>>>
  1631. #ifdef MACESTROLINK_SUPPORT
  1632. if ( (dsiInfo.uFileFlags == (pCurrFileRec->uFlags & dsiInfo.uFileFlagsMask)) &&
  1633. (0 == _wcsnicmp(dsiInfo.pszFileID, pszFileID, uFileIDLength))&& //MikeX_1119_2003: convert the file ID lower-case to upper-case.
  1634. (bBlurredlySearch || (uFoundFileIDLength == uFileIDLength)||IS_PLAYING_MLNK)) //Hansen_2004_12_30 Macestrolink can not compare file's length
  1635. #else
  1636. if ( (dsiInfo.uFileFlags == (pCurrFileRec->uFlags & dsiInfo.uFileFlagsMask)) &&
  1637. (0 == _wcsnicmp(dsiInfo.pszFileID, pszFileID, uFileIDLength))&& //MikeX_1119_2003: convert the file ID lower-case to upper-case.
  1638. (bBlurredlySearch || (uFoundFileIDLength == uFileIDLength))) //MikeX_1213_2004_A:compare the files' length when searching files.
  1639. #endif
  1640. {
  1641. bFileRecFound= TRUE;
  1642. }
  1643. #endif
  1644. // Continue to the next Directory/File Record
  1645. dsiInfo.cbCurrRecOffset += pCurrFileRec->cbLengthOfDirRecord;
  1646. }//endof while
  1647. if (bFileRecFound) {
  1648. // Assign the result
  1649. *o_pFileRecordPtr= pCurrFileRec;
  1650. }
  1651. else {
  1652. // No match was found - this Directory has been exhausted: mark that the entire
  1653. // contents was read, so that future calls will return immediately.
  1654. dsiInfo.cbRecListOffset= dsiInfo.dwDirectorySize;
  1655. dsiInfo.cbCurrRecOffset= 0;
  1656. // Free the memory
  1657. free(pCurrFileRec);
  1658. }
  1659. // Update the Directory-Search Info in the Search-Pool
  1660. if (! _FileSys_setSearchInfo(uSearchID, (const BYTE*)&dsiInfo)) {
  1661. dbg_printf(("WARNING: _findNextFileRecord() Failed [4]n"));
  1662. }
  1663. return bFileRecFound;
  1664. }
  1665. /////////////////////////////////////////////////////////////////////////////
  1666. // _findClose()
  1667. //
  1668. // Description: Terminates a search.
  1669. //
  1670. // Input: uSearchID - The ID of a search, that was returned from a
  1671. // previous call to _findFirstFileRecord().
  1672. // Output: None
  1673. // In/Out: None
  1674. // Return: TRUE if the search was successfully terminated; FALSE othewise.
  1675. //
  1676. // Remarks:
  1677. // Any search that is initiated via _findFirstFileRecord() must be terminated
  1678. // using a call to this method, in order to allow for proper release of
  1679. // resources that were allocated for that search. 
  1680. //  If the call to _findFirstFileRecord() returned NULL, it is prohibited 
  1681. // to call _findClose().
  1682. static BOOL _findClose(UINT16 uSearchID)
  1683. {
  1684. DirectorySearchInfo dsiInfo;
  1685. // Retrieve the Directory-Search Info from the Search-Pool
  1686. if ((NULL == uSearchID) ||
  1687. ! _FileSys_getSearchInfo(uSearchID, (BYTE*)&dsiInfo))
  1688. {
  1689. return FALSE;
  1690. }
  1691. if (dsiInfo.pszFileID != g_pszWildcardSearch)
  1692. free(dsiInfo.pszFileID);
  1693. sc_Free(dsiInfo.hDirFileRecordList, CONTAINER_COUNT(DIRECTORY_RECLIST_SZ));
  1694. _FileSys_freeSearchInfo(uSearchID);
  1695. return TRUE;
  1696. }
  1697. /////////////////////////////////////////////////////////////////////////////
  1698. // _getFileAttributes()
  1699. //
  1700. // Description: Translates a native File-Record into a FindData structure.
  1701. //
  1702. // Input: i_pFileRec - Points to a DirFileRecord structure to translate.
  1703. // Output: o_pFindData - Points to a FindData structure to receive the
  1704. //   translated information.
  1705. // In/Out: None
  1706. // Return: None
  1707. // Remarks: None
  1708. static void _getFileAttributes(const struct DirFileRecord *i_pFileRec,
  1709.    FindData *o_pFindData)
  1710. {
  1711. LPWSTR pszSeparator2;
  1712. // Now it's safe to access the Record
  1713. o_pFindData->uFileType= ((i_pFileRec->uFlags & FILE_FLAGS_DIRECTORY) ? 
  1714.  FILETYPE_DIRECTORY : FILETYPE_NORMAL);
  1715. o_pFindData->dwStartAddr= BB_DWORD(i_pFileRec->dwExtentLocation);
  1716. o_pFindData->cbFileSizeHigh= 0;
  1717. o_pFindData->cbFileSizeLow= BB_DWORD(i_pFileRec->dwDataLength);
  1718. // Extract the File-ID
  1719. if (!g_pISO9660Info->bIsUsingUnicode || (1 == i_pFileRec->cbLengthOfFileID)) {
  1720. // The File-ID is given in ANSI-ASCII: convert it into UNICODE
  1721. _str2wcs((LPCSTR)i_pFileRec->sFileID, o_pFindData->szFileID,
  1722.  ((i_pFileRec->cbLengthOfFileID + 1) * sizeof(WCHAR)));
  1723. }
  1724. else {
  1725. // The File-ID is given in UNICODE: manipulate as required
  1726. #ifdef MOTOROLA
  1727. memcpy(o_pFindData->szFileID, i_pFileRec->sFileID, i_pFileRec->cbLengthOfFileID);
  1728. #else
  1729. swab((LPSTR)i_pFileRec->sFileID, (LPSTR)o_pFindData->szFileID, i_pFileRec->cbLengthOfFileID);
  1730. #endif //MOTOROLA
  1731. o_pFindData->szFileID[i_pFileRec->cbLengthOfFileID / sizeof(WCHAR)]= 0;
  1732. }
  1733. // Eliminate the SEPARATOR2 from the end
  1734. pszSeparator2= wcsrchr(o_pFindData->szFileID, SEPARATOR2);
  1735. if (NULL != pszSeparator2)
  1736. *pszSeparator2= 0;
  1737. return;
  1738. }