···11+/*
22+This file is part of Darling.
33+44+Copyright (C) 2020 Lubos Dolezel
55+66+Darling is free software: you can redistribute it and/or modify
77+it under the terms of the GNU General Public License as published by
88+the Free Software Foundation, either version 3 of the License, or
99+(at your option) any later version.
1010+1111+Darling is distributed in the hope that it will be useful,
1212+but WITHOUT ANY WARRANTY; without even the implied warranty of
1313+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414+GNU General Public License for more details.
1515+1616+You should have received a copy of the GNU General Public License
1717+along with Darling. If not, see <http://www.gnu.org/licenses/>.
1818+*/
1919+2020+#include "ComponentManager.h"
2121+#include <CoreServices/MacErrors.h>
2222+2323+ComponentManager* ComponentManager::instance()
2424+{
2525+ static ComponentManager inst;
2626+ return &inst;
2727+}
2828+2929+ComponentManager::ComponentManager()
3030+{
3131+ discoverComponents();
3232+}
3333+3434+void ComponentManager::discoverComponents()
3535+{
3636+ // TODO
3737+}
3838+3939+Component ComponentManager::registerComponent(const ComponentDescription* cd, ComponentRoutineUPP entryPointIn, SInt16 flags,
4040+ const char* name, const char* info, void* icon)
4141+{
4242+ std::unique_lock<std::recursive_mutex> l(m_componentsMutex);
4343+ if (flags & registerComponentNoDuplicates)
4444+ {
4545+ if (!findMatching(cd).empty())
4646+ return nullptr;
4747+ }
4848+4949+ ComponentData data;
5050+ data.cd = *cd;
5151+ data.entryPoint = entryPointIn;
5252+ data.instances = 0;
5353+5454+ if (name)
5555+ data.name = name;
5656+ if (info)
5757+ data.info = info;
5858+5959+ ComponentData* dataPtr;
6060+ if (flags & registerComponentAfterExisting)
6161+ {
6262+ m_components.push_back(data);
6363+ dataPtr = &m_components.back();
6464+ }
6565+ else
6666+ {
6767+ m_components.push_front(data);
6868+ dataPtr = &m_components.front();
6969+ }
7070+7171+ Component c = Component(uintptr_t(nextComponentId++));
7272+ dataPtr->component = c;
7373+7474+ m_componentsMap.insert(std::make_pair(c, dataPtr));
7575+7676+ return c;
7777+}
7878+7979+void ComponentManager::setDefault(Component c, SInt16 flags)
8080+{
8181+ // FIXME: This is wrong, because we don't honor flags
8282+ std::unique_lock<std::recursive_mutex> l(m_componentsMutex);
8383+ // Just move the element to the front
8484+8585+ auto itMap = m_componentsMap.find(c);
8686+ if (itMap == m_componentsMap.end())
8787+ return;
8888+8989+ for (auto it = m_components.begin(); it != m_components.end(); it++)
9090+ {
9191+ ComponentData* d = &(*it);
9292+ if (d == itMap->second)
9393+ {
9494+ // TODO: Check whether element address is unchanged after this!
9595+ m_components.splice(m_components.begin(), m_components, it);
9696+ break;
9797+ }
9898+ }
9999+}
100100+101101+OSStatus ComponentManager::unregisterComponent(Component c)
102102+{
103103+ std::unique_lock<std::recursive_mutex> l(m_componentsMutex);
104104+105105+ auto itMap = m_componentsMap.find(c);
106106+ if (itMap == m_componentsMap.end())
107107+ return invalidComponentID;
108108+109109+ if (itMap->second->instances != 0)
110110+ return validInstancesExist;
111111+112112+ for (auto it = m_components.begin(); it != m_components.end(); it++)
113113+ {
114114+ ComponentData* d = &(*it);
115115+ if (d == itMap->second)
116116+ {
117117+ m_components.erase(it);
118118+ break;
119119+ }
120120+ }
121121+122122+ m_componentsMap.erase(itMap);
123123+ return noErr;
124124+}
125125+126126+std::vector<Component> ComponentManager::findMatching(const ComponentDescription* cd)
127127+{
128128+ std::vector<Component> rv;
129129+130130+ std::unique_lock<std::recursive_mutex> l(m_componentsMutex);
131131+132132+ for (const ComponentData& d : m_components)
133133+ {
134134+ if (!cd->componentManufacturer || cd->componentManufacturer == d.cd.componentManufacturer)
135135+ {
136136+ if (!cd->componentSubType || cd->componentSubType == d.cd.componentSubType)
137137+ {
138138+ if (!cd->componentType || cd->componentType == d.cd.componentType)
139139+ {
140140+ rv.push_back(d.component);
141141+ }
142142+ }
143143+ }
144144+ }
145145+146146+ return rv;
147147+}
148148+149149+ComponentInstance ComponentManager::getComponentInstance(ComponentParameters* desc)
150150+{
151151+#if __LP64__
152152+ return (ComponentInstance) desc->params[0];
153153+#else
154154+ return (ComponentInstance) desc->params[(desc->paramSize / sizeof(long)) - 1];
155155+#endif
156156+}
157157+158158+OSStatus ComponentManager::instantiate(Component c, ComponentInstance* out)
159159+{
160160+ std::unique_lock<std::recursive_mutex> l(m_componentsMutex);
161161+162162+ *out = nullptr;
163163+164164+ auto itMap = m_componentsMap.find(c);
165165+ if (itMap == m_componentsMap.end())
166166+ return invalidComponentID;
167167+168168+ ComponentInstanceData cid;
169169+170170+ cid.component = c;
171171+ cid.componentData = itMap->second;
172172+ cid.componentData->instances++;
173173+ cid.storage = nullptr;
174174+175175+ l.unlock();
176176+177177+ std::unique_lock<std::recursive_mutex> l2(m_componentInstancesMutex);
178178+ ComponentInstance inst = ComponentInstance(uintptr_t(nextInstanceId++));
179179+180180+ m_componentInstances.insert(std::make_pair(inst, cid));
181181+ l2.unlock();
182182+183183+ ComponentParameters cp;
184184+ cp.flags = 0;
185185+ cp.paramSize = sizeof(void*);
186186+ cp.what = kComponentOpenSelect;
187187+ cp.params[0] = uintptr_t(inst);
188188+189189+ OSStatus status = dispatch(&cp);
190190+ if (status != noErr)
191191+ {
192192+ // "Note that whenever an open request fails, the Component Manager always issues the close request."
193193+ dispose(inst);
194194+ return status;
195195+ }
196196+197197+ *out = inst;
198198+ return noErr;
199199+}
200200+201201+OSStatus ComponentManager::dispose(ComponentInstance c)
202202+{
203203+ std::unique_lock<std::recursive_mutex> l(m_componentsMutex);
204204+205205+ auto it = m_componentInstances.find(c);
206206+ if (it == m_componentInstances.end())
207207+ return badComponentInstance;
208208+209209+ ComponentParameters cp;
210210+ cp.flags = 0;
211211+ cp.paramSize = sizeof(void*);
212212+ cp.what = kComponentCloseSelect;
213213+ cp.params[0] = uintptr_t(c);
214214+215215+ OSStatus status = dispatch(&cp);
216216+217217+ m_componentInstances.erase(it);
218218+ return status;
219219+}
220220+221221+OSStatus ComponentManager::dispatch(ComponentParameters* cp)
222222+{
223223+ std::unique_lock<std::recursive_mutex> l(m_componentInstancesMutex);
224224+225225+ auto it = m_componentInstances.find(getComponentInstance(cp));
226226+ if (it == m_componentInstances.end())
227227+ return badComponentInstance;
228228+229229+ return it->second.componentData->entryPoint(cp, it->second.storage);
230230+}
231231+232232+Handle ComponentManager::getStorage(ComponentInstance ci)
233233+{
234234+ std::unique_lock<std::recursive_mutex> l(m_componentsMutex);
235235+236236+ auto it = m_componentInstances.find(ci);
237237+ if (it == m_componentInstances.end())
238238+ return nullptr;
239239+240240+ return it->second.storage;
241241+}
242242+243243+void ComponentManager::setStorage(ComponentInstance ci, Handle storage)
244244+{
245245+ std::unique_lock<std::recursive_mutex> l(m_componentsMutex);
246246+247247+ auto it = m_componentInstances.find(ci);
248248+ if (it == m_componentInstances.end())
249249+ return;
250250+251251+ it->second.storage = storage;
252252+}
+95
src/frameworks/CoreServices/ComponentManager.h
···11+/*
22+This file is part of Darling.
33+44+Copyright (C) 2020 Lubos Dolezel
55+66+Darling is free software: you can redistribute it and/or modify
77+it under the terms of the GNU General Public License as published by
88+the Free Software Foundation, either version 3 of the License, or
99+(at your option) any later version.
1010+1111+Darling is distributed in the hope that it will be useful,
1212+but WITHOUT ANY WARRANTY; without even the implied warranty of
1313+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414+GNU General Public License for more details.
1515+1616+You should have received a copy of the GNU General Public License
1717+along with Darling. If not, see <http://www.gnu.org/licenses/>.
1818+*/
1919+2020+#ifndef _CS_COMPONENT_MANAGER_H
2121+#define _CS_COMPONENT_MANAGER_H
2222+#include "Components.h"
2323+#include <unordered_map>
2424+#include <mutex>
2525+#include <memory>
2626+#include <vector>
2727+#include <list>
2828+#include <string>
2929+#include <stdint.h>
3030+#include <CoreServices/MacTypes.h>
3131+3232+class ComponentManager
3333+{
3434+private:
3535+ ComponentManager();
3636+3737+ // Search in /System/Library/Components for components
3838+ // Examine resource forks of the main binary, but also check for Resources/$BUNDLE_NAME.rsrc
3939+ void discoverComponents();
4040+public:
4141+ static ComponentManager* instance();
4242+4343+ Component registerComponent(const ComponentDescription* cd, ComponentRoutineUPP entryPoint, SInt16 flags, const char* name, const char* info, void* icon);
4444+ void setDefault(Component c, SInt16 flags);
4545+ OSStatus unregisterComponent(Component c);
4646+4747+ std::vector<Component> findMatching(const ComponentDescription* cd);
4848+4949+ // Extract ComponentInstance value based on current ABI
5050+ static ComponentInstance getComponentInstance(ComponentParameters* desc);
5151+5252+ // Instantiate and call kComponentOpenSelect
5353+ OSStatus instantiate(Component c, ComponentInstance* out);
5454+ // Call kComponentCloseSelect and free
5555+ OSStatus dispose(ComponentInstance c);
5656+ // Call component functions
5757+ OSStatus dispatch(ComponentParameters* cp);
5858+5959+ Handle getStorage(ComponentInstance ci);
6060+ void setStorage(ComponentInstance ci, Handle storage);
6161+private:
6262+ struct ComponentData
6363+ {
6464+ // Assigned identifier
6565+ Component component;
6666+6767+ ComponentDescription cd;
6868+ ComponentRoutineUPP entryPoint;
6969+ std::string name, info;
7070+7171+ uint32_t instances;
7272+ };
7373+7474+ struct ComponentInstanceData
7575+ {
7676+ // instance of
7777+ Component component;
7878+ ComponentData* componentData;
7979+8080+ // private data (context) of this instance
8181+ Handle storage;
8282+ };
8383+ std::unordered_map<ComponentInstance, ComponentInstanceData> m_componentInstances;
8484+ uint32_t nextInstanceId = 0x2000;
8585+ std::recursive_mutex m_componentInstancesMutex;
8686+8787+ std::list<ComponentData> m_components;
8888+ // Contains pointers into m_components
8989+ std::unordered_map<Component, ComponentData*> m_componentsMap;
9090+ uint32_t nextComponentId = 0x1000;
9191+9292+ std::recursive_mutex m_componentsMutex;
9393+};
9494+9595+#endif