this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

CoreServices: Introduce a basic component manager

+476 -66
+1
src/frameworks/CoreServices/CMakeLists.txt
··· 34 34 LSApplicationProxy.m 35 35 LSApplicationWorkspace.m 36 36 constants.m 37 + ComponentManager.cpp 37 38 ) 38 39 39 40 set(DYLIB_COMPAT_VERSION "1.0.0")
+252
src/frameworks/CoreServices/ComponentManager.cpp
··· 1 + /* 2 + This file is part of Darling. 3 + 4 + Copyright (C) 2020 Lubos Dolezel 5 + 6 + Darling is free software: you can redistribute it and/or modify 7 + it under the terms of the GNU General Public License as published by 8 + the Free Software Foundation, either version 3 of the License, or 9 + (at your option) any later version. 10 + 11 + Darling is distributed in the hope that it will be useful, 12 + but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + GNU General Public License for more details. 15 + 16 + You should have received a copy of the GNU General Public License 17 + along with Darling. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #include "ComponentManager.h" 21 + #include <CoreServices/MacErrors.h> 22 + 23 + ComponentManager* ComponentManager::instance() 24 + { 25 + static ComponentManager inst; 26 + return &inst; 27 + } 28 + 29 + ComponentManager::ComponentManager() 30 + { 31 + discoverComponents(); 32 + } 33 + 34 + void ComponentManager::discoverComponents() 35 + { 36 + // TODO 37 + } 38 + 39 + Component ComponentManager::registerComponent(const ComponentDescription* cd, ComponentRoutineUPP entryPointIn, SInt16 flags, 40 + const char* name, const char* info, void* icon) 41 + { 42 + std::unique_lock<std::recursive_mutex> l(m_componentsMutex); 43 + if (flags & registerComponentNoDuplicates) 44 + { 45 + if (!findMatching(cd).empty()) 46 + return nullptr; 47 + } 48 + 49 + ComponentData data; 50 + data.cd = *cd; 51 + data.entryPoint = entryPointIn; 52 + data.instances = 0; 53 + 54 + if (name) 55 + data.name = name; 56 + if (info) 57 + data.info = info; 58 + 59 + ComponentData* dataPtr; 60 + if (flags & registerComponentAfterExisting) 61 + { 62 + m_components.push_back(data); 63 + dataPtr = &m_components.back(); 64 + } 65 + else 66 + { 67 + m_components.push_front(data); 68 + dataPtr = &m_components.front(); 69 + } 70 + 71 + Component c = Component(uintptr_t(nextComponentId++)); 72 + dataPtr->component = c; 73 + 74 + m_componentsMap.insert(std::make_pair(c, dataPtr)); 75 + 76 + return c; 77 + } 78 + 79 + void ComponentManager::setDefault(Component c, SInt16 flags) 80 + { 81 + // FIXME: This is wrong, because we don't honor flags 82 + std::unique_lock<std::recursive_mutex> l(m_componentsMutex); 83 + // Just move the element to the front 84 + 85 + auto itMap = m_componentsMap.find(c); 86 + if (itMap == m_componentsMap.end()) 87 + return; 88 + 89 + for (auto it = m_components.begin(); it != m_components.end(); it++) 90 + { 91 + ComponentData* d = &(*it); 92 + if (d == itMap->second) 93 + { 94 + // TODO: Check whether element address is unchanged after this! 95 + m_components.splice(m_components.begin(), m_components, it); 96 + break; 97 + } 98 + } 99 + } 100 + 101 + OSStatus ComponentManager::unregisterComponent(Component c) 102 + { 103 + std::unique_lock<std::recursive_mutex> l(m_componentsMutex); 104 + 105 + auto itMap = m_componentsMap.find(c); 106 + if (itMap == m_componentsMap.end()) 107 + return invalidComponentID; 108 + 109 + if (itMap->second->instances != 0) 110 + return validInstancesExist; 111 + 112 + for (auto it = m_components.begin(); it != m_components.end(); it++) 113 + { 114 + ComponentData* d = &(*it); 115 + if (d == itMap->second) 116 + { 117 + m_components.erase(it); 118 + break; 119 + } 120 + } 121 + 122 + m_componentsMap.erase(itMap); 123 + return noErr; 124 + } 125 + 126 + std::vector<Component> ComponentManager::findMatching(const ComponentDescription* cd) 127 + { 128 + std::vector<Component> rv; 129 + 130 + std::unique_lock<std::recursive_mutex> l(m_componentsMutex); 131 + 132 + for (const ComponentData& d : m_components) 133 + { 134 + if (!cd->componentManufacturer || cd->componentManufacturer == d.cd.componentManufacturer) 135 + { 136 + if (!cd->componentSubType || cd->componentSubType == d.cd.componentSubType) 137 + { 138 + if (!cd->componentType || cd->componentType == d.cd.componentType) 139 + { 140 + rv.push_back(d.component); 141 + } 142 + } 143 + } 144 + } 145 + 146 + return rv; 147 + } 148 + 149 + ComponentInstance ComponentManager::getComponentInstance(ComponentParameters* desc) 150 + { 151 + #if __LP64__ 152 + return (ComponentInstance) desc->params[0]; 153 + #else 154 + return (ComponentInstance) desc->params[(desc->paramSize / sizeof(long)) - 1]; 155 + #endif 156 + } 157 + 158 + OSStatus ComponentManager::instantiate(Component c, ComponentInstance* out) 159 + { 160 + std::unique_lock<std::recursive_mutex> l(m_componentsMutex); 161 + 162 + *out = nullptr; 163 + 164 + auto itMap = m_componentsMap.find(c); 165 + if (itMap == m_componentsMap.end()) 166 + return invalidComponentID; 167 + 168 + ComponentInstanceData cid; 169 + 170 + cid.component = c; 171 + cid.componentData = itMap->second; 172 + cid.componentData->instances++; 173 + cid.storage = nullptr; 174 + 175 + l.unlock(); 176 + 177 + std::unique_lock<std::recursive_mutex> l2(m_componentInstancesMutex); 178 + ComponentInstance inst = ComponentInstance(uintptr_t(nextInstanceId++)); 179 + 180 + m_componentInstances.insert(std::make_pair(inst, cid)); 181 + l2.unlock(); 182 + 183 + ComponentParameters cp; 184 + cp.flags = 0; 185 + cp.paramSize = sizeof(void*); 186 + cp.what = kComponentOpenSelect; 187 + cp.params[0] = uintptr_t(inst); 188 + 189 + OSStatus status = dispatch(&cp); 190 + if (status != noErr) 191 + { 192 + // "Note that whenever an open request fails, the Component Manager always issues the close request." 193 + dispose(inst); 194 + return status; 195 + } 196 + 197 + *out = inst; 198 + return noErr; 199 + } 200 + 201 + OSStatus ComponentManager::dispose(ComponentInstance c) 202 + { 203 + std::unique_lock<std::recursive_mutex> l(m_componentsMutex); 204 + 205 + auto it = m_componentInstances.find(c); 206 + if (it == m_componentInstances.end()) 207 + return badComponentInstance; 208 + 209 + ComponentParameters cp; 210 + cp.flags = 0; 211 + cp.paramSize = sizeof(void*); 212 + cp.what = kComponentCloseSelect; 213 + cp.params[0] = uintptr_t(c); 214 + 215 + OSStatus status = dispatch(&cp); 216 + 217 + m_componentInstances.erase(it); 218 + return status; 219 + } 220 + 221 + OSStatus ComponentManager::dispatch(ComponentParameters* cp) 222 + { 223 + std::unique_lock<std::recursive_mutex> l(m_componentInstancesMutex); 224 + 225 + auto it = m_componentInstances.find(getComponentInstance(cp)); 226 + if (it == m_componentInstances.end()) 227 + return badComponentInstance; 228 + 229 + return it->second.componentData->entryPoint(cp, it->second.storage); 230 + } 231 + 232 + Handle ComponentManager::getStorage(ComponentInstance ci) 233 + { 234 + std::unique_lock<std::recursive_mutex> l(m_componentsMutex); 235 + 236 + auto it = m_componentInstances.find(ci); 237 + if (it == m_componentInstances.end()) 238 + return nullptr; 239 + 240 + return it->second.storage; 241 + } 242 + 243 + void ComponentManager::setStorage(ComponentInstance ci, Handle storage) 244 + { 245 + std::unique_lock<std::recursive_mutex> l(m_componentsMutex); 246 + 247 + auto it = m_componentInstances.find(ci); 248 + if (it == m_componentInstances.end()) 249 + return; 250 + 251 + it->second.storage = storage; 252 + }
+95
src/frameworks/CoreServices/ComponentManager.h
··· 1 + /* 2 + This file is part of Darling. 3 + 4 + Copyright (C) 2020 Lubos Dolezel 5 + 6 + Darling is free software: you can redistribute it and/or modify 7 + it under the terms of the GNU General Public License as published by 8 + the Free Software Foundation, either version 3 of the License, or 9 + (at your option) any later version. 10 + 11 + Darling is distributed in the hope that it will be useful, 12 + but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + GNU General Public License for more details. 15 + 16 + You should have received a copy of the GNU General Public License 17 + along with Darling. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #ifndef _CS_COMPONENT_MANAGER_H 21 + #define _CS_COMPONENT_MANAGER_H 22 + #include "Components.h" 23 + #include <unordered_map> 24 + #include <mutex> 25 + #include <memory> 26 + #include <vector> 27 + #include <list> 28 + #include <string> 29 + #include <stdint.h> 30 + #include <CoreServices/MacTypes.h> 31 + 32 + class ComponentManager 33 + { 34 + private: 35 + ComponentManager(); 36 + 37 + // Search in /System/Library/Components for components 38 + // Examine resource forks of the main binary, but also check for Resources/$BUNDLE_NAME.rsrc 39 + void discoverComponents(); 40 + public: 41 + static ComponentManager* instance(); 42 + 43 + Component registerComponent(const ComponentDescription* cd, ComponentRoutineUPP entryPoint, SInt16 flags, const char* name, const char* info, void* icon); 44 + void setDefault(Component c, SInt16 flags); 45 + OSStatus unregisterComponent(Component c); 46 + 47 + std::vector<Component> findMatching(const ComponentDescription* cd); 48 + 49 + // Extract ComponentInstance value based on current ABI 50 + static ComponentInstance getComponentInstance(ComponentParameters* desc); 51 + 52 + // Instantiate and call kComponentOpenSelect 53 + OSStatus instantiate(Component c, ComponentInstance* out); 54 + // Call kComponentCloseSelect and free 55 + OSStatus dispose(ComponentInstance c); 56 + // Call component functions 57 + OSStatus dispatch(ComponentParameters* cp); 58 + 59 + Handle getStorage(ComponentInstance ci); 60 + void setStorage(ComponentInstance ci, Handle storage); 61 + private: 62 + struct ComponentData 63 + { 64 + // Assigned identifier 65 + Component component; 66 + 67 + ComponentDescription cd; 68 + ComponentRoutineUPP entryPoint; 69 + std::string name, info; 70 + 71 + uint32_t instances; 72 + }; 73 + 74 + struct ComponentInstanceData 75 + { 76 + // instance of 77 + Component component; 78 + ComponentData* componentData; 79 + 80 + // private data (context) of this instance 81 + Handle storage; 82 + }; 83 + std::unordered_map<ComponentInstance, ComponentInstanceData> m_componentInstances; 84 + uint32_t nextInstanceId = 0x2000; 85 + std::recursive_mutex m_componentInstancesMutex; 86 + 87 + std::list<ComponentData> m_components; 88 + // Contains pointers into m_components 89 + std::unordered_map<Component, ComponentData*> m_componentsMap; 90 + uint32_t nextComponentId = 0x1000; 91 + 92 + std::recursive_mutex m_componentsMutex; 93 + }; 94 + 95 + #endif
+48 -22
src/frameworks/CoreServices/Components.cpp
··· 1 - #include "darling-config.h" 2 1 #include "Components.h" 3 - #include "ComponentsInternal.h" 4 - #include "darling-config.h" 5 2 #include <CoreServices/MacErrors.h> 6 - 7 - #define TRACE1(x) 8 - #define TRACE2(x,y) 3 + #include "ComponentManager.h" 9 4 10 5 Component FindNextComponent(Component prev, ComponentDescription* desc) 11 6 { 12 - TRACE2(prev, desc); 7 + std::vector<Component> components = ComponentManager::instance()->findMatching(desc); 8 + if (components.empty()) 9 + return nullptr; 10 + 11 + if (prev == nullptr) 12 + return components[0]; 13 + 14 + for (size_t i = 0; i < components.size()-1; i++) 15 + { 16 + if (components[i] == prev) 17 + { 18 + return components[i+1]; 19 + } 20 + } 21 + 13 22 return nullptr; 14 23 } 15 24 16 25 long CountComponents(ComponentDescription* desc) 17 26 { 18 - return 0; 27 + return ComponentManager::instance()->findMatching(desc).size(); 19 28 } 20 29 21 30 OSErr OpenAComponent(Component comp, ComponentInstance* out) 22 31 { 23 - TRACE1(comp); 32 + return ComponentManager::instance()->instantiate(comp, out); 33 + } 24 34 25 - if (!out) 26 - return paramErr; 35 + ComponentInstance OpenComponent(Component comp) 36 + { 37 + ComponentInstance rv; 38 + if (ComponentManager::instance()->instantiate(comp, &rv) == noErr) 39 + return rv; 40 + return nullptr; 41 + } 27 42 28 - *out = nullptr; 43 + OSErr CloseComponent(ComponentInstance inst) 44 + { 45 + return ComponentManager::instance()->dispose(inst); 46 + } 29 47 30 - return unimpErr; 48 + Component RegisterComponent(ComponentDescription *cd, ComponentRoutineUPP componentEntryPoint, SInt16 global, 49 + Handle componentName, Handle componentInfo, Handle componentIcon) 50 + { 51 + return ComponentManager::instance()->registerComponent(cd, componentEntryPoint, global, 52 + (const char*) componentName, (const char*) componentInfo, (void*) componentIcon); 31 53 } 32 54 33 - ComponentInstance OpenComponent(Component comp) 55 + OSErr SetDefaultComponent(Component c, SInt16 flags) 34 56 { 35 - // TRACE1(comp); 57 + ComponentManager::instance()->setDefault(c, flags); 58 + return noErr; 59 + } 36 60 37 - ComponentInstance inst; 38 - OpenAComponent(comp, &inst); 39 - return inst; 61 + ComponentResult CallComponentDispatch(ComponentParameters *cp) 62 + { 63 + return ComponentManager::instance()->dispatch(cp); 40 64 } 41 65 42 - OSErr CloseComponent(ComponentInstance inst) 66 + Handle GetComponentInstanceStorage(ComponentInstance aComponentInstance) 43 67 { 44 - // TRACE1(inst); 68 + return ComponentManager::instance()->getStorage(aComponentInstance); 69 + } 45 70 46 - delete inst; 47 - return noErr; 71 + void SetComponentInstanceStorage(ComponentInstance aComponentInstance, Handle theStorage) 72 + { 73 + ComponentManager::instance()->setStorage(aComponentInstance, theStorage); 48 74 } 49 75
-1
src/frameworks/CoreServices/ComponentsInternal.h
··· 1 - include/CoreServices/ComponentsInternal.h
+69 -8
src/frameworks/CoreServices/include/CoreServices/Components.h
··· 2 2 #define COMPONENTS_H 3 3 #include <MacTypes.h> 4 4 5 - #ifdef __cplusplus 6 - class CarbonComponent; 7 - #else 8 - struct __CarbonComponent; 9 - typedef struct __CarbonComponent CarbonComponent; 10 - #endif 11 5 struct ComponentDescription; 12 6 typedef struct ComponentDescription ComponentDescription; 13 7 14 - typedef CarbonComponent* ComponentInstance; 15 - typedef void* Component; 8 + typedef struct __ComponentInstance* ComponentInstance; 9 + 10 + typedef SInt32 ComponentResult; 11 + 12 + typedef struct ComponentRecord 13 + { 14 + long data[1]; 15 + } ComponentRecord; 16 + typedef ComponentRecord* Component; 17 + 18 + typedef struct ComponentParameters 19 + { 20 + UInt8 flags; 21 + UInt8 paramSize; 22 + SInt16 what; 23 + #if __LP64__ 24 + UInt32 padding; 25 + #endif 26 + // 64-bit platforms: 27 + // params[0] is ComponentInstance 28 + // params[1+] are arguments 29 + // 30 + // 32-bit platforms 31 + // params[last] is ComponentInstance 32 + // params[-last] are arguments in reverse order 33 + long params[1]; 34 + } ComponentParameters; 35 + 36 + enum { 37 + registerComponentGlobal = 1, 38 + registerComponentNoDuplicates = 2, 39 + registerComponentAfterExisting = 4, 40 + registerComponentAliasesOnly = 8, 41 + }; 42 + 43 + enum { 44 + kComponentOpenSelect = -1, 45 + kComponentCloseSelect = -2, 46 + kComponentCanDoSelect = -3, 47 + kComponentVersionSelect = -4, 48 + kComponentRegisterSelect = -5, 49 + kComponentTargetSelect = -6, 50 + kComponentUnregisterSelect = -7, 51 + kComponentGetMPWorkFunctionSelect = -8, 52 + kComponentExecuteWiredActionSelect = -9, 53 + kComponentGetPublicResourceSelect = -10, 54 + }; 55 + 56 + enum { 57 + defaultComponentIdentical = 0, 58 + defaultComponentFlags = 1, 59 + defaultComponentAnyManufacturer = 2, 60 + defaultComponentAnySubType = 4, 61 + defaultComponentAnyFlagsAnyManufacturer = (defaultComponentFlags + defaultComponentAnyManufacturer), 62 + defaultComponentAnyFlagsAnyManufacturerAnySubType = (defaultComponentFlags + defaultComponentAnyManufacturer + defaultComponentAnySubType), 63 + }; 64 + 65 + typedef ComponentResult (*ComponentRoutineProcPtr)(ComponentParameters* cp, Handle componentStorage); 66 + typedef ComponentRoutineProcPtr ComponentRoutineUPP; 16 67 17 68 #ifdef __cplusplus 18 69 extern "C" { ··· 24 75 OSErr OpenAComponent(Component comp, ComponentInstance* out); 25 76 ComponentInstance OpenComponent(Component comp); 26 77 OSErr CloseComponent(ComponentInstance inst); 78 + 79 + Component RegisterComponent(ComponentDescription *cd, ComponentRoutineUPP componentEntryPoint, SInt16 global, 80 + Handle componentName, Handle componentInfo, Handle componentIcon); 81 + OSErr SetDefaultComponent(Component c, SInt16 flags); 82 + 83 + // ComponentResult CallComponentFunction(ComponentParameters *params, ComponentFunctionUPP func); 84 + ComponentResult CallComponentDispatch(ComponentParameters *cp); 85 + 86 + Handle GetComponentInstanceStorage(ComponentInstance aComponentInstance); 87 + void SetComponentInstanceStorage(ComponentInstance aComponentInstance, Handle theStorage); 27 88 28 89 #ifdef __cplusplus 29 90 }
-35
src/frameworks/CoreServices/include/CoreServices/ComponentsInternal.h
··· 1 - #ifndef COMPONENTSINTERNAL_H 2 - #define COMPONENTSINTERNAL_H 3 - 4 - class CarbonComponent 5 - { 6 - public: 7 - virtual ~CarbonComponent() {} 8 - }; 9 - 10 - inline static UInt32 GetComponentType(Component comp) 11 - { 12 - long l = long(comp); 13 - return l & 0xffff0000; 14 - } 15 - 16 - inline static UInt32 GetComponentIndex(Component comp) 17 - { 18 - long l = long(comp); 19 - return l & 0xffff; 20 - } 21 - 22 - inline static Component CreateComponent(UInt32 type, UInt32 index) 23 - { 24 - long l = type & 0xffff0000; 25 - l |= (index & 0xffff); 26 - return (void*) l; 27 - } 28 - 29 - enum 30 - { 31 - kComponentTypeAudioUnit = 'au\0\0' 32 - }; 33 - 34 - #endif 35 -
+11
src/frameworks/CoreServices/include/CoreServices/MacErrors.h
··· 39 39 40 40 #define kMPTimeoutErr -29296 41 41 42 + enum { 43 + invalidComponentID = -3000, 44 + validInstancesExist = -3001, 45 + componentNotCaptured = -3002, 46 + componentDontRegister = -3003, 47 + unresolvedComponentDLLErr = -3004, 48 + retryComponentRegistrationErr = -3005, 49 + badComponentInstance = (int)0x80008001, 50 + badComponentSelector = (int)0x80008002, 51 + }; 52 + 42 53 #endif