Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1796 lines
41 KiB

  1. /*************************************************************************
  2. * *
  3. * IOFTS.C *
  4. * *
  5. * Copyright (C) Microsoft Corporation 1990-1994 *
  6. * All Rights reserved. *
  7. * *
  8. **************************************************************************
  9. * *
  10. * Module Intent *
  11. * Provide disk I/O for various types of files currently supported, *
  12. * which include: FS system file, FS subfile, regular files *
  13. * The I/O functions supported are: *
  14. * - File exist *
  15. * - File open, create *
  16. * - File seek/write *
  17. * - File sequential write *
  18. * - File seek/read *
  19. * - File sequential read *
  20. * - File close *
  21. * *
  22. * Comments: *
  23. * There are some PLATFORM DEPENDENT codes in the modules for *
  24. * calls such as _lopen, _lread, _lwrite. *
  25. * There are calls that are not supported, such as create a *
  26. * regular DOS file, since we never use them. Those calls can be *
  27. * implemented when the need arises *
  28. **************************************************************************
  29. * *
  30. * Written By : Binh Nguyen *
  31. * Current Owner: Binh Nguyen *
  32. * *
  33. **************************************************************************/
  34. #include <mvopsys.h>
  35. #include <mem.h>
  36. #include <misc.h>
  37. //#include <mvsearch.h>
  38. #include <iterror.h>
  39. #include <wrapstor.h>
  40. #include <io.h>
  41. #include <fcntl.h>
  42. #include <sys\types.h>
  43. #include <sys\stat.h>
  44. #include <string.h>
  45. #include <_mvutil.h>
  46. #include "iofts.h"
  47. #ifdef _DEBUG
  48. static BYTE NEAR s_aszModule[] = __FILE__; // Used by error return functions.
  49. #endif
  50. PRIVATE HANDLE NEAR PASCAL IoftsWin32Create(LPCSTR lpstr, DWORD w);
  51. PRIVATE HANDLE NEAR PASCAL IoftsWin32Open(LPCSTR lpstr, DWORD w);
  52. #ifdef _WIN32
  53. #define CREAT(sz, w) IoftsWin32Create(sz, w)
  54. #define OPEN(sz, w) IoftsWin32Open(sz, w)
  55. #define _COMMIT(hfile) (FlushFileBuffers(hfile) ? 0 : GetLastError())
  56. /* seek origins */
  57. #if !defined(wFSSeekSet)
  58. #define wFSSeekSet FILE_BEGIN
  59. #define wFSSeekCur FILE_CURRENT
  60. #define wFSSeekEnd FILE_END
  61. #endif // !defined(wFSSeekSet)
  62. #else // if ! _NT
  63. #define CREAT _lcreat
  64. #define OPEN _lopen
  65. #define _COMMIT _commit
  66. /* seek origins */
  67. #define wFSSeekSet 0
  68. #define wFSSeekCur 1
  69. #define wFSSeekEnd 2
  70. #endif // ! _NT
  71. #define OPENED_HFS (BYTE)0x80
  72. /*************************************************************************
  73. * INTERNAL PRIVATE FUNCTIONS
  74. *
  75. * Those functions should be declared NEAR
  76. *************************************************************************/
  77. // return pointer to portion of filename after !
  78. // fill lszTemp with copy of first half before !
  79. LPCSTR NEAR PASCAL GetSubFilename(LPCSTR lszFilename, LSZ lszTemp)
  80. {
  81. LSZ lszTempOriginal = lszTemp;
  82. LPCSTR lszFilenameOriginal=lszFilename;
  83. if (lszTemp)
  84. { while ((*lszFilename) && (*lszFilename!='!'))
  85. {
  86. *lszTemp++=*lszFilename++;
  87. }
  88. *lszTemp=0x00;
  89. }
  90. else
  91. {
  92. while ((*lszFilename) && (*lszFilename!='!'))
  93. {
  94. lszFilename++;
  95. }
  96. }
  97. if (*lszFilename=='!')
  98. lszFilename++;
  99. if (!*lszFilename)
  100. {
  101. if (lszTempOriginal)
  102. *lszTempOriginal=0x00;
  103. lszFilename=lszFilenameOriginal;
  104. }
  105. return lszFilename;
  106. }
  107. LPSTR FAR PASCAL CreateDefaultFilename(LPCSTR szFilename, LPCSTR szDefault, LPSTR szFullName)
  108. {
  109. LPCSTR szSubFilename = GetSubFilename(szFilename,szFullName);
  110. // Use default if no "!" was found.
  111. if (!*szFullName)
  112. wsprintf(szFullName,"%s!%s",szFilename,szDefault);
  113. else
  114. lstrcpy(szFullName,szFilename);
  115. return szFullName;
  116. }
  117. // Get an Hfs based on HFPB and Filename
  118. // if bCreate==FALSE, open for READ ONLY
  119. // if bCreate==TRUE, open for READ WRITE (create if non existant)
  120. HFS FAR PASCAL HfsFromHfpb(HFPB hfpb)
  121. {
  122. LPFPB lpfpbFS;
  123. HFS hfs=NULL;
  124. if (!hfpb)
  125. return NULL;
  126. lpfpbFS = (LPFPB)_GLOBALLOCK(hfpb);
  127. _ENTERCRITICALSECTION(&lpfpbFS->cs);
  128. hfs=lpfpbFS->fs.hfs;
  129. _LEAVECRITICALSECTION(&lpfpbFS->cs);
  130. _GLOBALUNLOCK(hfpb);
  131. return hfs;
  132. }
  133. HFS FAR PASCAL GetHfs(HFPB hfpbSysFile, LPCSTR lszFilename,
  134. BOOL bCreate, PHRESULT phr)
  135. {
  136. HFS hfs = NULL;
  137. if (!hfpbSysFile)
  138. {
  139. BYTE lszTemp[cbMAX_PATH];
  140. LPCSTR lszSubFilename;
  141. lszSubFilename=GetSubFilename(lszFilename,lszTemp);
  142. if (*lszSubFilename)
  143. {
  144. FM fm;
  145. fm = FmNewSzDir((LPSTR)lszTemp, dirCurrent, NULL);
  146. if (bCreate)
  147. {
  148. hfs = HfsOpenFm(fm, FSH_READWRITE, phr);
  149. if (!hfs)
  150. {
  151. if (!FileExist(NULL, lszTemp, FS_SYSTEMFILE))
  152. {
  153. hfs = HfsCreateFileSysFm(fm, NULL, phr);
  154. }
  155. }
  156. }
  157. else
  158. hfs = HfsOpenFm(fm, FSH_READONLY, phr);
  159. DisposeFm(fm);
  160. }
  161. else
  162. SetErrCode(phr,E_INVALIDARG);
  163. }
  164. else
  165. {
  166. LPFPB lpfpbFS = (LPFPB)_GLOBALLOCK(hfpbSysFile);
  167. _ENTERCRITICALSECTION(&lpfpbFS->cs);
  168. hfs=lpfpbFS->fs.hfs;
  169. if (!hfs)
  170. SetErrCode(phr,E_ASSERT);
  171. _LEAVECRITICALSECTION(&lpfpbFS->cs);
  172. _GLOBALUNLOCK(hfpbSysFile);
  173. }
  174. return hfs;
  175. }
  176. // if hfpbSysFile==NULL, and fFileType==FS_SUBFILE, then
  177. // lszFilename must contain filesys!subfile
  178. PUBLIC HRESULT FAR PASCAL FileExist (HFPB hfpbSysFile, LPCSTR lszFilename,
  179. int fFileType)
  180. {
  181. HFS hfs=NULL;
  182. FM fm;
  183. HRESULT errb;
  184. HRESULT rc=E_ASSERT;
  185. if (lszFilename == NULL )
  186. {
  187. SetErrCode (&errb, E_INVALIDARG);
  188. return 0;
  189. }
  190. errb=S_OK;
  191. switch (fFileType)
  192. {
  193. case FS_SYSTEMFILE:
  194. fm = FmNewSzDir((LPSTR)lszFilename, dirCurrent, NULL);
  195. if (FExistFm(fm))
  196. errb=S_OK;
  197. else
  198. errb=E_NOTEXIST;
  199. DisposeFm(fm);
  200. break;
  201. case FS_SUBFILE:
  202. hfs = GetHfs(hfpbSysFile,lszFilename,FALSE,&errb);
  203. if (hfs)
  204. {
  205. if (FAccessHfs(hfs,GetSubFilename(lszFilename,NULL),
  206. FACCESS_EXISTS,&errb))
  207. rc=S_OK;
  208. else
  209. rc = errb;
  210. // if it wasn't given to us above, remove it now
  211. if (!hfpbSysFile)
  212. RcCloseHfs(hfs);
  213. }
  214. else
  215. rc=errb;
  216. break;
  217. case REGULAR_FILE:
  218. /* There is no need to call this function for DOS files. */
  219. fm = FmNewSzDir((LPSTR)lszFilename, dirCurrent, NULL);
  220. if (FExistFm(fm))
  221. errb=S_OK;
  222. else
  223. errb=E_NOTEXIST;
  224. DisposeFm(fm);
  225. break;
  226. default:
  227. SetErrCode(&errb,E_INVALIDARG);
  228. return 0;
  229. }
  230. return errb;
  231. }
  232. #ifndef ITWRAP
  233. PUBLIC HFPB FAR PASCAL FileCreate (HFPB hfpbSysFile, LPCSTR lszFilename,
  234. int fFileType, PHRESULT phr)
  235. {
  236. LPFPB lpfpb; /* Pointer to file parameter block */
  237. FM fm;
  238. //HRESULT rc; /* Default open error code */
  239. HANDLE hMem;
  240. HFPB hfpb;
  241. /* Check for valid filename */
  242. if (lszFilename == NULL )
  243. {
  244. SetErrCode (phr, E_INVALIDARG);
  245. return 0;
  246. }
  247. /* Allocate a file's parameter block */
  248. if (!(hMem = _GLOBALALLOC(GMEM_ZEROINIT, sizeof(FPB))))
  249. {
  250. SetErrCode(phr,ERR_MEMORY);
  251. return NULL;
  252. }
  253. if (!(lpfpb = (LPFPB)_GLOBALLOCK(hMem)))
  254. {
  255. _GLOBALUNLOCK(hMem);
  256. SetErrCode(phr,ERR_MEMORY);
  257. return NULL;
  258. }
  259. _INITIALIZECRITICALSECTION(&lpfpb->cs);
  260. lpfpb->hStruct=hMem;
  261. switch (fFileType)
  262. {
  263. case FS_SYSTEMFILE:
  264. fm = FmNewSzDir((LPSTR)lszFilename, dirCurrent, NULL);
  265. lpfpb->fs.hfs = HfsCreateFileSysFm(fm, NULL, phr);
  266. DisposeFm(fm);
  267. if (lpfpb->fs.hfs== NULL)
  268. {
  269. goto ErrorExit;
  270. }
  271. break;
  272. case FS_SUBFILE:
  273. { HFS hfs = GetHfs(hfpbSysFile,lszFilename,TRUE,phr);
  274. if (hfs)
  275. {
  276. lpfpb->fs.hf = HfCreateFileHfs(hfs,GetSubFilename(lszFilename,
  277. NULL),HFOPEN_READWRITE,phr);
  278. lpfpb->ioMode = OF_READWRITE;
  279. if (lpfpb->fs.hf == 0)
  280. {
  281. if (!hfpbSysFile)
  282. RcCloseHfs(hfs);
  283. goto ErrorExit;
  284. }
  285. else
  286. {
  287. if (!hfpbSysFile)
  288. lpfpb->ioMode|=OPENED_HFS;
  289. }
  290. }
  291. else
  292. {
  293. goto ErrorExit;
  294. }
  295. break;
  296. }
  297. case REGULAR_FILE:
  298. /* Open the file */
  299. /* PLATFORM DEPENDENT code: _lcreat */
  300. if ((lpfpb->fs.hFile = (HFILE_GENERIC)CREAT (lszFilename, 0))
  301. == HFILE_GENERIC_ERROR)
  302. {
  303. SetErrCode(phr,ERR_FILECREAT_FAILED);
  304. goto ErrorExit;
  305. }
  306. lpfpb->ioMode = OF_READWRITE;
  307. break;
  308. }
  309. /* Set the filetype */
  310. lpfpb->fFileType = fFileType;
  311. _GLOBALUNLOCK(hfpb = lpfpb->hStruct);
  312. return hfpb;
  313. ErrorExit:
  314. _DELETECRITICALSECTION(&lpfpb->cs);
  315. _GLOBALFREE(hMem);
  316. return 0;
  317. }
  318. #endif
  319. #ifndef ITWRAP
  320. PUBLIC HFPB FAR PASCAL FileOpen (HFPB hfpbSysFile, LPCSTR lszFilename,
  321. int fFileType, int ioMode, PHRESULT phr)
  322. {
  323. LPFPB lpfpb; /* Pointer to file parameter block */
  324. FM fm;
  325. //HRESULT rc; /* Default open error code */
  326. HANDLE hMem;
  327. HFPB hfpb;
  328. /* Check for valid filename */
  329. if (lszFilename == NULL )
  330. {
  331. SetErrCode (phr, E_INVALIDARG);
  332. return 0;
  333. }
  334. /* Allocate a file's parameter block */
  335. if (!(hMem = _GLOBALALLOC(GMEM_ZEROINIT, sizeof(FPB))))
  336. {
  337. SetErrCode(phr,ERR_MEMORY);
  338. return NULL;
  339. }
  340. if (!(lpfpb = (LPFPB)_GLOBALLOCK(hMem)))
  341. {
  342. _GLOBALUNLOCK(hMem);
  343. SetErrCode(phr,ERR_MEMORY);
  344. return NULL;
  345. }
  346. _INITIALIZECRITICALSECTION(&lpfpb->cs);
  347. lpfpb->hStruct=hMem;
  348. switch (fFileType)
  349. {
  350. case FS_SYSTEMFILE:
  351. fm = FmNewSzDir((LPSTR)lszFilename, dirCurrent, NULL);
  352. lpfpb->fs.hfs = HfsOpenFm(fm,(BYTE)((ioMode==READ)?
  353. FSH_READONLY:FSH_READWRITE), phr);
  354. DisposeFm(fm);
  355. if (lpfpb->fs.hfs== NULL)
  356. {
  357. goto ErrorExit;
  358. }
  359. break;
  360. case FS_SUBFILE:
  361. {
  362. HFS hfs = GetHfs(hfpbSysFile,lszFilename,FALSE,phr);
  363. if (hfs)
  364. {
  365. lpfpb->fs.hf = HfOpenHfs(hfs,GetSubFilename(lszFilename,
  366. NULL),(BYTE)((ioMode==READ)?HFOPEN_READ:HFOPEN_READWRITE),phr);
  367. lpfpb->ioMode = ioMode;
  368. if (lpfpb->fs.hf == 0)
  369. {
  370. if (!hfpbSysFile)
  371. RcCloseHfs(hfs);
  372. SetErrCode (phr, E_NOTEXIST);
  373. goto ErrorExit;
  374. }
  375. else
  376. {
  377. if (!hfpbSysFile)
  378. lpfpb->ioMode|=OPENED_HFS;
  379. }
  380. }
  381. else
  382. {
  383. SetErrCode (phr, E_NOTEXIST);
  384. goto ErrorExit;
  385. }
  386. break;
  387. }
  388. case REGULAR_FILE:
  389. /* Set the IO mode and appropriate error messages */
  390. if (ioMode == READ)
  391. {
  392. /* Open the file */
  393. /* PLATFORM DEPENDENT code: _lopen */
  394. if ((lpfpb->fs.hFile = (HFILE_GENERIC)OPEN (lszFilename,
  395. ioMode)) == HFILE_GENERIC_ERROR)
  396. {
  397. SetErrCode(phr,E_NOTEXIST);
  398. goto ErrorExit;
  399. }
  400. }
  401. else
  402. {
  403. ioMode = OF_READWRITE;
  404. /* Open the file */
  405. /* PLATFORM DEPENDENT code: _lcreat */
  406. if ((lpfpb->fs.hFile = (HFILE_GENERIC)OPEN(lszFilename, ioMode))
  407. == HFILE_GENERIC_ERROR)
  408. {
  409. SetErrCode(phr,ERR_FILECREAT_FAILED);
  410. goto ErrorExit;
  411. }
  412. }
  413. lpfpb->ioMode = ioMode;
  414. }
  415. /* Set the filetype */
  416. lpfpb->fFileType = fFileType;
  417. _GLOBALUNLOCK(hfpb = lpfpb->hStruct);
  418. return hfpb;
  419. ErrorExit:
  420. _DELETECRITICALSECTION(&lpfpb->cs);
  421. _GLOBALFREE(hMem);
  422. return 0;
  423. }
  424. #endif
  425. /*************************************************************************
  426. * @doc INTERNAL
  427. *
  428. * @func FILEOFFSET FAR PASCAL | FileSeek |
  429. * Seek to a location in a file
  430. *
  431. * @parm HFPB | hfpb |
  432. * Handle to file paramter block
  433. *
  434. * @parm FILEOFFSET | foSeek |
  435. * Location to seek to
  436. *
  437. * @parm WORD | wOrigin |
  438. * Base of seek (0=begin, 1=current, 2=end)
  439. *
  440. * @parm PHRESULT | phr |
  441. * Error buffer.
  442. *
  443. * @rdesc Returns the location actually seeked to
  444. *
  445. *************************************************************************/
  446. PUBLIC FILEOFFSET FAR PASCAL FileSeek(HFPB hfpb, FILEOFFSET fo, WORD wOrigin, PHRESULT phr)
  447. {
  448. LPFPB lpfpb;
  449. HRESULT fCallBackRet;
  450. FILEOFFSET foSeeked=foInvalid;
  451. if (hfpb == NULL)
  452. {
  453. SetErrCode(phr, E_HANDLE);
  454. return foSeeked;
  455. }
  456. lpfpb = (LPFPB)_GLOBALLOCK(hfpb);
  457. _ENTERCRITICALSECTION(&lpfpb->cs);
  458. /* Execute user's status functions */
  459. if (lpfpb->lpfnfInterCb != NULL &&
  460. (fCallBackRet = (*lpfpb->lpfnfInterCb)(lpfpb->lpvInterCbParms))
  461. != S_OK)
  462. {
  463. SetErrCode(phr, fCallBackRet);
  464. goto ErrorExit;
  465. }
  466. if (phr)
  467. *phr = S_OK;
  468. switch (lpfpb->fFileType)
  469. {
  470. case FS_SYSTEMFILE:
  471. /* We should not seek a system file */
  472. SetErrCode(phr, E_ASSERT);
  473. goto ErrorExit;
  474. break;
  475. case FS_SUBFILE:
  476. foSeeked=FoSeekHf(lpfpb->fs.hf,fo,wOrigin,phr);
  477. break;
  478. case REGULAR_FILE:
  479. /* Regular files */
  480. #ifdef _WIN32
  481. foSeeked=fo;
  482. foSeeked.dwOffset=SetFilePointer(lpfpb->fs.hFile, fo.dwOffset, &foSeeked.dwHigh,(DWORD)wOrigin);
  483. #else
  484. foSeeked.dwHigh=0L;
  485. foSeeked.dwOffset=(DWORD)_llseek(lpfpb->fs.hFile, fo.dwOffset, wOrigin);
  486. #endif
  487. if (!FoEquals(fo,foSeeked))
  488. {
  489. SetErrCode (phr, E_FILESEEK);
  490. }
  491. break;
  492. }
  493. ErrorExit:
  494. _LEAVECRITICALSECTION(&lpfpb->cs);
  495. _GLOBALUNLOCK(hfpb);
  496. return foSeeked;
  497. }
  498. /*************************************************************************
  499. * @doc INTERNAL
  500. *
  501. * @func FILEOFFSET FAR PASCAL | FileSize |
  502. * Get the size of an opened file
  503. *
  504. * @parm HFPB | hfpb |
  505. * Handle to file paramter block
  506. *
  507. * @parm PHRESULT | phr |
  508. * Error buffer.
  509. *
  510. * @rdesc Returns the size of the file. If an error occurs, it returns
  511. * foInvalid, and phr contains the error info. For files under 2 gigs,
  512. * just look at the .dwOffset member of the returned file offset.
  513. *
  514. *************************************************************************/
  515. PUBLIC FILEOFFSET FAR PASCAL FileSize(HFPB hfpb, PHRESULT phr)
  516. {
  517. LPFPB lpfpb;
  518. FILEOFFSET foSeeked=foInvalid;
  519. FILEOFFSET foTemp;
  520. if (hfpb == NULL)
  521. {
  522. SetErrCode(phr, E_HANDLE);
  523. return foSeeked;
  524. }
  525. lpfpb = (LPFPB)_GLOBALLOCK(hfpb);
  526. _ENTERCRITICALSECTION(&lpfpb->cs);
  527. if (phr)
  528. *phr = S_OK;
  529. switch (lpfpb->fFileType)
  530. {
  531. case FS_SYSTEMFILE:
  532. /* We should not get the size of a system file */
  533. SetErrCode(phr, E_ASSERT);
  534. goto ErrorExit;
  535. break;
  536. case FS_SUBFILE:
  537. foSeeked=FoSizeHf(lpfpb->fs.hf, phr);
  538. break;
  539. case REGULAR_FILE:
  540. /* Regular files */
  541. #ifdef _WIN32
  542. // foTemp has current file position
  543. foTemp=foNil;
  544. foTemp.dwOffset=SetFilePointer(lpfpb->fs.hFile, 0L, &foTemp.dwHigh, FILE_CURRENT);
  545. foSeeked=foNil;
  546. foSeeked.dwOffset=SetFilePointer(lpfpb->fs.hFile, 0L, &foSeeked.dwHigh, FILE_END);
  547. SetFilePointer(lpfpb->fs.hFile,foTemp.dwOffset,&foTemp.dwHigh, FILE_BEGIN);
  548. #else
  549. foTemp.dwHigh=0L;
  550. foTemp.dwOffset=(DWORD)_llseek(lpfpb->fs.hFile, 0L, FILE_CURRENT);
  551. foSeeked=foNil;
  552. foSeeked.dwOffset=(DWORD)_llseek(lpfpb->fs.hFile, 0L, FILE_END);
  553. _llseek(lpfpb->fs.hFile, foTemp.dwOffset, FILE_BEGIN);
  554. #endif
  555. break;
  556. }
  557. ErrorExit:
  558. _LEAVECRITICALSECTION(&lpfpb->cs);
  559. _GLOBALUNLOCK(hfpb);
  560. return foSeeked;
  561. }
  562. /*************************************************************************
  563. * @doc INTERNAL
  564. *
  565. * @func FILEOFFSET FAR PASCAL | FileOffset |
  566. * Get the offset of a file if baggage
  567. *
  568. * @parm HFPB | hfpb |
  569. * Handle to file paramter block (of baggage file)
  570. *
  571. * @parm PHRESULT | phr |
  572. * Error buffer.
  573. *
  574. * @rdesc Returns the offset the file lives inside it's parent file.
  575. * This is the offset into an M20 of a baggage file, or zero for any
  576. * other type of file. If an error occurs, it returns
  577. * foInvalid, and phr contains the error info. For files under 2 gigs,
  578. * just look at the .dwOffset member of the returned file offset.
  579. *
  580. *************************************************************************/
  581. PUBLIC FILEOFFSET FAR PASCAL FileOffset(HFPB hfpb, PHRESULT phr)
  582. {
  583. LPFPB lpfpb;
  584. FILEOFFSET foOffset=foInvalid;
  585. if (hfpb == NULL)
  586. {
  587. SetErrCode(phr, E_HANDLE);
  588. return foOffset;
  589. }
  590. lpfpb = (LPFPB)_GLOBALLOCK(hfpb);
  591. _ENTERCRITICALSECTION(&lpfpb->cs);
  592. if (phr)
  593. *phr = S_OK;
  594. switch (lpfpb->fFileType)
  595. {
  596. case FS_SYSTEMFILE:
  597. /* We should not get the size of a system file */
  598. foOffset=foNil;
  599. goto ErrorExit;
  600. break;
  601. case FS_SUBFILE:
  602. foOffset=FoOffsetHf(lpfpb->fs.hf, phr);
  603. break;
  604. case REGULAR_FILE:
  605. /* Regular files */
  606. foOffset=foNil;
  607. goto ErrorExit;
  608. break;
  609. }
  610. ErrorExit:
  611. _LEAVECRITICALSECTION(&lpfpb->cs);
  612. _GLOBALUNLOCK(hfpb);
  613. return foOffset;
  614. }
  615. /*************************************************************************
  616. * @doc INTERNAL
  617. *
  618. * @func LONG FAR PASCAL | FileSeekRead |
  619. * Returns the number of bytes read
  620. *
  621. * @parm HFPB | hfpb |
  622. * Handle to file paramter block
  623. *
  624. * @parm LPV | lpvData |
  625. * Buffer to read into.
  626. *
  627. * @parm FILEOFFSET | foSeek |
  628. * File offset to read at.
  629. *
  630. * @parm LONG | lcbSize |
  631. * How many bytes to read.
  632. *
  633. * @parm PHRESULT | phr |
  634. * Error buffer.
  635. *
  636. * @rdesc Returns the number of bytes actually read
  637. *
  638. *************************************************************************/
  639. PUBLIC LONG FAR PASCAL FileSeekRead(HFPB hfpb, LPV lpvData, FILEOFFSET fo,
  640. LONG lcbSize, PHRESULT phr)
  641. {
  642. LONG lRead=0L;
  643. LPFPB lpfpb;
  644. HRESULT fCallBackRet;
  645. FILEOFFSET foSeeked=foInvalid;
  646. if (hfpb == NULL)
  647. {
  648. SetErrCode(phr, E_HANDLE);
  649. return 0L;
  650. }
  651. lpfpb = (LPFPB)_GLOBALLOCK(hfpb);
  652. _ENTERCRITICALSECTION(&lpfpb->cs);
  653. /* Execute user's status functions */
  654. if (lpfpb->lpfnfInterCb != NULL &&
  655. (fCallBackRet = (*lpfpb->lpfnfInterCb)(lpfpb->lpvInterCbParms))
  656. != S_OK)
  657. {
  658. SetErrCode(phr, fCallBackRet);
  659. goto ErrorExit;
  660. }
  661. if (phr)
  662. *phr = S_OK;
  663. switch (lpfpb->fFileType)
  664. {
  665. case FS_SYSTEMFILE:
  666. /* We should not read from a system file */
  667. SetErrCode(phr, E_ASSERT);
  668. goto ErrorExit;
  669. break;
  670. case FS_SUBFILE:
  671. foSeeked=fo;
  672. foSeeked=FoSeekHf(lpfpb->fs.hf,fo,0,phr);
  673. if (!FoEquals(foSeeked,fo))
  674. {
  675. SetErrCode (phr, E_FILESEEK);
  676. goto ErrorExit;
  677. }
  678. lRead=LcbReadHf(lpfpb->fs.hf, lpvData, lcbSize, phr);
  679. break;
  680. case REGULAR_FILE:
  681. /* Regular files */
  682. /* PLATFORM DEPENDENT code: _lread */
  683. #ifdef _WIN32
  684. foSeeked=fo;
  685. foSeeked.dwOffset=SetFilePointer(lpfpb->fs.hFile, fo.dwOffset, &foSeeked.dwHigh,0);
  686. #else
  687. foSeeked.dwHigh=0L;
  688. foSeeked.dwOffset=(DWORD)_llseek(lpfpb->fs.hFile, fo.dwOffset, 0);
  689. #endif
  690. if (!FoEquals(fo,foSeeked))
  691. {
  692. SetErrCode (phr, E_FILESEEK);
  693. goto ErrorExit;
  694. }
  695. #ifdef _WIN32
  696. ReadFile(lpfpb->fs.hFile, lpvData, lcbSize, &lRead, NULL);
  697. #else
  698. lRead=_lread(lpfpb->fs.hFile, lpvData, lcbSize);
  699. #endif
  700. break;
  701. }
  702. ErrorExit:
  703. _LEAVECRITICALSECTION(&lpfpb->cs);
  704. _GLOBALUNLOCK(hfpb);
  705. return lRead;
  706. }
  707. /*************************************************************************
  708. * @doc INTERNAL
  709. *
  710. * @func WORD FAR PASCAL | FileRead |
  711. * Read a number of bytes from a file
  712. *
  713. * @parm LPV | lpvData |
  714. * Buffer to read into.
  715. *
  716. * @parm LONG | lcbSize |
  717. * How many bytes to read.
  718. *
  719. * @parm PHRESULT | phr |
  720. * Error buffer.
  721. *
  722. * @rdesc Returns the number of bytes actually read.
  723. *
  724. *************************************************************************/
  725. PUBLIC LONG FAR PASCAL FileRead(HFPB hfpb, LPV lpvData,
  726. LONG lcbSize, PHRESULT phr)
  727. {
  728. LONG lRead=0L;
  729. LPFPB lpfpb;
  730. HRESULT fCallBackRet;
  731. if (hfpb == NULL || lpvData == NULL)
  732. {
  733. SetErrCode(phr, E_INVALIDARG);
  734. return 0L;
  735. }
  736. lpfpb = (LPFPB)_GLOBALLOCK(hfpb);
  737. _ENTERCRITICALSECTION(&lpfpb->cs);
  738. /* Execute user's status functions */
  739. if (lpfpb->lpfnfInterCb != NULL &&
  740. (fCallBackRet = (*lpfpb->lpfnfInterCb)(lpfpb->lpvInterCbParms))
  741. != S_OK)
  742. {
  743. SetErrCode(phr, fCallBackRet);
  744. goto ErrorExit;
  745. }
  746. if (phr)
  747. *phr = S_OK;
  748. switch (lpfpb->fFileType)
  749. {
  750. case FS_SYSTEMFILE:
  751. /* We should not read from a system file */
  752. SetErrCode(phr, E_ASSERT);
  753. goto ErrorExit;
  754. break;
  755. case FS_SUBFILE:
  756. lRead=LcbReadHf(lpfpb->fs.hf, lpvData, lcbSize, phr);
  757. break;
  758. case REGULAR_FILE:
  759. /* Regular files */
  760. /* PLATFORM DEPENDENT code: _lread */
  761. #ifdef _WIN32
  762. ReadFile(lpfpb->fs.hFile, lpvData, lcbSize, &lRead, NULL);
  763. #else
  764. lRead=_lread(lpfpb->fs.hFile, lpvData, lcbSize);
  765. #endif
  766. break;
  767. }
  768. ErrorExit:
  769. _LEAVECRITICALSECTION(&lpfpb->cs);
  770. _GLOBALUNLOCK(hfpb);
  771. return lRead;
  772. }
  773. /*************************************************************************
  774. * @doc INTERNAL
  775. *
  776. * @func int FAR PASCAL | FileSeekWrite |
  777. * Write number of bytes to a file at some specific location
  778. *
  779. * @parm HFPB | hfpb |
  780. * Handle to file parameter block
  781. *
  782. * @parm LPV | lpvData |
  783. * Buffer to write.
  784. *
  785. * @parm FILEOFFSET | foSeek |
  786. * File offset to write at.
  787. *
  788. * @parm LONG | lcbSize |
  789. * How many bytes to write.
  790. *
  791. * @parm PHRESULT | phr |
  792. * Error buffer.
  793. *
  794. * @rdesc Returns the number of bytes written
  795. *
  796. *************************************************************************/
  797. PUBLIC LONG FAR PASCAL FileSeekWrite(HFPB hfpb, LPV lpvData,
  798. FILEOFFSET fo, LONG lcbSize, PHRESULT phr)
  799. {
  800. LONG lWrote=0L;
  801. LPFPB lpfpb;
  802. HRESULT fCallBackRet;
  803. FILEOFFSET foSeeked=foInvalid;
  804. if (hfpb == NULL)
  805. {
  806. SetErrCode(phr, E_HANDLE);
  807. return 0L;
  808. }
  809. lpfpb = (LPFPB)_GLOBALLOCK(hfpb);
  810. _ENTERCRITICALSECTION(&lpfpb->cs);
  811. /* Execute user's status functions */
  812. if (lpfpb->lpfnfInterCb != NULL &&
  813. (fCallBackRet = (*lpfpb->lpfnfInterCb)(lpfpb->lpvInterCbParms)) != S_OK)
  814. {
  815. SetErrCode(phr, fCallBackRet);
  816. goto ErrorExit;
  817. }
  818. if (phr)
  819. *phr = S_OK;
  820. switch (lpfpb->fFileType)
  821. {
  822. case FS_SYSTEMFILE:
  823. /* We should not read from a system file */
  824. SetErrCode(phr, E_ASSERT);
  825. goto ErrorExit;
  826. break;
  827. case FS_SUBFILE:
  828. foSeeked=FoSeekHf(lpfpb->fs.hf,fo,0,phr);
  829. if (!FoEquals(foSeeked,fo))
  830. {
  831. SetErrCode (phr, E_FILESEEK);
  832. goto ErrorExit;
  833. }
  834. lWrote=LcbWriteHf(lpfpb->fs.hf, lpvData, lcbSize, phr);
  835. break;
  836. case REGULAR_FILE:
  837. /* Regular files */
  838. /* PLATFORM DEPENDENT code: _lread */
  839. #ifdef _WIN32
  840. foSeeked=fo;
  841. foSeeked.dwOffset=SetFilePointer(lpfpb->fs.hFile, fo.dwOffset, &foSeeked.dwHigh,0);
  842. #else
  843. foSeeked.dwHigh=0L;
  844. foSeeked.dwOffset=(DWORD)_llseek(lpfpb->fs.hFile, fo.dwOffset, 0);
  845. #endif
  846. if (!FoEquals(fo,foSeeked))
  847. {
  848. SetErrCode (phr, E_FILESEEK);
  849. goto ErrorExit;
  850. }
  851. #ifdef _WIN32
  852. WriteFile(lpfpb->fs.hFile, lpvData, lcbSize, &lWrote, NULL);
  853. #else
  854. lWrote=_lread(lpfpb->fs.hFile, lpvData, lcbSize);
  855. #endif
  856. break;
  857. }
  858. if (lWrote != lcbSize)
  859. SetErrCode (phr, E_DISKFULL);
  860. ErrorExit:
  861. _LEAVECRITICALSECTION(&lpfpb->cs);
  862. _GLOBALUNLOCK(hfpb);
  863. return lWrote;
  864. }
  865. /*************************************************************************
  866. * @doc INTERNAL
  867. *
  868. * @func LONG FAR PASCAL | FileWrite |
  869. * Write data to a file
  870. *
  871. * @parm HFPB | hfpb |
  872. * Handle to file parameter block
  873. *
  874. * @parm LPV | lpvData |
  875. * Buffer to write.
  876. *
  877. * @parm LONG | lcbSize |
  878. * How many bytes to write.
  879. *
  880. * @parm PHRESULT | phr |
  881. * Error buffer.
  882. *
  883. * @rdesc Returns the number of bytes written
  884. *
  885. *************************************************************************/
  886. PUBLIC LONG FAR PASCAL FileWrite(HFPB hfpb, LPV lpvData,
  887. LONG lcbSize, PHRESULT phr)
  888. {
  889. LONG lWrote=0L;
  890. LPFPB lpfpb;
  891. HRESULT fCallBackRet;
  892. if (hfpb == NULL)
  893. {
  894. SetErrCode(phr, E_HANDLE);
  895. return 0L;
  896. }
  897. lpfpb = (LPFPB)_GLOBALLOCK(hfpb);
  898. _ENTERCRITICALSECTION(&lpfpb->cs);
  899. /* Execute user's status functions */
  900. if (lpfpb->lpfnfInterCb != NULL &&
  901. (fCallBackRet = (*lpfpb->lpfnfInterCb)(lpfpb->lpvInterCbParms))
  902. != S_OK)
  903. {
  904. SetErrCode(phr, fCallBackRet);
  905. goto ErrorExit;
  906. }
  907. if (phr)
  908. *phr = S_OK;
  909. switch (lpfpb->fFileType)
  910. {
  911. case FS_SYSTEMFILE:
  912. /* We should not read from a system file */
  913. SetErrCode(phr, E_ASSERT);
  914. goto ErrorExit;
  915. break;
  916. case FS_SUBFILE:
  917. lWrote=LcbWriteHf(lpfpb->fs.hf, lpvData, lcbSize, phr);
  918. break;
  919. case REGULAR_FILE:
  920. /* Regular files */
  921. /* PLATFORM DEPENDENT code: _lread */
  922. #ifdef _WIN32
  923. WriteFile(lpfpb->fs.hFile, lpvData, lcbSize, &lWrote, NULL);
  924. #else
  925. lWrote=_lwrite(lpfpb->fs.hFile, lpvData, lcbSize);
  926. #endif
  927. break;
  928. }
  929. if (lWrote != lcbSize)
  930. SetErrCode (phr, E_DISKFULL);
  931. ErrorExit:
  932. _LEAVECRITICALSECTION(&lpfpb->cs);
  933. _GLOBALUNLOCK(hfpb);
  934. return lWrote;
  935. }
  936. /*************************************************************************
  937. * @doc INTERNAL
  938. *
  939. * @func VOID | SetFCallBack |
  940. * This function provides a simple interface to set the user's
  941. * interrupt function and parameters. The function will be called
  942. * everytime we do an I/O
  943. *
  944. * @parm GHANDLE | hfpb |
  945. * File's parameter block
  946. *
  947. * @parm INTERRUPT_FUNC | lpfnfInterCb |
  948. * User's interrupt function
  949. *
  950. * @parm LPV | lpvInterCbParms |
  951. * User's function parameters
  952. *************************************************************************/
  953. PUBLIC VOID SetFCallBack (GHANDLE hfpb, INTERRUPT_FUNC lpfnfInterCb,
  954. LPV lpvInterCbParms)
  955. {
  956. LPFPB lpfpb;
  957. if (hfpb == 0)
  958. return;
  959. if (lpfpb = (LPFPB)_GLOBALLOCK(hfpb))
  960. {
  961. _ENTERCRITICALSECTION(&lpfpb->cs);
  962. lpfpb->lpfnfInterCb = lpfnfInterCb;
  963. lpfpb->lpvInterCbParms = lpvInterCbParms;
  964. _LEAVECRITICALSECTION(&lpfpb->cs);
  965. }
  966. _GLOBALUNLOCK(hfpb);
  967. }
  968. /*************************************************************************
  969. * @doc PRIVATE
  970. *
  971. * @func VOID PASCAL | GetFSName |
  972. *
  973. * Given a filename which may include a system file and a sub-system
  974. * filename separated by '!', this function will break the given name
  975. * into separate components. If there is no sub-system filename, it
  976. * will use the default name
  977. *
  978. * @parm LSZ | lszFName |
  979. * Pointer to filename to be parsed
  980. *
  981. * @parm LSZ | aszNameBuf |
  982. * Common buffer to store the two names
  983. *
  984. * @parm LSZ FAR * | lplszSubFilename |
  985. * Pointer to subfile name to be updated
  986. *
  987. * @parm LSZ | lszDefaultName |
  988. * Default subname to be used
  989. *************************************************************************/
  990. PUBLIC VOID PASCAL FAR GetFSName(LSZ lszFName, LSZ aszNameBuf,
  991. LSZ FAR *lplszSubFilename, LSZ lszDefaultName)
  992. {
  993. register LSZ lsztmp = aszNameBuf;
  994. /* Look for the '!' delimiter */
  995. for (lsztmp = aszNameBuf;
  996. (*lsztmp = *lszFName) && *lsztmp != '!'; lsztmp++, lszFName++);
  997. *lsztmp++ = 0;
  998. if (*lszFName == 0)
  999. {
  1000. /* No subfile's name specified, use default */
  1001. *lplszSubFilename = lszDefaultName;
  1002. }
  1003. else
  1004. {
  1005. /* Copy the index subfile's name */
  1006. *lplszSubFilename = lsztmp;
  1007. lszFName++; // Skip the !
  1008. while (*lsztmp++ = *lszFName++);
  1009. }
  1010. }
  1011. /*************************************************************************
  1012. * @doc PRIVATE
  1013. *
  1014. * @func int PASCAL | IsFsName |
  1015. *
  1016. * Given a filename, determine if it is a sub-system filename or not
  1017. * The idea is to search for '!', which is a sub-system filename
  1018. * delimiter
  1019. *
  1020. * @parm LSZ | lszFName |
  1021. * Pointer to filename to be parsed
  1022. *
  1023. * @rdesc TRUE if the name is a sub-system file name, FALSE otherwise
  1024. *************************************************************************/
  1025. PUBLIC int PASCAL FAR IsFsName (register LSZ lszFName)
  1026. {
  1027. if (lszFName)
  1028. {
  1029. for (; *lszFName; lszFName ++)
  1030. {
  1031. if (*lszFName == '!')
  1032. return TRUE;
  1033. }
  1034. }
  1035. return FALSE;
  1036. }
  1037. /*************************************************************************
  1038. * @doc INTERNAL
  1039. *
  1040. * @func int FAR PASCAL | FileFlush |
  1041. * Flush the file
  1042. *
  1043. * @parm HANDLE | hfpb |
  1044. * If non-zero, handle to a file parameter block
  1045. *
  1046. * @rdesc S_OK if ereything is OK, else various errors
  1047. *************************************************************************/
  1048. PUBLIC int FAR PASCAL FileFlush(HFPB hfpb)
  1049. {
  1050. HRESULT errDos;
  1051. LPFPB lpfpb;
  1052. if (hfpb == NULL)
  1053. return E_HANDLE;
  1054. lpfpb = (LPFPB)_GLOBALLOCK(hfpb);
  1055. _ENTERCRITICALSECTION(&lpfpb->cs);
  1056. switch (lpfpb->fFileType)
  1057. {
  1058. case FS_SYSTEMFILE:
  1059. errDos = E_ASSERT;
  1060. break;
  1061. case FS_SUBFILE:
  1062. errDos=RcFlushHf(lpfpb->fs.hf);
  1063. break;
  1064. case REGULAR_FILE:
  1065. if ((errDos = (WORD)_COMMIT(lpfpb->fs.hFile)) != 0)
  1066. errDos = E_FILEWRITE;
  1067. break;
  1068. }
  1069. _LEAVECRITICALSECTION(&lpfpb->cs);
  1070. _GLOBALUNLOCK (hfpb);
  1071. return errDos;
  1072. }
  1073. /*************************************************************************
  1074. * @doc INTERNAL
  1075. *
  1076. * @func int FAR PASCAL | FileClose |
  1077. * Close the file and get rid of the file parameter block
  1078. *
  1079. * @parm HANDLE | hfpb |
  1080. * If non-zero, handle to a file parameter block
  1081. *
  1082. * @rdesc S_OK if ereything is OK, else various errors
  1083. *************************************************************************/
  1084. #ifndef ITWRAP
  1085. PUBLIC HRESULT FAR PASCAL FileClose(HFPB hfpb)
  1086. {
  1087. HRESULT rc;
  1088. LPFPB lpfpb;
  1089. if (hfpb == NULL)
  1090. return E_HANDLE;
  1091. lpfpb = (LPFPB)_GLOBALLOCK(hfpb);
  1092. _ENTERCRITICALSECTION(&lpfpb->cs);
  1093. rc = S_OK;
  1094. switch (lpfpb->fFileType)
  1095. {
  1096. case FS_SYSTEMFILE:
  1097. rc = RcCloseHfs(lpfpb->fs.hfs);
  1098. break;
  1099. case FS_SUBFILE:
  1100. {
  1101. HFS hfs=NULL;
  1102. if (lpfpb->ioMode&OPENED_HFS)
  1103. hfs=HfsGetFromHf(lpfpb->fs.hf);
  1104. rc = RcCloseHf(lpfpb->fs.hf);
  1105. if (hfs)
  1106. rc = RcCloseHfs(hfs);
  1107. break;
  1108. }
  1109. case REGULAR_FILE:
  1110. #ifdef _WIN32
  1111. rc = (!CloseHandle(lpfpb->fs.hFile))?ERR_CLOSEFAILED:S_OK;
  1112. #else
  1113. rc = (_lclose(lpfpb->fs.hFile))?ERR_CLOSEFAILED:S_OK;
  1114. #endif
  1115. break;
  1116. }
  1117. _LEAVECRITICALSECTION(&lpfpb->cs);
  1118. _DELETECRITICALSECTION(&lpfpb->cs);
  1119. /* Free the file parameter block structure */
  1120. _GLOBALFREE(lpfpb->hStruct);
  1121. return rc;
  1122. }
  1123. #endif
  1124. /*************************************************************************
  1125. *
  1126. * @doc INTERNAL
  1127. *
  1128. * @func int FAR PASCAL | FileUnlink |
  1129. * Unlink a file. This function is an example of difference between
  1130. * platforms. The filename is a far pointer under Windows, but
  1131. * _unlink() requires a near pointer in medium model. What happens
  1132. * is that we have to copy the name into an allocated near buffer
  1133. * for _unlink()
  1134. *
  1135. * @parm LPCSTR | lszFilename |
  1136. * Pointer to filename
  1137. *
  1138. * @parm int | iFileType |
  1139. * Any of FS_SYSTEMFILE, FS_SUBFILE, or REGULAR_FILE.
  1140. *
  1141. * @rdesc Return S_OK, ERR_MEMORY, or return value of _unlink()
  1142. *
  1143. *************************************************************************/
  1144. PUBLIC HRESULT FAR PASCAL FileUnlink (HFPB hfpbSysFile, LPCSTR lszFilename, int fFileType)
  1145. {
  1146. OFSTRUCT ofStruct;
  1147. HRESULT rc;
  1148. HRESULT errb;
  1149. FM fm;
  1150. switch (fFileType)
  1151. {
  1152. case FS_SYSTEMFILE:
  1153. fm = FmNewSzDir((LPSTR)lszFilename, dirCurrent, NULL);
  1154. rc = RcDestroyFileSysFm(fm);
  1155. DisposeFm(fm);
  1156. break;
  1157. case FS_SUBFILE:
  1158. {
  1159. HFS hfs = GetHfs(hfpbSysFile,lszFilename,TRUE,&errb);
  1160. if (hfs)
  1161. {
  1162. rc=RcUnlinkFileHfs(hfs, GetSubFilename(lszFilename,NULL));
  1163. if (!hfpbSysFile)
  1164. RcCloseHfs(hfs);
  1165. }
  1166. else
  1167. rc=errb;
  1168. break;
  1169. }
  1170. case REGULAR_FILE:
  1171. if ((HFILE) OpenFile(lszFilename, &ofStruct, OF_DELETE) != (HFILE_ERROR))
  1172. rc=S_OK;
  1173. else
  1174. rc=E_FILEDELETE;
  1175. break;
  1176. default:
  1177. rc=E_ASSERT;
  1178. }
  1179. return rc;
  1180. }
  1181. #if !defined(MOSMAP) // {
  1182. #ifdef _NT // {
  1183. // Can't have NULL as path... must be a string
  1184. WORD EXPORT_API PASCAL FAR GetTempFileNameEx(
  1185. LPCSTR lpszPath, /* address of name of dir. where temp. file is created */
  1186. LPCSTR lpszPrefix, /* address of prefix of temp. filename */
  1187. WORD uUnique, /* number used to create temp. filename */
  1188. LPSTR lpszTempFile /* address buffer that will receive temp. filename */
  1189. )
  1190. {
  1191. char lpszBuf[_MAX_PATH] ;
  1192. if (!lpszPath)
  1193. {
  1194. if (sizeof(lpszBuf) >= GetTempPath(sizeof(lpszBuf), lpszBuf))
  1195. lpszPath = lpszBuf ;
  1196. else
  1197. // default to current directory
  1198. lpszPath = "." ;
  1199. }
  1200. // Now call the regular function
  1201. return (WORD) GetTempFileName(lpszPath, lpszPrefix, uUnique, lpszTempFile) ;
  1202. }
  1203. #endif // _NT }
  1204. #endif // MOSMAP }
  1205. /*************************************************************************
  1206. * @doc PRIVATE
  1207. *
  1208. * @func LPFBI PASCAL FAR | FileBufAlloc |
  1209. * Allocate an I/O buffer associated with a file. This is to speed
  1210. * up I/O
  1211. *
  1212. * @parm HFPB | hfpb |
  1213. * Handle to file parameter block for an already opened file
  1214. *
  1215. * @parm WORD | Size |
  1216. * Size of the buffer
  1217. *
  1218. * @rdesc Pointer to a file buffer info if everything is OK, NULL
  1219. * if out of memory, or invalid file handle
  1220. *************************************************************************/
  1221. PUBLIC LPFBI PASCAL FAR EXPORT_API FileBufAlloc (HFPB hfpb, WORD Size)
  1222. {
  1223. LPFBI lpfbi; /* Pointer to file buffer info */
  1224. LPFPB lpfpb;
  1225. HANDLE hMem;
  1226. /* Sanity check, the file must be already opened */
  1227. if (hfpb == 0)
  1228. return NULL;
  1229. /* Allocate the structure. All fields are zeroed */
  1230. if (!(hMem=_GLOBALALLOC(GMEM_ZEROINIT,sizeof(FBI) + Size)))
  1231. {
  1232. return NULL;
  1233. }
  1234. if (!(lpfbi=(LPFBI)_GLOBALLOCK(hMem)))
  1235. {
  1236. _GLOBALFREE(hMem);
  1237. return NULL;
  1238. }
  1239. /* Initialize the fields */
  1240. lpfbi->lrgbBuf = (LPB)lpfbi + sizeof(FBI);
  1241. lpfbi->hStruct = hMem;
  1242. /* Get the DOS file handle associated with the file parameter block */
  1243. lpfpb = (LPFPB)_GLOBALLOCK(hfpb);
  1244. _ENTERCRITICALSECTION(&lpfpb->cs);
  1245. lpfbi->hFile = lpfpb->fs.hFile;
  1246. /* Update fields */
  1247. lpfbi->cbBufSize = Size;
  1248. lpfbi->hfpb = hfpb;
  1249. /* For read only file, assume the file's size is huge */
  1250. if (lpfpb->ioMode == READ)
  1251. lpfbi->foExtent = foMax;
  1252. _LEAVECRITICALSECTION(&lpfpb->cs);
  1253. _GLOBALUNLOCK(hfpb);
  1254. return lpfbi;
  1255. }
  1256. /*************************************************************************
  1257. * @doc PRIVATE
  1258. *
  1259. * @func int PASCAL FAR | FileBufFlush |
  1260. * Flush the buffer to the disk
  1261. *
  1262. * @parm LPFBI | lpfbi |
  1263. * Pointer to file buffer info
  1264. *
  1265. * @rdesc S_OK if everything is OK, else errors
  1266. *************************************************************************/
  1267. PUBLIC int PASCAL FAR FileBufFlush (LPFBI lpfbi)
  1268. {
  1269. LONG lWrote;
  1270. WORD cByteWritten;
  1271. HRESULT errb;
  1272. int fRet;
  1273. /* Sanity check */
  1274. if (lpfbi == NULL)
  1275. return E_INVALIDARG;
  1276. /* Calculate how many bytes are to be written */
  1277. cByteWritten = lpfbi->ibBuf;
  1278. lWrote = FileSeekWrite(lpfbi->hfpb, lpfbi->lrgbBuf,
  1279. lpfbi->foExtent, cByteWritten, &errb);
  1280. fRet=errb;
  1281. if (lWrote==(LONG)cByteWritten)
  1282. {
  1283. fRet=S_OK;
  1284. /* Update the the current offset into the file */
  1285. lpfbi->foExtent=lpfbi->fo=(FoAddDw(lpfbi->fo,cByteWritten));
  1286. lpfbi->ibBuf = lpfbi->cbBuf = 0;
  1287. }
  1288. return fRet;
  1289. }
  1290. /*************************************************************************
  1291. * @doc PRIVATE
  1292. *
  1293. * @func VOID PASCAL FAR | FileBufFree |
  1294. * Free all memory associated with the file buffer info
  1295. *
  1296. * @parm LPFBI | lpfbi |
  1297. * Pointer to file buffer info
  1298. *************************************************************************/
  1299. PUBLIC VOID PASCAL FAR FileBufFree (LPFBI lpfbi)
  1300. {
  1301. if (lpfbi == NULL)
  1302. return;
  1303. _GLOBALFREE(lpfbi->hStruct);
  1304. }
  1305. /*************************************************************************
  1306. * @doc PRIVATE
  1307. *
  1308. * @func BOOL FAR PASCAL | FileBufRewind |
  1309. * This function will:
  1310. * - Flush the file, update the file size
  1311. * - Reset the logical file offset to 0
  1312. * It prepares the file for reading
  1313. *
  1314. * @parm LPFBI | lpfbi |
  1315. * Pointer to file parameter info block
  1316. *
  1317. * @rdesc Error code or S_OK
  1318. *************************************************************************/
  1319. PUBLIC BOOL FAR PASCAL FileBufRewind (LPFBI lpfbi)
  1320. {
  1321. int fRet;
  1322. /* Sanity check */
  1323. if (lpfbi == NULL)
  1324. return E_INVALIDARG;
  1325. /* Flush the buffer. This will reset the size of the file (foExtent) */
  1326. if ((fRet = FileBufFlush(lpfbi)) != S_OK)
  1327. return fRet;
  1328. #if 0
  1329. /* Make sure that things go out to disk */
  1330. if ((fRet = FileFlush(lpfbi->hfpb)) != S_OK)
  1331. return fRet;
  1332. #endif
  1333. /* Reset the offset of the file */
  1334. lpfbi->fo = foNil;
  1335. return S_OK;
  1336. }
  1337. /*************************************************************************
  1338. * @doc PRIVATE
  1339. *
  1340. * @func int FAR PASCAL | FileBufFill |
  1341. * This function helps with file reads. It copies the left-over
  1342. * data in the I/O buffer to the start of the buffer, then fills
  1343. * the rest of the buffer with new data.
  1344. *
  1345. * @parm LPFBI | lpfbi |
  1346. * File buffer info.
  1347. *
  1348. * @parm PHRESULT | phr |
  1349. * Error return.
  1350. *
  1351. * @rdesc The function returns the number of bytes read, or cbIO_ERROR
  1352. * if error
  1353. *************************************************************************/
  1354. PUBLIC int FAR PASCAL FileBufFill (LPFBI lpfbi, PHRESULT phr)
  1355. {
  1356. WORD cbRead; // Number of bytes read.
  1357. WORD cbByteLeft; // Number of bytes left
  1358. DWORD dwFileByteLeft;
  1359. if (FoCompare(lpfbi->foExtent,lpfbi->fo)<=0)
  1360. return 0;
  1361. dwFileByteLeft = FoSubFo(lpfbi->foExtent,lpfbi->fo).dwOffset;
  1362. if (lpfbi->cbBuf < lpfbi->ibBuf)
  1363. {
  1364. SetErrCode (phr, E_INVALIDARG);
  1365. return cbIO_ERROR;
  1366. }
  1367. /* Preserve left-over data. */
  1368. if (cbByteLeft = lpfbi->cbBuf - lpfbi->ibBuf)
  1369. {
  1370. MEMCPY(lpfbi->lrgbBuf, lpfbi->lrgbBuf + lpfbi->ibBuf, cbByteLeft);
  1371. lpfbi->ibBuf = 0;
  1372. lpfbi->cbBuf = cbByteLeft;
  1373. }
  1374. else
  1375. {
  1376. /* There is nothing left. The buffer is considered to be empty */
  1377. lpfbi->cbBuf = lpfbi->ibBuf = 0;
  1378. }
  1379. /* Get new data. */
  1380. cbRead = lpfbi->cbBufSize - cbByteLeft;
  1381. if ((DWORD)cbRead > dwFileByteLeft)
  1382. cbRead = (WORD)dwFileByteLeft;
  1383. if ((cbRead = (WORD)FileSeekRead(lpfbi->hfpb, lpfbi->lrgbBuf + cbByteLeft,
  1384. lpfbi->fo, cbRead, phr)) != cbIO_ERROR)
  1385. {
  1386. lpfbi->cbBuf = cbByteLeft + cbRead;
  1387. lpfbi->fo=FoAddDw(lpfbi->fo,cbRead);
  1388. }
  1389. return cbRead;
  1390. }
  1391. /*************************************************************************
  1392. * @doc PRIVATE
  1393. *
  1394. * @func BOOL FAR PASCAL | FileBufBackPatch |
  1395. * This function will batchpatch a file at a certain location, in
  1396. * memory or at a some physical offset
  1397. *
  1398. * @parm LPFBI | lpfbi |
  1399. * Pointer to file buffer info block
  1400. *
  1401. * @parm LPV | lpvData |
  1402. * Pointer to data tempplate
  1403. *
  1404. * @parm FO | fo |
  1405. * File offset to write it at.
  1406. *
  1407. * @parm WORD | cbBytes |
  1408. * How many bytes to write.
  1409. *
  1410. * @rdesc Error code of S_OK
  1411. *************************************************************************/
  1412. PUBLIC BOOL FAR PASCAL FileBufBackPatch(LPFBI lpfbi, LPV lpvData,
  1413. FILEOFFSET fo, WORD cbBytes)
  1414. {
  1415. HRESULT errb;
  1416. if (FoCompare(fo,lpfbi->fo)>=0)
  1417. { // Not flushed, do copy.
  1418. MEMCPY(lpfbi->lrgbBuf + (short)FoSubFo(fo,lpfbi->fo).dwOffset, lpvData, cbBytes);
  1419. return S_OK;
  1420. }
  1421. return (FileSeekWrite(lpfbi->hfpb, lpvData, fo, cbBytes, &errb)==(LONG)cbBytes)?S_OK:errb;
  1422. }
  1423. #ifndef ITWRAP
  1424. PRIVATE HANDLE NEAR PASCAL IoftsWin32Create(LPCSTR lpstr, DWORD w)
  1425. {
  1426. SECURITY_ATTRIBUTES sa;
  1427. HANDLE hfile;
  1428. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  1429. sa.lpSecurityDescriptor = NULL;
  1430. sa.bInheritHandle = 0;
  1431. hfile= CreateFile(lpstr, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
  1432. &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  1433. return hfile;
  1434. }
  1435. PRIVATE HANDLE NEAR PASCAL IoftsWin32Open(LPCSTR lpstr, DWORD w)
  1436. {
  1437. SECURITY_ATTRIBUTES sa;
  1438. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  1439. sa.lpSecurityDescriptor = NULL;
  1440. sa.bInheritHandle = 0;
  1441. return CreateFile(lpstr, (w == READ) ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, &sa,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1442. }
  1443. #endif
  1444. /*************************************************************************
  1445. * @doc PRIVATE
  1446. *
  1447. * @func HSFB PASCAL FAR | FpbFromHfs |
  1448. * Allocate a file parameter buffer, set to hfs
  1449. *
  1450. * @parm HFS | hfsHandle |
  1451. * Handle of an HFS system file
  1452. *
  1453. * @parm PHRESULT | phr |
  1454. * Error buffer
  1455. *
  1456. * @rdesc Return a pointer to the newly allocated file parameter block
  1457. * if succeeded, else NULL
  1458. *************************************************************************/
  1459. PUBLIC HSFB PASCAL FAR FpbFromHfs(HFS hfsHandle, PHRESULT phr)
  1460. {
  1461. HFPB hfpb;
  1462. LPFPB lpfpb;
  1463. if ((hfpb = _GLOBALALLOC(GMEM_MOVEABLE | GMEM_ZEROINIT,
  1464. (WORD)sizeof(FPB))) == NULL)
  1465. {
  1466. SetErrCode(phr, E_OUTOFMEMORY);
  1467. return NULL;
  1468. }
  1469. lpfpb = (LPFPB)_GLOBALLOCK(hfpb);
  1470. _INITIALIZECRITICALSECTION(&lpfpb->cs);
  1471. lpfpb->hStruct = hfpb;
  1472. lpfpb->lpvInterCbParms = NULL;
  1473. lpfpb->lpfnfInterCb = NULL;
  1474. lpfpb->fFileType=FS_SYSTEMFILE;
  1475. lpfpb->fs.hfs = (HFS)hfsHandle;
  1476. _GLOBALUNLOCK(hfpb);
  1477. return hfpb;
  1478. }
  1479. /*************************************************************************
  1480. * @doc PRIVATE
  1481. *
  1482. * @func HSFB PASCAL FAR | FpbFromHf |
  1483. * Allocate a file parameter buffer, set to hf
  1484. *
  1485. * @parm HF | hfHandle |
  1486. * Handle of a subfile.
  1487. *
  1488. * @parm PHRESULT | phr |
  1489. * Error buffer
  1490. *
  1491. * @rdesc Return a pointer to the newly allocated file parameter block
  1492. * if succeeded, else NULL
  1493. *************************************************************************/
  1494. PUBLIC HSFB PASCAL FAR FpbFromHf(HF hfHandle, PHRESULT phr)
  1495. {
  1496. HFPB hfpb;
  1497. LPFPB lpfpb;
  1498. if ((hfpb = _GLOBALALLOC(GMEM_MOVEABLE | GMEM_ZEROINIT,
  1499. (WORD)sizeof(FPB))) == NULL)
  1500. {
  1501. SetErrCode(phr, E_OUTOFMEMORY);
  1502. return NULL;
  1503. }
  1504. lpfpb = (LPFPB)_GLOBALLOCK(hfpb);
  1505. lpfpb->hStruct = hfpb;
  1506. lpfpb->lpvInterCbParms = NULL;
  1507. lpfpb->lpfnfInterCb = NULL;
  1508. lpfpb->fFileType=FS_SUBFILE;
  1509. lpfpb->fs.hf = (HF)hfHandle;
  1510. _INITIALIZECRITICALSECTION(&lpfpb->cs);
  1511. _GLOBALUNLOCK(hfpb);
  1512. return hfpb;
  1513. }
  1514. /*************************************************************************
  1515. * @doc PRIVATE
  1516. *
  1517. * @func DWORD PASCAL FAR | FsTypeFromHfpb |
  1518. * Returns the type of file pointed to by a FPB.
  1519. *
  1520. * @parm HFPB | hfpb |
  1521. * Handle to a file parameter block.
  1522. *
  1523. * @rdesc Returns one of the following if successful:
  1524. * FS_SYSTEMFILE, FS_SUBFILE, REGULARFILE
  1525. Returns 0 if unsuccessful.
  1526. *************************************************************************/
  1527. PUBLIC DWORD PASCAL FAR FsTypeFromHfpb(HFPB hfpb)
  1528. {
  1529. LPFPB lpfpb;
  1530. DWORD dwFileType = 0;
  1531. if (hfpb != NULL)
  1532. {
  1533. lpfpb = (LPFPB)_GLOBALLOCK(hfpb);
  1534. _ENTERCRITICALSECTION(&lpfpb->cs);
  1535. dwFileType = (DWORD) lpfpb->fFileType;
  1536. _LEAVECRITICALSECTION(&lpfpb->cs);
  1537. _GLOBALUNLOCK(hfpb);
  1538. }
  1539. return (dwFileType);
  1540. }
  1541. // Frees the critical section and the HFPB
  1542. PUBLIC VOID PASCAL FAR FreeHfpb(HFPB hfpb)
  1543. {
  1544. LPFPB lpfpb;
  1545. lpfpb = (LPFPB)_GLOBALLOCK(hfpb);
  1546. _DELETECRITICALSECTION(&lpfpb->cs);
  1547. _GLOBALUNLOCK(hfpb);
  1548. _GLOBALFREE(hfpb);
  1549. }