[comp.sys.mac.programmer] Danger Will Robinson, traps for young player

JON@wehi.dn.mu.oz (Jon Eaves) (08/20/90)

G'day People,
	I have found an interesting little problem with programming in C. I
have found a cure, but I would like to know the 'sanctioned' way to get
around this problem.

I want to extract the UserName from the Chooser. No problems, just use 
tempHandle = GetString(CHOOSERNAME), then how do I get the "string" from
the tempHandle.  The process I was using was
	 strcpy(tempString,PtoCstr((char *)(*tempHandle));
Great, this sets tempString correctly. BUT, the Chooser Name field gets
mangled because the resource handle is now in 'C' string format.
When the application exits, the resource map is saved and the System
becomes unstable (Got the 'Cant Load the Finder', bomb !!)

Now some questions.
1) Why the hell is the handle to the resource attached to that resource?
   Doesn't it make some sort of copy? At no stage do I explicitly use
	ChangedResource(tempHandle);WriteResource(tempHandle);
   Why is it saved then?
   My understanding from IM is that resources will not get saved unless you
   explicitly use the above process.
2) What is the best way to extract stuff from 'tempHandle' so that things
   like that don't happen?  I presume there is a nice 'safe' way of doing
   this.

aTdHvAaNnKcSe....
--------------------------------------------------------------------------------
  Jon Eaves         
	"Quim, don't you ever try to teach me about good and evil. I've
   	 been there and you've seen nothing but the map" - Novinha.
ACSnet    ( jon@wehi.dn.mu.oz )    
UUCP      ( uunet!munnari!wehi.dn.mu.oz!jon )
Internet  ( jon%wehi.dn.mu.oz@uunet.uu.net )
--------------------------------------------------------------------------------

stephen@cs.uow.edu.au (The Mighty Ogbo) (08/20/90)

JON@wehi.dn.mu.oz (Jon Eaves) writes:

>I want to extract the UserName from the Chooser. No problems, just use 
>tempHandle = GetString(CHOOSERNAME), then how do I get the "string" from
>the tempHandle.  The process I was using was
>	 strcpy(tempString,PtoCstr((char *)(*tempHandle));
>Great, this sets tempString correctly. BUT, the Chooser Name field gets
>mangled because the resource handle is now in 'C' string format.
>When the application exits, the resource map is saved and the System
>becomes unstable (Got the 'Cant Load the Finder', bomb !!)

I believe a call to DetachResource() would be useful here. It unlinks
the information in memory from the resource itself. This way you can
go and play with the memory copy quite happily and not accidently screw
your resource.

>  Jon Eaves

|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Stephen Nicholson (The Mighty Ogbo)                stephen@wraith.cs.uow.edu.au
"Rooster of a Fightin' Stock / Would you let a Saecsen cock
Crow out upon an Irish Rock  / Fly up an teach him manners!" - Planxty
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

ccc_ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) (08/20/90)

I don't think it's a good idea calling DetachResource on *any* resource
coming from the System file. Somebody else may have a copy of the resource
handle, and they end up using your (mangled) private copy instead.

If you want a private copy, use HandToHand. This gives you your own
handle, leaving the original resource one untouched.

Lawrence D'Oliveiro                       fone: +64-71-562-889
Computer Services Dept                     fax: +64-71-384-066
University of Waikato            electric mail: ldo@waikato.ac.nz
Hamilton, New Zealand    37^ 47' 26" S, 175^ 19' 7" E, GMT+12:00
Ears pierced while you wait...is there any other way?

russotto@eng.umd.edu (Matthew T. Russotto) (08/20/90)

In article <11591@wehi.dn.mu.oz> JON@wehi.dn.mu.oz (Jon Eaves) writes:
>I want to extract the UserName from the Chooser. No problems, just use 
>tempHandle = GetString(CHOOSERNAME), then how do I get the "string" from
>the tempHandle.  The process I was using was
>	 strcpy(tempString,PtoCstr((char *)(*tempHandle));
>Great, this sets tempString correctly. BUT, the Chooser Name field gets
>mangled because the resource handle is now in 'C' string format.
>When the application exits, the resource map is saved and the System
>becomes unstable (Got the 'Cant Load the Finder', bomb !!)
>
>Now some questions.
>1) Why the hell is the handle to the resource attached to that resource?

You would have to ask an oldtimer@apple.com, but my guess would be MEMORY--
making copies each time you call GetString is expensive, especially in 128K.

>   Doesn't it make some sort of copy? At no stage do I explicitly use
>	ChangedResource(tempHandle);WriteResource(tempHandle);
>   Why is it saved then?

It may not be-- it may only be changed until you reboot-- remember that there
is only one resource handle for all applications that use the string.

>2) What is the best way to extract stuff from 'tempHandle' so that things
>   like that don't happen?  I presume there is a nice 'safe' way of doing
>   this.

strncpy(tempString,((char *)(*tempHandle)) + 1,
	 (size_t)(*(unsigned char *)(*tempHandle)));
tempString[*(unsigned char *)(*tempHandle)] = '\0';
--
Matthew T. Russotto	russotto@eng.umd.edu	russotto@wam.umd.edu
][, ][+, ///, ///+, //e, //c, IIGS, //c+ --- Any questions?

russotto@eng.umd.edu (Matthew T. Russotto) (08/20/90)

In article <1990Aug20.033702.5883@cs.uow.edu.au> stephen@cs.uow.edu.au (The Mighty Ogbo) writes:
>JON@wehi.dn.mu.oz (Jon Eaves) writes:
>
>>I want to extract the UserName from the Chooser. No problems, just use 
>>tempHandle = GetString(CHOOSERNAME), then how do I get the "string" from
>>the tempHandle.  The process I was using was
>
>I believe a call to DetachResource() would be useful here. It unlinks
>the information in memory from the resource itself. This way you can
>go and play with the memory copy quite happily and not accidently screw
>your resource.

I think it would be bad to call DetachResource on a shared resource-- other
applications using the handle might get messed up.
--
Matthew T. Russotto	russotto@eng.umd.edu	russotto@wam.umd.edu
][, ][+, ///, ///+, //e, //c, IIGS, //c+ --- Any questions?

pepke@gw.scri.fsu.edu (Eric Pepke) (08/20/90)

void pstrcpy(s2, s1)
unsigned char *s2, *s1;
/*Copies a pascal string from s1 to s2*/
{
    register int n;
    n = *s1;
    do
    {
        *s2++ = *s1++;
    } while (n--);
}

It's not optimized for speed, but so what.

Eric Pepke                                    INTERNET: pepke@gw.scri.fsu.edu
Supercomputer Computations Research Institute MFENET:   pepke@fsu
Florida State University                      SPAN:     scri::pepke
Tallahassee, FL 32306-4052                    BITNET:   pepke@fsu

Disclaimer: My employers seldom even LISTEN to my opinions.
Meta-disclaimer: Any society that needs disclaimers has too many lawyers.

philip@pescadero.Stanford.EDU (Philip Machanick) (08/21/90)

In article <1990Aug20.143025.2160@eng.umd.edu>, russotto@eng.umd.edu
(Matthew T. Russotto) writes:
> It may not be-- it may only be changed until you reboot-- remember that there
> is only one resource handle for all applications that use the string.
Clarification please. If the resource is loaded into the system heap, this may
be true, but don't the resource loading traps treat requests from different
applications independently (1 resource map per application zone)?

Philip Machanick
philip@pescadero.stanford.edu

rmh@apple.com (Rick Holzgrafe) (08/21/90)

[I hope this isn't being posted twice - if so, I apologize. The mailer
hiccuped the first time and I don't know if it went out or not.]

In article <11591@wehi.dn.mu.oz> JON@wehi.dn.mu.oz (Jon Eaves) writes:
> I want to extract the UserName from the Chooser. No problems, just use 
> tempHandle = GetString(CHOOSERNAME), then how do I get the "string" from
> the tempHandle.  The process I was using was
>          strcpy(tempString,PtoCstr((char *)(*tempHandle));
> Great, this sets tempString correctly. BUT, the Chooser Name field gets
> mangled because the resource handle is now in 'C' string format.
> When the application exits, the resource map is saved and the System
> becomes unstable (Got the 'Cant Load the Finder', bomb !!)

I doubt if the resource is being changed on disk. But the chooser name 
resource is probably in the System Heap, where it will stay even after 
your app exits, and be shared by any other apps (including Finder) that 
look for it. Rebooting should "unmangle" it, because the disk copy will 
still be OK.

> Now some questions.
> 1) Why the hell is the handle to the resource attached to that resource?
>    Doesn't it make some sort of copy? At no stage do I explicitly use
>         ChangedResource(tempHandle);WriteResource(tempHandle);
>    Why is it saved then?
>    My understanding from IM is that resources will not get saved unless 
you
>    explicitly use the above process.

You're right, it doesn't get saved - but as I said above, it gets shared 
until reboot.

In article <11591@wehi.dn.mu.oz> JON@wehi.dn.mu.oz (Jon Eaves) writes:
> 2) What is the best way to extract stuff from 'tempHandle' so that things
>    like that don't happen?  I presume there is a nice 'safe' way of doing
>    this.

Any number of things you can do. Given your sample code, the simplest is 
probably:
     BlockMove ((Ptr)(*tempHandle), tempString, GetHandleSize(tempHandle));
     PtoCstr(tempString);
(Or you could just do a CtoPstr on (char *)(*tempHandle) after the strcpy 
you are currently using, to restore the original to its pristine state. 
But I prefer my code, since it leaves no little "windows of opportunity" 
for other code, say some asynchronous networking routine, to come along at 
just the wrong instant and find your temporarily-mangled handle.)

I don't recommend strncpy over BlockMove unless you lock the handle down 
first; calling a library routine can move memory and invalidate the 
pointer you just got from the de-referenced handle.

Hope this helps.

==========================================================================
Rick Holzgrafe              |    {sun,voder,nsc,mtxinu,dual}!apple!rmh
Software Engineer           | AppleLink HOLZGRAFE1          rmh@apple.com
Apple Computer, Inc.        |  "All opinions expressed are mine, and do
20525 Mariani Ave. MS: 3-PK |    not necessarily represent those of my
Cupertino, CA 95014         |        employer, Apple Computer Inc."

minow@mountn.dec.com (Martin Minow) (08/21/90)

Here's a simple Pascal string copy:

    #define pstrcpy(dst, src)	\
	BlockMove((src), (dst), ((unsigned char *)(src))[0] + 1)

Note that "src" may not have side-effects: "pstrcpy(dst, *foo++)" will
fail.  Writing a concatenator is a bit more difficult as you have to
make sure you don't overflow the 255 byte limit.

You'll find source for useful Pascal string functions in the Think C
libraries (look in the Class library if you don't find anything in the
normal library).

Martin Minow
minow@bolt.enet.dec.com

d88-jwa@dront.nada.kth.se (Jon W{tte) (08/22/90)

In article <1990Aug20.143025.2160@eng.umd.edu> russotto@eng.umd.edu (Matthew T. Russotto) writes:
>>1) Why the hell is the handle to the resource attached to that resource?

Use DetachResource() !

>>2) What is the best way to extract stuff from 'tempHandle' so that things
>>   like that don't happen?  I presume there is a nice 'safe' way of doing
>>   this.

>strncpy(tempString,((char *)(*tempHandle)) + 1,
>	 (size_t)(*(unsigned char *)(*tempHandle)));
>tempString[*(unsigned char *)(*tempHandle)] = '\0';

WARNING ! Lock the handles first !!!!!! (And unlock them after, or, better
yet, use HGetState() and HSetState())

What I would do is use HandToHand.

							h+

	Jon W{tte, Stockholm, Sweden, h+@nada.kth.se

rmh@apple.com (Rick Holzgrafe) (08/22/90)

In article <1990Aug20.193639.7986@Neon.Stanford.EDU> 
philip@pescadero.Stanford.EDU (Philip Machanick) writes:
> In article <1990Aug20.143025.2160@eng.umd.edu>, russotto@eng.umd.edu
> (Matthew T. Russotto) writes:
> > It may not be-- it may only be changed until you reboot-- remember 
that there
> > is only one resource handle for all applications that use the string.
> Clarification please. If the resource is loaded into the system heap, 
this may
> be true, but don't the resource loading traps treat requests from 
different
> applications independently (1 resource map per application zone)?
> 
> Philip Machanick
> philip@pescadero.stanford.edu

If your app opens a resource file explicitly, yes. Your app's own resource 
fork, yes. These are private copies in your own application heap. But the 
System resource map is shared among all running apps. The map is kept in 
the System heap and is unique. (Imagine the chaos if two apps made 
differing changes to private copies of the system resource map, and then 
wrote them out.)

==========================================================================
Rick Holzgrafe              |    {sun,voder,nsc,mtxinu,dual}!apple!rmh
Software Engineer           | AppleLink HOLZGRAFE1          rmh@apple.com
Apple Computer, Inc.        |  "All opinions expressed are mine, and do
20525 Mariani Ave. MS: 3-PK |    not necessarily represent those of my
Cupertino, CA 95014         |        employer, Apple Computer Inc."

russotto@eng.umd.edu (Matthew T. Russotto) (08/22/90)

In article <1990Aug20.193639.7986@Neon.Stanford.EDU> philip@pescadero.stanford.edu writes:
>In article <1990Aug20.143025.2160@eng.umd.edu>, russotto@eng.umd.edu
>(Matthew T. Russotto) writes:
>> It may not be-- it may only be changed until you reboot-- remember that there
>> is only one resource handle for all applications that use the string.
>Clarification please. If the resource is loaded into the system heap, this may
>be true, but don't the resource loading traps treat requests from different
>applications independently (1 resource map per application zone)?

Yes, however, it is only possible for one application to have write permission
to a resource file, and if one application writes to a resource file that
another is using read-only, the system can crash (apple has a technote on
doing that).  

In any case, the System resource map is always in the system heap, and shared
by all applications.
--
Matthew T. Russotto	russotto@eng.umd.edu	russotto@wam.umd.edu
][, ][+, ///, ///+, //e, //c, IIGS, //c+ --- Any questions?

rmh@apple.com (Rick Holzgrafe) (08/23/90)

In article <1990Aug21.181707.19112@nada.kth.se> d88-jwa@dront.nada.kth.se 
(Jon W{tte) writes:
> In article <1990Aug20.143025.2160@eng.umd.edu> russotto@eng.umd.edu 
(Matthew T. Russotto) writes:
> >>1) Why the hell is the handle to the resource attached to that 
resource?
> 
> Use DetachResource() !

Um, don't use DetachResource for a resource from the System file. It's 
shared, you could screw up somebody else (like the System). Use 
HandToHand, as many have suggested, if you need a handle to a private, 
unattached copy.

==========================================================================
Rick Holzgrafe              |    {sun,voder,nsc,mtxinu,dual}!apple!rmh
Software Engineer           | AppleLink HOLZGRAFE1          rmh@apple.com
Apple Computer, Inc.        |  "All opinions expressed are mine, and do
20525 Mariani Ave. MS: 3-PK |    not necessarily represent those of my
Cupertino, CA 95014         |        employer, Apple Computer Inc."

ts@cup.portal.com (Tim W Smith) (09/14/90)

You could call CtoPstr after the strcpy is done to fix the
string.

					Tim Smith