Add wrapper code around PFI to save the server/zone names and properly return them in FIListSessions2.

This is necessary because FIListSessions2 has a bug that causes it to return garbage in the server/zone fields for DSI sessions. (The bug is essentially that PFI is indexing into its own tables based on the ASP/DSI session number, rather than properly using a PFI-level session index.)
This commit is contained in:
Stephen Heumann 2017-04-18 17:46:33 -05:00
parent 444fdbee49
commit 33c4871183
5 changed files with 179 additions and 8 deletions

View File

@ -13,7 +13,7 @@ MOUNTAFP_PROG = mountafp
DUMPCMDTBL_OBJS = dumpcmdtbl.o asmglue.o
DUMPCMDTBL_PROG = dumpcmdtbl
AFPBRIDGE_OBJS = afpinit.o afpbridge.o aspinterface.o dsi.o readtcp.o endian.o tcpconnection.o atipmapping.o asmglue.o installcmds.o cmdproc.o callat.o afpoptions.o strncasecmp.o
AFPBRIDGE_OBJS = afpinit.o afpbridge.o aspinterface.o dsi.o readtcp.o endian.o tcpconnection.o atipmapping.o asmglue.o installcmds.o cmdproc.o callat.o afpoptions.o strncasecmp.o savenames.o
AFPBRIDGE_PROG = AFPBridge
AFPMOUNTER_OBJS = cdevstart.o afpcdev.o afpurlparser.o afpoptions.o strncasecmp.o

View File

@ -52,6 +52,42 @@ doOrig short i ;push original procedure ptr
rtl ;jump to it
end
pfiLoginCmdProc start
lda cmdRecPtr+2
pha
lda cmdRecPtr
pha
jslOldPFILogin entry
jsl jslOldPFILogin ; to be changed
rep #$30 ; ensure full native mode
jsl SaveNames
rtl
end
pfiLogin2CmdProc start
lda cmdRecPtr+2
pha
lda cmdRecPtr
pha
jslOldPFILogin2 entry
jsl jslOldPFILogin2 ; to be changed
rep #$30 ; ensure full native mode
jsl SaveNames
rtl
end
pfiListSessions2CmdProc start
lda cmdRecPtr+2
pha
lda cmdRecPtr
pha
jslOldPFIListSessions2 entry
jsl jslOldPFIListSessions2 ; to be changed
rep #$30 ; ensure full native mode
jsl InsertCorrectNames
rtl
end
CallCompletionRoutine start
phb
jsl ForceLCBank2 ;use LC bank 2

View File

@ -3,6 +3,12 @@
void cmdProc(void);
void nbpCmdProc(void);
void pfiLoginCmdProc(void);
extern LongWord jslOldPFILogin;
void pfiLogin2CmdProc(void);
extern LongWord jslOldPFILogin2;
void pfiListSessions2CmdProc(void);
extern LongWord jslOldPFIListSessions2;
void CallCompletionRoutine(void *);
#endif

View File

@ -9,22 +9,28 @@
typedef struct NewCmd {
Word cmdNum;
void (*cmdAddr)(void);
LongWord *jslOldCmdLocation;
} NewCmd;
NewCmd newCmds[] = {
{aspGetStatusCommand, cmdProc},
{aspOpenSessionCommand, cmdProc},
{aspCloseSessionCommand, cmdProc},
{aspCommandCommand, cmdProc},
{aspWriteCommand, cmdProc},
{nbpLookupNameCommand, nbpCmdProc},
{0, 0}
{aspGetStatusCommand, cmdProc, NULL},
{aspOpenSessionCommand, cmdProc, NULL},
{aspCloseSessionCommand, cmdProc, NULL},
{aspCommandCommand, cmdProc, NULL},
{aspWriteCommand, cmdProc, NULL},
{nbpLookupNameCommand, nbpCmdProc, NULL},
{pfiLoginCommand, pfiLoginCmdProc, &jslOldPFILogin},
{pfiLogin2Command, pfiLogin2CmdProc, &jslOldPFILogin2},
{pfiListSessions2Command, pfiListSessions2CmdProc, &jslOldPFIListSessions2},
{0, 0, 0}
};
LongWord *cmdTable = (LongWord *)0xE1D600;
LongWord oldCmds[MAX_CMD + 1]; /* holds old entries for commands we changed */
#define JSL 0x22
void installCmds(void) {
Word savedStateReg;
NewCmd *cmd;
@ -35,6 +41,8 @@ void installCmds(void) {
oldCmds[cmd->cmdNum] = cmdTable[cmd->cmdNum];
cmdTable[cmd->cmdNum] =
(oldCmds[cmd->cmdNum] & 0xFF000000) | (LongWord)cmd->cmdAddr;
if (cmd->jslOldCmdLocation != NULL)
*cmd->jslOldCmdLocation = JSL | (oldCmds[cmd->cmdNum] << 8);
}
RestoreStateReg(savedStateReg);

121
savenames.c Normal file
View File

@ -0,0 +1,121 @@
#include <string.h>
#include <appletalk.h>
#include "aspinterface.h"
#include "asmglue.h"
/*
* This code is responsible for saving away the server name and zone at
* the time of an FILogin(2) call, and then writing them into the result
* records returned by FIListSessions2.
*
* This code is needed because FIListSessions2 has a bug that will cause
* these fields of its result records to contain garbage for AFP-over-TCP
* connections and in some cases also wrong values for concurrent
* AFP-over-AppleTalk sessions.
*/
#define SERVER_NAME_SIZE 32
#define ZONE_NAME_SIZE 33
typedef struct NameRec {
unsigned char serverName[SERVER_NAME_SIZE];
unsigned char zoneName[ZONE_NAME_SIZE];
} NameRec;
#define MAX_ASP_SESSION_NUM 8
NameRec aspSessionNames[MAX_ASP_SESSION_NUM + 1];
NameRec dsiSessionNames[MAX_SESSIONS];
static unsigned char emptyStr[1] = {0};
typedef struct ListSessions2Buffer {
Byte refNum;
Byte slotDrive;
char volName[28];
Word volID;
char serverName[32];
char zoneName[33];
} ListSessions2Buffer;
/*
* This is called following an FILogin or FILogin2 call, to save the names.
*/
#pragma databank 1
void SaveNames(PFILogin2Rec *commandRec) {
unsigned char *serverName, *zoneName;
unsigned int i;
unsigned int strLen;
NameRec *nameRec;
Word stateReg;
stateReg = ForceRomIn();
/* Don't save names for failed connections */
if (commandRec->result != 0 && commandRec->result != pfiLoginContErr)
goto ret;
if (commandRec->sessRefID <= MAX_ASP_SESSION_NUM) {
nameRec = &aspSessionNames[commandRec->sessRefID];
} else if (commandRec->sessRefID >= SESSION_NUM_START) {
nameRec = &dsiSessionNames[commandRec->sessRefID - SESSION_NUM_START];
} else {
goto ret;
}
/* Get the names (or default to empty strings if not provided) */
if (commandRec->command == pfiLogin2Command) {
serverName = commandRec->serverName;
zoneName = commandRec->zoneName;
} else {
serverName = emptyStr;
zoneName = emptyStr;
}
memset(nameRec, 0, sizeof(*nameRec));
strLen = serverName[0];
if (strLen >= SERVER_NAME_SIZE)
strLen = SERVER_NAME_SIZE - 1;
memcpy(&nameRec->serverName, serverName, strLen + 1);
nameRec->serverName[0] = strLen;
strLen = zoneName[0];
if (strLen >= ZONE_NAME_SIZE)
strLen = ZONE_NAME_SIZE - 1;
memcpy(&nameRec->zoneName, zoneName, strLen + 1);
nameRec->zoneName[0] = strLen;
ret:
RestoreStateReg(stateReg);
}
#pragma databank 0
#pragma databank 1
void InsertCorrectNames(PFIListSessions2Rec *commandRec) {
unsigned int i;
ListSessions2Buffer *resultBuf;
NameRec *nameRec;
Word stateReg;
stateReg = ForceRomIn();
if (commandRec->result != 0 && commandRec->result != pfiBufferToSmallErr)
goto ret;
resultBuf = (ListSessions2Buffer *)commandRec->bufferPtr;
for (i = 0; i < commandRec->entriesRtn; i++) {
if (resultBuf[i].refNum <= MAX_ASP_SESSION_NUM) {
nameRec = &aspSessionNames[resultBuf[i].refNum];
} else if (resultBuf[i].refNum >= SESSION_NUM_START) {
nameRec = &dsiSessionNames[resultBuf[i].refNum - SESSION_NUM_START];
} else {
continue;
}
memcpy(&resultBuf[i].serverName, nameRec, sizeof(*nameRec));
}
ret:
RestoreStateReg(stateReg);
}
#pragma databank 0