/* File: Thing Manager.c Copyright: © 1990-1993 by Apple Computer, Inc., all rights reserved. Change History (most recent first): 11/29/93 JDR When cloning a component, need to preserve the flag determining if it's a PowerPC code fragment. 9/23/93 JDR If ResolveCodeFragment fails, return a nil address. When searching the ComponentPlatformInfo, need to increment the pointer to the next entry. __LoadComponent needs to test for a nil rtRoutineHandle. 8/9/93 JDR Warnings were not available in SuperMario builds, so after fixing that I found the Gestalt proc didn't set the OSErr result. Removed some Cyclone ROM hacks from RegisterROMComponents. 8/5/93 JDR integrate component mgr from reality <20+> 7/26/93 JDR fix problems <20> 7/21/93 JDR Needed to move the #if ForROM to always allow the _RegisterRomComponents symbol to be compiled into the object file (for the LinkPatchTool). <19> 7/21/93 JDR Added _RegisterRomComponents. Corrected Gestalt interfaces. Used kComponentResourceType constant. <18> 7/20/93 DTY Get rid of some unused variables. <17> 7/16/93 JDR Added SupportNativeComponents. Fixed InitComponentManager to ignore the cut back address. 7/13/93 CSS Fix conditionals involving POWER_PC_NATIVE_QT since this is a feature and will be defined if the feature is off (but will be =0) 7/7/93 RC moved around a couple of the #ifdefs for the native component support to kill some compile time warnings <14> 7/2/93 IH Reality Update: Change Gestalt call to use SelectorFunctionProcPtr. Correct prototype of ThingyGestalt to take long*. 6/23/93 CSS Conditionalized RegisterHandleTrashNotification call out until we figure out why the trap isn't available. Update from Reality: <16> 6/13/93 JDR Rolled in the ComponentMgr sources from QuickTime 1.6. <15> 1/20/93 DTY MFPrivate is now ProcessesPriv. 6/14/93 kc Roll in Ludwig. 1/4/93 fau Modified RegisterFromROMResource to set a flag in slot 0 PRAM so that components could check whether they are being opened just to be registered. This flag should really be in ExpandMem or something but... 12/10/92 DH Updated RegisterComponentROMResource routine to call GetSystemThenROMRes routine to search in gibbley then rom for thng associated resources. 11/16/92 CSS Update from Reality: <14> 11/13/92 JDR I misspelled kComponentInitialTableEntries. <13> 11/12/92 JDR rolled in QuickTime 1.5 bug fixes. Fixed a problem with LoadComponent under low memory conditions to not rob the system heap beyond the emMinSysHeapFreeSpace amount. Fixed a deferenced handle problem in RegisterComponent. Created kComponentInitialTableEntries which was set to 32 entries in System 7.1, but I cut it back to only 16 to help save some RAM for the general user. 11/10/92 CSS Update from Reality: <12> 10/28/92 DTY Use new Get/Set macro pairs for ExpandMem access. 7/29/92 CSS On the last change I forgot to remove a procedure, CheckSysHeapSlop(), that is no longer called, and other cleanup. 7/14/92 CSS I missed some of the changes for <11>. 7/7/92 CSS Update from Reality: <11> 7/1/92 JH #1033507,1033505 : Remove check for sysheap slop so real components can be opened in the application heap. We will move this check to TSM which opens unreal components that like to do things like allocate 200K of the system heap for themselves. 7/6/92 fau Blew away to put in the two new routines that Bruce Leak wrote to search components in ROM: RegisterRomComponents and RegisterComponentRomResource. This probably affected changes. 7/1/92 RB Make the routine LoadComponent look for resources also in ROM. Let resources be found in ROM when the resource file being scanned is 0, meaning the system file. 6/29/92 RB Allow component resources to be in ROM by setting MapTrue in ROMMapInsert <10> 2/6/92 JH #1018985, RegisterComponentResource locks the component resource registers it, and then unlocks it. Unfortunately, the dereferenced handle is used down below and some memory calls are made before it gets used. Changing the code so it just uses the handle rather than the dereferenced handle. <9> 12/12/91 DTY Get rid of the spaces in the file names <8> 12/6/91 YK Removed System6 conditionals. Object compare identical to <7>. <7> 12/5/91 YK Rolled in QuickTime GM: BAL make it compile BAL return the componentID in the componentFlagsMask field in order to guarantee uniqueness from GetComponentInfo BAL When growing the component table, make sure the component instance table is at least as big as the component table so that if a component ID is used to index into the instance table it will look at known signature values which will never match instead of random heap blocks which may. KIP put strings and icons in app heap for local components. also start with 32 entry table. KIP don't check for system heap slop if getresource failed. KIP move component high in app heap before locking KIP make sure that rtRoutine is zero when the component is not loaded BAL now zeros rtRoutine pointer when the component is unloaded to prevent spurious unregistrations. <6> 12/4/91 YK Do more reliable checking for the System heap slop. <5> 11/23/91 YK Check the System heap free space after every open call. <4> 10/30/91 YK Moved CompopnentSearch call to ComponentMgrInstall proc so that InitComponentManager will not search files. <3> 10/29/91 YK Added missing ComponentSearch call so that 'thng' files in the Extensions folder will be registered at startup. It was lost when rolled in. <2> 10/29/91 YK Conditionalized code for System 6. Replace them with System 7 traps. <46> 10/15/91 MD install gestalt proc <45> 10/15/91 MD don't dereference ResLoad twice in RegisterComponentResourceFile <44> 10/11/91 BAL Patch into to RsrcZoneInit to know when zones are going away at init time. Multifinder doesn't call this through the trap. <43> 10/2/91 BAL Torch components which are registered locally when their a5 world is destroyed even if they aren't loaded. <42> 10/1/91 BAL cast everything so peter doesn't have to. <41> 10/1/91 BAL Added RegisterComponentResourceFile and its support stuff. <40> 9/29/91 PH stop DestroyComponent from looping forever <39> 9/25/91 BAL Now happy about loading components in the app heap if there isn't enough system heap. <38> 9/21/91 BAL Deals with low or no system heap better. Now leaves a free space cushion in the system heap. <37> 9/2/91 BAL Grow default size of instance table to avoid the statistically possible crash which festers mark. <36> 8/28/91 BL make it compile <35> 8/28/91 BAL Added OpenDefaultComponent for your convenience. <34> 7/24/91 BAL Change open to set flag for fast dispatch things. <33> 7/10/91 JW return appropriate errors <32> 7/7/91 BL Remove compiler warnings <31> 7/2/91 PH to compile again <30> 7/2/91 JW Change result of OpenComponentResFile from OSErr to refnum <29> 5/18/91 dvb Thing->Component <28> 5/6/91 BAL add a valid thing check to set default thing <27> 5/3/91 MK fix flag masking in findnextmatchingthing <26> 5/2/91 BAL Send register message to those who request it. If loading in system heap fails then try app heap--if that succeeds clone off a local copy of the thing. <25> 4/24/91 BAL conditionalized debugger breaks <24> 4/19/91 BAL fix setDefaultThing return value and FindNextCommonThingInstance(0,x,x). <23> 4/18/91 BAL Got rid of when and self from thingParams. Now pass self as a param to Open and Close. <22> 4/16/91 JB Moved param defs into proc call so that they will be used as prototypes <21> 4/15/91 JB Fixed testing of flags within SetDefaultThing <20> 4/15/91 JB SetDefaultThing was passing a struct instead of a ptr to an internal routine <19> 4/14/91 BAL reordered the flags to SetDefaultThing. <18> 4/14/91 BAL <18> 4/14/91 BAL Replaced some of the Debugger's with DebugStr's. <17> 4/14/91 BAL Fixed countThings so that it actually works. <16> 4/11/91 MK fix countthings and do loadresource <15> 4/11/91 MK fix countthings and do loadresource <14> 4/3/91 dvb CallThing needed return value to avoid warning. <13> 4/1/91 MK put rtRefNum and flags mask back to be separate <12> 3/28/91 PH fixing closething again... <11> 3/28/91 PH CloseThing was not calling the Thing with storage <10> 3/28/91 KD Add the dummy proc CallThing{}. <9> 3/28/91 BAL Do some file management. Support Capture, Chain, and Default. <8> 2/23/91 BAL Close all things at Re-install time. <7> 2/21/91 MK slime some globals for codec manager <6> 2/18/91 BAL Fix KillHeapThingInstances to check to see if the instance is active first. <5> 2/16/91 BAL Added InitThingManager call. <4> 2/11/91 BAL Fixed bug in ValidThingInstance which compared against #instances used not available. <3> 2/5/91 MK fix destroy thing to not remove from list <2> 1/31/91 MK fix heap zone in register thing <3> 12/30/90 bal changed name to thing manager <2> 10/06/90 dvb Make it work To Do: Proper use of warhol globals */ /* Movies Thing Manager by Bruce Leak, David Van Brink, Jim Batson, Mark Krueger, Peter Hoddie Copyright 1990 Apple Computer, Inc. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef applec // #define tLINKED #endif #include "PrivateThingManager.h" #ifdef SupportNativeComponents #include "FragLoad.h" #endif #ifdef applec extern long OLDPMGR; extern char PMANAGEREXITCHAIN; extern long OLDRSRC; extern char RSRCZONEINITCHAIN; extern pascal short ThingyGestalt(OSType selector, long* responsePtr); #endif #pragma parameter __D0 CoolReplaceGestalt(__D0,__A0) pascal OSErr CoolReplaceGestalt(OSType selector,SelectorFunctionProcPtr selectorFunction) = {0xA5AD}; #pragma parameter __A0 rHandToHand(__A0) Handle rHandToHand(Handle theHndl) = {0xA9E1,0x31c0,0x0220}; pascal void __InitComponentManager(Ptr *cutBackAddress); pascal long __ComponentManagerVersion(void); pascal OSErr __GrowRegisteredComponentInstanceTable( short growCount ); pascal OSErr __GrowRegisteredComponentTable( short growCount ); pascal long __GetComponentListModSeed(void); long RegisteredComponentPointerToComponentID(RegisteredComponent *rt); RegisteredComponent *ComponentIDtoRegisteredComponentPointer(long t); RegisteredComponent *FindMatchingComponent(ComponentDescription *td, RegisteredComponent *rtList); pascal long __CountComponents(ComponentDescription *td); pascal long CountSame(RegisteredComponent *new); RegisteredComponent *FindPreviousMatchingComponent(ComponentDescription *td, RegisteredComponent *rtList); pascal Component __RegisterComponent(ComponentDescription *td, ComponentRoutine ComponentEntryPoint, short global, Handle ComponentName, Handle ComponentInfo, Handle ComponentIcon); pascal Component __RegisterComponentResource(ComponentResource **htr, short global); pascal long __RegisterComponentResourceFile(short resRefNum, short global); pascal RegisteredComponentInstancePtr __ValidComponentInstance(ComponentInstance aComponentInstance); pascal RegisteredComponentPtr __ValidComponent(Component aComponent); int RemoveRTFromList(RegisteredComponent *rt, RegisteredComponent **pRTList); pascal OSErr __UnregisterComponent(Component aComponent); pascal OSErr __SetDefaultComponent(Component aComponent, short flags); pascal Component __CaptureComponent(Component slave, Component master); pascal OSErr __UncaptureComponent(Component aComponent); pascal short __OpenComponentResFile(Component aComponent); pascal OSErr __CloseComponentResFile(short refnum); RegisteredComponentInstance *ComponentInstanceIDToComponentInstancePointer(long t); long ComponentInstancePointerToComponentInstanceID(RegisteredComponentInstance *rti); pascal long __CountComponentInstances(Component aComponent); pascal RegisteredComponent *CloneComponent(long componentID, short global); pascal long __LoadComponent(long componentID); pascal OSErr __UnloadComponent(long componentID); pascal ComponentInstance FindNextCommonComponentInstance(ComponentInstance aComponentInstance, Component aComponent, ComponentRoutine entryPoint); pascal OSErr __DestroyComponent(Component aComponent); pascal RegisteredComponent *DestroyOlder( register RegisteredComponent *new, long version ); void KillHeapComponentInstances(Ptr heapStart, Ptr heapEnd); void KillHeapComponents(Ptr heapStart, Ptr heapEnd); pascal void __CleanUpApplicationComponents(void); pascal Component __FindNextComponent(long previousComponent, ComponentDescription *td); void HandToXHand(Handle srcHandle, Handle dstHandle); pascal OSErr __GetComponentInfoPrivate( Component aComponent, Handle nameHand, Handle infoHand, Handle iconHand ); pascal OSErr __GetComponentInfo(Component aComponent, ComponentDescription *td, Handle nameHand, Handle infoHand, Handle iconHand); pascal long __GetComponentRefcon(long aComponent); pascal void __SetComponentRefcon(long aComponent, long theRefcon); pascal OSErr __GetComponentInstanceError(long aComponentInstance); pascal void __SetComponentInstanceError(long aComponentInstance, OSErr theError); pascal Handle __GetComponentInstanceStorage(long aComponentInstance); pascal void __SetComponentInstanceStorage(long aComponentInstance, Handle theStorage); pascal long __GetComponentInstanceA5(long aComponentInstance); pascal void __SetComponentInstanceA5(long aComponentInstance, long theA5); pascal ComponentInstance __OpenComponent(long componentID); pascal OSErr __CloseComponent(ComponentInstance componentInstanceID); pascal ComponentInstance __OpenDefaultComponent(OSType componentType, OSType componentSubType); pascal ComponentResult __CallComponent(void); pascal void __ComponentSearch(void); RegisteredComponentInstance *FindNextComponentInstance( register RegisteredComponentInstance *rti, register RegisteredComponent *rt ); static pascal void ThingMemoryTrashed(Ptr startAddr, Ptr stopAddr); pascal long goComponentOpen( long theComponent, long self ) = ComponentCallNow( kComponentOpenSelect, 4); pascal long goComponentClose(long theComponent, long self ) = ComponentCallNow( kComponentCloseSelect,4); pascal long goComponentRegister(long theComponent ) = ComponentCallNow( kComponentRegisterSelect,0); pascal long goComponentUnregister(long theComponent ) = ComponentCallNow( kComponentUnregisterSelect,0); // Gestalt proc for returning the version of the installed Component Mgr pascal OSErr GestaltComponentMgrVersion(OSType selector, long* responsePtr) { #pragma unused (selector) *responsePtr = ComponentManagerVersion(); return (noErr); } //#ifdef tLINKED void KillHeapComponents(Ptr heapStart, Ptr heapEnd); pascal long __ComponentManagerVersion(void) { return 3; } Handle fixHandle(register Handle h) { if (h == 1) h = 0; return h; } #ifdef SupportNativeComponents pascal void * ResolveCodeFragment(RegisteredComponentPtr rt) { Str255 errStr; Ptr mainAddr; THz oldZone; OSErr err; #ifdef WARHOL_DEBUG Handle nameHand; nameHand = NewHandle(0); if (nameHand == nil) return (0); err = GetComponentInfo(RegisteredComponentPointerToComponentID(rt), nil, nameHand, nil, nil); if (err != noErr) { DebugStr("\pno info"); DisposeHandle(nameHand); goto bail; } HLock(nameHand); #endif oldZone = GetZone(); SetZone(SystemZone()); #ifdef WARHOL_DEBUG err = GetMemFragment(*rt->rtRoutineHandle,0,*nameHand,kLoadNewCopy,&rt->rtConnectionID,&mainAddr,errStr); #else err = GetMemFragment(*rt->rtRoutineHandle,0,"\pComponent",kLoadNewCopy,&rt->rtConnectionID,&mainAddr,errStr); #endif SetZone(oldZone); #ifdef WARHOL_DEBUG DisposeHandle(nameHand); #endif if (err != noErr) { #ifdef WARHOL_DEBUG DebugStr(errStr); #endif return (nil); } bail: return (mainAddr); } #endif pascal OSErr __GrowRegisteredComponentTable( short growCount ) /* * Grow the table of registered components. String the new entries onto the free list. * Since the table moved, all absolute references to entries in the registered * component table must be relocated--including the rtNext chaining links. * Interrupts need not be disabled as long as the old table is kept intact and used until * the new one is finished. If the table were a handle and SetHandleSize were used then * interrupts would have to be disabled across the bulk of this routine. */ { register RegisteredComponent *aTable; RegisteredComponent *oldTable, *newTable, *freeChain; long oldTableSize; oldTableSize = ComponentManagerGlobals->rtTableEntryCount * sizeof(RegisteredComponent); oldTable = ComponentManagerGlobals->rtTable; newTable = aTable = (RegisteredComponent *)NewPtrSysClear( oldTableSize + (long)growCount * sizeof(RegisteredComponent)); #ifdef WARHOL_DEBUG if (!aTable) DebugStr("\pCould not expand component table"); #endif if (!aTable) return MemError(); BlockMove((Ptr)oldTable, (Ptr)aTable, oldTableSize); { register short i; register long offset; offset = (char *)newTable - (char *)oldTable; for(i = 0; irtTableEntryCount; i++) /* relocate old entries' next & parent links */ { if (aTable->rtNext) aTable->rtNext = (RegisteredComponent *)((char *)aTable->rtNext + offset); if (aTable->rtParent) aTable->rtParent = (RegisteredComponent *)((char *)aTable->rtParent + offset); aTable++; } /* Relocate the back pointers in the componentInstanceList as well */ { register RegisteredComponentInstance *rti; rti = ComponentManagerGlobals->rtInstanceTable; i = ComponentManagerGlobals->rtInstanceTableTotalCount; for(--i; i >= 0; --i) { if (rti->rtiEntry) rti->rtiEntry = (RegisteredComponent *)((char *)rti->rtiEntry + offset); rti++; } } if (ComponentManagerGlobals->rtUsedChain) /* relocate used chain */ ComponentManagerGlobals->rtUsedChain = (RegisteredComponent *)((char *)ComponentManagerGlobals->rtUsedChain + offset); freeChain = ComponentManagerGlobals->rtFreeChain; /* relocate and save current free chain */ if (freeChain) freeChain = (RegisteredComponent *)((char *)freeChain + offset); ComponentManagerGlobals->rtFreeChain = aTable; /* start free chain with new entries */ for(i = 1; irtNext = aTable+1; aTable++; } aTable->rtNext = freeChain; /* hook previous free chain on to the end */ } ComponentManagerGlobals->rtTable = newTable; /* begin using new table */ ComponentManagerGlobals->rtTableEntryCount += growCount; if (oldTable) DisposPtr((Ptr)oldTable); /* dump the old one */ if (ComponentManagerGlobals->rtTableEntryCount > ComponentManagerGlobals->rtInstanceTableTotalCount) GrowRegisteredComponentInstanceTable( ComponentManagerGlobals->rtTableEntryCount - ComponentManagerGlobals->rtInstanceTableTotalCount); return 0; } pascal OSErr __GrowRegisteredComponentInstanceTable( short growCount ) /* * Grow the table of registered component instances. * Interrupts need not be disabled as long as the old table is kept intact and used until * the new one is finished. If the table were a handle and SetHandleSize were used then * interrupts would have to be disabled across the bulk of this routine. */ { register RegisteredComponentInstance *aTable; RegisteredComponentInstance *oldTable, *newTable; long oldTableSize; oldTableSize = ComponentManagerGlobals->rtInstanceTableTotalCount * sizeof(RegisteredComponentInstance); oldTable = ComponentManagerGlobals->rtInstanceTable; newTable = aTable = (RegisteredComponentInstance *)NewPtrSysClear( oldTableSize + (long)growCount * sizeof(RegisteredComponentInstance)); #ifdef WARHOL_DEBUG if (!aTable) DebugStr("\pCould not expand component instance table"); #endif if (!aTable) return MemError(); BlockMove((Ptr)oldTable, (Ptr)aTable, oldTableSize); if (!newTable->rtiEntryUseCount) newTable->rtiEntryUseCount = 0x81; /* force nil componentInstances invalid */ ComponentManagerGlobals->rtInstanceTable = newTable; /* begin using new table */ ComponentManagerGlobals->rtInstanceTableTotalCount += growCount; if (oldTable) DisposPtr((Ptr)oldTable); /* dump the old one */ return 0; } #define BumpModificationSeed( pSeed ) (*(pSeed))++ /* void BumpModificationSeed( register long *pSeed ) { register long ticks; ticks = TickCount(); if (*pSeed >= ticks ) *pSeed++; else *pSeed = ticks; } */ pascal long __GetComponentListModSeed( ) { return ComponentManagerGlobals->rtModSeed; } long RegisteredComponentPointerToComponentID(register RegisteredComponent *rt) /* should be a macro */ { /* don't let valid components be negative */ return rt ? ( rt - ComponentManagerGlobals->rtTable + ((long)rt->rtEntryUseCount<<16) ) : 0; } #if 1 #define ComponentIDtoRegisteredComponentPointer(t) ((RegisteredComponent *)( ComponentManagerGlobals->rtTable + (short)(t & 0xffff))) #else RegisteredComponent *ComponentIDtoRegisteredComponentPointer( register long t ) /* should be a macro */ { return ( ComponentManagerGlobals->rtTable + (short)(t & 0xffff) ); } #endif RegisteredComponent *FindMatchingComponent( ComponentDescription *td, register RegisteredComponent *rtList ) /* * Find the RegisteredComponent that matches the ComponentDescription provided; * If, in the "looking" record, a zero is passed * for Type, subType, Manufacturer or flags, then they are wildcards. * * Returns componentID or nil if not found. */ { register long mask, flags; mask = td->componentFlagsMask; flags = td->componentFlags & mask; while ((rtList) && ( ((rtList->rtDesc.componentType != td->componentType) && td->componentType) || (td->componentSubType && (rtList->rtDesc.componentSubType != td->componentSubType)) || (td->componentManufacturer && (rtList->rtDesc.componentManufacturer != td->componentManufacturer)) || ((rtList->rtDesc.componentFlags & mask) != flags) || (rtList->rtLocalA5 && (rtList->rtLocalA5 != *(long *)CurrentA5)) || (rtList->rtFlags & (rtfCaptured+rtfChild)) ) ) { rtList = rtList->rtNext; } return rtList; } pascal long __CountComponents( register ComponentDescription *td ) /* */ { register RegisteredComponent *rt = ComponentManagerGlobals->rtUsedChain; register long count = 0; while ( (rt=FindMatchingComponent(td, rt)) ) { rt = rt->rtNext; count++; } return count; } pascal long CountSame( register RegisteredComponent *new ) /* */ { register RegisteredComponent *rtList = ComponentManagerGlobals->rtUsedChain; register long count = 0; while (rtList) { if ( (rtList->rtDesc.componentType == new->rtDesc.componentType) && (rtList->rtDesc.componentSubType == new->rtDesc.componentSubType) && (rtList->rtDesc.componentManufacturer == new->rtDesc.componentManufacturer) && (rtList->rtDesc.componentFlags == new->rtDesc.componentFlags) && // (rtList->rtFileNumber == new->rtFileNumber) && (rtList->rtResourceID == new->rtResourceID) && (rtList->rtResourceType == new->rtResourceType) && (rtList->rtLocalA5 == new->rtLocalA5) ) count++; rtList = rtList->rtNext; } return count; } RegisteredComponent *FindPreviousMatchingComponent( register ComponentDescription *td, register RegisteredComponent *rtList ) /* * Find the RegisteredComponent in the rtList that logically precedes the ComponentDescription provided; * */ { register RegisteredComponent *prev = nil; while ((rtList) && ((rtList->rtDesc.componentType < td->componentType) || ((rtList->rtDesc.componentType == td->componentType) && ((rtList->rtDesc.componentSubType < td->componentSubType) || ((rtList->rtDesc.componentSubType == td->componentSubType) && ((rtList->rtDesc.componentManufacturer < td->componentManufacturer) ) ) ) ) ) ) { prev = rtList; rtList = rtList->rtNext; } return prev; /* return pointer to one before where it belongs */ } static Handle cmHandToHand(register Handle h) { if ((long)(h == 0) || ((long)h == 1)) return h; else { #ifdef WARHOL_DEBUG if (!*h) DebugStr("\pyou suck."); #endif return rHandToHand(h); } } pascal short __ResolveComponentPlatform(ComponentResource **htr, ComponentDescription *cd, ResourceSpec *rs) { ComponentResourceExtension *cre; long response = gestalt68k; ComponentPlatformInfoArray *cpia; ComponentPlatformInfo *cpi; short count; short platformType = 0; // set up the default return stuff if (cd) *cd = (**htr).cd; if (rs) *rs = (**htr).component; // bail if no extension present if (GetHandleSize((Handle)htr) < (sizeof(ComponentResource) + sizeof(ComponentResourceExtension))) goto bail; cre = (ComponentResourceExtension *)((long)*htr + sizeof(ComponentResource)); // bail if no platform information if (!(cre->componentRegisterFlags & componentHasMutliplePlatforms)) goto bail; // bail if no way to determine system architecture if (Gestalt(gestaltSysArchitecture, &response) != noErr) goto bail; // cycle through the array of platform descriptions looking for a match cpia = (ComponentPlatformInfoArray *)((long)*htr + sizeof(ComponentResource) + sizeof(ComponentResourceExtension)); count = cpia->count; cpi = cpia->platformArray; while (count--) { if (cpi->platformType == response) { if (cd) cd->componentFlags = cpi->componentFlags; if (rs) *rs = cpi->component; platformType = response; goto bail; } cpi++; } bail: // If the platform type is still unknown, then assume this means the 68k. // But if there is a resType for the component's code, then it means it // has 68k type code available and we need to update the platform type. if (platformType == 0) { if ((**htr).component.resType != 0) platformType = gestalt68k; } return (platformType); } pascal Component __RegisterComponent(ComponentDescription *td, ComponentRoutine ComponentEntryPoint, short global, Handle ComponentName, Handle ComponentInfo, Handle ComponentIcon) /* * Register a new Component with the Component manager. * Returns index of RegisteredComponent or zero if registration failed. */ { THz saveZone; register RegisteredComponent *new, *previous; ComponentDescription atd = *td; // duplicate so that if it moves (or gets trashed...) we still have it if (!ComponentManagerGlobals->rtFreeChain) { /* no free entries available */ if (GrowRegisteredComponentTable( kComponentAllocationSize)) /* expand (and MOVE…) the table */ return 0; /* out of memory */ } new = ComponentManagerGlobals->rtFreeChain; ComponentManagerGlobals->rtFreeChain = new->rtNext; new->rtDesc = atd; new->rtRoutine = (ComponentRoutine *)StripAddress((Ptr)ComponentEntryPoint); new->rtLocalA5 = (long)((global & registerComponentGlobal) ? 0 : *(long *)CurrentA5 ); saveZone = (THz)GetZone(); if (global & registerComponentGlobal) SetZone(*(THz *)SysZone); new->rtNameHand = cmHandToHand( ComponentName ); new->rtInfoHand = cmHandToHand( ComponentInfo ); new->rtIconHand = cmHandToHand( ComponentIcon ); SetZone((THz)saveZone); if (global & registerComponentAfterExisting) /* register after other similar ones */ atd.componentType++; /* find the entry ordered before this one */ if ( previous = FindPreviousMatchingComponent( &atd, ComponentManagerGlobals->rtUsedChain ) ) { new->rtNext = previous->rtNext; /* add this one to the ordered chain */ previous->rtNext = new; } else { /* no one before this one */ new->rtNext = ComponentManagerGlobals->rtUsedChain; /* chain it in at the head of the list */ ComponentManagerGlobals->rtUsedChain = new; } if (global & registerComponentAfterExisting) /* restore component type */ atd.componentType--; BumpModificationSeed( &ComponentManagerGlobals->rtModSeed ); if (!new->rtEntryUseCount) new->rtEntryUseCount++; /* zero use count not valid */ new->rtParent = 0; new->rtRoutineHandle = 0; new->rtFlags = 0; // the upper byte is the platform type, but 0 means unknown and assumed to be 68k if (((unsigned short)global >> 8) > gestalt68k) new->rtFlags |= rtfCodeFragment; new->rtDesc.componentFlagsMask = 0; /* re-use this field: rt->rtRefcon */ new->rtFileNumber = -1; /* flag as not a resource */ new->rtResourceType = 0; /* flag as not a resource even more */ return RegisteredComponentPointerToComponentID( new ); /* return index with useCount in highword */ } pascal Component __RegisterComponentResource(ComponentResource **htr, short global) /* * Register a new Component based on component resource with the Component manager. * Returns index of RegisteredComponent or zero if registration failed. */ { long result = 0; char saveState; register ComponentResource *tr; Handle componentRoutine; short resID; OSType resType; Str255 wastedName; long version = 0; short platformType; GetResInfo((Handle)htr, &resID, &resType, wastedName); // don't need the name under system 7 if (result = ResError()) return 0; saveState = HGetState((Handle)htr); HLock((Handle)htr); tr = *htr; platformType = ResolveComponentPlatform(htr, &tr->cd, nil); if (platformType == 0) { HSetState((Handle)htr, saveState); return componentDontRegister; } result = RegisterComponent(&tr->cd, (ComponentRoutine )0L, (global & 0x00FF) | (platformType << 8), nil, nil, nil); HSetState((Handle)htr, saveState); if (result) { register RegisteredComponent *new = ComponentIDtoRegisteredComponentPointer(result); new->rtNameHand = (Handle)(tr->componentName.resType != 0); new->rtInfoHand = (Handle)(tr->componentInfo.resType != 0); new->rtIconHand = (Handle)(tr->componentIcon.resType != 0); // deal with the compoent resource extension, if present // note: this is done before any calls that might move memory and therefore purge the resource if (GetHandleSize((Handle)htr) >= (sizeof(ComponentResource) + sizeof(ComponentResourceExtension))) { ComponentResourceExtension *cre = (long *)((long)*htr + sizeof(ComponentResource)); version = cre->componentVersion; if (cre->componentRegisterFlags & componentDoAutoVersion) { new->rtFlags |= rtfAutoVersion; if (cre->componentRegisterFlags & componentAutoVersionIncludeFlags) new->rtFlags |= rtfAutoVersionUseFlags; } if (cre->componentRegisterFlags & componentWantsUnregister) new->rtFlags |= rtfWantsUnregister; if (cre->componentIconFamily) new->rtFlags |= rtfHasIconSuite; } new->rtFileNumber = AddComponentResFile( (Handle)htr ); if ( new->rtFileNumber < 0) { #ifdef WARHOL_DEBUG Debugger(); /* should never fail (can fail if no memory and couldn't get a file id)*/ #endif UnregisterComponent(result); return 0; } componentRoutine = NewHandleSys(0); EmptyHandle(componentRoutine); new->rtResourceID = resID; new->rtResourceType = resType; new->rtRoutineHandle = componentRoutine; new->rtRoutine = 0L; /* check for duplicates if necessary */ if ( (global & registerComponentNoDuplicates) && (CountSame(new)>1) ) { UnregisterComponent(result); return 0; } // check for register message if (( new->rtDesc.componentFlags & kComponentNeedsRegisterKiss ) ) if (goComponentRegister((ComponentInstance)result)) { UnregisterComponent(result); return 0; } // scan the Component table for possible duplicates and kill the older one(s) (if auto versioning on) // (can't do this before the register message since we might call GetComponentVersion on the component, // which it might not be able to deal with before the register) if (DestroyOlder(new, version) == nil) { // we are too old. don't register. UnregisterComponent(result); return 0; } } return result; } pascal long __RegisterComponentResourceFile(short resRefNum, short global) /* * Register components found in this resource file. */ { short saveRef; short err; Boolean oldResLoad; Handle hdl; oldResLoad = *(Boolean *)ResLoad; saveRef = CurResFile(); SetResLoad(true); UseResFile(resRefNum); if ((err=ResError()) == noErr) { register short count, i; if ((count = Count1Resources(kComponentResourceType)) > 0) { for (i=1; i<=count; i++) { hdl = Get1IndResource(kComponentResourceType, i); if (hdl) { if (RegisterComponentResource((ComponentResource **)hdl, global)) err++; /* we registered something */ } } } } UseResFile(saveRef); SetResLoad(oldResLoad); return err; } pascal RegisteredComponentInstancePtr __ValidComponentInstance(register ComponentInstance aComponentInstance) { register long signature; register RegisteredComponentInstance *result; signature = aComponentInstance>>16; if ( (aComponentInstance <=0) || (!signature) ) /* valid ComponentID's are > 0 */ return false; aComponentInstance &= 0xffff; if ( aComponentInstance < 0 || aComponentInstance > ComponentManagerGlobals->rtInstanceTableTotalCount || signature != (result = ComponentManagerGlobals->rtInstanceTable + aComponentInstance)->rtiEntryUseCount ) return 0; else return result; } pascal RegisteredComponentPtr __ValidComponent(register Component aComponent) { register long signature; register RegisteredComponent *result; register RegisteredComponentInstance *vti; signature = aComponent>>16; if ( ( aComponent <=0 ) || (!signature) ) /* valid ComponentID's are > 0 */ return 0; aComponent &= 0xffff; if ( aComponent >= 0 && aComponent < ComponentManagerGlobals->rtTableEntryCount && signature == (result = ComponentManagerGlobals->rtTable + (short)aComponent)->rtEntryUseCount ) return result; else { if (vti = ValidComponentInstance(aComponent + (signature<<16))) return vti->rtiEntry; } return 0; } int RemoveRTFromList( register RegisteredComponent *rt, RegisteredComponent **pRTList ) { register RegisteredComponent *rtList; register RegisteredComponent *prev = nil; if (!(rtList = *pRTList)) return -1; /* error: empty list */ while ((rtList) && (rtList != rt)) { prev = rtList; rtList = rtList->rtNext; } if (!rtList) return -1; /* error: not found in list */ if (!prev) *pRTList = rt->rtNext; /* we are removing the head */ else prev->rtNext = rt->rtNext; /* we are removing from the middle */ return 0; } pascal OSErr __UnregisterComponent(Component aComponent) /* * Returns an error if aComponent is currently open * */ { register RegisteredComponent *rt; if( ! (rt = ValidComponent(aComponent)) ) return invalidComponentID; /* error : not a valid component ID */ if ( rt->rtReferenceCount ) /* error: valid instances exist */ return validInstancesExist; if ( (rt->rtFlags & rtfWantsUnregister) && (rt->rtFlags & rtfHasBeenOpened) ) goComponentUnregister(aComponent); if ( RemoveRTFromList( rt, &ComponentManagerGlobals->rtUsedChain ) ) return invalidComponentID; /* error: not found in list */ rt->rtNext = ComponentManagerGlobals->rtFreeChain; /* add this entry to the free list */ ComponentManagerGlobals->rtFreeChain = rt; if (rt->rtNameHand != 1) DisposHandle(rt->rtNameHand); if (rt->rtInfoHand != 1) DisposHandle(rt->rtInfoHand); if (rt->rtIconHand != 1) DisposHandle(rt->rtIconHand); DisposHandle(rt->rtRoutineHandle); RemoveComponentResFile( rt->rtFileNumber ); /* decrement the use count */ if (rt->rtParent) /* if child, unchain from parent */ /* note: this also unchains a parent from a child. this can happen, if the component is loaded into the application heap for the register message, and the component doesn't want to be registered. */ { register RegisteredComponent *previous; previous = rt->rtParent; while (previous->rtParent != rt) previous = previous->rtParent; /* find previous node */ if (previous == rt->rtParent) previous->rtParent = 0; /* no more children */ else previous->rtParent = rt->rtParent; /* take us out of chain */ } BumpModificationSeed( &ComponentManagerGlobals->rtModSeed ); /* even bump for children in case someone cached it */ rt->rtEntryUseCount++; if (!(rt->rtEntryUseCount &= 0x7f)) rt->rtEntryUseCount++; /* ensure entry counts wrap and are nonzero*/ return 0; } pascal OSErr __SetDefaultComponent( Component aComponent, register short flags ) { register RegisteredComponent *rt; register RegisteredComponent *previous; ComponentDescription td; if( ! (rt = ValidComponent(aComponent)) ) return invalidComponentID; /* error : not a valid component ID */ GetComponentInfo( aComponent, &td, 0L, 0L, 0L ); if (flags & defaultComponentAnySubType) td.componentSubType = 0; if (flags & defaultComponentAnyManufacturer) td.componentManufacturer = 0; if (flags & defaultComponentAnyFlags) td.componentFlags = 0; td.componentFlagsMask = 0; if ( RemoveRTFromList( rt, &ComponentManagerGlobals->rtUsedChain ) ) { #ifdef WARHOL_DEBUG Debugger(); /* error: should not happen */ #endif return invalidComponentID; } /* find the entry ordered before this one */ if ( previous = FindPreviousMatchingComponent( &td, ComponentManagerGlobals->rtUsedChain ) ) { rt->rtNext = previous->rtNext; /* add this one to the ordered chain */ previous->rtNext = rt; } else { /* no one before this one */ rt->rtNext = ComponentManagerGlobals->rtUsedChain; /* chain it in at the head of the list */ ComponentManagerGlobals->rtUsedChain = rt; } return 0; } pascal Component __CaptureComponent( Component slave, Component master ) { register RegisteredComponent *s, *m; if( ! (s = ValidComponent(slave)) ) return invalidComponentID; /* error : not a valid component ID */ if( ! (m = ValidComponent(master)) ) return invalidComponentID; /* error : not a valid component ID */ if (s->rtFlags & rtfCaptured) { #ifdef WARHOL_DEBUG DebugStr("\pComponent has already been captured"); /* already captured !!! */ #endif return 0; } s->rtFlags |= rtfCaptured; BumpModificationSeed( &ComponentManagerGlobals->rtModSeed ); return slave; } pascal OSErr __UncaptureComponent( Component aComponent ) { register RegisteredComponent *rt; if( ! (rt = ValidComponent(aComponent)) ) return invalidComponentID; /* error : not a valid component ID */ if (!(rt->rtFlags & rtfCaptured)) /* not captured !!! */ return componentNotCaptured; rt->rtFlags &= ~rtfCaptured; BumpModificationSeed( &ComponentManagerGlobals->rtModSeed ); return 0; } pascal short __OpenComponentResFile( Component aComponent ) { register RegisteredComponent *rt; register short fn; short saveResLoad; short result; rtFile *rtFileList; FSSpec theFile; if( ! (rt = ValidComponent(aComponent)) ) return -1; /* error : not a valid component ID */ fn = rt->rtFileNumber; if ((fn < 0) || (fn >= ComponentManagerGlobals->rtFileTotalCount)) return -1; /* no file here */ // figure out where the file is rtFileList = ComponentManagerGlobals->rtFileTable + fn; if (rtFileList->vRefNum == 0) theFile = **(FSSpec **)rtFileList->fileID; else { HParamBlockRec pb; theFile.name[0] = 0; pb.fidParam.ioNamePtr = theFile.name; pb.fidParam.ioVRefNum = rtFileList->vRefNum; pb.fidParam.ioFileID = rtFileList->fileID; if (PBResolveFileIDRefSync(&pb) != noErr) return -1; theFile.vRefNum = rtFileList->vRefNum; theFile.parID = pb.fidParam.ioSrcDirID; } saveResLoad = *(Boolean *)ResLoad; SetResLoad(false); result = FSpOpenResFile( &theFile, fsRdPerm ); SetResLoad(saveResLoad); return result; } pascal OSErr __CloseComponentResFile( short refnum ) { if (refnum>0) { CloseResFile( refnum ); return ResError(); } return 0; } RegisteredComponentInstance *ComponentInstanceIDToComponentInstancePointer( register long t ) /* should be a macro */ { return ( ComponentManagerGlobals->rtInstanceTable + (t & 0xffff) ); } long ComponentInstancePointerToComponentInstanceID(register RegisteredComponentInstance *rti) /* should be a macro */ { return rti ? ( rti - ComponentManagerGlobals->rtInstanceTable + ((long)rti->rtiEntryUseCount<<16) ) : 0; } RegisteredComponentInstance *FindNextComponentInstance( register RegisteredComponentInstance *rti, register RegisteredComponent *rt ) { register short i; i = ComponentManagerGlobals->rtInstanceTableTotalCount; if (!rti) rti = ComponentManagerGlobals->rtInstanceTable; else { rti++; i -= rti - ComponentManagerGlobals->rtInstanceTable; } for(--i; i >= 0; --i) { if (rt == rti->rtiEntry) return rti; rti++; } return 0; /* not found */ } pascal long __CountComponentInstances(Component aComponent) /* * */ { register RegisteredComponent *rt; if( ! (rt = ValidComponent(aComponent)) ) return 0; /* error : not a valid component ID */ return (rt->rtReferenceCount); } pascal RegisteredComponent* CloneComponent( long componentID, short global ) /* */ { register RegisteredComponent *rt, *nt; long newComponent; Handle componentRoutine; long saveSeed; if( ! (rt = ValidComponent(componentID)) ) return 0; /* error : not a valid component ID */ saveSeed = ComponentManagerGlobals->rtModSeed; if (rt->rtFileNumber >= 0) newComponent = RegisterComponent(&rt->rtDesc, rt->rtRoutine, global, (Handle)(rt->rtNameHand != 0), (Handle)(rt->rtInfoHand != 0), (Handle)(rt->rtIconHand != 0)); else newComponent = RegisterComponent(&rt->rtDesc, rt->rtRoutine, global, rt->rtNameHand, rt->rtInfoHand, rt->rtIconHand); if (newComponent) { rt = ComponentIDtoRegisteredComponentPointer(componentID); /* it may have moved !!! */ nt = ComponentIDtoRegisteredComponentPointer(newComponent); nt->rtResourceID = rt->rtResourceID; nt->rtResourceType = rt->rtResourceType; nt->rtFileNumber = rt->rtFileNumber; (ComponentManagerGlobals->rtFileTable[rt->rtFileNumber]).referenceCount++; componentRoutine = NewHandle(0); EmptyHandle(componentRoutine); nt->rtRoutineHandle = componentRoutine; nt->rtRoutine = 0L; if (!global) { nt->rtFlags |= rtfChild; /* mark as child -- hide from findnext */ nt->rtFlags |= (rt->rtFlags & (rtfAutoVersion|rtfHasIconSuite|rtfWantsUnregister|rtfAutoVersionUseFlags|rtfCodeFragment)); // transfer obscure flags nt->rtLocalA5 = *(long *)CurrentA5; /* mark for this app only */ ComponentManagerGlobals->rtModSeed = saveSeed; /* seed must not change */ if (rt->rtParent) { nt->rtParent = rt->rtParent; /* insert the new one into the list */ rt->rtParent = nt; } else { rt->rtParent = nt; /* chain them together */ nt->rtParent = rt; } } } else nt = 0; return nt; } pascal long __LoadComponent( long componentID ) /* */ { register RegisteredComponent *rt, *child = 0; Handle entryPoint = nil; THz saveZone; short refnum; if( ! (rt = ValidComponent(componentID)) ) return 0; /* error : not a valid component ID */ if (rt->rtParent) /* check for children in this app */ { child = rt->rtParent; while ( (child!=rt) && (child->rtLocalA5 != *(long *)CurrentA5) ) child = child->rtParent; if (child==rt) child = 0; else if (*child->rtRoutineHandle) rt = child; /* we found a child and it is loaded */ } if (rt->rtFileNumber>=0) { /* resource file exists */ if (!rt->rtReferenceCount) /* don't bump count until success */ { if (!rt->rtRoutineHandle || !*rt->rtRoutineHandle) /* code is purged, so go get it */ { short saveCurRes = CurResFile(); ResourceSpec resSpec; ComponentResource **htr; refnum = OpenComponentResFile( componentID ); if (refnum == -1) return 0; /* could not open the file */ // load the thing resource so that we can figure out where the code resource lives htr = (ComponentResource **)Get1Resource(rt->rtResourceType, rt->rtResourceID); if (!htr) goto closeDownFile; LoadResource((Handle)htr); if (!*htr) goto closeDownFile; // we ignore the result, since it has already be determined to be correct ResolveComponentPlatform(htr, nil, &resSpec); ReleaseResource((Handle)htr); saveZone = (THz)GetZone(); if (!rt->rtLocalA5) SetZone(*(THz *)SysZone); if (entryPoint = Get1Resource(resSpec.resType, resSpec.resID)) { LoadResource(entryPoint); DetachResource(entryPoint); if (!rt->rtLocalA5) { // try to keep components from being cloned at boot time so they can set up their // globals in the system heap cleanly. this is somewhat misguided and mostly // intended to keep ill-behaved components from dying miserably. if (GetExpandMemProcessMgrExists()) { if (!EnoughSystemHeapSlop()) EmptyHandle(entryPoint); /* not enough space, so dump our handle */ } } } SetZone(saveZone); #ifdef WARHOL_DEBUG if (!entryPoint || !*entryPoint) DebugStr("\pFailed to load component in sys heap.;g"); #endif /* If we couldn't put it in the System heap, try the App heap */ if ((!entryPoint || !*entryPoint) && (!rt->rtLocalA5)) { entryPoint = Get1Resource(resSpec.resType, resSpec.resID); LoadResource(entryPoint); DetachResource(entryPoint); if (entryPoint && *entryPoint) /* we got it */ { HNoPurge( entryPoint ); /* done let clone purge it */ if (child) rt = child; /* refill the existing private copy */ else rt = CloneComponent(componentID, false); /* make a private copy */ if (!rt) { #ifdef WARHOL_DEBUG if (!rt) DebugStr("\pClone component failed."); #endif DisposHandle(entryPoint); entryPoint = nil; /* dump it, we'll exit soon */ } } } closeDownFile: CloseComponentResFile(refnum); UseResFile(saveCurRes); if (!entryPoint || !*entryPoint) return 0; /* not enough memory */ DisposHandle( rt->rtRoutineHandle ); /* dump the purged handle */ rt->rtRoutineHandle = entryPoint; } if (rt->rtLocalA5) MoveHHi( rt->rtRoutineHandle ); /* if it's in the app heap then force it high */ else { if (ComponentManagerGlobals->hasMoveHLo) MoveHLow(rt->rtRoutineHandle); // if it's in the system heap, force it low if possible } HLock( rt->rtRoutineHandle ); /* lock it down */ #ifdef SupportNativeComponents if(rt->rtFlags & rtfCodeFragment) { rt->rtRoutine = ResolveCodeFragment(rt); if (rt->rtRoutine == nil) { DisposHandle( rt->rtRoutineHandle ); // error, bail out rt->rtRoutineHandle = nil; // forget about this return 0; } } else #endif rt->rtRoutine = (void *)StripAddress( *rt->rtRoutineHandle ); } } rt->rtReferenceCount++; /* one more client */ return (long)rt; } pascal OSErr __UnloadComponent( long componentID ) /* */ { register RegisteredComponent *rt; #ifdef SupportNativeComponents THz oldZone; #endif OSErr result; result = noErr; if( ! (rt = ValidComponent(componentID)) ) return invalidComponentID; /* error : not a valid component ID */ rt->rtReferenceCount--; /* one fewer client */ if (rt->rtFileNumber>=0) { /* resource file exists */ if (!rt->rtReferenceCount) { /* recover handle and make it purgeable */ rt->rtRoutine = 0L; /* no longer valid */ #ifdef SupportNativeComponents if (rt->rtFlags & rtfCodeFragment) { oldZone = GetZone(); SetZone(SystemZone()); result = CloseConnection(&rt->rtConnectionID); SetZone(oldZone); #ifdef WARHOL_DEBUG if (result != noErr) DebugStr("\pCloseConnection failed"); #endif } #endif HUnlock(rt->rtRoutineHandle); HPurge(rt->rtRoutineHandle); } } return result; } #if 0 pascal ComponentInstance FindNextCommonComponentInstance(ComponentInstance aComponentInstance, Component aComponent, ComponentRoutine entryPoint ) /* * */ { register RegisteredComponentInstance *rti = 0; register RegisteredComponent *rt; if (!(rt = ValidComponent(aComponent)) || (rt->rtRoutine != (void *)StripAddress((Ptr)entryPoint)) ) return 0; if (aComponentInstance) { if ( !(rti = ValidComponentInstance(aComponentInstance)) || ( rti->rtiEntry->rtRoutine != (void *)StripAddress((Ptr)entryPoint) )) return 0; /* error : not a valid component ID or entry point doesn't match */ } return ComponentInstancePointerToComponentInstanceID(FindNextComponentInstance(rti, rt)); } #endif pascal OSErr __DestroyComponent(Component aComponent) /* * semi-Private routine for unregistering a component that is currently open * */ { register RegisteredComponent *rt; register RegisteredComponentInstance *rti; if( ! (rt = ValidComponent(aComponent)) ) return invalidComponentID; /* error : not a valid component ID */ while (rt->rtReferenceCount) { rti = FindNextComponentInstance( 0L, rt ); /* start at beginning */ if (!rti) { #ifdef WARHOL_DEBUG Debugger(); /* should never happen */ #endif rt->rtReferenceCount = 0; /* force all instances to be gone.... */ break; } CloseComponent( ComponentInstancePointerToComponentInstanceID(rti) ); } return UnregisterComponent(aComponent); } long getComponentVersion(register RegisteredComponent *rt) { long version = 0; short fref; Component t = RegisteredComponentPointerToComponentID(rt); fref = OpenComponentResFile(t); if (fref != -1) { ComponentResource **htr; // load the component resource to see if the version number is available htr = (ComponentResource **)Get1Resource(rt->rtResourceType, rt->rtResourceID); if (htr) { LoadResource((Handle)htr); if (*htr) { if ( GetHandleSize((Handle)htr) >= (sizeof(ComponentResource) + sizeof(ComponentResourceExtension)) ) { ComponentResourceExtension *cre = (long *)((long)*htr + sizeof(ComponentResource)); version = cre->componentVersion; } } } CloseComponentResFile(fref); if (version) return version; } // that failed, so just ask the Component version = GetComponentVersion(t); if (version < 0) version = 0; return version; } pascal RegisteredComponent *DestroyOlder( register RegisteredComponent *new, long version ) /* */ { register RegisteredComponent *rtList = ComponentManagerGlobals->rtUsedChain; while (rtList) { if ( (rtList->rtDesc.componentType == new->rtDesc.componentType) && (rtList->rtDesc.componentSubType == new->rtDesc.componentSubType) && (rtList->rtDesc.componentManufacturer == new->rtDesc.componentManufacturer) && (rtList->rtLocalA5 == new->rtLocalA5) && ((rtList->rtFlags & rtfAutoVersion) || (new->rtFlags & rtfAutoVersion)) && (rtList != new) ) { long thisVersion; Component c; if ( ((rtList->rtFlags & rtfAutoVersionUseFlags) || (new->rtFlags & rtfAutoVersionUseFlags)) && (rtList->rtDesc.componentFlags != new->rtDesc.componentFlags) ) goto next; // found one that's the same thisVersion = getComponentVersion(rtList); c = RegisteredComponentPointerToComponentID(rtList); rtList = rtList->rtNext; // get the next one (assumes UnregisterComponent never kills more than one Component) if (!version) version = getComponentVersion(new); #ifdef WARHOL_DEBUG DebugStr("\pDeath to the old."); #endif if (thisVersion <= version) { // kill the other one, let us live DestroyComponent(c); } else { // we are older than this one, so kill us return nil; } } else { next: rtList = rtList->rtNext; } } return new; } void KillHeapComponentInstances(register Ptr heapStart, register Ptr heapEnd) { register RegisteredComponentInstance *rti; register short i; rti = ComponentManagerGlobals->rtInstanceTable; i = ComponentManagerGlobals->rtInstanceTableTotalCount; for(--i; i >= 0; --i) { if ( (rti->rtiEntry) && ((Ptr)rti->rtiStorage >= heapStart) && ((Ptr)rti->rtiStorage <= heapEnd) ) CloseComponent( ComponentInstancePointerToComponentInstanceID(rti) ); rti++; } } void KillHeapComponents(register Ptr heapStart, register Ptr heapEnd) { register RegisteredComponent *rt = ComponentManagerGlobals->rtUsedChain; register RegisteredComponent *rt2; while (rt) { rt2 = rt; rt=rt->rtNext; if ((((Ptr)rt2->rtRoutine >= heapStart) && ((Ptr)rt2->rtRoutine <= heapEnd)) || ((Ptr)rt2->rtRoutineHandle >= heapStart) && ((Ptr)rt2->rtRoutineHandle <= heapEnd) || (((Ptr)rt2->rtLocalA5 >= heapStart) && ((Ptr)rt2->rtLocalA5 <= heapEnd))) DestroyComponent( RegisteredComponentPointerToComponentID(rt2) ); } } pascal void ThingMemoryTrashed(Ptr startAddr, Ptr stopAddr) { KillHeapComponentInstances(startAddr, stopAddr); KillHeapComponents(startAddr, stopAddr); } pascal void __CleanUpApplicationComponents(void) { #if 0 // if we use the strange MemoryTrashed zone notification stuff, then this is not necessary Ptr zoneBegin, zoneEnd; GetApplZoneBounds(&zoneBegin, &zoneEnd); KillHeapComponentInstances(zoneBegin, zoneEnd); KillHeapComponents(zoneBegin, zoneEnd); #endif } pascal Component __FindNextComponent( long previousComponent, ComponentDescription *td ) /* * If, in the "looking" record, a zero is passed * for Type, subType, Manufacturer or flags, then they are wildcards. * * If previousComponent is nil then find the first such component. */ { register RegisteredComponent *rt; if( previousComponent && (rt = ValidComponent(previousComponent)) ) rt = rt->rtNext; /* valid component ID, so start with successor */ else rt = ComponentManagerGlobals->rtUsedChain; /* start from beginning */ return RegisteredComponentPointerToComponentID(FindMatchingComponent( td, rt )); /* return ID or nil */ } void HandToXHand(register Handle srcHandle, register Handle dstHandle) { register long size; if (dstHandle) { srcHandle = fixHandle(srcHandle); if (srcHandle && *srcHandle) { size = GetHandleSize(srcHandle); SetHandleSize( dstHandle, size ); if (MemError() == -109) ReallocHandle(dstHandle, size); // we return empty handles, so let the pass them to us if (! MemError()) { BlockMove( *srcHandle, *dstHandle, size ); return; } } EmptyHandle( dstHandle ); /* return empty handle if src is nil or empty */ } } pascal OSErr __GetComponentInfoPrivate( Component aComponent, Handle nameHand, Handle infoHand, Handle iconHand ) { register RegisteredComponent *rt = ValidComponent(aComponent); if ( rt->rtResourceType) { Boolean force = false; if (nameHand && (rt->rtNameHand == 1)) {rt->rtNameHand = 0; force = true;} if (infoHand && (rt->rtInfoHand == 1)) {rt->rtInfoHand = 0; force = true;} if (iconHand && (rt->rtIconHand == 1)) {rt->rtIconHand = 0; force = true;} if ( force || (nameHand && rt->rtNameHand && !*rt->rtNameHand) || (infoHand && rt->rtInfoHand && !*rt->rtInfoHand) || (iconHand && rt->rtIconHand && !*rt->rtIconHand) ) { // reload the whole lot THz saveZone = (THz)GetZone(); short saveRes = CurResFile(); short resRef; SetZone(*(THz *)SysZone); resRef = OpenComponentResFile(aComponent); if (resRef != -1) { Boolean saveResLoad = *(Boolean *)ResLoad; register RegisteredComponent *thisRT = ComponentManagerGlobals->rtUsedChain; SetResLoad(true); for (thisRT = ComponentManagerGlobals->rtUsedChain; thisRT && (thisRT->rtDesc.componentType <= rt->rtDesc.componentType); thisRT = thisRT->rtNext) { Handle h; if ((thisRT->rtFileNumber != rt->rtFileNumber) || (thisRT->rtDesc.componentType != rt->rtDesc.componentType)) continue; h = Get1Resource(thisRT->rtResourceType, thisRT->rtResourceID); if (h) { ComponentResource cr = **(ComponentResource **)h; ReleaseResource(h); if (nameHand && cr.componentName.resType) { DisposHandle(fixHandle(thisRT->rtNameHand)); if (thisRT->rtNameHand = Get1Resource(cr.componentName.resType, cr.componentName.resID)) { HNoPurge(thisRT->rtNameHand); DetachResource(thisRT->rtNameHand); } } if (infoHand && cr.componentInfo.resType) { DisposHandle(fixHandle(thisRT->rtInfoHand)); if (thisRT->rtInfoHand = Get1Resource(cr.componentInfo.resType, cr.componentInfo.resID)) { HNoPurge(thisRT->rtInfoHand); DetachResource(thisRT->rtInfoHand); } } if (iconHand && cr.componentIcon.resType) { DisposHandle(fixHandle(thisRT->rtIconHand)); if (thisRT->rtIconHand = Get1Resource(cr.componentIcon.resType, cr.componentIcon.resID)) { HNoPurge(thisRT->rtIconHand); DetachResource(thisRT->rtIconHand); } } if (thisRT != rt) { HPurge(fixHandle(thisRT->rtNameHand)); HPurge(fixHandle(thisRT->rtInfoHand)); HPurge(fixHandle(thisRT->rtIconHand)); } } } SetResLoad(saveResLoad); CloseComponentResFile(resRef); } SetZone(saveZone); UseResFile(saveRes); } } HandToXHand(rt->rtNameHand, nameHand); HandToXHand(rt->rtInfoHand, infoHand); HandToXHand(rt->rtIconHand, iconHand); if (rt->rtResourceType) { HPurge(fixHandle(rt->rtNameHand)); HPurge(fixHandle(rt->rtInfoHand)); HPurge(fixHandle(rt->rtIconHand)); } return noErr; } pascal void ClearD0(void) = 0x7000; pascal OSErr __GetComponentInfo( Component aComponent, register ComponentDescription *td, Handle nameHand, Handle infoHand, Handle iconHand ) /* */ { register RegisteredComponent *rt; OSErr err; if ( rt = ValidComponent(aComponent)) { if (td) { register RegisteredComponent *rtTemp = rt; *td = rt->rtDesc; /* copy type, subtype, manufacturer, flags */ while (rtTemp->rtFlags & rtfChild) { rtTemp = rtTemp->rtParent; #ifdef WARHOL_DEBUG if (!rtTemp) DebugStr("\pClonedComponentHell"); #endif } td->componentFlagsMask = RegisteredComponentPointerToComponentID(rtTemp); } /* return component ID for uniqueness */ if (nameHand || infoHand || iconHand) err = GetComponentInfoPrivate(aComponent, nameHand, infoHand, iconHand); else err = noErr; } else err = invalidComponentID; /* error : not a valid component ID */ ClearD0(); //•• this makes the 7.1 Keyboard menu code not crash (fun, huh?) return err; } pascal long __GetComponentRefcon( long aComponent ) /* */ { register RegisteredComponent *rt; if (rt = ValidComponent(aComponent)) { return rt->rtDesc.componentFlagsMask; /* re-use this field: rt->rtRefcon */ } else return 0; /* error : not a valid component ID */ } pascal void __SetComponentRefcon( long aComponent, long theRefcon ) /* */ { register RegisteredComponent *rt; if( rt = ValidComponent(aComponent) ) rt->rtDesc.componentFlagsMask = theRefcon; /* re-use this field: rt->rtRefcon */ } pascal OSErr __GetComponentInstanceError( long aComponentInstance ) /* */ { register RegisteredComponentInstance *rti; short err; if( ! (rti = ValidComponentInstance(aComponentInstance)) ) return invalidComponentID; /* error : not a valid component ID */ err = rti->rtiError; rti->rtiError=0; return err; } pascal void __SetComponentInstanceError( long aComponentInstance, OSErr theError ) /* */ { register RegisteredComponentInstance *rti; if( rti = ValidComponentInstance(aComponentInstance) ) rti->rtiError = theError; } pascal Handle __GetComponentInstanceStorage( long aComponentInstance ) /* */ { register RegisteredComponentInstance *rti; if( ! (rti = ValidComponentInstance(aComponentInstance)) ) return 0; /* error : not a valid component ID */ return rti->rtiStorage; } pascal void __SetComponentInstanceStorage( long aComponentInstance, Handle theStorage ) /* */ { register RegisteredComponentInstance *rti; if( rti = ValidComponentInstance(aComponentInstance) ) rti->rtiStorage = theStorage; } pascal long __GetComponentInstanceA5( long aComponentInstance ) /* */ { register RegisteredComponentInstance *rti; if( ! (rti = ValidComponentInstance(aComponentInstance)) ) return 0; /* error : not a valid component ID */ return rti->rtiSwitchedA5; } pascal void __SetComponentInstanceA5( long aComponentInstance, long theA5 ) /* */ { register RegisteredComponentInstance *rti; if( rti = ValidComponentInstance(aComponentInstance) ) rti->rtiSwitchedA5 = theA5; } pascal ComponentInstance __OpenComponent( long componentID ) /* */ { register RegisteredComponent *rt; register RegisteredComponentInstance *rti; ComponentInstance ti; long result; if( ! (rt = (RegisteredComponent*)LoadComponent(componentID) ) ) { #ifdef WARHOL_DEBUG DebugStr("\pFailed to load component. Not enough memory.;g"); #endif return 0; } if (( ComponentManagerGlobals->rtInstanceTableUsedCount >= ComponentManagerGlobals->rtInstanceTableTotalCount ) && (GrowRegisteredComponentInstanceTable( kComponentInstanceAllocationSize ))) return 0; /* error: could not allocate an instance record */ if (! (rti = FindNextComponentInstance( 0L, 0L)))/* start at beginning and look for a nil component ptr */ return 0; /* error: should never happen */ ComponentManagerGlobals->rtInstanceTableUsedCount++; rt->rtFlags |= rtfHasBeenOpened; // remember that this one has been used rti->rtiEntry = rt; /* store pointer to the parent registered component */ rti->rtiStorage = 0; /* set high bit of flags with component flags bit 30 */ rti->rtiFlags = (((~rt->rtDesc.componentFlags) >> 23) & 0x80); rti->rtiError = 0; rti->rtiSwitchedA5 = rt->rtLocalA5; if (!rti->rtiEntryUseCount) rti->rtiEntryUseCount = 0x81; /* distinguish between componentID's and componentInstances */ /***** Call the Component with the OPEN message Here *******/ ti = ComponentInstancePointerToComponentInstanceID(rti); result = goComponentOpen( ti, ti ); /* 4 bytes of params, selector open = -1 */ if (result) /* error returned from open */ { #ifdef WARHOL_DEBUG DebugStr("\pOpen component failed."); #endif CloseComponent(ti); return 0; } return ti; } pascal OSErr __CloseComponent( ComponentInstance componentInstanceID ) /* */ { register RegisteredComponent *rt; register RegisteredComponentInstance *rti; ComponentInstance ti; long result; if( ! (rti = ValidComponentInstance(componentInstanceID)) ) return invalidComponentID; /* error : not a valid component ID */ /***** Call the Component with the CLOSE message Here *******/ ti = ComponentInstancePointerToComponentInstanceID(rti); result = goComponentClose( ti , ti); /* 4 bytes of params, selector close = -2 */ UnloadComponent( componentInstanceID ); /* Drops reference count */ rt = rti->rtiEntry; ComponentManagerGlobals->rtInstanceTableUsedCount--; rti->rtiEntry = 0; /* Invalidate entry; kill pointer to the parent registered component */ rti->rtiEntryUseCount++; /* invalidate all stale references */ if (!(rti->rtiEntryUseCount &= 0x7f)) rti->rtiEntryUseCount++; /* ensure entry counts wrap and are nonzero*/ rti->rtiEntryUseCount |= 0x80; /* flag as a componentInstance */ return result; } pascal ComponentInstance __OpenDefaultComponent( OSType componentType, OSType componentSubType ) /* */ { Component cmp = 0; ComponentInstance result = 0; ComponentDescription look; look.componentType = componentType; look.componentSubType = componentSubType; look.componentManufacturer = 0; look.componentFlags = 0; look.componentFlagsMask = 0; while (!result) { if (!(cmp = FindNextComponent(cmp, &look))) return 0; result = OpenComponent(cmp); } return result; } // this is only here because of CubeE which links it in… pascal void __ComponentSearch (void) { doComponentSearch(); } //#endif /******************************** everything below here is cut back by after InitComponentManager is called. ********************************/ pascal void __InitComponentManager(Ptr *cutBackAddress) // Called only once at install time { #pragma unused (cutBackAddress) long saveCodecManagerGlobals = -1; #if 0 *cutBackAddress = (Ptr)&_InitComponentManager; // for QuickTime use only #endif RegisterHandleTrashNotification(ThingMemoryTrashed, kComponentManagerPriority, 0); if ( (long)ComponentManagerGlobals != -1) { // don't install if already there (but always return cutback address) // 7.1 calls GetComponentManagerVersion via JSR, not a trap CoolReplaceGestalt(gestaltComponentMgr,GestaltComponentMgrVersion); goto bail; } NewGestalt(gestaltComponentMgr, GestaltComponentMgrVersion); ComponentManagerGlobals = (ComponentManagerGlobalsRecord *)NewPtrSysClear( sizeof(ComponentManagerGlobalsRecord) ); ComponentManagerGlobals->rtReservedForCodecManager = saveCodecManagerGlobals; GrowRegisteredComponentTable( 32 ); bail: ComponentManagerGlobals->hasMoveHLo = (GetOSTrapAddress(_MoveHLow) != GetToolboxTrapAddress(_Unimplemented)); } pascal ComponentResult __CallComponent(void) /* referenced by dispatch table--but never called */ { return 0; } Handle GetSystemThenROMRes(ResType theType, short resIndex) { Handle H; short saveResFile; /*Do a quick check to see if we are looking for a valid resource*/ if (theType == 0 ) return(nil); /*First look for the resource in the system file*/ saveResFile = CurResFile(); UseResFile(0); /*set to the system resource file*/ H = Get1Resource(theType, resIndex); UseResFile(saveResFile); /*restore resource file */ if (H != nil) return(H); /*If we got a resource then just return with it*/ /*If we didnt find a resource, then try looking for it in ROM*/ LMSetROMMapInsert(mapTrue); H = Get1Resource(theType, resIndex); return(H); /*return system resource file if found */ } pascal Component RegisterComponentRomResource(ComponentResource **htr, short global) /* * Register a new Component based on component resource. * Returns index of RegisteredComponent or zero if registration failed. * Resource must refer to Component Code and associated resources in ROM. */ { long result = 0; char saveState; ComponentResource *tr; Handle H1, H2, H3, H4; saveState = HGetState((Handle)htr); HLock((Handle)htr); tr = *htr; H1 = GetSystemThenROMRes(tr->componentName.resType, tr->componentName.resID); H2 = GetSystemThenROMRes(tr->componentInfo.resType, tr->componentInfo.resID); H3 = GetSystemThenROMRes(tr->componentIcon.resType, tr->componentIcon.resID); H4 = GetSystemThenROMRes(tr->component.resType, tr->component.resID); result = RegisterComponent(&tr->cd, (ComponentRoutine )*H4, global, H1, H2, H3); HSetState((Handle)htr, saveState); ReleaseResource(H1); ReleaseResource(H2); ReleaseResource(H3); ReleaseResource(H4); /* The code is actually still around since it's in ROM */ if (result) { if (( tr->cd.componentFlags & kComponentNeedsRegisterKiss ) ) if (goComponentRegister((ComponentInstance)result)) { UnregisterComponent(result); return 0; } } } pascal void __RegisterRomComponents(void) /* * Register components found in the ROM resource file. */ { #if ForROM // don't need this code after booting, so the system or init versions shouldn't need // to carry it around. But this entry point does need to be here. Boolean oldResLoad; Handle hdl; short count, i; oldResLoad = ResLoad; SetResLoad(true); LMSetROMMapInsert(mapTrue); if ((count = Count1Resources(kComponentResourceType)) > 0) { for (i=1; i<=count; i++) { LMSetROMMapInsert(mapTrue); hdl = Get1IndResource(kComponentResourceType, i); if ( hdl ) RegisterComponentRomResource((ComponentResource **)hdl, true); } } SetResLoad(oldResLoad); #endif }