|
|
/* 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; }
|