Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

584 lines
15 KiB

#include "precomp.h"
#pragma hdrstop
EnableAssert
/* This file contains non version-specific lower level functions used by the
* version specific routines as well as general utility type stuff.
*/
/* Checks to see if a vector of cchMac characters is a Nm */
F
FIsNm(
char far lrgch[], // String to test
int cchMac,
int *pfTrailZ) // Set according to nature of data after name
{
register char far *lpchT = lrgch;
register char far *lpchMac = lrgch + cchMac;
AssertF(cchMac >= 0);
/* must have only alphanumerics or punctuation */
while (lpchT < lpchMac && (isalnum(*lpchT) || ispunct(*lpchT)))
lpchT++;
if (lpchT == lrgch || lpchT < lpchMac && *lpchT != 0)
/* no alnum/punct or does not end in 0 */
{
*pfTrailZ = fFalse;
return fFalse;
}
/* loop over zeros */
while (lpchT < lpchMac && *lpchT == 0)
lpchT++;
*pfTrailZ = (lpchT == lpchMac);
return fTrue;
}
/* This function takes a pth and checks its syntax to see whether or not it
is a valid pth.
*/
F FIsPth(
PTH far *pth,
int cchMac,
int * pfTrailZ)
{
register char far *lpchPth = pth;
register char far *lpchSlash; /* pointer to slash */
Unreferenced(cchMac);
*pfTrailZ = fFalse;
if (*lpchPth++ != '/' || *lpchPth++ != '/') /* need two slashes */
return fFalse;
/* see if looking at drive name and volume */
if (isalpha(*lpchPth) && *(lpchPth + 1) == ':')
{
/* volume must be a non-nil legal user name */
NM nm[cchVolMax];
lpchPth += 2;
lpchSlash = LszIndex(lpchPth, '/');
ClearPbCb((char *)nm, cchVolMax);
NmCopy(nm, lpchPth, (unsigned)((unsigned long)(lpchSlash ? lpchSlash : LszIndex(lpchPth,'\0')) - (unsigned long)lpchPth));
if (!FIsNm((char far *)nm, cchVolMax, pfTrailZ) || !*pfTrailZ)
return fFalse;
}
else
{
/* //mach/shortname type path; do machine name */
NM nm[cchMachMax];
lpchSlash = LszIndex(lpchPth, '/');
ClearPbCb((char *)nm, cchMachMax);
NmCopy(nm, lpchPth, (unsigned)((unsigned long)(lpchSlash ? lpchSlash : LszIndex(lpchPth, '\0')) - (unsigned long)lpchPth));
if (!FIsNm((char far *)nm, cchMachMax, pfTrailZ) || !*pfTrailZ)
return fFalse;
}
/* at this point lpchSlash = position of next '/', 0 if none
* if it is 0 we must check for zeroes at end.
*/
while (lpchSlash != 0)
{
/* move to next position after '/' */
lpchPth = lpchSlash + 1;
lpchSlash = LszIndex(lpchPth, '/');
if (!FIsFileNm(lpchPth, (lpchSlash ? lpchSlash : LszIndex(lpchPth, '\0')) - lpchPth, pfTrailZ) ||
!*pfTrailZ)
return fFalse;
}
/* must end in all zeroes */
for (lpchPth = LszIndex(lpchPth, '\0'); lpchPth < pth + cchPthMax && *lpchPth == 0; lpchPth++)
;
*pfTrailZ = (lpchPth == pth + cchPthMax);
return fTrue;
}
/* This function determines whether the string of length cchMac pointed to by
* lrgch is a valid file name. These are not necessarily zero terminated.
* XENIX allows any 14 charactrer name with no bad characters,
* DOS allows 8.3 of legal characters.
*/
F
FIsFileNm(
char far lrgch[],
int cchMac,
int *pfTrailZ)
{
#define szBad "\"/\\[]:|<>; "
#define cchFnameMax 8 /* max number of charcters in file name */
#define cchExtMax 3 /* max number of characters in extension */
register char far *lpch1;
register char far *lpch2;
char far *lpchMac;
char far *lpchLim;
*pfTrailZ = fFalse;
AssertF(cchMac >= 0);
if (cchMac > cchFileMax)
return fFalse;
lpchMac = lrgch + cchMac;
lpchLim = lrgch + cchFnameMax;
for (lpch1 = lrgch; lpch1 < lpchLim && lpch1 < lpchMac && *lpch1 != 0 && *lpch1 != '.'; lpch1++)
{
if (!isascii(*lpch1) || index(szBad, *lpch1) != 0 || iscntrl(*lpch1))
return fFalse;
}
if (lpch1 == lrgch)
/* zero length name, no chars or extension only */
return fFalse;
if (lpch1 == lpchMac)
{
/* done; no extension if dos */
*pfTrailZ = fTrue;
return fTrue;
}
if (*lpch1 != 0)
{
if (*lpch1 != '.')
return fFalse; /* no '.' at start of ext */
lpch1++;
}
lpchLim = lpch1 + cchExtMax;
for (lpch2 = lpch1; lpch2 < lpchLim && lpch2 < lpchMac && *lpch2 != 0; lpch2++)
{
if (!isascii(*lpch2) || index(szBad, *lpch2) != 0 ||
iscntrl(*lpch2) || *lpch2 == '.')
return fFalse;
}
if (lpch2 < lpchMac && *lpch2 != 0)
/* does not end in 0 */
return fFalse;
/* make sure whatever is left is zero */
while (lpch2 < lpchMac && *lpch2 == 0)
lpch2++;
*pfTrailZ = (lpch2 == lpchMac);
return fTrue;
}
/* This function takes a string and removes unprintable characters,
* changing them in place to dots.
*/
void
MakePrintLsz(
register char far *lsz)
{
while (*lsz)
{
if (!isascii(*lsz) || !isprint(*lsz))
*lsz = '.';
lsz++;
}
}
/*VARARGS2*/
F
FQueryPsd(
SD *psd,
char *sz, ...)
{
va_list ap;
F f;
va_start(ap, sz);
f = VaFQueryPsd(psd, sz, ap);
va_end(ap);
return f;
}
/* This function handles all queries concerning changes to the status file.
* If permission to alter contents of status file is given, we set the
* fAnyChanges flag.
* NB: This function must be called when an answer of yes to a query leads
* to a change in the status buffer. It should only be called when the status
* file was loaded via FLoadSd, never when from FLoadStatus.
*/
F
VaFQueryPsd(
SD *psd,
char *sz,
va_list ap)
{
if (VaFQueryApp(sz, "Fix", ap))
return (psd->fAnyChanges = fTrue);
else
return fFalse;
}
/* This function examines the etc directory to find what the biNext should be.
*/
BI
GetBiNext(
PTH *pthDir)
{
int bi;
BI biNext = biMin;
DE de;
char szFile[cchFileMax + 1];
FA fa;
OpenDir(&de, pthDir, faFiles);
while (FGetDirSz(&de, szFile, &fa))
{
if (szFile[0] == 'B' && isdigit(szFile[1]) &&
*PchGetW(szFile + 1, &bi) == 0)
{
AssertF( bi >= 0 );
if ((unsigned)bi + 1 > biNext)
biNext = bi + 1;
}
}
CloseDir(&de);
return biNext;
}
/* This function creates a sorted linked list of NE of the contents of the
* directory pth.
*/
NE *
PneSortDir(
PTH pth[cchPthMax])
{
FA fa;
DE de;
char sz[cchFileMax + 1]; /* assume that cchFileMax > cchDirMax */
NE neDummy; /* holds start of list */
register NE *pneComp; /* NE being compared */
register NE *pnePrevious; /* back pointer */
neDummy.pneNext = 0;
OpenDir(&de, pth, faFiles | faDir);
/* Insertion sort. */
while (FGetDirSz(&de, sz, &fa))
{
for (pnePrevious = &neDummy, pneComp = neDummy.pneNext;
pneComp && NeCmpiSz(pneComp, sz) < 0;
pneComp = (pnePrevious = pneComp)->pneNext)
;
pnePrevious->pneNext = PneNewNm((NM far *)sz, strlen(sz), fa);
pnePrevious->pneNext->pneNext = pneComp;
}
CloseDir(&de);
return neDummy.pneNext;
}
/* Function checks if cb bytes at lpb are all zero */
F
FAllZero(
register char far *lpb,
register int cb)
{
while (cb-- > 0 && *lpb++ == 0)
;
return (cb == -1);
}
/* This function examines two files to determine if they are identical;
Note: this function has a 2 K frame
*/
F
FSameFile(
PTH *pth1,
PTH *pth2)
{
#define cbBufMax 1024
unsigned cbCmpMax = 0;
unsigned cb1;
unsigned cb2;
register char far *lpb1;
register char far *lpb2;
MF *pmf1, *pmf2;
char rgb1[cbBufMax];
char rgb2[cbBufMax];
if ((pmf1 = PmfOpen(pth1, omReadOnly, fxNil)) == 0)
{
return fFalse;
}
else if ((pmf2 = PmfOpen(pth2, omReadOnly, fxNil)) == 0)
{
CloseMf(pmf1);
return fFalse;
}
if ((lpb1 = LpbAllocCb((unsigned)(63*1024),fFalse)) != 0)
{
if ((lpb2 = LpbAllocCb((unsigned)(63*1024),fFalse)) != 0)
cbCmpMax = 63*1024;
else
FreeLpb(lpb1);
}
if (cbCmpMax == 0 && (lpb1 = LpbAllocCb((unsigned)(32*1024),fFalse)) != 0)
{
if ((lpb2 = LpbAllocCb((unsigned)(32*1024),fFalse)) != 0)
cbCmpMax = 32*1024;
else
FreeLpb(lpb1);
}
if (cbCmpMax == 0 && (lpb1 = LpbAllocCb(16*1024,fFalse)) != 0)
{
if ((lpb2 = LpbAllocCb(16*1024,fFalse)) != 0)
cbCmpMax = 16*1024;
else
FreeLpb(lpb1);
}
if (cbCmpMax == 0)
{
cbCmpMax = cbBufMax;
lpb1 = (char far *)rgb1;
lpb2 = (char far *)rgb2;
}
while ((cb1 = CbReadMf(pmf1, lpb1, cbCmpMax)) ==
(cb2 = CbReadMf(pmf2, lpb2, cbCmpMax)) && cb1 > 0)
{
if (!FCmpLpbCb(lpb1, lpb2, cb1))
{
CloseMf(pmf1);
CloseMf(pmf2);
if (cbCmpMax != cbBufMax)
{
FreeLpb(lpb1);
FreeLpb(lpb2);
}
return fFalse;
}
}
if (cbCmpMax != cbBufMax)
{
FreeLpb(lpb1);
FreeLpb(lpb2);
}
CloseMf(pmf1);
CloseMf(pmf2);
return (cb1 == cb2);
}
F FReadOnly(pst)
struct _stat *pst;
{
return ((pst->st_mode & (S_IREAD|S_IWRITE)) == S_IREAD);
}
F FCkWritePth(pth, pst)
/* This function is simiilar to FMkPth, but more passive. It checks if we can
* write to a directory specified by pth. Returns fFalse if error.
*/
PTH pth[cchPthMax];
register struct _stat *pst;
{
char sz[cchPthMax];
SzPhysPath(sz, pth); /* convert for error messages */
if ((pst->st_mode&S_IFREG) != 0)
{
Error("regular file %s should be replaced with directory\n",sz);
return fFalse;
}
else
/* must be dir; on DOS we can always write to a directory */
return fTrue;
}
/****************************************************************/
/* generic index ordering functions */
INO *PinoNew(short iindMac, PFN_CMP pfnCmp)
/*
* Build a new index ordering
*/
{
INO *pino;
pino = (INO *)PbAllocCb(sizeof(INO), fFalse);
pino->iindMac = iindMac;
pino->iindLim = 0;
pino->rgind = (IND *)PbAllocCb(iindMac*sizeof(IND), fFalse);
pino->pfnCmp = pfnCmp;
return pino;
}
void FreeIno(pino)
/*
* Free the storage associated with the ordering.
*/
INO *pino;
{
free((char *)pino->rgind);
free((char *)pino);
}
IND *PindLookup(SD *psd, IND ind, INO *pino)
/*
* Look for the Index entry in the ordering which compares equal to the given
* index. If there is no such entry, return the first entry which compares
* greater than the given element.
*/
{
IND *pind;
short iind;
for (pind = pino->rgind, iind = 0;
iind < pino->iindLim && (*pino->pfnCmp)(psd, ind, *pind) >= 0;
pind++, iind++)
;
return pind;
}
void InsertInd(SD *psd, IND ind, INO *pino)
/*
* Insert the given index into the ordering, using the given comparison
* function.
*/
{
IND *pind;
AssertF(pino->iindLim < pino->iindMac); /* assert entry available */
pind = PindLookup(psd, ind, pino);
/* blt the entire index, including nil terminator to make room */
CopyOverlapLrgb((char far *)pind,
(char far *)pind+sizeof(ind),
(pino->iindLim - (pind - pino->rgind))*sizeof(ind));
pino->iindLim++;
*pind = ind;
}
void ApplyIno(INO *pino, char far *rgelt, unsigned short cbElt)
/*
* Apply the given ordering to the given range of elements. Each element
* is the same length, nd they must be contiguous.
*/
{
F *pf, *pfMac;
F *rgfUsed; /* rgfUsed[x] <==> rgind[x] already applied */
char *peltSrc = PbAllocCb(cbElt, fFalse);
char *peltSave = PbAllocCb(cbElt, fFalse);
short iind;
/* set up marking array */
rgfUsed = (F *)PbAllocCb(pino->iindLim*sizeof(F), fFalse);
for (pf = rgfUsed, pfMac = pf + pino->iindLim;
pf < pfMac;
pf++)
{
*pf = fFalse;
}
for (iind = -1;;)
{
/*
* Apply the ordering until no indices remain. We
* cycle through the array, keeping the most recently
* overwritten element in peltSrc. If it has already
* been remapped, we start again with the first unused
* element.
*/
if (iind == -1 || rgfUsed[iind])
{
/* find first unused */
for (iind = 0; iind < pino->iindLim; iind++)
{
if (!rgfUsed[iind])
break;
}
if (iind == pino->iindLim)
{
/* no more unused elements, break */
break;
}
/* copy rgelt[rgind[iind]] into peltSrc */
CopyLrgb(rgelt+(pino->rgind[iind]*cbElt),
peltSrc,
cbElt);
}
/* copy rgelt[iind] into peltSave */
CopyLrgb(rgelt+(iind*cbElt),
peltSave,
cbElt);
/* copy peltSrc into rgelt[iind] */
CopyLrgb(peltSrc,
rgelt+(iind*cbElt),
cbElt);
/* mark the operation as done */
rgfUsed[iind] = fTrue;
BLOCK
{
short iindT;
/* find position of *peltSave in new ordering */
for (iindT = 0; pino->rgind[iindT] != (IND)iind;
iindT++)
;
iind = iindT;
}
BLOCK
{
char *peltT;
/* Swap save and src to avoid copying. */
peltT = peltSrc;
peltSrc = peltSave;
peltSave = peltT;
}
}
free((char *)rgfUsed);
free(peltSrc);
free(peltSave);
}
/****************************************************************/