770 lines
18 KiB
C
770 lines
18 KiB
C
|
/* 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;
|
||
|
}
|