home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Frameworks / Disinfectant 2.4 / Notes / ToolBox Gotchas < prev   
Encoding:
Text File  |  1989-06-09  |  6.3 KB  |  136 lines  |  [TEXT/MPS ]

  1. While devoping Disinfectant I ran into a number of "gotchas" that
  2. caused me great grief.  I thought it would be nice to tell the
  3. rest of you about these problems, in the hope that you'll be able
  4. to avoid them in your own programs.  I've told DTS about most of this stuff.
  5.  
  6. Gotcha #1. Watch out for PBGetCatInfo calls with TOPS.
  7.  
  8. The file manager routine PBGetCatInfo uses a parameter block of type
  9. CInfoPBRec.  Make certain that you pass a pointer to the full parameter 
  10. block when using MPW C, even if you know in advance that the object is a 
  11. directory.  Don't just allocate and pass a pointer to the DirInfo variant.  
  12. The DirInfo variant is four bytes shorter than the full union type, and with
  13. TOPS the PBGetCatInfo call sets those four bytes at the end.  If your 
  14. parameter block is not big enough you'll trash the stack.  
  15.  
  16. Gotcha #2. Make certain you're in the proper heap zone before calling
  17. ReleaseResource.
  18.  
  19. At the bottom of IM II-26, in the Memory Mangler chapter, is the warning 
  20. "Be sure, when calling routines that access blocks, that the zone in which 
  21. the block is located is the current zone."  Heed this warning, especially
  22. when releasing resources.  Bob Hablutzel and I discovered (after hours in 
  23. Macsbug) that on the 128K ROMs, if you try to release an empty (unloaded) 
  24. resource in the system heap, and if you neglect to set the current zone to 
  25. the system zone, then the system will trash the free master pointer list.  
  26. This is not good, and will almost undoubtably lead to subsequent bizarre 
  27. behaviour.
  28.  
  29. Here's the code I use to release a resource:
  30.  
  31.    curZone = GetZone();
  32.    SetZone(HandleZone(theRez));
  33.    ReleaseResource(theRez);
  34.    SetZone(curZone);
  35.     
  36. Gotcha #3. Don't believe Inside Macintosh.
  37.  
  38. On page IM II-34 we read the following warning in the description of the
  39. HandleZone routine: "If handle h is empty (points to a NIL master pointer),
  40. HandleZone returns a pointer to the current heap zone."  This is false -
  41. HandleZone properly returns a pointer to the heap zone that contains the
  42. master pointer.  See Gotcha #2 above.
  43.  
  44. Gotcha #4. Don't expect OpenResFile to do sanity checking.
  45.  
  46. Neither OpenResFile nor OpenRFPerm does any sanity checking of any sort
  47. when opening a resource file.  If the file is damaged or contains trash it
  48. is very possible for the Resource Mangler to bomb or hang inside the
  49. OpenResFile or OpenRFPerm call.  Often what happens is that it makes a
  50. Memory Mangler request for some ridiculously huge block of memory.  If you
  51. have a GrowZone proc this can cause problems.
  52.  
  53. To prevent this problem you must write a sanity checker of your own that
  54. opens the resource file as a binary file and checks at least the most
  55. important structural characteristics of the file.  If your sanity check
  56. fails you must avoid calling OpenResFile or OpenRFPerm on the file.  In
  57. Disinfectant I check that the resource map and resource data are 
  58. within the logical EOF of the file and don't overlap, I check that the
  59. resource type list immediately follows the resource map, and I check that
  60. the resource name list starts within the logical eof.
  61.  
  62. DTS tells me that the only way to be completely safe is to do a complete
  63. sanity check of the entire resource fork - e.g., rewrite the RezDet MPW
  64. tool.
  65.  
  66. Damaged and trashed resource forks are much more common than you might 
  67. think.
  68.  
  69. Gotcha #5. Don't believe Inside Macintosh.
  70.  
  71. In the description of the OpenResFile routine, IM I-115 states "If the
  72. resource file is already open, it doesn't make it the current resource
  73. file; it simply returns the reference number."  This is false.  If the
  74. resource file is already open, OpenResFile in fact DOES make it the 
  75. current resource file.  OpenRFPerm also has the same behaviour, in those
  76. cases where OpenRFPerm returns the reference number of the previously
  77. opened copy of the file, rather than opening a new access path (see
  78. IM IV-17 and TN 185).
  79.  
  80. Gotcha #6. Watch out for Standard File if you unmount volumes.
  81.  
  82. The standard file package keeps track of the last volume it used in the low
  83. core global SFSaveDisk, which contains the negative of the vol ref num of
  84. the last volume used.  If your program unmounts this volume and then later
  85. calls the standard file package again, it will post an alert saying that
  86. "A system error has occurred.  Please try again."  A simple fix for this
  87. problem is to check the vRefNum stored in SFSaveDisk immediately before 
  88. any calls to standard file.  Call PBGetVInfo to see if the volume still
  89. exists.  If it doesn't, make an indexed call to PBGetVInfo to get the 
  90. vRefNum of the first volume in the VCB queue, and set SFSaveDisk to the
  91. negative of this vRefNum.  Also set CurDirStore to fsRtDirID.
  92.  
  93. Gotcha #7. Don't believe Inside Macintosh.
  94.  
  95. IM I-116 states that "When calling the CurResFile and HomeResFile routines,
  96. described below, be aware that for the system resource file the actual
  97. reference number is returned."  This is false.  CurResFile does indeed
  98. return the actual reference number of the system file (2), but 
  99. HomeResFile in fact returns 0 for system file resources.
  100.  
  101. Gotcha #8. Don't believe Inside Macintosh.
  102.  
  103. IM I-126 states "Like the attributes of individual resources, resource file
  104. attributes are specified by bits in the low-order byte of a word."  This
  105. is false.  In fact, the resource file attributes are stored in the
  106. high-order byte of the word.
  107.  
  108. Gotcha #9. Directory IDs are longs, not shorts, stupid.
  109.  
  110. Directory IDs, unlike volume reference numbers and working directory ids,
  111. are longs, not shorts.  Watch out for this one.  It's really easy to 
  112. declare a dirID to be a short by mistake, and unless you're using Modula-2
  113. you probably won't catch the bug even with extensive beta testing.  Don't
  114. feel too stupid if you do this - I have it on good authority that ResEdit
  115. once had this bug!
  116.  
  117. Gotcha #10. Always set the ioNamePtr field in file manager param blocks.
  118.  
  119. See TN 179.  Read it.  Believe it.  Always set ioNamePtr.  Set it to nil
  120. if you don't care about the name.  I made this mistake three times while
  121. developing Disinfectant, and all three times it took FOREVER to find the
  122. bug.  The problem is those silly little arrows in the file manager 
  123. chapter of IM IV.  They all point to the left for ioNamePtr, which usually
  124. means that you don't have to set the field before calling the routine.
  125.  
  126. I hope my experiences help somebody.
  127.  
  128. John Norstad
  129. Academic Computing and Network Services
  130. Northwestern University
  131.  
  132. Bitnet:      jln@nuacc
  133. Internet:    jln@acns.nwu.edu
  134. AppleLink:   a0173
  135. CompuServe:  76666,573
  136.