home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / pr / src / md / mac / macdll.c next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  9.5 KB  |  362 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /*
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  * 
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  * 
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #undef OLDROUTINENAMES
  20. #define OLDROUTINENAMES 1
  21.  
  22. #include <Files.h>
  23. #include <Errors.h>
  24. #include <Folders.h>
  25. #include <CodeFragments.h>
  26. #include <Aliases.h>
  27.  
  28. #include "MacErrorHandling.h"
  29. #include "primpl.h"
  30. #include "plstr.h"
  31.  
  32. typedef struct CfrgItem CfrgItem, *CfrgItemPtr;
  33. struct CfrgItem 
  34. {
  35.         OSType          fArchType;
  36.         UInt32          fUpdateLevel;
  37.         UInt32             fCurVersion;
  38.         UInt32             fOldDefVersion;
  39.         UInt32          fAppStackSize;
  40.         UInt16          fAppSubFolder;
  41.         UInt8           fUsage;
  42.         UInt8           fLocation;
  43.         UInt32          fCodeOffset;
  44.         UInt32          fCodeLength;
  45.         UInt32          fReserved1;
  46.         UInt32          fReserved2;
  47.         UInt16          fItemSize; // %4 == 0
  48.         Str255          fName;
  49.         // Only make the final p-string as long as needed, then align to
  50.         // a longword boundary
  51. };
  52.  
  53. typedef struct CfrgHeader CfrgHeader, *CfrgHeaderPtr, **CfrgHeaderHandle;
  54. struct CfrgHeader 
  55. {
  56.         UInt32          fReserved1;
  57.         UInt32          fReserved2;
  58.         UInt32          fVersion;
  59.         UInt32          fReserved3;
  60.         UInt32          fReserved4;
  61.         UInt32          fFiller1;
  62.         UInt32          fFiller2;
  63.         UInt32          fItemCount;
  64.         CfrgItem        fCfrgItemArray[1];
  65. };
  66.  
  67. /*
  68.     turds used to iterate through the directories looking
  69.     for the desired library.
  70. */
  71.  
  72. struct GetSharedLibraryFilterProcData
  73. {
  74.     Boolean                inRecursive;
  75.     StringPtr            inName;
  76.     
  77.     Boolean                outFound;
  78.     CFragConnectionID    outID;
  79.     Ptr                    outAddress;
  80.     OSErr                outError;
  81. };
  82. typedef struct GetSharedLibraryFilterProcData GetSharedLibraryFilterProcData;
  83.  
  84. static pascal void
  85. GetSharedLibraryFilterProc(const CInfoPBRec* const inCpb, Boolean* inWantQuit, void *inFilterData);
  86.  
  87.  
  88. /*
  89.     NSGetSharedLibrary
  90.     
  91.     Unfortunately CFM doesn't support user specified loader paths,
  92.     so we emulate the behavior.  Effectively this is a GetSharedLibrary
  93.     where the loader path is user defined.
  94. */
  95.  
  96. extern OSErr
  97. NSGetSharedLibrary(Str255 inLibName, CFragConnectionID* outID, Ptr* outMainAddr)
  98. {
  99.     char*        curLibPath;
  100.     char*        freeCurLibPath;
  101.     OSErr        tempErr;
  102.     Boolean        recursive;
  103.     FSSpec        curFolder;    
  104.     GetSharedLibraryFilterProcData filterData;
  105.     char        *endCurLibPath;
  106.     Boolean        done;
  107.     
  108.     filterData.outFound = false;
  109.     filterData.outID = (CFragConnectionID)(-1);
  110.     filterData.outAddress = NULL;
  111.     filterData.inName = inLibName;
  112.         
  113.     freeCurLibPath = curLibPath = strdup(PR_GetLibraryPath());
  114.     
  115.     if (curLibPath == NULL)
  116.         return (fragLibNotFound);
  117.     
  118.     tempErr = fragLibNotFound;
  119.     
  120.     do
  121.     {
  122.         endCurLibPath = PL_strchr(curLibPath, PR_PATH_SEPARATOR);
  123.         done = (endCurLibPath == NULL);
  124.  
  125. #if 0
  126.         // we overload the first character of a path if it's :
  127.         // then we want to recursively search that path
  128.         // see if path should be recursive
  129.         if (*curLibPath == ':')
  130.         {
  131.             // ':' is an illegal character in the name of a file
  132.             // if we start any path with this, we want to allow 
  133.             // search recursively
  134.             curLibPath++;
  135.             recursive = true;
  136.         }
  137.         else
  138. #endif
  139.         {
  140.             recursive = false;
  141.         }
  142.         
  143.         if (!done)
  144.             *endCurLibPath = '\0';    // NULL terminate the string
  145.         
  146.         // convert to FSSpec
  147.         tempErr = ConvertUnixPathToFSSpec(curLibPath, &curFolder);    
  148.  
  149.         // now look in this directory
  150.         if (noErr == tempErr)
  151.         {
  152.             filterData.inRecursive = recursive;
  153.             FSpIterateDirectory(&curFolder, recursive ? 0 : 1, &GetSharedLibraryFilterProc, &filterData);
  154.             
  155.             if (filterData.outFound)
  156.             {
  157.                 *outID = filterData.outID;
  158.                 *outMainAddr = filterData.outAddress;
  159.                 tempErr = noErr;
  160.                 break;
  161.             }
  162.             else 
  163.             {
  164.                 tempErr = fragLibNotFound;
  165.             }
  166.         }
  167.         
  168.         curLibPath = endCurLibPath + 1;    // skip to next path (past the '\0');
  169.     } while (!done);
  170.  
  171.     free(freeCurLibPath);
  172.     return (tempErr);
  173. }
  174.  
  175.  
  176. static Boolean
  177. LibInPefContainer(const FSSpec* inSpec, StringPtr inName, UInt32* outCodeOffset, UInt32* outCodeLength);
  178.  
  179.  
  180. /*
  181.     GetSharedLibraryFilterProc
  182.     
  183.     Callback to FSpIterateDirectory, finds a library with the name matching the
  184.     data in inFilterData (of type GetSharedLibraryFilterProcData).  Forces a quit
  185.     when a match is found.
  186. */
  187.  
  188. static pascal void
  189. GetSharedLibraryFilterProc(const CInfoPBRec* const inCpb, Boolean* inWantQuit, void *inFilterData)
  190. {
  191.     GetSharedLibraryFilterProcData* pFilterData = (GetSharedLibraryFilterProcData*) inFilterData;
  192.  
  193.     if ((inCpb->hFileInfo.ioFlAttrib & (1 << ioDirFlg)) == 0)
  194.     {
  195.         FSSpec    fragSpec;
  196.         OSErr    tempErr;
  197.         Str255    errName;
  198.         Boolean    crap;
  199.         UInt32    codeOffset;
  200.         UInt32    codeLength;
  201.         
  202.         // it's a file
  203.         
  204.         // Ñ fix-me do we really want to allow all 'APPL's' for in which to find this library?
  205.         switch (inCpb->hFileInfo.ioFlFndrInfo.fdType)
  206.         {
  207.             case kCFragLibraryFileType:
  208.             case 'APPL':
  209.                 tempErr = FSMakeFSSpec(inCpb->hFileInfo.ioVRefNum, inCpb->hFileInfo.ioFlParID, inCpb->hFileInfo.ioNamePtr, &fragSpec);
  210.  
  211.                 // this shouldn't fail
  212.                 if (noErr != tempErr)
  213.                 {
  214.                     return;
  215.                 }
  216.                 
  217.                 // resolve an alias if this was one
  218.                 tempErr = ResolveAliasFile(&fragSpec, true, &crap, &crap);
  219.  
  220.                 // if got here we have a shlb (or app-like shlb)
  221.                 if (noErr != tempErr)
  222.                 {
  223.                     // probably couldn't resolve an alias
  224.                     return;
  225.                 }
  226.         
  227.                 break;
  228.             default:
  229.                 return;
  230.         }
  231.     
  232.         // see if this symbol is in this fragment
  233.         if (LibInPefContainer(&fragSpec, pFilterData->inName, &codeOffset, &codeLength))
  234.             tempErr = GetDiskFragment(&fragSpec, codeOffset, codeLength, pFilterData->inName, kLoadLib, &pFilterData->outID, &pFilterData->outAddress, errName);
  235.         else
  236.             return;
  237.                 
  238.         // stop if we found a library by that name
  239.         if (noErr == tempErr)
  240.         {            
  241.             *inWantQuit = true;
  242.             pFilterData->outFound = true;
  243.             pFilterData->outError = tempErr;
  244.         }
  245.     }
  246.     // FSpIterateDirectory will automagically call us for subsequent sub-dirs if necessary
  247. }
  248.  
  249.  
  250. /*
  251.     LibInPefContainer
  252.     
  253.     Tell whether library inName is contained it the file pointed to by inSpec.
  254.     Return the codeOffset and codeLength information, for a subsequent
  255.     call to GetDiskFragment.
  256. */
  257.  
  258. static Boolean
  259. LibInPefContainer(const FSSpec* inSpec, StringPtr inName, UInt32* outCodeOffset, UInt32* outCodeLength)
  260. {
  261.     short                refNum;
  262.     CfrgHeaderHandle    hCfrg;
  263.     CfrgItem*            pCurItem;
  264.     UInt32                curLibIndex;
  265.     Boolean                found;
  266.     
  267.     // asume we didn't find it
  268.     found = false;
  269.     
  270.     // open the resource fork, if we can't bail
  271.     refNum = FSpOpenResFile(inSpec, fsRdPerm);
  272.     require(-1 != refNum, Exit);
  273.     
  274.     // grab out the alias record, if it's not there bail
  275.     hCfrg = (CfrgHeaderHandle) Get1Resource(kCFragResourceType, kCFragResourceID);
  276.     require(NULL != hCfrg, CloseResourceAndExit);
  277.     
  278.     HLock((Handle)hCfrg);
  279.     
  280.     // get ptr to first item
  281.     pCurItem = &(*hCfrg)->fCfrgItemArray[0];
  282.     for (curLibIndex = 0; curLibIndex < (*hCfrg)->fItemCount; curLibIndex++)
  283.     {
  284.         // is this our library?
  285.         if ((pCurItem->fName[0] == inName[0]) &&
  286.             (strncmp((char*) inName + 1, (char*) pCurItem->fName + 1, PR_MIN(pCurItem->fName[0], inName[0])) == 0))
  287.         {
  288.             *outCodeOffset = pCurItem->fCodeOffset;
  289.             *outCodeLength = pCurItem->fCodeLength;
  290.             found = true;
  291.         }
  292.         
  293.         // skip to next one
  294.         pCurItem = (CfrgItem*) ((char*) pCurItem + pCurItem->fItemSize);                        
  295.     }
  296.     
  297.     HUnlock((Handle)hCfrg);
  298.     
  299. CloseResourceAndExit:
  300.     CloseResFile(refNum);
  301. Exit:
  302.     return (found);
  303.  
  304. }
  305.  
  306.  
  307. /*
  308.     NSFindSymbol
  309.     
  310.     Workaround bug in CFM FindSymbol (in at least 7.5.5) where symbols with lengths
  311.     greater than 63 chars cause a "paramErr".  We iterate through all symbols
  312.     in the library to find the desired symbol.
  313. */
  314.  
  315. extern OSErr
  316. NSFindSymbol(CFragConnectionID inID, Str255 inSymName, Ptr*    outMainAddr, SymClass *outSymClass)
  317. {
  318.     OSErr    err;
  319.     
  320.     if (inSymName[0] > 63)
  321.     {
  322.         /* 
  323.             if there are greater than 63 characters in the
  324.             name, CFM FindSymbol fails, so let's iterate through all
  325.             of the symbols in the fragment and grab it 
  326.             that way.
  327.         */
  328.         long     symbolCount;
  329.         Str255    curSymName;
  330.         long    curIndex;
  331.         Boolean found;
  332.         
  333.         found = false;
  334.         err = CountSymbols(inID, &symbolCount);
  335.         if (noErr == err)
  336.         {
  337.             /* now iterate through all the symbols in the library */
  338.             /* per DTS the indices apparently go 0 to n-1 */
  339.             for (curIndex = 0; (curIndex <= symbolCount - 1 && !found); curIndex++)
  340.             {
  341.                 err = GetIndSymbol(inID, curIndex, curSymName, outMainAddr, outSymClass);
  342.                 if (noErr == err && curSymName[0] == inSymName[0] && !strncmp((char*)curSymName + 1, (char*)inSymName + 1, curSymName[0]))
  343.                 {
  344.                     /* found our symbol */
  345.                     found = true;
  346.                 }
  347.             }
  348.             
  349.             /* if we didn't find it set the error code so below it won't take this symbol */
  350.             if (!found)
  351.                 err = fragSymbolNotFound;
  352.         }    
  353.     }
  354.     else
  355.     {    
  356.         err = FindSymbol(inID, inSymName, outMainAddr, outSymClass);
  357.     }
  358.     
  359.     return (err);
  360. }
  361.  
  362.