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.

760 lines
19 KiB

  1. /*****************************************************************************
  2. * *
  3. * FID.C *
  4. * *
  5. * Copyright (C) Microsoft Corporation 1989 - 1994. *
  6. * All Rights reserved. *
  7. * *
  8. *****************************************************************************
  9. * *
  10. * Module Intent *
  11. * *
  12. * Low level file access layer, Windows version. *
  13. * *
  14. *****************************************************************************
  15. * *
  16. * Current Owner: UNDONE *
  17. * *
  18. *****************************************************************************
  19. * *
  20. * Released by Development: *
  21. * *
  22. *****************************************************************************/
  23. /*****************************************************************************
  24. *
  25. * Revision History:
  26. * -- Mar 92 adapted from WinHelp FID.C, DAVIDJES
  27. * 9/26/95 davej Autodoc'd
  28. * 3/05/97 erinfox Change errors to HRESULTS
  29. *****************************************************************************/
  30. /*****************************************************************************
  31. *
  32. * Issues:
  33. * How to communicate super large (> DWORD) seeks over MOS. See FoSeekFid
  34. *
  35. *****************************************************************************/
  36. static char s_aszModule[] = __FILE__; /* For error report */
  37. #include <mvopsys.h>
  38. #include <iterror.h>
  39. #ifdef _32BIT
  40. #define FP_OFF
  41. #endif
  42. #include <direct.h>
  43. #include <orkin.h>
  44. #include <misc.h>
  45. #include <wrapstor.h>
  46. #include <_mvutil.h>
  47. #ifdef MOSMAP
  48. #include <mapfile.h>
  49. #endif
  50. #ifndef _MAC
  51. #include <dos.h> /* for FP_OFF macros and file attribute constants */
  52. #endif
  53. #include <io.h> /* for tell() and eof() */
  54. #include <errno.h> /* this is for chsize() */
  55. /***************************************************************************
  56. *
  57. * Defines
  58. *
  59. ***************************************************************************/
  60. #define UCBMAXRW ((WORD)0xFFFE)
  61. #define LCBSIZESEG ((ULONG)0x10000)
  62. /***************************************************************************
  63. *
  64. * Macros
  65. *
  66. ***************************************************************************/
  67. #define _WOpenMode(w) (_rgwOpenMode[ (w) & wRWMask ] | \
  68. _rgwShare[ ((w) & wShareMask) >> wShareShift ] )
  69. /***************************************************************************
  70. *
  71. * Private Functions
  72. *
  73. ***************************************************************************/
  74. HRESULT PASCAL FAR RcMapDOSErrorW(WORD);
  75. /***************************************************************************
  76. *
  77. * Public Functions
  78. *
  79. ***************************************************************************/
  80. /***************************************************************************
  81. * @doc INTERNAL
  82. *
  83. * @func BOOL PASCAL FAR | FidFlush |
  84. *
  85. * @parm FID |fid|
  86. *
  87. * @rdesc TRUE if file flushed OK, FALSE if could not flush.
  88. *
  89. ***************************************************************************/
  90. // Fill in non-win-32
  91. PUBLIC BOOL PASCAL FAR FidFlush(FID fid)
  92. {
  93. BOOL bSuccess=TRUE;
  94. #ifdef _WIN32
  95. bSuccess=FlushFileBuffers(fid);
  96. #else
  97. Need code here
  98. #endif
  99. #ifdef _DEBUGMVFS
  100. DPF2("FidFlush: fid %ld, returned %d\n", (LONG)fid, bSuccess);
  101. #endif
  102. return bSuccess;
  103. }
  104. /***************************************************************************
  105. *
  106. * @doc INTERNAL
  107. *
  108. * @func FID PASCAL FAR | FidCreateFm |
  109. * Create a file
  110. *
  111. * @parm FM | fm |
  112. * the file moniker
  113. *
  114. * @parm WORD | wOpenMode |
  115. * read/write/share mode
  116. *
  117. * @parm WORD | wPerm |
  118. * file permissions
  119. *
  120. * @parm PHRESULT | phr |
  121. * Error return
  122. *
  123. * @rdesc fidNil on failure, valid fid otherwise
  124. *
  125. ***************************************************************************/
  126. PUBLIC FID FAR PASCAL FidCreateFm(FM fm, WORD wOpenMode,
  127. WORD wPerm, PHRESULT phr)
  128. {
  129. #ifdef MOSMAP // {
  130. // Disable function
  131. SetErrCode(phr, ERR_NOTSUPPORTED);
  132. return fidNil;
  133. #else // } {
  134. FID fid;
  135. QAFM qafm;
  136. if (fm == fmNil)
  137. {
  138. SetErrCode(phr, E_INVALIDARG);
  139. return fidNil;
  140. }
  141. qafm = (QAFM)fm;
  142. //qafm = _GLOBALLOCK((HANDLE)fm);
  143. #ifdef _WIN32
  144. fid = CreateFile((LPSTR)qafm->rgch,
  145. ((wOpenMode&wRead)?GENERIC_READ:0)|((wOpenMode&wWrite)?GENERIC_WRITE:0),
  146. ((wOpenMode&wShareRead)?FILE_SHARE_READ:0)|((wOpenMode&wShareWrite)?FILE_SHARE_WRITE:0),
  147. NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  148. // Note: Some really cool optimizations can be made by specifying how the file
  149. // is intended to be used!
  150. #else
  151. fid =_lcreat((LPSTR)qafm->rgch, _rgwPerm[ (wPerm) & wRWMask ]);
  152. #endif
  153. if (fid == fidNil)
  154. SetErrCode(phr, E_FILECREATE);
  155. //_GLOBALUNLOCK((HANDLE)fm);
  156. #ifdef _DEBUGMVFS
  157. DPF2("FidCreateFm: fid %ld for '%s'.\n", (LONG)fid, (LPSTR)qafm->rgch);
  158. #endif
  159. return fid;
  160. #endif //}
  161. }
  162. /***************************************************************************
  163. *
  164. * @doc INTERNAL
  165. *
  166. * @func FID PASCAL FAR | FidOpenFm |
  167. * Open a file in binary mode.
  168. *
  169. * @parm FM | fm |
  170. * the file moniker
  171. *
  172. * @parm WORD | wOpenMode |
  173. * read/write/share modes. Undefined if wRead and wWrite both unset.
  174. *
  175. * @parm PHRESULT | phr |
  176. * Error return
  177. *
  178. * @rdesc fidNil on failure, else a valid FID.
  179. *
  180. ***************************************************************************/
  181. PUBLIC FID FAR PASCAL FidOpenFm(FM fm, WORD wOpenMode, PHRESULT phr)
  182. {
  183. FID fid;
  184. QAFM qafm;
  185. if (fm == fmNil)
  186. {
  187. SetErrCode(phr, E_INVALIDARG);
  188. return fidNil;
  189. }
  190. qafm = (QAFM)fm;
  191. //qafm = _GLOBALLOCK((HANDLE)fm);
  192. #ifdef MOSMAP // {
  193. // Open File Mapping, or get ref to existing one
  194. if ((fid = (HFILE)MosOpenMapFile((LPSTR)qafm->rgch)) == fidNil)
  195. SetErrCode(phr, ERR_FAILED);
  196. #else // } {
  197. #ifdef _WIN32
  198. if ((fid = CreateFile((LPSTR)qafm->rgch,
  199. ((wOpenMode&wRead)?GENERIC_READ:0)|((wOpenMode&wWrite)?GENERIC_WRITE:0),
  200. ((wOpenMode&wShareRead)?FILE_SHARE_READ:0)|((wOpenMode&wShareWrite)?FILE_SHARE_WRITE:0),
  201. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == fidNil)
  202. #else
  203. if ((fid = _lopen((LPSTR)qafm->rgch, _WOpenMode(wOpenMode))) == fidNil)
  204. #endif // _WIN32
  205. SetErrCode(phr, RcGetDOSError());
  206. #endif //}
  207. //_GLOBALUNLOCK((HANDLE)fm);
  208. #ifdef _DEBUGMVFS
  209. DPF2("FidOpenFm: fid %ld for '%s'.\n", (LONG)fid, (LPSTR)qafm->rgch);
  210. #endif
  211. return fid;
  212. }
  213. /***************************************************************************
  214. *
  215. * @doc INTERNAL
  216. *
  217. * @func LONG PASCAL FAR | LcbReadFid |
  218. * Read data from a file.
  219. *
  220. * @parm FID | fid |
  221. * valid FID of an open file
  222. *
  223. * @parm QV | qv |
  224. * pointer to user's buffer assumed huge enough for data
  225. *
  226. * @parm LONG | lcb |
  227. * count of bytes to read (must be less than 2147483648)
  228. *
  229. * @parm PHRESULT | phr |
  230. * Error return
  231. *
  232. * @rdesc count of bytes actually read or -1 on error
  233. *
  234. ***************************************************************************/
  235. PUBLIC LONG FAR PASCAL LcbReadFid(FID fid, QV qv, LONG lcb, PHRESULT phr)
  236. {
  237. LONG lcbTotalRead = (LONG)0;
  238. #ifdef MOSMAP // {
  239. // Read map file
  240. lcbTotalRead = MosReadMapFile((LPVOID)fid, qv, lcb) ;
  241. if (lcbTotalRead == -1)
  242. #else // } {
  243. #ifdef _WIN32
  244. if (!ReadFile(fid, qv, lcb, &lcbTotalRead, NULL))
  245. SetErrCode(phr, RcGetDOSError());
  246. #else
  247. BYTE HUGE *hpb = (BYTE HUGE *)qv;
  248. WORD ucb, ucbRead;
  249. do {
  250. ucb = (WORD)min(lcb, UCBMAXRW);
  251. ucb = (WORD)min((ULONG) ucb, LCBSIZESEG - (ULONG) FP_OFF(hpb));
  252. ucbRead = _lread(fid, hpb, ucb);
  253. if (ucbRead == (WORD)-1)
  254. {
  255. if (!lcbTotalRead)
  256. {
  257. lcbTotalRead = (LONG)-1;
  258. }
  259. break;
  260. }
  261. else
  262. {
  263. lcbTotalRead += ucbRead;
  264. lcb -= ucbRead;
  265. hpb += ucbRead;
  266. }
  267. } while (lcb > 0 && ucb == ucbRead);
  268. if (ucbRead == (WORD)-1)
  269. SetErrCode(phr, ERR_CANTREAD);
  270. #endif
  271. #endif //}
  272. #ifdef _DEBUGMVFS
  273. DPF2("LcbReadFid: fid %ld returned %ld bytes.\n", (LONG)fid, lcbTotalRead);
  274. #endif
  275. return lcbTotalRead;
  276. }
  277. /***************************************************************************
  278. *
  279. * @doc INTERNAL
  280. *
  281. * @func LONG PASCAL FAR | LcbWriteid |
  282. * Write data to a file.
  283. *
  284. * @parm FID | fid |
  285. * valid FID of an open file
  286. *
  287. * @parm QV | qv |
  288. * pointer to user's buffer assumed huge enough for data
  289. *
  290. * @parm LONG | lcb |
  291. * count of bytes to read (must be less than 2147483648)
  292. *
  293. * @parm PHRESULT | phr |
  294. * Error return
  295. *
  296. * @rdesc count of bytes actually read or -1 on error
  297. *
  298. ***************************************************************************/
  299. PUBLIC LONG FAR PASCAL LcbWriteFid(FID fid, QV qv, LONG lcb, PHRESULT phr)
  300. {
  301. LONG lcbTotalWrote = (LONG)0;
  302. #ifdef MOSMAP // {
  303. // Disable function
  304. SetErrCode(phr, ERR_NOTSUPPORTED);
  305. return 0;
  306. #else // } {
  307. #ifdef _WIN32
  308. if (!WriteFile(fid, qv, lcb, &lcbTotalWrote, NULL))
  309. SetErrCode(phr, RcGetDOSError());
  310. #else
  311. BYTE HUGE *hpb = (BYTE HUGE *)qv;
  312. WORD ucb, ucbWrote;
  313. if (lcb == 0L)
  314. {
  315. phr->err = S_OK;
  316. return 0L;
  317. }
  318. do
  319. {
  320. ucb = (WORD)min(lcb, (ULONG) UCBMAXRW);
  321. ucb = (WORD)min((ULONG) ucb, LCBSIZESEG - (WORD) FP_OFF(hpb));
  322. ucbWrote = _lwrite(fid, hpb, ucb);
  323. if (ucbWrote == (WORD)-1)
  324. {
  325. if (!lcbTotalWrote)
  326. lcbTotalWrote = -1L;
  327. break;
  328. }
  329. else
  330. {
  331. lcbTotalWrote += ucbWrote;
  332. lcb -= ucbWrote;
  333. hpb += ucbWrote;
  334. }
  335. } while (lcb > 0 && ucb == ucbWrote);
  336. if (ucb != ucbWrote)
  337. {
  338. if (ucbWrote == (WORD)-1L)
  339. SetErrCode (phr, RcGetDOSError());
  340. else
  341. SetErrCode (phr, E_DISKFULL);
  342. }
  343. #endif
  344. #endif // }
  345. #ifdef _DEBUGMVFS
  346. DPF2("LcbWriteFid: fid %ld wrote %ld bytes.\n", (LONG)fid, lcbTotalWrote);
  347. #endif
  348. return lcbTotalWrote;
  349. }
  350. /***************************************************************************
  351. *
  352. * @doc INTERNAL
  353. *
  354. * @func HRESULT PASCAL FAR | RcCloseFid |
  355. * Close a file.
  356. *
  357. * @parm FID | fid |
  358. * valid FID of an open file
  359. *
  360. * @rdesc rcSuccess or something else
  361. *
  362. ***************************************************************************/
  363. PUBLIC HRESULT FAR PASCAL RcCloseFid(FID fid)
  364. {
  365. #ifdef MOSMAP // {
  366. if (MosCloseMapFile((LPVOID)fid) == HFILE_ERROR)
  367. {
  368. #else // } {
  369. #ifdef _WIN32
  370. if (!CloseHandle(fid))
  371. {
  372. #else
  373. if (_lclose( fid) == (HFILE)-1 )
  374. {
  375. #endif
  376. #endif //}
  377. #ifdef _DEBUGMVFS
  378. DPF2("RcCloseFid: fid %ld was NOT closed(%d).\n", (LONG)fid, 0);
  379. #endif
  380. return E_FILECLOSE;
  381. }
  382. #ifdef _DEBUGMVFS
  383. DPF2("RcCloseFid: fid %ld was closed(%d).\n", (LONG)fid, 1);
  384. #endif
  385. return S_OK;
  386. }
  387. /***************************************************************************
  388. *
  389. * @doc INTERNAL
  390. *
  391. * @func LONG PASCAL FAR | LTellFid |
  392. * Return current file position in an open file.
  393. *
  394. * @parm FID | fid |
  395. * valid FID of an open file
  396. *
  397. * @parm PHRESULT | phr |
  398. * Error return
  399. *
  400. * @rdesc offset from beginning of file in bytes; -1L on error.
  401. *
  402. ***************************************************************************/
  403. LONG FAR PASCAL LTellFid(FID fid, PHRESULT phr)
  404. {
  405. LONG l;
  406. #ifdef MOSMAP // {
  407. l = MosSeekMapFile((LPVOID)fid, 0L, 1) ;
  408. #else // } {
  409. #ifdef _WIN32
  410. DWORD dwHigh = 0L;
  411. l = SetFilePointer(fid, 0L, &dwHigh, FILE_CURRENT);
  412. // OK, just plain no support for +4gig files here...
  413. if ((l==(LONG)-1L) || (dwHigh))
  414. SetErrCode(phr, E_FILESEEK);
  415. #else
  416. l = _llseek(fid, 0L, 1);
  417. #endif
  418. #endif //}
  419. if ( l == (LONG)-1L )
  420. SetErrCode(phr, E_FILESEEK);
  421. #ifdef _DEBUGMVFS
  422. DPF2("LTellFid: fid %ld is at %ld\n", (LONG)fid, l);
  423. #endif
  424. return l;
  425. }
  426. /***************************************************************************
  427. *
  428. * @doc INTERNAL
  429. *
  430. * @func LONG PASCAL FAR | LSeekFid |
  431. * Move file pointer to a specified location. It is an error
  432. * to seek before beginning of file, but not to seek past end
  433. * of file.
  434. *
  435. * @parm FID | fid |
  436. * valid FID of an open file
  437. *
  438. * @parm LONG | lPos |
  439. * offset from origin
  440. *
  441. * @parm WORD | wOrg |
  442. * one of: wSeekSet: beginning of file, wSeekCur: current file pos,
  443. * wSeekEnd: end of file
  444. *
  445. * @parm PHRESULT | phr |
  446. * Error return
  447. *
  448. * @rdesc offset in bytes from beginning of file or -1L on error
  449. *
  450. ***************************************************************************/
  451. PUBLIC LONG FAR PASCAL LSeekFid(FID fid, LONG lPos, WORD wOrg, PHRESULT phr)
  452. {
  453. LONG l;
  454. #ifdef MOSMAP // {
  455. l = MosSeekMapFile((LPVOID)fid, lPos, wOrg) ;
  456. #else // } {
  457. #ifdef _WIN32
  458. DWORD dwHigh = 0L;
  459. l = SetFilePointer(fid, lPos, &dwHigh, wOrg);
  460. // OK, just plain no support for +4gig files here...
  461. if ((l!=lPos) || (dwHigh))
  462. SetErrCode(phr, E_FILESEEK);
  463. #else
  464. l = _llseek(fid, lPos, wOrg);
  465. if (l == (LONG)-1L)
  466. SetErrCode(phr, E_FILESEEK);
  467. #endif
  468. #endif //}
  469. #ifdef _DEBUGMVFS
  470. DPF2("LSeekFid: fid %ld is at %ld\n", (LONG)fid, l);
  471. #endif
  472. return l;
  473. }
  474. /***************************************************************************
  475. *
  476. * @doc INTERNAL
  477. *
  478. * @func FILEOFFSET PASCAL FAR | FoSeekFid |
  479. * Move file pointer to a specified location. It is an error
  480. * to seek before beginning of file, but not to seek past end
  481. * of file. This function is meant to handle offsets larger than 4
  482. * gigabytes.
  483. *
  484. * @parm FID | fid |
  485. * valid FID of an open file
  486. *
  487. * @parm FILEOFFSET | foPos |
  488. * offset from origin
  489. *
  490. * @parm WORD | wOrg |
  491. * one of: wSeekSet: beginning of file, wSeekCur: current file pos,
  492. * wSeekEnd: end of file
  493. *
  494. * @parm PHRESULT | phr |
  495. * Error return
  496. *
  497. * @rdesc offset in bytes from beginning of file or -1L on error
  498. *
  499. ***************************************************************************/
  500. PUBLIC FILEOFFSET FAR PASCAL FoSeekFid(FID fid, FILEOFFSET foPos, WORD wOrg, PHRESULT phr)
  501. {
  502. DWORD dw;
  503. DWORD dwHigh=0L;
  504. FILEOFFSET foSeeked;
  505. #ifdef MOSMAP // {
  506. SetErrCode(phr,ERR_NOTSUPPORTED);
  507. return -1L;
  508. //l = MosSeekMapFile((LPVOID)fid, lPos, wOrg) ;
  509. #else // } {
  510. #ifdef _WIN32
  511. dwHigh=(LONG)foPos.dwHigh;
  512. dw = SetFilePointer((HANDLE)fid, foPos.dwOffset, &dwHigh, wOrg);
  513. #else // not really supported for 16-bit
  514. dw = (DWORD)_llseek(fid, foPos.dwOffset, wOrg);
  515. #endif
  516. #endif //}
  517. foSeeked.dwOffset=dw;
  518. foSeeked.dwHigh=dwHigh;
  519. if (dw == (LONG)-1L)
  520. {
  521. if (GetLastError()!=NO_ERROR)
  522. SetErrCode(phr, E_FILESEEK);
  523. else
  524. *phr = S_OK;
  525. }
  526. #ifdef _DEBUGMVFS
  527. DPF2("FoSeekFid: fid %ld is at %ld\n", (LONG)fid, foPos.dwOffset);
  528. #endif
  529. return foSeeked;
  530. }
  531. #if 0
  532. #if !defined ( _WIN32 )
  533. /***************************************************************************
  534. *
  535. * @doc INTERNAL
  536. *
  537. * @func BOOL PASCAL FAR | FEofFid |
  538. * Tells ye if ye're at the end of the file.
  539. *
  540. * @parm FID | fid |
  541. * valid FID of an open file
  542. *
  543. * @rdesc TRUE if at EOF, FALSE if not or error has occurred (?)
  544. *
  545. ***************************************************************************/
  546. PUBLIC BOOL PASCAL FAR FEofFid(FID fid)
  547. {
  548. WORD wT;
  549. if (( wT = eof( fid) ) == (WORD)-1 )
  550. SetErrCode(RcGetDOSError());
  551. else
  552. SetErrCode(rcSuccess);
  553. return (BOOL)(wT == 1);
  554. }
  555. #endif // !defined ( _WIN32 )
  556. #endif
  557. PUBLIC HRESULT PASCAL FAR RcGetDOSError (void)
  558. {
  559. #ifdef _WIN32
  560. // NT does not support errno in the multi threaded environment.
  561. switch( GetLastError() )
  562. {
  563. case NO_ERROR:
  564. return S_OK;
  565. case ERROR_ACCESS_DENIED:
  566. return E_NOPERMISSION;
  567. case ERROR_INVALID_HANDLE:
  568. return E_HANDLE;
  569. case ERROR_HANDLE_DISK_FULL:
  570. case ERROR_DISK_FULL:
  571. return E_DISKFULL;
  572. default:
  573. return E_INVALIDARG;
  574. }
  575. #else
  576. switch (errno) {
  577. case EACCES:
  578. return E_NOPERMISSION;
  579. break;
  580. case EBADF:
  581. return E_INVALIDARG;
  582. break;
  583. case ENOSPC:
  584. return E_DISKFULL;
  585. break;
  586. default:
  587. return E_INVALIDARG;
  588. break;
  589. }
  590. #endif // _WIN32
  591. }
  592. /***************************************************************************
  593. *
  594. * @doc INTERNAL
  595. *
  596. * @func HRESULT PASCAL FAR | RcChSizeFid |
  597. * Change the size of a file
  598. *
  599. * @parm FID | fid |
  600. * valid FID of an open file
  601. *
  602. * @parm LONG | lcb |
  603. * New size of file
  604. *
  605. * @rdesc Returns S_OK if all OK, else the error.
  606. *
  607. ***************************************************************************/
  608. PUBLIC HRESULT PASCAL FAR RcChSizeFid(FID fid, LONG lcb)
  609. {
  610. #if !defined ( _WIN32 )
  611. if (chsize( fid, lcb) == -1 )
  612. return RcGetDOSError();
  613. else
  614. #endif // !defined ( _WIN32 )
  615. return S_OK;
  616. }
  617. /***************************************************************************
  618. *
  619. * @doc INTERNAL
  620. *
  621. * @func HRESULT PASCAL FAR | RcUnlinkFm |
  622. * Delete a DOS file given the filename
  623. *
  624. * @parm FM | fm |
  625. * Name of file to remove. (An FM is the same as an LPSTR).
  626. *
  627. * @rdesc Returns S_OK if all OK, else the error.
  628. *
  629. ***************************************************************************/
  630. PUBLIC HRESULT PASCAL FAR EXPORT_API RcUnlinkFm(FM fm)
  631. {
  632. #ifdef MOSMAP // {
  633. // Disable function
  634. return ERR_NOTSUPPORTED;
  635. #else // } {
  636. QAFM qafm = (QAFM)fm;
  637. //QAFM qafm = _GLOBALLOCK((HANDLE)fm);
  638. OFSTRUCT ofStruct;
  639. int fRet = S_OK;
  640. if (OpenFile((LPSTR)qafm->rgch, &ofStruct, OF_DELETE) == HFILE_ERROR)
  641. fRet = E_FILEDELETE;
  642. //_GLOBALUNLOCK((HANDLE)fm);
  643. return fRet;
  644. #endif // }
  645. }
  646. #ifdef _IT_FULL_CRT // {
  647. #ifndef _MAC // {
  648. /* This function was previously present in dlgopen.c. It has been brought */
  649. /* here as it is making INT21 call. */
  650. /***************************************************************************
  651. *
  652. * @doc INTERNAL
  653. *
  654. * @func BOOL PASCAL FAR | FDriveOk |
  655. * Cheks if the drive specified with thwe file name is OK.
  656. *
  657. * @parm LPSTR | szFile |
  658. * Name of file
  659. *
  660. * @rdesc TRUE if drive is OK.
  661. *
  662. ***************************************************************************/
  663. PUBLIC BOOL PASCAL FAR EXPORT_API FDriveOk(LPSTR szFile)
  664. /* -- Check if drive is valid */
  665. {
  666. // the static variables here are static only because we are in a DLL
  667. // and need to pass a near pointer to them to a C Run-Time routine.
  668. // These should be Locally-Alloc'd so they don't waste space in
  669. // our data segment.
  670. static int wDiskCur;
  671. int wDisk;
  672. wDiskCur = _getdrive();
  673. /* change to new disk if specified */
  674. if ((wDisk = (int)((*szFile & 0xdf) - ('A' - 1))) != wDiskCur) {
  675. if (_chdrive (wDisk) == (int)-1)
  676. return FALSE;
  677. }
  678. return TRUE;
  679. }
  680. #endif // } _MAC
  681. #endif // }