cak3g@astsun7.astro.Virginia.EDU (Colin Klipsch) (06/06/90)
In article <8560@goofy.Apple.COM> lsr@Apple.COM (Larry Rosenstein) writes: >In article <1990Jun5.142604.11826@asterix.drev.dnd.ca> >louis@asterix.drev.dnd.ca (Louis Demers) writes: >> What happens if you disable the init and it is not loaded. Your >> resource is still there pointing to some area it has no right to > >I would place a magic series of bytes in memory and have the cdev check >that the resource points to the expected magic bytes. > >I've used this technique before, but users complained that the file in >their system folder was modified each time they booted, so it was always >being backed up. Here's my experience in writing TappyType, for what it's worth. . . The first technique I used was the one stated above: the INIT, on startup would store a pointer to my system heap variables in a resource of type "TapT", ID#2 (if I remember correctly). This has the advantage of being more "compatible" than just about any other solution I've heard of, but which has the above disadvantage. Plus, if the user is especially mischievious and does things like: locks the CDEV file, temporarily moves it to another folder, deletes the resource, etc., you've got problems. Using an entire auxilliary file for CDEV-INIT communication is subject to the same problems, and more. Of course, you can argue that anyone pretentious enough to commit any of these crimes against your CDEV deserves what he or she gets. The next method I used -- briefly -- was searching the system heap for a block of the right size, and which began with a particular magic string. After rereading the Memory Manager chapter and various tech notes, however, I soon realized that this is a BAD idea. It relies completely on the format of memory blocks, which very very very probably will change in the future at arbitrary times. I suppose you could search the system heap for a magic string without paying attention to block boundaries, but this still seems rather iffy. The current solution is a bit of a hack, but requires no auxilliary resources, nor installing a driver: The INIT installs the code and variables in system heap memory from a resource (remember to use DetachResource!), and patches a few traps. Among them is _AddResource. For CDEV-INIT communication, I needed a trap which could be called in some way that my patch could uniquely identify as being a call from the CDEV. My patch looks at every AddResource call. If the call is made with a resource of my particular type, my particular ID, if the name pointer points to four bytes of zeros, and if the return address is near a particular magic string, then my patch assumes the call was made by my CDEV. It then puts a pointer to my system heap variables in the four bytes of zeros pointed to by the name pointer, which my CDEV can pick up and use. The patch ends by jumping to the original AddResource address that the INIT found on startup (with NGetTrapAddress). Note that adding a resource which already exists is harmless, so the resource I "add" from the CDEV is just my options resource, which my CDEV has previously loaded anyway. If TappyType has not been installed, then my patch won't be there, and the the four bytes of zeros will remain just that after the call. Otherwise, if it's non-zero, it's a pointer to my system heap variables. To be even more anal-retentive, one could do the following: - check that the handle being added is a resource, and that it's the right size - check to see that the current resource file is of type "cdev" and creator "TapT" (using GetFileInfo) - pass a pointer to four zero bytes as before, but after the four bytes is also a pointer to the magic string; check for it In fact, I like that last one much better, now that I thought of it. I think I'll rewrite it that way for the next version. . . Hope this helps. AddResource is undoubtedly not the only trap you could use; it's just the first feasible one I thought of. The time overhead is low, particularly if you write it in assembly (as one should probably). I invite (constructive) criticism on this method. Anyone from Apple see anything wrong with this? (Anyone from anywhere, for that matter?) ---------------------------------------------------------------------- "May the forces of evil become confused on the way to your house." -- George Carlin Bemusedly, | DISCLAIMER: Colin Klipsch | This text is actually a horrendously UVa Astronomy Department | garbled excerpt from _Mating_Rituals_ Charlottesville, Virginia | of_West_African_Ostriches_, Vol IV, cak3g@virginia.edu | by Davis & Griffin, 1913, p. 137 ____________________________/ \_______________________________________
marykuca@uvicctr.UVic.CA.UUCP (Brent Marykuca) (06/08/90)
It seems to me that all this kludgy-sounding passing around of resources and testing for "magic strings" can be eliminated fairly easily by using the Gestalt Manager, which can be found in all Macintosh systems after 6.0.4, and in glue form in MPW 3.2. Have the INIT use NewGestalt to install a new Gestalt selector function which returns a pointer (or handle, or whatever is required) to the data to be exchanged. Then have the cdev call Gestalt to pick up the handle. If the INIT hasn't been loaded, then Gestalt will return an error. This seems clean (no prefs file cluttering up your System Folder, no validity checking to do on the resource if it is there) and compatible. About the only thing that I can see that is wrong with this approach (and if I've missed anything, I'm certain that somebody will point it out) is that Gestalt is supposed to be used for feature testing, not as a mailbox for data. Cheers, Brent Marykuca Computing User Services University of Victoria
lsr@Apple.COM (Larry Rosenstein) (06/08/90)
In the future the best approach to this will be to use the Gestalt trap. Gestalt will allow one piece of code to register a value under a 4-character ID, and another piece to look up the value associated with the ID. Also, in most cases, the reason for the CDEV/INIT communication is so that changes in the CDEV are immediately reflected in the INIT. That's a nice feature to have, but sometimes it isn't necessary. Larry Rosenstein, Apple Computer, Inc. Object Specialist Internet: lsr@Apple.com UUCP: {nsc, sun}!apple!lsr AppleLink: Rosenstein1
benw@microsoft.UUCP (Ben WALDMAN) (06/09/90)
On cdev-INIT communication: One problem that a lot of the proposed solutions have is that they assume they can write to disk. This won't be the case if the user boots off a locked floppy. The way I do it is to write my what's really my INIT as a driver. Then, the actual INIT resource opens the driver by name, putting into the system heap. (And the driver's open routine patches the traps I want to patch, etc.). The driver also provides a status call, which returns the address of its globals. The cdev, when it wants to communicate with the INIT, can simply look through the unit table (this is described in a tech note), and find the driver (by name). Then, the cdev can make a status call to the driver, and, voila, the status call returns the info the driver needs. In my case, I returned a pointer to the INITs globals (the init is locked in memory), but you could, of course, return a handle, or an address of a function you wanted to call, etc. The scheme fails if a dorky user changes the name of the DRVR resource with ResEdit, but will still succeed if the DRVR gets renumbered. Ben Waldman Software Design Engineer Excel Development Team Microsoft Corp. Disclaimer: These are my thoughts, idea, and opinions, and are in no way, indicative of those of my employer.
lsr@Apple.COM (Larry Rosenstein) (06/09/90)
In article <1121@uvicctr.UVic.CA.UUCP> marykuca@uvicctr.UVic.CA.UUCP (Brent Marykuca) writes: > About the only thing that I can see that is wrong with this approach > (and if I've missed anything, I'm certain that somebody will point it > out) is that Gestalt is supposed to be used for feature testing, not > as a mailbox for data. I don't see anything wrong with using it in the way you suggest. In addition to telling the CDEV that the INIT exists (a feature) it returns information that the CDEV actually uses. Larry Rosenstein, Apple Computer, Inc. Object Specialist Internet: lsr@Apple.com UUCP: {nsc, sun}!apple!lsr AppleLink: Rosenstein1
urlichs@smurf.sub.org (Matthias Urlichs) (06/10/90)
In comp.sys.mac.programmer, article <55103@microsoft.UUCP>,
benw@microsoft.UUCP (Ben WALDMAN) writes:
< On cdev-INIT communication:
< The way I do it is to write my what's really my INIT as a driver.
< Then, the actual INIT resource opens the driver by name, putting into the
< system heap. (And the driver's open routine patches the traps I want to
< patch, etc.). The driver also provides a status call, which returns the
< address of its globals.
<
< The cdev, when it wants to communicate with the INIT, can simply
< look through the unit table (this is described in a tech note), and find
< the driver (by name). Then, the cdev can make a status call to the driver,
When you already know the driver's name, why not do an OpenDriver(name)?
That'll get you its refnum much easier and safer (WRT compatibility).
Apple specifically recommends not to scan the unit table if at all possible.
< and, voila, the status call returns the info the driver needs. In my case,
< I returned a pointer to the INITs globals (the init is locked in memory),
< but you could, of course, return a handle, or an address of a function you
< wanted to call, etc.
<
If you want the driver to do anything, it'd be much cleaner just to call the
driver through _Control and/or _Status calls, no?
That way the whole thing will also work if the user boots with version X of
your driver, then installs Y (not necessarily greater than X), and opens the
control panel...
< The scheme fails if a dorky user changes the name of the DRVR resource
< with ResEdit, but will still succeed if the DRVR gets renumbered.
<
You'll _have_to_ check in the unit table for a free refnum and install your
driver there. You may have to make the unit table bigger; don't forget to zero
the new table, record the new size in the appropriate global, don't free the
old table because you don't know where it came from, and turn off interrupts
while you do it.
--
Matthias Urlichs -- urlichs@smurf.sub.org -- urlichs@smurf.ira.uka.de
Humboldtstrasse 7 - 7500 Karlsruhe 1 - FRG -- +49+721+621127(Voice)/621227(PEP)