windows-nt/Source/XPSP1/NT/base/mvdm/dos/dem/demfcb.c

770 lines
18 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/* demfcb.c - SVC handlers for misc. FCB operations
*
* demCloseFCB
* demCreateFCB
* demDate16
* demDeleteFCB
* demFCBIO
* demGetFileInfo
* demOpenFCB
* demRenameFCB
*
* Modification History:
*
* Sudeepb 09-Apr-1991 Created
* Sudeepb 21-Nov-1991 Added FCB based IO functions
* Jonle 30-Jun-1994 add wild card support for fcb rename
*/
#include "dem.h"
#include "demmsg.h"
#include <softpc.h>
#include <winbase.h>
#include <mvdm.h>
#define DOT '.'
#define QMARK '?'
/* demDeleteFCB - FCB based File Delete
*
*
* Entry - Client (ES:DI) - Full File Path
* Client (AL) - 0 if not extended FCB
* Client (DL) - File Attr. to be deleted (valid only if Al !=0 )
*
* Exit
* SUCCESS
* Client (CF) = 0
*
* FAILURE
* Client (CF) = 1
* Client (AX) = system status code
* HARD ERROR
* Client (CF) = 1
* Client (AX) = 0ffffh
*
* Notes: Following are the rules for FCB based delete:
* 1. If normal FCB than dont allow delete on hidden,system files
* 2. if extended FCB than search attributes should include hidden,
* system or read-only if that kind of file is to be deleted.
*/
VOID demDeleteFCB (VOID)
{
HANDLE hFind;
LPSTR lpFileName;
BYTE bClientAttr=0;
BOOL fExtendedFCB=FALSE;
WIN32_FIND_DATA wfBuffer;
BOOL fSuccess = FALSE;
DWORD dwAttr;
USHORT uErr;
CHAR szPath_buffer[_MAX_PATH];
CHAR szDrive[_MAX_DRIVE];
CHAR szDir[_MAX_DIR];
CHAR szFname[_MAX_FNAME];
CHAR szExt[_MAX_EXT];
DWORD dwErrCode = 0, dwErrCodeKeep = 0;
// Get the file name
lpFileName = (LPSTR) GetVDMAddr (getES(),getDI());
_splitpath( lpFileName, szDrive, szDir, szFname, szExt );
// Check if handling extended FCB
if(getAL() != 0){
bClientAttr = getDL();
/* Special case for delete volume label (INT 21 Func 13H, Attr = 8H */
if((bClientAttr == ATTR_VOLUME_ID)) {
if((uErr = demDeleteLabel(lpFileName[DRIVEBYTE]))) {
setCF(1);
setAX(uErr);
return;
}
setAX(0);
setCF(0);
return;
}
bClientAttr &= (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM);
fExtendedFCB = TRUE;
}
// Find the first instance of file
if((hFind = FindFirstFileOem (lpFileName,&wfBuffer)) == (HANDLE)-1){
demClientError(INVALID_HANDLE_VALUE, *lpFileName);
return;
}
// loop for all files which match the name and attributes
do {
// Check if read_only,hidden or system file
if((dwAttr= wfBuffer.dwFileAttributes & (FILE_ATTRIBUTE_READONLY |
FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM))){
// if so, try next file if normal FCB case. If extended fcb case
// then check if right attributes are given by client.
if(fExtendedFCB && ((dwAttr & (DWORD)bClientAttr) == dwAttr)){
// Yes, right attributes are given. So if the file is read
// only then change the modes to normal. Note NT will
// delete hidden and system files anyway.
if (dwAttr & FILE_ATTRIBUTE_READONLY){
strcpy( szPath_buffer, szDrive);
strcat( szPath_buffer, szDir);
strcat( szPath_buffer, wfBuffer.cFileName);
// if set attributes fail try next file
if(SetFileAttributesOem (szPath_buffer,
FILE_ATTRIBUTE_NORMAL) == -1)
continue;
}
}
else {
dwErrCodeKeep = ERROR_ACCESS_DENIED;
continue;
}
}
strcpy( szPath_buffer, szDrive);
strcat( szPath_buffer, szDir);
strcat( szPath_buffer, wfBuffer.cFileName);
if(DeleteFileOem(szPath_buffer) == FALSE) {
dwErrCode = GetLastError();
SetLastError(dwErrCode);
if (((dwErrCode >= ERROR_WRITE_PROTECT) &&
(dwErrCode <= ERROR_GEN_FAILURE)) ||
dwErrCode == ERROR_WRONG_DISK ) {
demClientError(INVALID_HANDLE_VALUE, szPath_buffer[0]);
return;
}
continue;
}
// We have deleted at least one file, so report success
fSuccess = TRUE;
} while (FindNextFileOem(hFind,&wfBuffer) == TRUE);
if(FindClose(hFind) == FALSE)
demPrintMsg (MSG_INVALID_HFIND);
if (fSuccess == TRUE){
setCF(0);
return;
}
setCF(1);
if(dwErrCodeKeep)
setAX((SHORT) dwErrCodeKeep);
else
setAX(ERROR_FILE_NOT_FOUND);
return;
}
/* demRenameFCB - FCB based Rename file
*
* Entry - Client (DS:SI) Sources file to be renamed
* Client (ES:DI) Destination file to be renamed to
*
* Exit - SUCCESS
* Client (CF) = 0
*
* FAILURE
* Client(CF) = 1
* Client(AX) = error code
*/
VOID demRenameFCB (VOID)
{
LPSTR lpSrc,lpDst;
DWORD dw;
HANDLE hFind;
PCHAR pNewDstFilePart;
PCHAR pDstFilePart;
PCHAR pCurrSrcFilePart;
WIN32_FIND_DATA W32FindData;
CHAR NewDst[MAX_PATH];
CHAR CurrSrc[MAX_PATH];
lpSrc = (LPSTR) GetVDMAddr (getDS(),getSI());
lpDst = (LPSTR) GetVDMAddr (getES(),getDI());
// Find the first instance of the source file
hFind = FindFirstFileOem (lpSrc,&W32FindData);
if (hFind == INVALID_HANDLE_VALUE) {
dw = GetLastError();
if (dw == ERROR_BAD_PATHNAME || dw == ERROR_DIRECTORY ) {
SetLastError(ERROR_PATH_NOT_FOUND);
}
demClientError(INVALID_HANDLE_VALUE, *lpSrc);
return;
}
//
// Source string consists of the path taken from the original
// source specified plus the filename part retrieved from the
// FindFile call
//
strcpy(CurrSrc, lpSrc);
pCurrSrcFilePart = strrchr(CurrSrc, '\\');
pCurrSrcFilePart++;
//
// Destination string is template for meta character substitution
//
pDstFilePart = strrchr(lpDst, '\\');
pDstFilePart++;
//
// NewDst string is constructed from template and the source string
// when doing meta file character substitution.
//
strcpy(NewDst, lpDst);
pNewDstFilePart = strrchr(NewDst, '\\');
pNewDstFilePart++;
do {
PCHAR pNew;
PCHAR pSrc;
PCHAR pDst;
strcpy(pCurrSrcFilePart,
W32FindData.cAlternateFileName[0]
? W32FindData.cAlternateFileName
: W32FindData.cFileName //// ??? hpfs lfns ????
);
pSrc = pCurrSrcFilePart; // source fname
pNew = pNewDstFilePart; // dest fname to be constructed
pDst = pDstFilePart; // raw dest fname template (with metas)
while (*pDst) {
//
// If Found a '?' in Dest template, use character from src
//
if (*pDst == QMARK) {
if (*pSrc != DOT && *pSrc)
*pNew++ = *pSrc++;
}
//
// if Found a DOT in Dest template, Align DOTS between Src\Dst
//
else if (*pDst == DOT) {
while (*pSrc != DOT && *pSrc) { // mov src to one past DOT
pSrc++;
}
if (*pSrc)
pSrc++;
*pNew++ = DOT;
}
//
// Nothing special found, use character from Dest template
//
else {
if (*pSrc != DOT && *pSrc)
pSrc++;
*pNew++ = *pDst;
}
pDst++;
}
*pNew = '\0';
//
// MoveFile does not return error if dst and src are the same,
// but DOS does, so check first..
//
if (!_stricmp (CurrSrc, NewDst)) {
setCF(1);
setAX(0x5);
FindClose(hFind);
return;
}
if (!MoveFileOem(CurrSrc, NewDst)){
demClientError(INVALID_HANDLE_VALUE, *lpSrc);
FindClose(hFind);
return;
}
} while (FindNextFileOem(hFind,&W32FindData));
//
// If the search on the source string for any reason besides
// no more files, then its a genuine error.
//
dw = GetLastError();
if (dw != ERROR_NO_MORE_FILES) {
if (dw == ERROR_BAD_PATHNAME || dw == ERROR_DIRECTORY ) {
SetLastError(ERROR_PATH_NOT_FOUND);
}
demClientError(INVALID_HANDLE_VALUE, *lpSrc);
}
else {
setCF(0);
}
FindClose(hFind);
return;
}
/* demCloseFCB - Close the NT handle associated with the FCB being closed.
*
* Entry - Client (AX:SI) DWORD NT handle
*
* Exit - SUCCESS
* Client (CF) = 0
*
* FAILURE
* Client(CF) = 1
* Client(AX) = error code
*/
VOID demCloseFCB (VOID)
{
HANDLE hFile;
hFile = GETHANDLE (getAX(),getSI());
if(hFile == 0) {
setCF(0);
return;
}
if (CloseHandle (hFile) == FALSE){
demClientError(hFile, (CHAR)-1);
return;
}
setCF(0);
return;
}
/* demCreateFCB - An FCB is being created get the NT handle.
*
* Entry - Client (AL) Creation Mode
* 00 - Normal File
* 01 - Read-only file
* 02 - Hidden File
* 04 - System file
* Client (DS:SI) Full path filename
* Client (ES:DI) SFT address
*
* Exit - SUCCESS
* Client (CF) = 0
* Client (AX:BP) = NT Handle
* Client (BX) = Time
* Client (CX) = Date
* Client (DX:SI) = Size
*
* FAILURE
* Client(CF) = 1
* Client(AX) = error code
*/
VOID demCreateFCB (VOID)
{
demFCBCommon (CREATE_ALWAYS);
return;
}
/* demDate16 - Get the current date/time in DOS FCB format.
*
* Entry - None
*
* Exit - Always Success
* Client (AX) has date
* Client (DX) has time
* NOTES:
*
* DemDate16 returns the current date in AX, current time in DX in this format
* AX - YYYYYYYMMMMDDDDD years months days
* DX - HHHHHMMMMMMSSSSS hours minutes seconds/2
*/
VOID demDate16 (VOID)
{
SYSTEMTIME TimeDate;
GetLocalTime(&TimeDate);
// date is stored in a packed word: ((year-1980)*512) + (month*32) + day
setAX ( (USHORT) (((TimeDate.wYear-1980) << 9 ) |
((TimeDate.wMonth & 0xf) << 5 ) |
(TimeDate.wDay & 0x1f))
);
setDX ( (USHORT) ((TimeDate.wHour << 11) |
((TimeDate.wMinute & 0x3f) << 5) |
((TimeDate.wSecond / 2) & 0x1f))
);
return;
}
/* demFCBIO - Carry out the FCB based IO operation.
*
* Entry - Client (BX) = 1 if read operation, 0 if write
* Client (AX:BP) NT Handle
* Client (DI:DX) offset to start the operation with
* Client (CX) Count of bytes
*
* Exit - SUCCESS
* Client (CF) = 0
* Client (CX) = counts of bytes read/written
* Client (AX:BX) = size
*
* FAILURE
* Client(CF) = 1
* Client(AX) = error code
*/
VOID demFCBIO (VOID)
{
HANDLE hFile;
ULONG CurOffset;
PVOID pBuf;
DWORD dwBytesIO;
DWORD dwSize,dwSizeHigh;
DWORD dwErrCode;
hFile = GETHANDLE (getAX(),getBP());
CurOffset = (((ULONG)getDI()) << 16) + (ULONG)getDX();
if (SetFilePointer (hFile,
(LONG)CurOffset,
NULL,
(DWORD)FILE_BEGIN) == -1L){
demClientError(hFile, (CHAR)-1);
return ;
}
pBuf = (PVOID)GetVDMAddr(*((PUSHORT)pulDTALocation + 1),
*((PUSHORT)pulDTALocation));
if(getBX()) { // Read Operation
if (ReadFile (hFile,
pBuf,
(DWORD)getCX(),
&dwBytesIO,
NULL) == FALSE){
Sim32FlushVDMPointer(*pulDTALocation, getCX(), pBuf, FALSE);
Sim32FreeVDMPointer(*pulDTALocation, getCX(), pBuf, FALSE);
demClientError(hFile, (CHAR)-1);
return ;
}
Sim32FlushVDMPointer (*pulDTALocation, getCX(),pBuf, FALSE);
Sim32FreeVDMPointer (*pulDTALocation, getCX(), pBuf, FALSE);
}
else {
if (WriteFile (hFile,
pBuf,
(DWORD)getCX(),
&dwBytesIO,
NULL) == FALSE) {
// If disk is full then we should return number of bytes written
// AX = 1 and CF = 1
dwErrCode = GetLastError();
if(dwErrCode == ERROR_DISK_FULL) {
setCX( (USHORT) dwBytesIO);
setAX(1);
setCF(1);
return;
}
SetLastError(dwErrCode);
demClientError(hFile, (CHAR)-1);
return ;
}
}
// Get File Size
if((dwSize = GetFileSize(hFile,&dwSizeHigh)) == -1){
demPrintMsg(MSG_FILEINFO);
ASSERT(FALSE);
demClientError(hFile, (CHAR)-1);
return;
}
if(dwSizeHigh) {
demPrintMsg(MSG_FILESIZE_TOOBIG);
ASSERT(FALSE);
demClientError(hFile, (CHAR)-1);
return;
}
// Setup the exit registers
setCX((USHORT)dwBytesIO);
setBX((USHORT)dwSize);
setAX((USHORT)(dwSize >> 16 ));
setCF(0);
return;
}
/* demGetFileInfo - Get Misc. file info in FCB format.
*
* Entry - Client (DS:SI) full path file name
*
* Exit - SUCCESS
* Client (CF) = 0
* Client (AX) = Attribute of file
* Client (CX) = Time stamp of file
* Client (DX = Date stamp of file
* Client (BX:DI)= Size of file (32 bit)
*
* FAILURE
* Client(CF) = 1
* Client(AX) = error code
*/
VOID demGetFileInfo (VOID)
{
HANDLE hFile;
LPSTR lpFileName;
WORD wDate,wTime;
DWORD dwSize,dwAttr;
lpFileName = (LPSTR) GetVDMAddr (getDS(),getSI());
if ((hFile = CreateFileOem(lpFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL)) == (HANDLE)-1){
demClientError(INVALID_HANDLE_VALUE, *lpFileName);
return;
}
// Get Misc. INfo
if (demGetMiscInfo (hFile,&wTime, &wDate, &dwSize) == FALSE) {
CloseHandle (hFile);
return;
}
CloseHandle (hFile);
if ((dwAttr = GetFileAttributesOem (lpFileName)) == -1) {
demClientError(INVALID_HANDLE_VALUE, *lpFileName);
return;
}
if (dwAttr == FILE_ATTRIBUTE_NORMAL)
dwAttr = 0;
setAX((USHORT)dwAttr);
setCX(wTime);
setDX(wDate);
setDI((USHORT)dwSize);
setBX((USHORT)(dwSize >> 16));
return;
}
/* demOpenFCB - An FCB is being opened get the NT handle.
*
* Entry - Client (AL) Open Mode
* Client (DS:SI) Full path filename
*
* Exit - SUCCESS
* Client (CF) = 0
* Client (AX:BP) = NT Handle
* Client (BX) = Time
* Client (CX) = Date
* Client (DX:SI) = Size
*
* FAILURE
* Client(CF) = 1
* Client(AX) = error code
*/
VOID demOpenFCB (VOID)
{
demFCBCommon (OPEN_EXISTING);
return;
}
/* demFCBCommon - FCB Open/Create.
*
* Entry - CreateDirective - Open/Create
* Client (AL) Open Mode
* Client (DS:SI) Full path filename
*
* Exit - SUCCESS
* Client (CF) = 0
* Client (AX:BP) = NT Handle
* Client (BX) = Time
* Client (CX) = Date
* Client (DX:SI) = Size
*
* FAILURE
* Client(CF) = 1
* Client(AX) = error code
*/
VOID demFCBCommon (ULONG CreateDirective)
{
HANDLE hFile;
LPSTR lpFileName;
UCHAR uchMode,uchAccess;
DWORD dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
WORD wDate,wTime;
DWORD dwSize,dwAttr=0;
USHORT uErr;
SECURITY_ATTRIBUTES sa;
lpFileName = (LPSTR) GetVDMAddr (getDS(),getSI());
uchMode = getAL();
/* Special case for delete volume label (INT 21 Func 13H, Attr = 8H */
if((uchMode == ATTR_VOLUME_ID) && (CreateDirective == CREATE_ALWAYS)) {
if((uErr = demCreateLabel(lpFileName[DRIVEBYTE],
lpFileName+LABELOFF))) {
setCF(1);
setAX(uErr);
return;
}
setAX(0);
setBP(0);
setCF(0);
return;
}
// In create case AL has creation attributes. By default
// Access is for read/write and sharing for both. In open
// case AL has appropriate access and sharing information.
if((CreateDirective == CREATE_ALWAYS) && ((uchMode &0xff) == 0)) {
dwAttr = FILE_ATTRIBUTE_NORMAL;
dwShareMode = FILE_SHARE_WRITE | FILE_SHARE_READ;
}
else {
uchAccess = uchMode & (UCHAR)ACCESS_MASK;
if (uchAccess == OPEN_FOR_READ)
dwDesiredAccess = GENERIC_READ;
else if (uchAccess == OPEN_FOR_WRITE)
dwDesiredAccess = GENERIC_WRITE;
uchMode = uchMode & (UCHAR)SHARING_MASK;
switch (uchMode) {
case SHARING_DENY_BOTH:
dwShareMode = 0;
break;
case SHARING_DENY_WRITE:
dwShareMode = FILE_SHARE_READ;
break;
case SHARING_DENY_READ:
dwShareMode = FILE_SHARE_WRITE;
break;
}
}
sa.nLength = sizeof (SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
if ((hFile = CreateFileOem(lpFileName,
dwDesiredAccess,
dwShareMode | FILE_SHARE_DELETE,
&sa,
CreateDirective,
dwAttr,
NULL)) == (HANDLE)-1){
demClientError(INVALID_HANDLE_VALUE, *lpFileName);
return;
}
// Get Misc. INfo
if (demGetMiscInfo (hFile,&wTime, &wDate, &dwSize) == FALSE)
return;
// Setup the exit registers
setBX(wTime);
setCX(wDate);
setBP((USHORT)hFile);
setAX((USHORT)((ULONG)hFile >> 16));
setSI((USHORT)dwSize);
setDX((USHORT)(dwSize >> 16));
setCF(0);
return;
}
BOOL demGetMiscInfo (hFile, lpTime, lpDate, lpSize)
HANDLE hFile;
LPWORD lpTime;
LPWORD lpDate;
LPDWORD lpSize;
{
FILETIME LastWriteTime,ftLocal;
DWORD dwSizeHigh=0;
if(GetFileTime (hFile,NULL,NULL,&LastWriteTime) == -1){
demPrintMsg(MSG_FILEINFO);
ASSERT(FALSE);
demClientError(hFile, (CHAR)-1);
CloseHandle (hFile);
return FALSE;
}
FileTimeToLocalFileTime (&LastWriteTime,&ftLocal);
if(FileTimeToDosDateTime(&ftLocal,
lpDate,
lpTime) == FALSE){
demPrintMsg(MSG_FILEINFO);
ASSERT(FALSE);
demClientError(hFile, (CHAR)-1);
return FALSE;
}
if((*lpSize = GetFileSize(hFile,&dwSizeHigh)) == -1){
demPrintMsg(MSG_FILEINFO);
ASSERT(FALSE);
demClientError(hFile, (CHAR)-1);
return FALSE;
}
if(dwSizeHigh) {
demPrintMsg(MSG_FILESIZE_TOOBIG);
ASSERT(FALSE);
demClientError(hFile, (CHAR)-1);
return FALSE;
}
return TRUE;
}