mirror of https://github.com/lianthony/NT4.0
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.
895 lines
25 KiB
895 lines
25 KiB
/*****************************************************************************
|
|
* *
|
|
* FM.c *
|
|
* *
|
|
* Copyright (C) Microsoft Corporation 1990. *
|
|
* All Rights reserved. *
|
|
* *
|
|
******************************************************************************
|
|
* *
|
|
* Module Intent *
|
|
* *
|
|
* Routines for manipulating FMs (File Monikers, equivalent to file names). *
|
|
* WINDOWS LAYER
|
|
* *
|
|
*****************************************************************************/
|
|
#include "stdafx.h"
|
|
|
|
#pragma hdrstop
|
|
|
|
#include <dos.h> // for FP_OFF macros and file attribute constants
|
|
#include <io.h> // for tell() and eof()
|
|
#include <errno.h> // this is for chsize()
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Defines *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
#define MAX_MESSAGE 50
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Prototypes *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
PSTR STDCALL SzGetDir(DIR dir, PSTR sz);
|
|
void STDCALL SnoopPath(PCSTR sz, int * iDrive, int * iDir, int * iBase, int * iExt);
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
- Name: FmNewTemp
|
|
-
|
|
* Purpose: Create a unique FM for a temporary file
|
|
*
|
|
* Arguments: none
|
|
*
|
|
* Returns: the new FM, or fmNil if failure
|
|
*
|
|
* Globals Used: rcIOError
|
|
*
|
|
* +++
|
|
*
|
|
* Notes:
|
|
*
|
|
***************************************************************************/
|
|
|
|
FM STDCALL FmNewTemp(void)
|
|
{
|
|
char szTmpName[MAX_PATH];
|
|
|
|
strcpy(szTmpName, GetTmpDirectory());
|
|
GetTempFileName(szTmpName, txtTmpName, 0, szTmpName);
|
|
|
|
#ifdef _DEBUG
|
|
SendStringToParent("Creating a temporary file");
|
|
#endif
|
|
return FmNew(szTmpName);
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
- Name: FmNew
|
|
-
|
|
* Purpose: Allocate and initialize a new FM
|
|
*
|
|
* Arguments: sz - filename string
|
|
*
|
|
* Returns: FM (handle to fully canonicalized filename)
|
|
*
|
|
* Globals Used: rcIOError
|
|
*
|
|
* +++
|
|
*
|
|
* Notes:
|
|
*
|
|
***************************************************************************/
|
|
|
|
FM STDCALL FmNew(PCSTR psz)
|
|
{
|
|
char szFullPath[MAX_PATH];
|
|
FM fm;
|
|
PSTR pszFileName;
|
|
|
|
if (IsEmptyString(psz))
|
|
return NULL;
|
|
|
|
rcIOError = RC_Success;
|
|
|
|
// Canonicalize filename
|
|
|
|
if (GetFullPathName(psz, sizeof(szFullPath), szFullPath, &pszFileName) == 0) {
|
|
rcIOError = RC_Invalid;
|
|
return NULL;
|
|
}
|
|
else {
|
|
fm = lcStrDup(szFullPath);
|
|
|
|
/*
|
|
* Convert to upper case to make it less likely that two FMs will
|
|
* contain different strings yet refer to the same file.
|
|
*/
|
|
|
|
CharUpper(fm);
|
|
}
|
|
return fm;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
- SzPartsFm
|
|
-
|
|
* Purpose:
|
|
* Extract a string from an FM
|
|
*
|
|
* Arguments:
|
|
* FM - the File Moniker you'll be extracting the string from
|
|
* PSTR szDest - destination string
|
|
* INT iPart - the parts of the full pathname you want
|
|
*
|
|
* Returns:
|
|
* szDest, or NULL if error (?)
|
|
*
|
|
* Globals Used:
|
|
*
|
|
* +++
|
|
*
|
|
* Notes:
|
|
*
|
|
***************************************************************************/
|
|
|
|
void STDCALL SzPartsFm(FM fm, PSTR pszDest, int iPart)
|
|
{
|
|
int iDrive, iDir, iBase, iExt;
|
|
|
|
if (!fm || pszDest == NULL) {
|
|
rcIOError = RC_BadArg;
|
|
return;
|
|
}
|
|
|
|
// special case so we don't waste effort
|
|
|
|
if (iPart == PARTALL) {
|
|
strcpy(pszDest, fm);
|
|
return;
|
|
}
|
|
|
|
SnoopPath(fm, &iDrive, &iDir, &iBase, &iExt);
|
|
|
|
*pszDest = '\0';
|
|
|
|
if (iPart & PARTDRIVE) {
|
|
strcat(pszDest, fm + iDrive);
|
|
}
|
|
|
|
if (iPart & PARTDIR) {
|
|
strcat(pszDest, fm + iDir);
|
|
}
|
|
|
|
if (iPart & PARTBASE) {
|
|
strcat(pszDest, fm + iBase);
|
|
}
|
|
|
|
ASSERT(!(iPart & PARTEXT));
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
- Name: SnoopPath()
|
|
-
|
|
* Purpose:
|
|
* Looks through a string for the various components of a file name and
|
|
* returns the offsets into the string where each part starts.
|
|
*
|
|
* Arguments:
|
|
* sz - string to snoop
|
|
* *iDrive - offset for the drive specification if present
|
|
* *iDir - offset for the directory path if present
|
|
* *iBase - offset to the filename if present
|
|
* *iExt - offset to the extension (including dot) if present
|
|
*
|
|
* Returns:
|
|
* sets the index parameters for each respective part. the index is set
|
|
* to point to the end of the string if the part is not present (thus
|
|
* making it point to a null string).
|
|
*
|
|
*
|
|
* +++
|
|
*
|
|
* Notes:
|
|
*
|
|
***************************************************************************/
|
|
|
|
void STDCALL SnoopPath(PCSTR szFile, int *pDrive, int *pDirPos,
|
|
int *pBasePos, int *pExtPos)
|
|
{
|
|
int i;
|
|
int cb = strlen(szFile);
|
|
BOOL fDir = FALSE;
|
|
|
|
*pDrive = *pExtPos = cb;
|
|
*pDirPos = *pBasePos = 0;
|
|
|
|
for (i = 0; szFile[i]; i++) {
|
|
switch (szFile[i]) {
|
|
case ':':
|
|
*pDrive = 0;
|
|
*pDirPos = i + 1;
|
|
*pBasePos = i + 1;
|
|
break;
|
|
|
|
case '\\':
|
|
// [olympus 306 - chauv ]
|
|
// check to see if it's really a backslash or a trail byte.
|
|
// if it's a trail byte, skip the detection. Otherwise, fall thru.
|
|
if ( (i > 0) && IsDBCSLeadByte(szFile[i-1]))
|
|
break;
|
|
// NOTE !!!!!! must fall thru here....
|
|
case '/':
|
|
fDir = TRUE;
|
|
*pBasePos = i + 1;
|
|
*pExtPos = cb;
|
|
break;
|
|
|
|
case '.':
|
|
if (szFile[i + 1] != '.')
|
|
*pExtPos = i;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
if (!fDir)
|
|
*pDirPos = i;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
- Name: FmNewSzDir
|
|
-
|
|
* Purpose: Create an FM describing the file "sz" in the directory "dir"
|
|
* If sz is a simple filename the FM locates the file in the
|
|
* directory specified. If there is a drive or a rooted path
|
|
* in the filename the directory parameter is ignored.
|
|
* Relative paths are allowed and will reference off the dir
|
|
* parameter or the default (current) directory as appropriate.
|
|
*
|
|
* This does not create a file or expect one to exist at the
|
|
* final destination (that's what FmNewExistSzDir is for), all
|
|
* wind up with is a cookie to a fully qualified path name.
|
|
*
|
|
* Arguments: sz - filename ("File.ext"),
|
|
* or partial pathname ("Dir\File.ext"),
|
|
* or current directory ("c:File.ext"),
|
|
* or full pathname ("C:\Dir\Dir\File.ext")
|
|
* dir - DIR_CURRENT et al.
|
|
*
|
|
* Returns: the new FM, or fmNil if error
|
|
* sz is unchanged
|
|
*
|
|
* Globals Used:
|
|
*
|
|
* +++
|
|
*
|
|
* Notes:
|
|
*
|
|
***************************************************************************/
|
|
|
|
FM STDCALL FmNewSzDir(PCSTR szFile, DIR dir)
|
|
{
|
|
int iDrive, iDir, iBase, iExt;
|
|
int cb;
|
|
|
|
if (IsEmptyString(szFile)) {
|
|
rcIOError = RC_BadArg;
|
|
return NULL;
|
|
}
|
|
|
|
cb = strlen(szFile);
|
|
SnoopPath(szFile, &iDrive, &iDir, &iBase, &iExt);
|
|
|
|
if (!szFile[iBase]) { // no name
|
|
rcIOError = RC_BadArg;
|
|
return NULL;
|
|
}
|
|
else if (szFile[iDrive] || szFile[iDir] == '\\' ||
|
|
szFile[iDir] == '/' || szFile[iDir] == '.') {
|
|
|
|
/*
|
|
* there's a drive or root slash so we have an implicit directory
|
|
* spec and we can ignore the directory parameter and use what was
|
|
* passed.
|
|
*/
|
|
|
|
return FmNew(szFile);
|
|
}
|
|
|
|
else {
|
|
|
|
/*
|
|
* dir & (dir-1) checks to make sure there is only one bit set which
|
|
* is followed by a check to make sure that it is also a permitted bit
|
|
*/
|
|
|
|
CHAR szBuf[MAX_PATH];
|
|
|
|
ASSERT(((dir & (dir - 1)) == 0) &&
|
|
(dir &
|
|
(DIR_CURRENT | DIR_BOOKMARK | DIR_ANNOTATE | DIR_TEMP | DIR_HELP)));
|
|
|
|
if (SzGetDir(dir, szBuf) == NULL)
|
|
return NULL;
|
|
strcat(szBuf, szFile + iBase);
|
|
|
|
return FmNew(szBuf);
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
- Name: SzGetDir
|
|
-
|
|
* Purpose: returns the rooted path of a DIR
|
|
*
|
|
* Arguments: dir - DIR (must be one field only, and must be an actual dir -
|
|
* not DIR_PATH)
|
|
* sz - buffer for storage (should be at least MAX_PATH)
|
|
*
|
|
* Returns: sz - fine
|
|
* NULL - OS Error (check rcIOError)
|
|
*
|
|
* Globals Used: rcIOError
|
|
*
|
|
* +++
|
|
*
|
|
***************************************************************************/
|
|
|
|
PSTR STDCALL SzGetDir(DIR dir, PSTR sz)
|
|
{
|
|
int i=0;
|
|
PSTR psz;
|
|
|
|
ASSERT(sz);
|
|
|
|
switch (dir) {
|
|
case DIR_CURRENT:
|
|
GetCurrentDirectory(MAX_PATH, sz);
|
|
break;
|
|
|
|
case DIR_BOOKMARK:
|
|
case DIR_ANNOTATE:
|
|
GetWindowsDirectory(sz, MAX_PATH);
|
|
break;
|
|
|
|
case DIR_HELP:
|
|
GetModuleFileName(hinstApp, sz, MAX_PATH);
|
|
psz = sz + strlen(sz);
|
|
|
|
// psz should point to the last non-null character in the string.
|
|
|
|
if (psz > sz)
|
|
psz--;
|
|
|
|
// Be careful of plain old file names, as ROM Windows supports
|
|
|
|
// [olympus 306 - chauv]
|
|
// replaced the next 2 lines with a while/case loop below to take care of trailing
|
|
// backslash problem in double-byte situations.
|
|
|
|
// while (*psz != '\\' && *psz != '/' && *psz != '\0')
|
|
// --psz;
|
|
|
|
while (1) {
|
|
switch (*psz) {
|
|
case '\\':
|
|
// this is pretty dangerous because I could step pass first character here
|
|
// but I don't have any reference - yikes !!!!
|
|
if ( IsDBCSLeadByte(*(psz-1)) )
|
|
break;
|
|
// Note !!! must fall thru here....
|
|
case '/':
|
|
case '\0':
|
|
break;
|
|
}
|
|
--psz;
|
|
}
|
|
|
|
if (*psz == '\0') {
|
|
|
|
// For some reason, there is no path name (ROM Windows?)
|
|
|
|
rcIOError = RC_Failure;
|
|
sz = NULL;
|
|
}
|
|
else
|
|
*psz = '\0';
|
|
break;
|
|
|
|
// case DIR_SYSTEM:
|
|
/* this should, of course, be taken care of some day */
|
|
/* it currently just falls through */
|
|
default:
|
|
rcIOError = RC_BadArg;
|
|
sz = NULL;
|
|
break;
|
|
}
|
|
|
|
if (sz != NULL) {
|
|
ASSERT(*sz);
|
|
psz = SzEnd(sz);
|
|
|
|
|
|
// Make sure that the string ends with a slash.
|
|
|
|
// [olympus 306 - chauv]
|
|
// added code to check trailing backslash.
|
|
// Again, this is pretty dangerous since I could step pass buffer's max length.
|
|
if ( (*(psz-1) != '\\' && *(psz-1) != '/') ||
|
|
(*(psz-1) == '\\' && IsDBCSLeadByte(*(psz-2)))
|
|
)
|
|
{
|
|
*psz++='\\';
|
|
*psz='\0';
|
|
}
|
|
ASSERT(psz < sz + MAX_PATH && *psz == '\0');
|
|
}
|
|
|
|
return sz;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* Defines
|
|
*
|
|
\***************************************************************************/
|
|
|
|
// DOS int 21 AX error codes
|
|
|
|
#define wHunkyDory 0x00
|
|
#define wInvalidFunctionCode 0x01
|
|
#define wFileNotFound 0x02
|
|
#define wPathNotFound 0x03
|
|
#define wTooManyOpenFiles 0x04
|
|
#define wAccessDenied 0x05
|
|
#define wInvalidHandle 0x06
|
|
#define wInvalidAccessCode 0x0c
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* Macros
|
|
*
|
|
\***************************************************************************/
|
|
|
|
#define _WOpenMode(w) ( _rgwOpenMode[ (w) & wRWMask ] | \
|
|
_rgwShare[ ( (w) & wShareMask ) >> wShareShift ] )
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* Global Data
|
|
*
|
|
\***************************************************************************/
|
|
|
|
// these arrays get indexed by wRead and wWrite |ed together
|
|
|
|
UINT _rgwOpenMode[] = {
|
|
(UINT) HFILE_ERROR,
|
|
OF_READ,
|
|
OF_WRITE,
|
|
OF_READWRITE,
|
|
};
|
|
|
|
UINT _rgwPerm[] = {
|
|
(UINT) HFILE_ERROR,
|
|
_A_RDONLY,
|
|
_A_NORMAL,
|
|
_A_NORMAL,
|
|
};
|
|
|
|
UINT _rgwShare[] = {
|
|
OF_SHARE_EXCLUSIVE,
|
|
OF_SHARE_DENY_WRITE,
|
|
OF_SHARE_DENY_READ,
|
|
OF_SHARE_DENY_NONE,
|
|
};
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* Function: FidOpenFm()
|
|
*
|
|
* Purpose: Open a file in binary mode.
|
|
*
|
|
* ASSUMES
|
|
*
|
|
* args IN: fm
|
|
* wOpenMode - read/write/share modes
|
|
* Undefined if wRead and wWrite both unset.
|
|
*
|
|
* PROMISES
|
|
*
|
|
* returns: HFILE_ERROR on failure, else a valid HFILE.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
HFILE STDCALL FidOpenFm(FM fm, UINT fnOpenMode)
|
|
{
|
|
HFILE hf;
|
|
|
|
if (!fm) {
|
|
rcIOError = RC_BadArg;
|
|
return HFILE_ERROR;
|
|
}
|
|
|
|
if ((hf = _lopen(fm, fnOpenMode)) == HFILE_ERROR)
|
|
rcIOError = RcGetLastError();
|
|
else
|
|
rcIOError = RC_Success;
|
|
|
|
return hf;
|
|
}
|
|
|
|
HFILE STDCALL FidCreateFm(FM fm, UINT fnOpenMode)
|
|
{
|
|
HFILE hf;
|
|
|
|
if (!fm) {
|
|
rcIOError = RC_BadArg;
|
|
return HFILE_ERROR;
|
|
}
|
|
|
|
hf = _lcreat(fm, fnOpenMode);
|
|
|
|
if (hf != HFILE_ERROR) {
|
|
if (_lclose(hf) == 0)
|
|
hf = _lopen(fm, fnOpenMode);
|
|
else
|
|
hf = HFILE_ERROR;
|
|
}
|
|
|
|
if (hf == HFILE_ERROR)
|
|
rcIOError = RcGetLastError();
|
|
else
|
|
rcIOError = RC_Success;
|
|
|
|
return hf;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* Function: LcbReadFid()
|
|
*
|
|
* Purpose: Read data from a file.
|
|
*
|
|
* ASSUMES
|
|
*
|
|
* args IN: hf - valid HFILE of an open file
|
|
* lcb - count of bytes to read (must be less than 2147483648)
|
|
*
|
|
* PROMISES
|
|
*
|
|
* returns: count of bytes actually read or -1 on error
|
|
*
|
|
* args OUT: qv - pointer to user's buffer assumed huge enough for data
|
|
*
|
|
* globals OUT: rcIOError
|
|
*
|
|
\***************************************************************************/
|
|
|
|
int STDCALL LcbReadFid(HFILE hf, void* pv, int lcb)
|
|
{
|
|
int lcbTotalRead;
|
|
|
|
if ((lcbTotalRead = _lread(hf, pv, lcb)) == HFILE_ERROR)
|
|
rcIOError = RcGetLastError();
|
|
else
|
|
rcIOError = RC_Success;
|
|
|
|
return lcbTotalRead;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* Function: LcbWriteFid()
|
|
*
|
|
* Purpose: Write data to a file.
|
|
*
|
|
* ASSUMES
|
|
*
|
|
* args IN: hf - valid hf of an open file
|
|
* qv - pointer to user's buffer
|
|
* lcb - count of bytes to write (must be less than 2147483648)
|
|
*
|
|
* PROMISES
|
|
*
|
|
* returns: count of bytes actually written or -1 on error
|
|
*
|
|
* globals OUT: rcIOError
|
|
*
|
|
\***************************************************************************/
|
|
|
|
int STDCALL LcbWriteFid(HFILE hf, void* qv, int lcb)
|
|
{
|
|
if (lcb == 0L) {
|
|
rcIOError = RC_Success;
|
|
return 0L;
|
|
}
|
|
|
|
int lcbTotalWrote = _lwrite(hf, (LPCSTR) qv, lcb);
|
|
|
|
if (lcbTotalWrote == HFILE_ERROR)
|
|
rcIOError = RcGetLastError();
|
|
else
|
|
rcIOError = RC_Success;
|
|
|
|
return lcbTotalWrote;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* Function: RcCloseFid()
|
|
*
|
|
* Purpose: Close a file.
|
|
*
|
|
* Method:
|
|
*
|
|
* ASSUMES
|
|
*
|
|
* args IN: hf - a valid hf of an open file
|
|
*
|
|
* PROMISES
|
|
*
|
|
* returns: RC_Success or something else
|
|
*
|
|
\***************************************************************************/
|
|
|
|
RC_TYPE STDCALL RcCloseFid(HFILE hf)
|
|
{
|
|
if (_lclose(hf) == HFILE_ERROR)
|
|
rcIOError = RcGetLastError();
|
|
else
|
|
rcIOError = RC_Success;
|
|
|
|
return rcIOError;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* Function: LTellFid()
|
|
*
|
|
* Purpose: Return current file position in an open file.
|
|
*
|
|
* ASSUMES
|
|
*
|
|
* args IN: hf - valid hf of an open file
|
|
*
|
|
* PROMISES
|
|
*
|
|
* returns: offset from beginning of file in bytes; -1L on error.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
int STDCALL LTellFid(HFILE hf)
|
|
{
|
|
int l;
|
|
|
|
if ((l = _tell(hf)) == HFILE_ERROR)
|
|
rcIOError = RcGetLastError();
|
|
else
|
|
rcIOError = RC_Success;
|
|
|
|
return l;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* Function: LSeekFid()
|
|
*
|
|
* Purpose: Move file pointer to a specified location. It is an error
|
|
* to seek before beginning of file, but not to seek past end
|
|
* of file.
|
|
*
|
|
* ASSUMES
|
|
*
|
|
* args IN: hf - valid hf of an open file
|
|
* lPos - offset from origin
|
|
* wOrg - one of: SEEK_SET: beginning of file
|
|
* SEEK_CUR: current file pos
|
|
* SEEK_END: end of file
|
|
*
|
|
* PROMISES
|
|
*
|
|
* returns: offset in bytes from beginning of file or -1L on error
|
|
*
|
|
\***************************************************************************/
|
|
|
|
int STDCALL LSeekFid(HFILE hf, int lPos, int wOrg)
|
|
{
|
|
int l = _llseek((HFILE) hf, lPos, wOrg);
|
|
|
|
if (l == HFILE_ERROR)
|
|
rcIOError = RcGetLastError();
|
|
else
|
|
rcIOError = RC_Success;
|
|
|
|
return l;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* Function: FEofFid()
|
|
*
|
|
* Purpose: Tells ye if ye're at the end of the file.
|
|
*
|
|
* ASSUMES
|
|
*
|
|
* args IN: hf
|
|
*
|
|
* PROMISES
|
|
*
|
|
* returns: fTrue if at EOF, FALSE if not or error has occurred (?)
|
|
*
|
|
\***************************************************************************/
|
|
|
|
BOOL STDCALL FEofFid(HFILE hf)
|
|
{
|
|
WORD wT;
|
|
|
|
if ((wT = _eof(hf)) == (WORD) -1)
|
|
rcIOError = RcGetLastError();
|
|
else
|
|
rcIOError = RC_Success;
|
|
|
|
return (BOOL) (wT == 1);
|
|
}
|
|
|
|
RC_TYPE STDCALL RcChSizeFid(HFILE hf, int lcb)
|
|
{
|
|
SetFilePointer((HANDLE) hf, lcb, NULL, FILE_BEGIN);
|
|
if (!SetEndOfFile((HANDLE) hf))
|
|
return rcIOError = RC_BadArg;
|
|
else
|
|
return rcIOError = RC_Success;
|
|
|
|
#if 0
|
|
if (_chsize(hf, lcb) == -1) {
|
|
switch (errno) {
|
|
case EACCES:
|
|
rcIOError = RC_NoPermission;
|
|
break;
|
|
|
|
case EBADF:
|
|
rcIOError = RC_BadArg; // this could be either bad hf or r/o file
|
|
break;
|
|
|
|
case ENOSPC:
|
|
rcIOError = RC_DiskFull;
|
|
break;
|
|
|
|
default:
|
|
rcIOError = RC_Invalid;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
rcIOError = RC_Success;
|
|
|
|
return rcIOError;
|
|
#endif
|
|
}
|
|
|
|
|
|
RC_TYPE STDCALL RcUnlinkFm(FM fm)
|
|
{
|
|
char szBuf[MAX_PATH];
|
|
|
|
strcpy(szBuf, fm); // make a local copy
|
|
|
|
if (remove(szBuf) == -1)
|
|
rcIOError = RcGetLastError();
|
|
else
|
|
rcIOError = RC_Success;
|
|
return rcIOError;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: DeleteAndDisposeFm
|
|
|
|
PURPOSE: Delete the file, free the FM memory, and set passed fm to NULL
|
|
|
|
PARAMETERS:
|
|
pfm
|
|
|
|
RETURNS:
|
|
|
|
COMMENTS:
|
|
|
|
MODIFICATION DATES:
|
|
18-Sep-1993 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
void STDCALL DeleteAndDisposeFm(FM FAR* pfm)
|
|
{
|
|
if (*pfm) {
|
|
remove(*pfm);
|
|
lcFree(*pfm);
|
|
}
|
|
*pfm = NULL;
|
|
}
|
|
|
|
RC_TYPE STDCALL RcGetLastError(void)
|
|
{
|
|
switch (GetLastError()) {
|
|
case NO_ERROR:
|
|
return RC_Success;
|
|
|
|
case ERROR_INVALID_HANDLE:
|
|
case ERROR_INVALID_FUNCTION:
|
|
return RC_BadArg;
|
|
|
|
case ERROR_INVALID_DRIVE:
|
|
case ERROR_PATH_NOT_FOUND:
|
|
case ERROR_FILE_NOT_FOUND:
|
|
return RC_NoExists;
|
|
|
|
case ERROR_TOO_MANY_OPEN_FILES:
|
|
return RC_NoFileHandles;
|
|
|
|
case ERROR_ACCESS_DENIED:
|
|
return RC_NoPermission;
|
|
|
|
case ERROR_OUTOFMEMORY:
|
|
case ERROR_NOT_ENOUGH_MEMORY:
|
|
return RC_OutOfMemory;
|
|
|
|
case ERROR_WRITE_PROTECT:
|
|
return RC_CantWrite;
|
|
|
|
case ERROR_DISK_FULL:
|
|
case ERROR_HANDLE_DISK_FULL:
|
|
return RC_DiskFull;
|
|
|
|
default:
|
|
return RC_Failure;
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: RemoveFM
|
|
|
|
PURPOSE: Same as DisposeFm, but this one also zero's the handle.
|
|
|
|
PARAMETERS:
|
|
pfm
|
|
|
|
RETURNS:
|
|
|
|
COMMENTS:
|
|
|
|
MODIFICATION DATES:
|
|
25-Oct-1993 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
void STDCALL RemoveFM(FM* pfm)
|
|
{
|
|
if (*pfm) {
|
|
lcFree((void*) *pfm);
|
|
*pfm = NULL;
|
|
}
|
|
}
|