From 33c48711835690d4fe76cf32d70b63302547fd30 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Tue, 18 Apr 2017 17:46:33 -0500 Subject: [PATCH] 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.) --- Makefile.mk | 2 +- cmdproc.asm | 36 +++++++++++++++ cmdproc.h | 6 +++ installcmds.c | 22 ++++++--- savenames.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 179 insertions(+), 8 deletions(-) create mode 100644 savenames.c diff --git a/Makefile.mk b/Makefile.mk index 932111a..9c23b15 100644 --- a/Makefile.mk +++ b/Makefile.mk @@ -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 diff --git a/cmdproc.asm b/cmdproc.asm index 2d4b774..817e846 100644 --- a/cmdproc.asm +++ b/cmdproc.asm @@ -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 diff --git a/cmdproc.h b/cmdproc.h index 356a1f8..996f917 100644 --- a/cmdproc.h +++ b/cmdproc.h @@ -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 diff --git a/installcmds.c b/installcmds.c index ef71705..0437140 100644 --- a/installcmds.c +++ b/installcmds.c @@ -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); diff --git a/savenames.c b/savenames.c new file mode 100644 index 0000000..d5dcf36 --- /dev/null +++ b/savenames.c @@ -0,0 +1,121 @@ +#include +#include +#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 +