Leaked source code of windows server 2003
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

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