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.
496 lines
12 KiB
496 lines
12 KiB
/* 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>
|
|
#include "dpmtbls.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);
|
|
|
|
//
|
|
// Note that we don't check for failure in this case as edlin,
|
|
// for instance, can have the file position be negative and
|
|
// we still need to do the cleanup below. Note that we are not
|
|
// even sure why seeking on close matter, but the DOS code does it...
|
|
//
|
|
DPM_SetFilePointer (hFile,
|
|
lLoc,
|
|
NULL,
|
|
FILE_BEGIN);
|
|
|
|
}
|
|
|
|
if (DPM_CloseHandle (hFile) == FALSE){
|
|
demClientError(hFile, (CHAR)-1);
|
|
}
|
|
|
|
//
|
|
// 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 ((DPM_SetFilePointer (hFile,
|
|
lLoc,
|
|
&Zero,
|
|
FILE_BEGIN) == -1L) &&
|
|
(GetLastError() != NO_ERROR)) {
|
|
goto readFailureExit;
|
|
}
|
|
|
|
}
|
|
|
|
if (DPM_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 ((DPM_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 (DPM_SetEndOfFile(hFile) == FALSE){
|
|
demClientError(hFile, (CHAR)-1);
|
|
return;
|
|
}
|
|
setCF (0);
|
|
return;
|
|
}
|
|
|
|
if (DPM_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 = DPM_SetFilePointer (hFile,
|
|
lLoc,
|
|
NULL,
|
|
(DWORD)getBL())) == -1L){
|
|
demClientError(hFile, (CHAR)-1);
|
|
return ;
|
|
}
|
|
|
|
setCF(0);
|
|
setAX((USHORT)dwLoc);
|
|
setDX((USHORT)(dwLoc >> 16));
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
/* 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 = DPM_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);
|
|
}
|