** Demonstrate how to mount AFP volumes by pretending (to the AppleShare
** rdev) that the Chooser was calling it.
**
** Disclaimer:
**
** Novell, Inc. makes no representations or warranties with respect to
** any NetWare software, and specifically disclaims any express or
** implied warranties of merchantability, title, or fitness for a
** particular purpose.
**
** Distribution of any NetWare software is forbidden without the
** express written consent of Novell, Inc. Further, Novell reserves
** the right to discontinue distribution of any NetWare software.
**
** Novell is not responsible for lost profits or revenue, loss of use
** of the software, loss of data, costs of re-creating lost data, the
** cost of any substitute equipment or program, or claims by any party
** other than you. Novell strongly recommends a backup be made before
** any software is installed. Developer support for this software
** may be provided at the discretion of Novell.
**
** Programmers:**** Ini Who Firm** -------------------------------------------------------------------------** ABJ Adam B. Jerome Novell Developer Support.**** History:**** When Who What** -------------------------------------------------------------------------** 06-29-95 ABJ Initial code for public use.
*//********************************************************************************* Compiler setup.*/#pragma once /*-------------------------------------------------------------------------- ** Include headers. */ #include <Devices.h> #include "FindFolder.h" #include "BootDrive.h" /*-------------------------------------------------------------------------- ** Type definitions. */ typedef pascal OSErr (*DeviceFuncPtr)(short message, short caller, StringPtr objName, StringPtr zoneName, long p1, long p2); typedef struct PackHeader { unsigned short branch; unsigned short deviceID; unsigned long pack; unsigned short resID; unsigned short version; unsigned long flags; } PackHeader, *PackHeaderPtr, **PackHeaderHdl; /*-------------------------------------------------------------------------- ** Function prototypes. */ OSErr GetIndFile(short whichFile, short vRefNum, StringPtr fileName, FInfo *finderInfo); OSErr FindAShare(short wdref, short *fref); OSErr OpenAppleShare(short *fRefNum); OSErr CallDevicePackage(DeviceFuncPtr func, short selector, short id, StringPtr name, StringPtr zone, long param1, long param2); OSErr AppleShareLogin(StringPtr serverName, StringPtr zoneName, AddrBlock addr); /*-------------------------------------------------------------------------- ** Define macros. */ #define myDummyID 128 /* Application ID */ #define DoubleTime 10 /*-------------------------------------------------------------------------- ** Type definitions. *//********************************************************************************* Returns the fileName and finderInfo for the file indexed by whichFile()** on the volume or working directory specified by vRefNum.**** Start at whichFile = 1 and increment whichFile until fnfErr.*/OSErr GetIndFile(short whichFile, short vRefNum, StringPtr fileName, FInfo *finderInfo) { OSErr err; ParamBlockRec pb; pb.fileParam.ioNamePtr = fileName; /* File name will be returned. */ pb.fileParam.ioVRefNum = vRefNum; /* Volume or working directory. */ pb.fileParam.ioFVersNum = 0; /* Version 0 in this lifetime. */ pb.fileParam.ioFDirIndex = whichFile; /* This index (from 1) specifies */ /* the file. */ err = PBGetFInfo( &pb, false ); /* Synchronous call. */ if(!err) *finderInfo = pb.fileParam.ioFlFndrInfo; /* ...This is the treasure. */ return(err); } /********************************************************************************* AppleShare might have a different name (eg, in another language), so search** the working directory for type 'RDEV' and creator 'afps'.*/OSErr FindAShare(short wdref, short *fref) { OSErr err; short fIndex; /* Index (from 1) of file in directory. */ Str255 fileName; /* File name (pascal string). */ FInfo finderInfo; /* Finder information block. */ *fref = 0; fIndex = 1; do { err = GetIndFile(fIndex, wdref, fileName, &finderInfo); if(!err) { /*-------------------------------------------------------------------- ** Compare file type and creator with 'RDEV' and 'afps'. */ if((finderInfo.fdType == 'RDEV') && (finderInfo.fdCreator == 'afps')) { *fref = OpenRFPerm(fileName, wdref, fsRdPerm); break; /* Got it, exit loop. */ } } fIndex++; } while(err == noErr); if(*fref == 0) err = fBsyErr; return(err); } /******************************************************************************** Opens AppleShare RDEV and returns file refNum.**** First uses FindFolder to find the extensions folder, and
** looks there. If we don't have FindFolder, or if we don't
** have an extensions folder, or if AppleShare isn't in the
** extensions folder, look in the system folder.
**** FindAppleShareFolder uses Gestalt (first appeared in
** SYS 6.0.4) to see if FindFolder is present (first appeared
** in sys 7.0). It first checks for the presence of Gestalt.
** This code should work on 7.0, 6.04-6.07, 6.0.3 and
** earlier, and MFS as well as HFS.
*/OSErr OpenAppleShare(short *fRefNum) { OSErr err; OSErr fFolderErr; /* Find folder error return. */ short extWDRefNum; /* Wdref of extensions folder. */ short volumeRefNum; /* Volume or working directory. */ /*-----------------------------------------------------------------------
** Under system 7, use FindFolder to find the Folder in which AppleShare
** lives.
*/ fFolderErr = FindAppleShareFolder(&extWDRefNum); /* WD refnum, actually */ if(fFolderErr == noErr) { err = FindAShare(extWDRefNum, fRefNum); if(err == noErr) return(noErr); } volumeRefNum = GetRealBootDrive(); /* Get refnum of volume or blessed */ /* folder WD. */ return(FindAShare(volumeRefNum, fRefNum)); }/********************************************************************************* Run the device package.** Save all registers, as the package is allowed to trash them.*/OSErr CallDevicePackage(DeviceFuncPtr func, short selector, short id, StringPtr name, StringPtr zone, long param1, long param2) { OSErr err; asm { movem.l d3-d7/a2-a7,-(sp) } err = func(selector, id, name, zone, param1, param2); asm { movem.l (sp)+,d3-d7/a2-a7 } return(err); }/********************************************************************************* AppleShareLogin*/OSErr AppleShareLogin(StringPtr serverName, StringPtr zoneName, AddrBlock serverAddr) { int savedHState; /*-------------------------------------------------------------------------- ** Window variables. */ Rect bounds; WindowPtr myWindow; GrafPtr savedPort; /*-------------------------------------------------------------------------- ** List variables; */ Rect rView; Rect dataBounds; Point cSize; ListHandle myListHdl; Boolean drawIt; Boolean dummyB; EventRecord myEvent; Cell aCell; /*-------------------------------------------------------------------------- ** File access variables. */ short fileRefNum; short oldResFile; PackHeaderHdl packHdl; OSErr err; Str255 vName; Str255 fName; /*-------------------------------------------------------------------------- ** Dummy var for Delay(). */ long dummy; /*-------------------------------------------------------------------------- ** Create our one and only invisible window. */ GetPort(&savedPort); SetRect(&bounds, 10, 40, 200, 200); myWindow = NewWindow(NULL, &bounds, "\pMYOB", false, dBoxProc, NULL, false, 1); if(myWindow == nil) { SetPort(savedPort); return(memFullErr); /* -108 */ } SetPort(myWindow); /*-------------------------------------------------------------------------- ** Create a list manager list in the window. */ rView = myWindow->portRect; InsetRect(&rView, 15, 0); SetRect(&dataBounds, 0, 0, 2, 1); cSize.h = 100; /* Obese cell */ cSize.v = 100; drawIt = false; myListHdl = LNew(&rView, &dataBounds, cSize, 0, myWindow, drawIt, false, false, false); if(myListHdl == NULL) { SetPort(savedPort); DisposeWindow(myWindow); return(memFullErr); /* -108 */ } /*-------------------------------------------------------------------------- ** Build a list of one NetWare AFP Server. */ aCell.h = 0; /* Column 0 stores server names. */ aCell.v = 0; /* Always row 0 since there is only one. */ LSetCell( &serverName[1], (short)serverName[0], aCell, myListHdl); aCell.h = 1; /* Column 1 stores network addresses */ LSetCell(&serverAddr, 4, aCell, myListHdl); /*-------------------------------------------------------------------------- ** A click just before this seems to confuse LClick, ** so we'll just wait a little while to ensure that this fake ** click will work. My working hypothesis is that it looks like ** a double-click, but since our flags say we don't want double-clicks ** LClick returns false, and since it thinks that we just got (and ** probably processed) a click, it doesn't act on this one. */ Delay(DoubleTime+2, &dummy); /*-------------------------------------------------------------------------- ** Dummy up events to have list manager select the server name cell. */ myEvent.where.h = 50; /* Dummy click near center of cell. */ myEvent.where.v = 50; myEvent.modifiers = 0x0; dummyB = LClick( myEvent.where, myEvent.modifiers, myListHdl ); /*-------------------------------------------------------------------------- ** Open the AppleShare Chooser device file. */ oldResFile = CurResFile(); err = OpenAppleShare(&fileRefNum); if(!err) { packHdl = (PackHeaderHdl) GetResource('PACK', -4096); err = ResError(); if((!err) && (packHdl != NULL)) { short volref; short set_vol = false; /*-------------------------------------------------------------------- ** 11-21-90 MRW SetVol to the system folder so that UAMs will get ** called if requested. */ if(GetVol((StringPtr)0, &volref) == noErr) { SetVol((StringPtr)0, GetRealBootDrive()); set_vol = true; } HLock((Handle)packHdl); HNoPurge((Handle)packHdl); /*-------------------------------------------------------------------- ** Run the device package. Issue a buttonMsg call. */ err = CallDevicePackage((DeviceFuncPtr)*packHdl, buttonMsg, myDummyID, serverName, zoneName, (long)myListHdl, (long)1); /*-------------------------------------------------------------------- ** Clean up. */ SetCursor(&arrow); HUnlock((Handle)packHdl); HPurge((Handle)packHdl); /* Might need it again ... or not ... */ if(set_vol) (void) SetVol((StringPtr)0, volref); } CloseResFile(fileRefNum); } UseResFile( oldResFile ); /* Important! maybe the old res file wasn't at */ /* the top. */ SetPort(savedPort); LDispose(myListHdl); DisposeWindow(myWindow); return(err); }