|
|
/* demhndl.c - SVC handlers for calls where file handle is provided.
* * demClose * demRead * demWrite * demChgFilePtr * demFileTimes * * Modification History: * * Sudeepb 02-Apr-1991 Created * rfirth 25-Sep-1991 Added Vdm Redir stuff for named pipes */
#include "dem.h"
#include "demmsg.h"
#include <softpc.h>
#include <io.h>
#include <fcntl.h>
#include <vrnmpipe.h>
#include <exterr.h>
#include <mvdm.h>
BOOL (*VrInitialized)(VOID); // POINTER TO FUNCTION
extern BOOL IsVdmRedirLoaded(VOID);
/* demClose - Close a file
* * * Entry - Client (AX:BP) File Handle * Client (CX:DX) File position (if -1 no seek needed before closing * the handle. * (VadimB) * Client (es:di) SFT ptr - this is implied in abort.asm code * * Exit * SUCCESS * Client (CY) = 0 * * FAILURE * Client (CY) = 1 * Client (AX) = system status code * */
VOID demClose (VOID) { HANDLE hFile; LONG lLoc; USHORT usDX,usCX;
hFile = GETHANDLE (getAX(),getBP());
if (hFile == 0) { setCF (0); return; }
usCX = getCX(); usDX = getDX();
if (!((usCX == (USHORT)-1) && (usDX == (USHORT)-1))) { lLoc = (LONG)((((int)usCX) << 16) + (int)usDX); if (SetFilePointer (hFile, lLoc, NULL, FILE_BEGIN) == -1L){ demClientError(hFile, (CHAR)-1); return ; }
}
if (CloseHandle (hFile) == FALSE){ demClientError(hFile, (CHAR)-1); return; }
//
// if the redir TSR is being run in this VDM session, check if the handle
// being closed references a named pipe - we have to delete some info
// that we keep for the open named pipe
//
if (IsVdmRedirLoaded()) { VrRemoveOpenNamedPipeInfo(hFile); }
setCF(0); return; }
/* demRead - Read a file
* * * Entry - Client (AX:BP) File Handle * Client (CX) Count to read * Client (DS:DX) Buffer Address * Client (BX:SI) = current file pointer location. * ZF = 1 if seek is not needed prior to read. * * Exit * SUCCESS * Client (CY) = 0 * Client (AX) = Count of bytes read * * FAILURE * Client (CY) = 1 * Client (AX) = system status code * */
VOID demRead (VOID) { HANDLE hFile; LPVOID lpBuf; DWORD dwBytesRead; USHORT usDS,usDX; DWORD dwReadError; BOOL ok; UCHAR locus, action, class; LONG lLoc;
hFile = GETHANDLE (getAX(),getBP()); usDS = getDS(); usDX = getDX(); lpBuf = (LPVOID) GetVDMAddr (usDS,usDX);
//
// if this handle is a named pipe then use VrReadNamedPipe since we have
// to perform an overlapped read, and wait on the event handle for completion
// even though we're still doing synchronous read
//
if (IsVdmRedirLoaded()) { if (VrIsNamedPipeHandle(hFile)) {
//
// named pipe read always sets the extended error information in the
// DOS data segment. This is the only way we can return bytes read
// information and a more data indication
//
ok = VrReadNamedPipe(hFile, lpBuf, (DWORD)getCX(), &dwBytesRead, &dwReadError ); switch (dwReadError) { case NO_ERROR: locus = action = class = 0; break;
case ERROR_NO_DATA: case ERROR_MORE_DATA: locus = errLOC_Net; class = errCLASS_TempSit; action = errACT_Retry; break;
default:
//
// any error other than the specific ones we handle here should be
// correctly handled by DOS
//
goto readFailureExit; } pExtendedError->ExtendedErrorLocus = locus; STOREWORD(pExtendedError->ExtendedError, (WORD)dwReadError); pExtendedError->ExtendedErrorAction = action; pExtendedError->ExtendedErrorClass = class; if (ok) { goto readSuccessExit; } else { goto readFailureExit; } } }
//
// if the redir TSR is not loaded, or the handle is not a named pipe then
// perform normal file read
//
if (!getZF()) { ULONG Zero = 0; lLoc = (LONG)((((int)getBX()) << 16) + (int)getSI()); if ((SetFilePointer (hFile, lLoc, &Zero, FILE_BEGIN) == -1L) && (GetLastError() != NO_ERROR)) { goto readFailureExit; }
}
if (ReadFile (hFile, lpBuf, (DWORD)getCX(), &dwBytesRead, NULL) == FALSE){
readFailureExit: Sim32FlushVDMPointer (((ULONG)(usDS << 16)) | usDX, getCX(), (PBYTE )lpBuf, FALSE); Sim32FreeVDMPointer (((ULONG)(usDS << 16)) | usDX, getCX(), (PBYTE )lpBuf, FALSE);
if (GetLastError() == ERROR_BROKEN_PIPE) { setAX(0); setCF(0); return; } demClientError(hFile, (CHAR)-1); return ; }
readSuccessExit: Sim32FlushVDMPointer (((ULONG)(usDS << 16)) | usDX, getCX(), (PBYTE )lpBuf, FALSE); Sim32FreeVDMPointer (((ULONG)(usDS << 16)) | usDX, getCX(), (PBYTE )lpBuf, FALSE); setCF(0); setAX((USHORT)dwBytesRead); return; }
/* demWrite - Write to a file
* * * Entry - Client (AX:BP) File Handle * Client (CX) Count to write * Client (DS:DX) Buffer Address * Client (BX:SI) = current file pointer location. * ZF = 1 if seek is not needed prior to write. * * Exit * SUCCESS * Client (CY) = 0 * Client (AX) = Count of bytes written * * FAILURE * Client (CY) = 1 * Client (AX) = system status code * */
VOID demWrite (VOID) { HANDLE hFile; DWORD dwBytesWritten; LPVOID lpBuf; LONG lLoc; DWORD dwErrCode;
hFile = GETHANDLE (getAX(),getBP()); lpBuf = (LPVOID) GetVDMAddr (getDS(),getDX());
//
// if this handle is a named pipe then use VrWriteNamedPipe since we have
// to perform an overlapped write, and wait on the event handle for completion
// even though we're still doing synchronous write
//
if (IsVdmRedirLoaded()) { if (VrIsNamedPipeHandle(hFile)) { if (VrWriteNamedPipe(hFile, lpBuf, (DWORD)getCX(), &dwBytesWritten)) { goto writeSuccessExit; } else { goto writeFailureExit; } } }
//
// if the redir TSR is not loaded, or the handle is not a named pipe then
// perform normal file write
//
if (!getZF()) { ULONG Zero = 0; lLoc = (LONG)((((int)getBX()) << 16) + (int)getSI()); if ((SetFilePointer (hFile, lLoc, &Zero, FILE_BEGIN) == -1L) && (GetLastError() != NO_ERROR)) { demClientError(hFile, (CHAR)-1); return ; }
}
// In DOS CX=0 truncates or extends the file to current file pointer.
if (getCX() == 0){ if (SetEndOfFile(hFile) == FALSE){ demClientError(hFile, (CHAR)-1); return; } setCF (0); return; }
if (WriteFile (hFile, lpBuf, (DWORD)getCX(), &dwBytesWritten, NULL) == FALSE){
// If disk is full then we should return 0 byte written and CF is clear
dwErrCode = GetLastError(); if(dwErrCode == ERROR_DISK_FULL) {
setCF(0); setAX(0); return; }
SetLastError(dwErrCode);
writeFailureExit: demClientError(hFile, (CHAR)-1); return ; }
writeSuccessExit: setCF(0); setAX((USHORT)dwBytesWritten); return; }
/* demChgFilePtr - Change File Pointer
* * * Entry - Client (AX:BP) File Handle * Client (CX:DX) New Location * Client (BL) Positioning Method * 0 - File Absolute * 1 - Relative to Current Position * 2 - Relative to end of file * * Exit * SUCCESS * Client (CY) = 0 * Client (DX:AX) = New Location * * FAILURE * Client (CY) = 1 * Client (AX) = system status code * */
VOID demChgFilePtr (VOID) { HANDLE hFile; LONG lLoc; DWORD dwLoc;
#if (FILE_BEGIN != 0 || FILE_CURRENT != 1 || FILE_END !=2)
#error "Win32 values not DOS compatible"
#
#endif
hFile = GETHANDLE (getAX(),getBP()); lLoc = (LONG)((((int)getCX()) << 16) + (int)getDX());
if ((dwLoc = SetFilePointer (hFile, lLoc, NULL, (DWORD)getBL())) == -1L){ demClientError(hFile, (CHAR)-1); return ; }
setCF(0); setAX((USHORT)dwLoc); setDX((USHORT)(dwLoc >> 16)); return; }
#if 0
/*
* Completely moved to demlfn.c * * * */
/* demFileTimes - Change or Get File date and times
* * GET TIME (Client(BL) = 0) * * Entry * Client(AX:BP) * NT Handle * * Exit * SUCCESS * Client(CF) = 0 * Client(CX) = File time * Client(DX) = File date * FAILURE * Client(CF) = 1 * Client(AX) = error code * * SET TIME (Client(BL) = 1) * * Entry * Client(AX:BP) * Nt Handle * Client(CX) * New file time * Client(DX) * New file date * * Exit * SUCCESS * Client(CF) = 0 * FAILURE * Client(CF) = 1 * Client(AX) = error code * * Hard Error Exit * Client(CF) = 1 * Client(AX) = 0FFFFh * * GET TIME For device (Client(BL) = 2) * * Entry * Client(AX:BP) * NT Handle - not in use * * Exit * SUCCESS * Client(CF) = 0 * Client(CX) = Current time * Client(DX) = Curren date * FAILURE * None * */
VOID demFileTimes (VOID) { HANDLE hFile; WORD wDate,wTime; FILETIME LastWriteTime,ftTemp; SYSTEMTIME stCurrentTime; UCHAR uchOpt = 0;
uchOpt = getBL(); if(uchOpt != 2) hFile = GETHANDLE(getAX(),getBP());
if(uchOpt != 1){
if(!uchOpt) { if(GetFileTime (hFile,NULL,NULL,&LastWriteTime) == -1){ demClientError(hFile, (CHAR)-1); return; } } else { // Device case. We should return current time
GetSystemTime(&stCurrentTime); SystemTimeToFileTime(&stCurrentTime, &LastWriteTime);
}
FileTimeToLocalFileTime (&LastWriteTime,&ftTemp); if(FileTimeToDosDateTime(&ftTemp, (LPWORD)&wDate, (LPWORD)&wTime) == FALSE){ demPrintMsg(MSG_TIMEDATE); setCF(0); return; }
setCX(wTime); setDX(wDate); setCF(0); return; }
wDate = getDX(); wTime = getCX();
if (DosDateTimeToFileTime(wDate, wTime, &LastWriteTime) == FALSE){ demPrintMsg(MSG_TIMEDATE); setCF(0); return; } LocalFileTimeToFileTime (&LastWriteTime,&ftTemp);
if(!SetFileTime(hFile,NULL,NULL,&ftTemp)){ demClientError(hFile, (CHAR)-1); return; }
setCF(0); return; }
#endif
/* DemCommit -- Commit File(Flush file buffers)
* * Entry - Client (AX:BP) File Handle * * Exit * SUCCESS * Client (CY) = 0 * buffer flushed * * FAILURE * Client (CY) = 1 * */ VOID demCommit(VOID) { HANDLE hFile; BOOL bRet;
hFile = GETHANDLE(getAX(),getBP()); bRet = FlushFileBuffers(hFile); #if DBG
if (!bRet) {
//
// FlushFileBuffers fails with access denied if the handle
// is open for read-only access, however it's not an error
// for DOS.
//
DWORD LastError; LastError = GetLastError();
if (LastError != ERROR_ACCESS_DENIED) { sprintf(demDebugBuffer, "ntvdm demCommit warning: FlushFileBuffers error %d\n", LastError); OutputDebugStringOem(demDebugBuffer); } } #endif
setCF(0);
}
/* function to check if new data has been written to the file or
if the file has been marked EOF
Input: Client (AX:BP) = 32bits NT file handle Output: Client ZF = 1 if new data or EOF CF = 1 if EOF */
VOID demPipeFileDataEOF(VOID) { HANDLE hFile; BOOL fEOF; BOOL DataEOF; DWORD FileSizeLow; DWORD FileSizeHigh;
hFile = GETHANDLE(getAX(), getBP());
DataEOF = cmdPipeFileDataEOF(hFile, &fEOF); if (fEOF) { //EOF, get file size, max size = 32bits
FileSizeLow = GetFileSize(hFile, &FileSizeHigh); setAX((WORD)(FileSizeLow / 0x10000)); setBP((WORD)FileSizeLow); setCF(1); // EOF is encountered
} else setCF(0); setZF(DataEOF ? 0 : 1); }
/* function to check if the file has been marked EOF
Input: Client(AX:BP) = 32bits NT file handle Output: Client CY = 1 if EOF */
VOID demPipeFileEOF(VOID) { HANDLE hFile; DWORD FileSizeLow; DWORD FileSizeHigh;
hFile = GETHANDLE(getAX(), getBP()); if (cmdPipeFileEOF(hFile)) { FileSizeLow = GetFileSize(hFile, &FileSizeHigh); setAX((WORD)(FileSizeLow / 0x10000)); // file size in 32bits
setBP((WORD)FileSizeLow); setCF(1); //EOF is encountered
} else setCF(0); }
|