#define patchSize (650) // because of CodeWarrior asm limitations
#define HFSDispatchTrapNum 0x60
#define kNumKilledDrivers 15
#define kNumOtherDrivers 63
pascal long main(short message, short /*item*/, short /*numItems*/, short /*cPanelID*/, EventRecord */*theEvent*/, long cdevValue, DialogPtr /*cpDialog*/)
{
long resp;
if (cdevValue) {
switch (message) {
case initDev:
return cdevGenErr;
break;
case macDev:
// normally you shouldn't check against the System version but against individual features
// but in this case we want to know whether custom icons are used by the Finder
if (TrapAvailable(_Gestalt)) {
if (Gestalt(gestaltSystemVersion, &resp) == noErr)
if (resp >= 0x700) {
mypatch();
return 1;
}
}
// no _Gestalt => very old System (< 6.0.4)
return 0;
break;
}
}
return cdevValue;
}
asm void mypatch(void)
{
moveq #HFSDispatchTrapNum,d0 // patch HFSDispatch
_GetOSTrapAddress
move.l OurHFSDispatch,d0
cmp.l (a0),d0
// if the patch is already there do nothing
beq.s bad
lea oldHFSDispatch,a1
move.l a0,(a1)
subq.w #4,sp
move.l #'STR#',-(SP)
move.w #128,-(sp)
_Get1Resource
move.l (sp)+,d0
beq.s bad
lea stringH,a0
move.l d0,(a0) // remember string handle
move.l d0,-(sp)
_DetachResource
bsr findDriverbyName
move.l #patchSize,d0
_NewPtr //Sys
// this block is installed in the System heap anyway, because
// the Finder calls our cdev with the current zone set to the System zone
// (at least under 7.5.5!)
// in theory we should install everything in the Finder heap since it now
// belongs there; but since the Finder malfunctions when its heap is low
// (maybe the current zone is not set to the Finder zone for this reason)
// we refrain from forcing the Finder zone with GetZone/SetZone
bne.s baddisposepref
movea.l a0,a1
lea OurHFSDispatch,a0
move.l #patchSize,d0
_BlockMove
moveq #HFSDispatchTrapNum,d0
movea.l a1,a0
_SetOSTrapAddress
// MOVE.L #0xffff0080,-(SP)
// JSR ShowIcon
bad:
rts
baddisposepref:
movea.l stringH,a0
_DisposHandle
rts
// BEGIN may run at interrupt time
OurHFSDispatch:
cmp.w #9,d0 // Test for GetCatInfo selector
bne.s dontdoit
// the trap dispatcher always puts the trapword in register D1
btst #10,d1 // sync?
beq.s tailpatch // tail patch only sync calls
// for async calls, we intercept the completion routine
move.l a1,-(sp)
lea savedCompletion+3,a1
bclr #0,(a1) // test and clear -- be reentrant!
beq.s restoreA1fin // cannot save over existing completion
subq.w #3,a1 // point to savedCompletion
move.l struct (DirInfo.ioCompletion)(a0),(a1) // save
lea myCompletion,a1
move.l a1, struct (DirInfo.ioCompletion)(a0) // put our own
restoreA1fin:
movea.l (sp)+,a1
bra.s dontdoit
tailpatch:
pea continued
dontdoit:
move.l oldHFSDispatch,-(sp) // Call thru
rts
// END may run at interrupt time
continued:
tst.w struct (DirInfo.ioResult)(a0)
bne.s fin // give up on error
btst #2,struct (DirInfo.ioDrUsrWds.frFlags)(a0)
beq.s fin // give up unless custom icon
movem.l a1/d1,-(sp)
bsr cmdkeyisdown
bne.s leave
movea.l 0x358,a1 // first volume control block LMGetVCBQHdr()+2