1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
|
#include <precomp.h>
#include <bfc/wasabi_std.h>
#include "compon.h"
//#include <api/wac/main.h> // CUT!
#ifndef WASABINOMAINAPI
#include <api/metadb/metadb.h>
#include <api/wac/papi.h>
#endif
#include <api/script/objects/compoobj.h>
#include <api/wndmgr/container.h>
#include <api/skin/skinparse.h>
#include <api/wac/wac.h>
#include <api/script/objects/wacobj.h>
#include <api/wnd/wndtrack.h>
#include <api/script/objecttable.h>
#include <api/config/items/cfgitemi.h>
#include <bfc/loadlib.h>
//#include <bfc/util/profiler.h>
#include <api/locales/xlatstr.h>
#include <bfc/file/recursedir.h>
#include <api/service/svc_enum.h>
#include <api/service/services.h>
#include <api/service/servicei.h>
#include <api/skin/skin.h>
#include <api/script/scriptmgr.h>
#include <bfc/parse/pathparse.h>
#ifndef WASABINOMAINAPI
#include <api/api1.h>
#endif
#include <api/application/wkc.h>
#include <api/wndmgr/skinembed.h>
#include <api/script/objects/compoobj.h>
#include <api/wnd/usermsg.h>
#include <bfc/util/inifile.h>
class CShutdownCallback {
public:
virtual void rl_onShutdown()=0;
};
extern GUID baseGUID;
static TList<GUID> loadlist, banlist;
// compon.cpp : maintains the list of installed components, and installs
// each one
// keep a list of component pointers as well as instances
class component_slot
{
public:
#ifndef WASABINOMAINAPI
component_slot(Library *_dll, WaComponent *_wac, ComponentAPI *_api, GUID g, const wchar_t *orig_path)
: dll(_dll), wac(_wac), path(orig_path), guid(g), componentapi(_api) {
#else
component_slot(Library *_dll, WaComponent *_wac, GUID g, const wchar_t *orig_path)
: dll(_dll), wac(_wac), path(orig_path), guid(g) {
#endif
int fnlen = wcslen(Wasabi::Std::filename(orig_path));
path.trunc(-fnlen);
postonregsvcs = 0;
postoncreate = 0;
loadearly = 0; // will be filled in later
}
~component_slot() {
#ifndef WASABINOMAINAPI
if (dll != NULL) PAPI::destroyAPI(componentapi);
#endif
delete dll;
}
void registerServices() {
#ifndef WASABINOMAINAPI
if (!postonregsvcs) wac->registerServices(componentapi);
#else
if (!postonregsvcs) wac->registerServices(WASABI_API_SVC);
#endif
postonregsvcs = 1;
}
void onCreate() {
if (!postoncreate) wac->onCreate();
postoncreate = 1;
}
Library *dll;
WaComponent *wac; // we don't delete this
StringW path;
GUID guid; // prevent spoofing
#ifndef WASABINOMAINAPI
ComponentAPI *componentapi;
#endif
int postoncreate;
int postonregsvcs;
int loadearly;
};
static PtrList<component_slot> components;
/*static PtrList<cd_entry> cd_list;
static PtrList<ComponentObject> co_list;*/
// the minimum SDK version # we accept
const int WA_COMPONENT_VER_MIN = WA_COMPONENT_VERSION;
static int postComponentCommand(GUID guid, const wchar_t *command, int p1, int p2, void *ptr, int ptrlen, int waitforanswer);
class ComponPostEntry {
public:
ComponPostEntry(GUID pguid, const wchar_t *pcommand, int pp1, int pp2, void *pptr, int pptrlen, int pwait) :
guid(pguid), command(pcommand), p1(pp1), p2(pp2), ptr(pptr), ptrlen(pptrlen), waitforanswer(pwait),
posted(0), result(0) { }
GUID guid;
StringW command;
int p1, p2;
void *ptr;
int ptrlen;
int waitforanswer;
int posted;
int result;
};
static PtrList<StringW> preloads;
void ComponentManager::addStaticComponent(WaComponent *component) {
GUID guid = component->getGUID();
if (!checkGUID(guid)) return; // guid check (banlist etc.)
#ifndef WASABINOMAINAPI
// reuse main api *
components.addItem(new component_slot(NULL, component, api, guid, NULL));
#else
components.addItem(new component_slot(NULL, component, guid, NULL));
#endif
}
void ComponentManager::addPreloadComponent(const wchar_t *filename)
{
foreach(preloads)
if (PATHEQL(filename, preloads.getfor()->getValue())) return;// no dups
endfor
preloads.addItem(new StringW(filename));
}
void ComponentManager::loadPreloads() {
foreach(preloads)
load(preloads.getfor()->getValue());
endfor
preloads.deleteAll();
}
void ComponentManager::load(const wchar_t *filename) {
// ensure no duplicate filenames
foreach(components)
if (PATHEQL(filename, components.getfor()->dll->getName())) return;
endfor
#ifdef WA3COMPATIBILITY
// let kernel controller test the file
WasabiKernelController *wkc = Main::getKernelController();
if (wkc && !wkc->testComponent(filename)) return;
#endif
// check if they have an ini (to get guid faster)
StringW inifile = filename;
const wchar_t *ext = Wasabi::Std::extension(inifile);
int len = wcslen(ext);
inifile.trunc(-len);
inifile.cat(L"ini");
IniFile ini(inifile);
GUID ini_guid = ini.getGuid(L"component", L"guid");
if (!checkGUID(ini_guid, TRUE)) return;
// PR_ENTER2("load component", filename);
// attach the DLL
Library *dll = new Library(filename);
if (!dll->load()) {
delete dll;
return;
}
// check the version of SDK it was compiled with
WACGETVERSION wac_get_version = (WACGETVERSION)dll->getProcAddress("WAC_getVersion");
if (wac_get_version == NULL) {
delete dll;
return;
}
int version = (*wac_get_version)();
if (version < WA_COMPONENT_VER_MIN || // defined above
version > WA_COMPONENT_VERSION) { // from wac.h
delete dll;
return;
}
// init the dll itself
WACINIT wacinit = (WACINIT)dll->getProcAddress("WAC_init");
if (wacinit != NULL) (*wacinit)(dll->getHandle());
WACENUMCOMPONENT wec = (WACENUMCOMPONENT)dll->getProcAddress("WAC_enumComponent");
if (wec == NULL) {
delete dll;
return;
}
// fetch the pointer
WaComponent *wac = (*wec)(0);
GUID guid = wac->getGUID();
if (ini_guid != INVALID_GUID && guid != ini_guid) {
delete dll;
DebugString("guids didn't match! %s", filename);
return;
}
// check if we want to load this GUID
if (!checkGUID(guid)) {
delete dll;
return;
}
#ifndef WASABINOMAINAPI
// allocate an api pointer bound to their GUID
ComponentAPI *newapi = PAPI::createAPI(wac, guid);
if (newapi == NULL) {
delete dll;
return;
}
#endif
PathParserW pp(filename);
StringW path;
for (int i=0;i<pp.getNumStrings()-1;i++)
{
path.AppendFolder(pp.enumString(i));
}
wac->setComponentPath(path);
// keep track of dll handles for shutdown
components.addItem(new component_slot(dll, wac,
#ifndef WASABINOMAINAPI
newapi,
#endif
guid, filename));
// PR_LEAVE();
}
const wchar_t *ComponentManager::getComponentPath(GUID g) {
foreach(components)
if (g == components.getfor()->guid) {
return components.getfor()->path;
}
endfor
return NULL;
}
void ComponentManager::startupDBs() {
/* for (int i=0;i<components.getNumItems();i++)
MetaDB::addComponentDB(components.enumItem(i)->wac);*/
}
void ComponentManager::shutdownDBs() {
#ifndef WASABINOMAINAPI
for (int i = 0; i < components.getNumItems(); i++) {
//MetaDB::getBaseDB()->removeComponentDB(components[i]->wac);
(static_cast<ComponentAPI1 *>(components[i]->componentapi))->shutdownDB();
}
#else
//MULTIAPI-FIXME: solve the shutdownDB puzzle
#endif
}
void ComponentManager::unloadAll() {
// cable out! let 'er go!
// deleteAllCD(); // deletes compwnds
foreach(components)
components.getfor()->wac->deregisterServices();
endfor
foreach(components)
components.getfor()->wac->onDestroy();
endfor
components.deleteAll(); // free the DLLs, and kill their API *'s
}
int ComponentManager::checkGUID(GUID &g, int invalid_ok) {
// no invalid guid
if (!invalid_ok && g == INVALID_GUID) return FALSE;
// check against banlist
if (banlist.haveItem(g)) return FALSE;
// check against load-only list
if (loadlist.getNumItems() && !loadlist.haveItem(g)) return FALSE;
// ensure no duplicate GUIDs
foreach(components)
if (g == components.getfor()->guid) {
//CUT StringPrintf s("%s and %s", components.getfor()->dll->getName(), filename);
//CUT Std::messageBox(s, "Duplicate component guid", MB_OK);
return FALSE;
}
endfor
// ok
return TRUE;
}
WaComponent *ComponentManager::enumComponent(int component) {
if (component < 0 || component >= components.getNumItems()) return NULL;
return components[component]->wac;
}
void ComponentManager::loadAll(const wchar_t *path) {
#if 0//CUT
static const char *loadorder[] = {
"wasabi.system/pngload.wac",
"wasabi.player/core.wac",
"metrics.wac", // so metrics dialog appears before the splash screen
"winamp/winamp.wac", // so splash screen displays right after startup
"winamp/pledit.wac",
"winamp/library.wac",
"preferences.wac", // so prefs has the system groups at the top
"skinswitch.wac", // so skinswitch is the first non internal prefs screen, ignored if not present. fucko: need to modify prefs system so we don't need to load in any particular order
NULL
};
for (int i = 0; loadorder[i] != NULL; i++) {
StringPrintf fn("%s%s%s", WACDIR, DIRCHARSTR, loadorder[i]);
ComponentManager::load(fn);
}
#endif
RecurseDir dir(path, L"*.*");// have to do *.* to get subdirs
while (dir.next()) {
StringPathCombine fn(dir.getPath(), dir.getFilename());
const wchar_t *ext = Wasabi::Std::extension(fn);
if (!WCSICMP(ext, L"wac"))
ComponentManager::load(fn);
}
}
void ComponentManager::postLoad(int f) { // two-level startup procedure
// note we're calling the slot, not the component directly
// allow punk-ass bitches to load early if need be
foreach(components)
if ((components.getfor()->loadearly = !!components.getfor()->wac->onNotify(WAC_NOTIFY_LOADEARLY))) {
components.getfor()->registerServices();
}
endfor
foreach(components)
if (!components.getfor()->loadearly)
components.getfor()->registerServices();
endfor
foreach(components)
components.getfor()->onCreate();
endfor
if (f) ObjectTable::loadExternalClasses();
}
void ComponentManager::broadcastNotify(int cmd, int param1, int param2) {
foreach(components)
if ((components.getfor()->loadearly = !!components.getfor()->wac->onNotify(WAC_NOTIFY_LOADEARLY, cmd, param1, param2)))
components.getfor()->wac->onNotify(cmd, param1, param2);
endfor
foreach(components)
if (!components.getfor()->loadearly)
components.getfor()->wac->onNotify(cmd, param1, param2);
endfor
}
void ComponentManager::sendNotify(GUID guid, int cmd, int param1, int param2) {
WaComponent *wac = getComponentFromGuid(guid);
if (wac)
wac->onNotify(cmd, param1, param2);
}
int ComponentManager::sendCommand(GUID guid, const wchar_t *command, int p1, int p2, void *ptr, int ptrlen) {
if (command == NULL) return 0;
WaComponent *wac = getComponentFromGuid(guid);
if (wac) return wac->onCommand(command, p1, p2, ptr, ptrlen);
return 0;
}
int ComponentManager::postCommand(GUID guid, const wchar_t *command, int p1, int p2, void *ptr, int ptrlen, int waitforanswer) {
#ifdef WA3COMPATIBILITY // todo: make thread id part of application api
if(Std::getCurrentThreadId()==Main::getThreadId() && waitforanswer) {
// if it is already the main thread calling, just pass the command to sendCommand
return sendCommand(guid,command,p1,p2,ptr,ptrlen);
}
#endif
ComponPostEntry *cpe=new ComponPostEntry(guid,command,p1,p2,ptr,ptrlen,waitforanswer);
componPostEntries.addItem(cpe);
#ifdef WIN32
#ifdef WA3COMPATIBILITY // todo: make this a call to application api
PostMessage(Main::gethWnd(),UMSG_COMPON_POSTMESSAGE,0,0); // ask the main thread to call mainthreadpostCommands();
#endif
#else
PostMessage(None,UMSG_COMPON_POSTMESSAGE,0,0); // ask the main thread to call mainthreadpostCommands();
#endif
if(waitforanswer) {
while(!cpe->posted) Sleep(1);
int res=cpe->result;
componPostEntries.removeItem(cpe);
delete(cpe);
return res;
}
return 0; // cpe will get deleted by mainthreadpostCommands();
}
void ComponentManager::broadcastCommand(const wchar_t *command, int p1, int p2, void *ptr, int ptrlen) {
if (command == NULL) return;
for (int i = 0; i < components.getNumItems(); i++) {
components[i]->wac->onCommand(command, p1, p2, ptr, ptrlen);
}
}
int ComponentManager::getNumComponents() {
return components.getNumItems();
}
GUID ComponentManager::getComponentGUID(int c) {
if (c >= components.getNumItems()) return INVALID_GUID;
return components[c]->guid;
}
const wchar_t *ComponentManager::getComponentName(GUID g)
{
WaComponent *wac = getComponentFromGuid(g);
if (wac)
return wac->getName();
return NULL;
}
CfgItem *ComponentManager::getCfgInterface(GUID g) {
WaComponent *wac = getComponentFromGuid(g);
if (wac == NULL) return NULL;
return wac->getCfgInterface(0);
}
WaComponent *ComponentManager::getComponentFromGuid(GUID g) {
if (g == INVALID_GUID) return NULL;
for (int i=0;i<components.getNumItems();i++) {
if (g == components[i]->guid)
return components[i]->wac;
}
return NULL;
}
void ComponentManager::mainThread_handlePostCommands() {
// critical section
for(int i=0;i<componPostEntries.getNumItems();i++) {
ComponPostEntry *cpe=componPostEntries[i];
if(!cpe->posted) {
sendCommand(cpe->guid,cpe->command.getValue(),cpe->p1,cpe->p2,cpe->ptr,cpe->ptrlen);
if(cpe->waitforanswer) cpe->posted=1;
else {
delete cpe;
componPostEntries.removeByPos(i);
i--;
}
}
}
}
PtrList<ComponPostEntry> ComponentManager::componPostEntries;
|