home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-04-06 | 8.1 KB | 173 lines | [TEXT/R*ch] |
- Extension Shell (Source) ReadMe
- -------------------------------
-
- This folder contains the current release of Extension Shell. THINK C source for all three code resources is
- supplied, and there's a ResEdit file containing the compiled versions.
-
- ExtensionShell.c is the main module, and control branches out of there to accomplish various tasks. The
- three projects in the folder (the Extension Shell INIT code, the RESP code, and the default address table
- code) are all discussed below. Also discussed is ParamBlock.h - which describes how your ES Handler
- interfaces with Extension Shell.
-
-
-
-
-
-
- Extension Shell.π
- -----------------
-
- This project is the heart of Extension Shell. It generates the INIT code that's actually run at startup - it
- takes care of installing code, removing code, showing icons, posting Notification Manager notes, installing
- an address table, and calling your ES Handler. It compiles up as an 'INIT' resource, of ID 5000, with the
- System and Locked bits set. It calls your ES Handler, and tries to install what your handler requests. Do
- not change the System/Locked bits - the code depends on this, and makes no attempt to lock itself down.
-
- If your handler wanted an address table installed, it is called again to initialise any extension specific fields
- it has added. If there's a problem your handler is called again when it can decide how it wants to handle
- errors (e.g., beep, post a message, show a different icon). Extension Shell then shows the icon(s) your
- handler requested, posts any messages, and exits.
-
-
-
-
-
-
- RESP.π
- ------
-
- This project is used by Extension Shell to remove Notification Manager notes after the user has read them.
- It compiles up as a 'CODE' resource, of ID 5001. It can be omitted from your Extensions, but any notes you
- post (in NotifyMsg.c) won't be removed after the user has read them - they remain stuck in the System
- heap.
-
-
-
-
-
-
- AddrsTable.π
- ------------
-
- This project is used by Extension Shell as a Gestalt selector function. It compiles up as a 'CODE' resource,
- of ID 5002. It can be removed if your Extension doesn't need an address table. If your Extension does need
- an address table you can either use this code, or supply your own. This code is called by Extension Shell to
- initialise one of its global variables, like so (from 'InstallCode.c'):
-
-
- AddressTable *gTheAddressTable;
- …
- theErr = Gestalt(theParamBlock.addressTableSelector, &gTheAddressTable);
-
-
- The Gestalt selector's purpose is to correct initialise gTheAddressTable. The address table structure itself is
- declared as a global in the selector's code, and so remains locked in the System heap with the selector.
- Your installed code can call Gestalt to get the address of this structure, and look up the address of the code
- it replaced.
-
- The behaviour of this Gestalt selector can be extended by supplying your own ('CODE', 5002) selector
- instead. Your routine should have the same behaviour as the original routine - it should return the address
- of its global address table structure, in its parameter, and nothing else. If you are supplying your own
- routine, be aware that Extension Shell expects the address table structure to start with an array of
- ProcPtrs. However, it only initialises as many ProcPtrs as it uses, and relies on your ES Handler code
- to initialise any further fields - provided the first N fields of your address table are the N ProcPtrs for
- the code resources you want installed, everyone will be happy.
-
-
-
- Original
- --------
- typedef struct {
- ProcPtr theTable[kMaxNumCodeResources+1];
- } AddressTable;
-
-
- Extended
- --------
- typedef struct {
- ProcPtr theTable[...]; // Must be first
- long myFieldOne;
- Boolean myFieldTwo;
- ProcPtr myOtherProc;
- } MyExtendedAddressTable;
-
-
-
- This ability to extend the address table, and thus remove the need for another selector to communicate
- with any Control Panels, was the main reason for choosing this way to get addresses to the code that
- needed them. I've given some other alternatives that have been suggested below but, for now, I feel that
- going through Gestalt is probably the cleanest way. If you've got any other ideas, feel free to let me know.
-
-
- • Search for a pre-initialised variable in the actual 'CODE' resource, and store the address
- there. This relies on 'CODE' resources having their globals embedded in them, and would
- involve flushing caches for every thing that was installed. Search times couldn't be
- predicted in advance, which might be inefficient if somebody wanted to install something
- huge.
-
- • Store the address at a fixed offset in the 'CODE' resource. This wouldn't be too much
- hassle for people writing stuff in assembly, but it's too restrictive for high level
- languages.
-
- • Store the address in a resource in our Extension's resource fork. If more than one 'CODE'
- resource wanted to find an address, the resource would grow to become an AddressTable,
- and the trap-patches/etc would have the extra work of finding their Extension (hoping it
- hadn't been moved or renamed before the trap they patched was called), opening its resource
- fork, etc, etc. It could also mean problems for people patching Resource Manager calls. The
- address could also be stored in the preferences file, but the same problems apply.
-
- • Search the System heap for a block of the right size, which begins with a predefined
- signature. The signature would have to be shared between 'CODE' resources (unless
- Extension Shell read it from another resource), but this explicitly relies on the format of
- memory blocks. You *could* just go ahead and search the whole System heap, but this
- might be a bit excessive...
-
- • Add an assembly patch to a trap, copy the address of the original trap into it at a fixed
- address, and use that trap as a sort of Gestalt selector. If its parameters are a certain value,
- and one of them points to a unique signature, etc - then assume (gulp!) that we're being called
- to return the value of an address table/old routine.
-
-
-
-
-
-
- ParamBlock.h
- ------------
-
- Out of all the header files, this is probably the most important. This defines the structure that Extension
- Shell uses to communicate with your ES Handler. Each code resource that you want to install has an entry
- in the ‘theCodeResources’ array. The type specific details (trap number, gestalt selector, etc) are
- contained in a union within the structures of this array. The details required are commented inside
- ParamBlock.h, but to see them in practice look at the sample extensions.
-
-
-
-
-
-
- Other things...
- ---------------
-
- • The “Extension Shell #includes” folder contains include files that all the Extension Shell projects require.
- Place an alias to it in your “THINK C:Mac #includes” folder before you try and compile things.
-
- • Where arrays are used in the source code, valid indexes are from 1..kMaxNumSomeDescriptiveName.
-
- • If you have to share .h files between projects, don't make an alias and #include that. THINK C will open
- the alias file itself rather than resolving it... Put them in a shared directory.
-
- • The logic in the sample Extensions isn't valid for Control Panels. They all assume that after testing for
- System 7 and shift/the mouse button being down then it's OK to install themselves. If you are using
- Extension Shell in a Control Panel, and your Control Panel has an on/off switch, you will need to test the
- status of your switch before checking to see if shift/the mouse button is down. Otherwise your Control
- Panel might be off, but holding down shift/the mouse button will make it show its disabled icon.
-
- • There are four calls to DebugStr() in Extension Shell. While it's not a good idea to ship products with
- DebugStr calls in them, Extension Shell will only call them if something *very* serious has gone wrong... If
- it can't load your ES Handler then it calls DebugStr - presumably you'll notice this before you ship. ;-) It
- also calls DebugStr if your Extension has requested an address table, but the table couldn't be found or
- installed. If this happens, ES wouldn't be able to install your patches anyway (since you requested an
- address table, presumably they expect it to be there) - again, this is something you need to know before
- you ship: so the calls stay for now.
-