1 /*****************************************************************************
2 * main.cpp: ActiveX control for VLC
3 *****************************************************************************
4 * Copyright (C) 2005 the VideoLAN team
6 * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
34 #define COMPANY_STR "VideoLAN"
35 #define PROGRAM_STR "VLCPlugin"
36 #define DESCRIPTION "VideoLAN VLC ActiveX Plugin"
38 #define THREADING_MODEL "Apartment"
39 #define MISC_STATUS "131473"
41 #define PROGID_STR COMPANY_STR"."PROGRAM_STR
43 #define GUID_STRLEN 39
46 ** MingW headers do not declare those
48 extern const CATID CATID_SafeForInitializing;
49 extern const CATID CATID_SafeForScripting;
51 static LONG i_class_ref= 0;
52 static HINSTANCE h_instance= 0;
54 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
56 HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
60 if( (CLSID_VLCPlugin == rclsid)
61 || (CLSID_VLCPlugin2 == rclsid) )
63 VLCPluginClass *plugin = new VLCPluginClass(&i_class_ref, h_instance, rclsid);
64 hr = plugin->QueryInterface(riid, ppv);
70 STDAPI DllCanUnloadNow(VOID)
72 return (0 == i_class_ref) ? S_OK: S_FALSE;
75 static inline HKEY keyCreate(HKEY parentKey, LPCSTR keyName)
78 if( ERROR_SUCCESS == RegCreateKeyExA(parentKey, keyName, 0, NULL,
79 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &childKey, NULL) )
86 static inline HKEY keySet(HKEY hKey, LPCSTR valueName, const void *s, size_t len)
90 RegSetValueExA(hKey, valueName, 0, REG_SZ,
96 static inline HKEY keySetDef(HKEY hKey, const void *s, size_t len)
98 return keySet(hKey, NULL, s, len);
101 static inline HKEY keySetDef(HKEY hKey, LPCSTR s)
103 return keySetDef(hKey, s, strlen(s)+1);
106 static inline HKEY keyClose(HKEY hKey)
115 static HRESULT UnregisterProgID(REFCLSID rclsid, unsigned int version)
117 LPCSTR psz_CLSID = CStrFromGUID(rclsid);
119 if( NULL == psz_CLSID )
120 return E_OUTOFMEMORY;
122 char progId[sizeof(PROGID_STR)+16];
123 sprintf(progId, "%s.%u", PROGID_STR, version);
125 SHDeleteKeyA(HKEY_CLASSES_ROOT, progId);
128 if( ERROR_SUCCESS == RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_WRITE, &hClsIDKey) )
130 SHDeleteKey(hClsIDKey, psz_CLSID);
131 RegCloseKey(hClsIDKey);
133 CoTaskMemFree((void *)psz_CLSID);
136 STDAPI DllUnregisterServer(VOID)
138 // unregister type lib from the registry
139 UnRegisterTypeLib(LIBID_AXVLC, 1, 0, LOCALE_NEUTRAL, SYS_WIN32);
141 // remove component categories we supports
143 if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
144 NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
145 CATID implCategories[] = {
147 CATID_PersistsToPropertyBag,
148 CATID_SafeForInitializing,
149 CATID_SafeForScripting,
152 pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin,
153 sizeof(implCategories)/sizeof(CATID), implCategories);
154 pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin2,
155 sizeof(implCategories)/sizeof(CATID), implCategories);
159 SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
161 UnregisterProgID(CLSID_VLCPlugin, 1);
162 UnregisterProgID(CLSID_VLCPlugin2, 1);
167 static HRESULT RegisterClassID(HKEY hParent, REFCLSID rclsid, unsigned int version, const char *path, size_t pathLen)
171 LPCSTR psz_CLSID = CStrFromGUID(rclsid);
173 if( NULL == psz_CLSID )
174 return E_OUTOFMEMORY;
176 hClassKey = keyCreate(hParent, psz_CLSID);
177 CoTaskMemFree((void *)psz_CLSID);
179 if( NULL != hClassKey )
182 keySetDef(hClassKey, DESCRIPTION, sizeof(DESCRIPTION));
185 keyClose(keyCreate(hClassKey, "Control"));
187 // Insertable key value
188 //keyClose(keyCreate(hClassKey, "Insertable"));
190 // ToolboxBitmap32 key value
192 char iconPath[pathLen+3];
193 memcpy(iconPath, path, pathLen);
194 strcpy(iconPath+pathLen, ",1");
195 keyClose(keySetDef(keyCreate(hClassKey,
197 iconPath, sizeof(iconPath)));
200 #ifdef BUILD_LOCALSERVER
201 // LocalServer32 key value
202 keyClose(keySetDef(keyCreate(hClassKey,
203 "LocalServer32", path, pathLen+1)));
205 // InprocServer32 key value
207 HKEY hSubKey = keySetDef(keyCreate(hClassKey,
212 THREADING_MODEL, sizeof(THREADING_MODEL));
217 // MiscStatus key value
218 keyClose(keySetDef(keyCreate(hClassKey,
220 MISC_STATUS, sizeof(MISC_STATUS)));
222 // Programmable key value
223 keyClose(keyCreate(hClassKey, "Programmable"));
227 char progId[sizeof(PROGID_STR)+16];
228 sprintf(progId, "%s.%u", PROGID_STR, version);
229 keyClose(keySetDef(keyCreate(hClassKey,
234 // VersionIndependentProgID key value
235 keyClose(keySetDef(keyCreate(hClassKey,
236 "VersionIndependentProgID"),
237 PROGID_STR, sizeof(PROGID_STR)));
242 sprintf(ver, "%u.0", version);
243 keyClose(keySetDef(keyCreate(hClassKey,
249 LPCSTR psz_LIBID = CStrFromGUID(LIBID_AXVLC);
250 if( NULL != psz_LIBID )
252 keyClose(keySetDef(keyCreate(hClassKey,
254 psz_LIBID, GUID_STRLEN));
255 CoTaskMemFree((void *)psz_LIBID);
257 RegCloseKey(hClassKey);
262 static HRESULT RegisterProgID(REFCLSID rclsid, unsigned int version)
264 LPCSTR psz_CLSID = CStrFromGUID(rclsid);
266 if( NULL == psz_CLSID )
267 return E_OUTOFMEMORY;
269 char progId[sizeof(PROGID_STR)+16];
270 sprintf(progId, "%s.%u", PROGID_STR, version);
272 HKEY hBaseKey = keyCreate(HKEY_CLASSES_ROOT, progId);
273 if( NULL != hBaseKey )
276 keySetDef(hBaseKey, DESCRIPTION, sizeof(DESCRIPTION));
278 keyClose(keySetDef(keyCreate(hBaseKey, "CLSID"),
282 //hSubKey = keyClose(keyCreate(hBaseKey, "Insertable"));
284 RegCloseKey(hBaseKey);
286 CoTaskMemFree((void *)psz_CLSID);
291 static HRESULT RegisterDefaultProgID(REFCLSID rclsid, unsigned int version)
293 LPCSTR psz_CLSID = CStrFromGUID(rclsid);
295 if( NULL == psz_CLSID )
296 return E_OUTOFMEMORY;
298 HKEY hBaseKey = keyCreate(HKEY_CLASSES_ROOT, PROGID_STR);
299 if( NULL != hBaseKey )
302 keySetDef(hBaseKey, DESCRIPTION, sizeof(DESCRIPTION));
304 keyClose(keySetDef(keyCreate(hBaseKey, "CLSID"),
308 char progId[sizeof(PROGID_STR)+16];
309 sprintf(progId, "%s.%u", PROGID_STR, version);
311 keyClose(keySetDef(keyCreate(hBaseKey, "CurVer"),
314 CoTaskMemFree((void *)psz_CLSID);
317 STDAPI DllRegisterServer(VOID)
319 DllUnregisterServer();
321 char DllPath[MAX_PATH];
322 DWORD DllPathLen=GetModuleFileNameA(h_instance, DllPath, sizeof(DllPath)) ;
323 if( 0 == DllPathLen )
328 if( ERROR_SUCCESS != RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_CREATE_SUB_KEY, &hBaseKey) )
329 return SELFREG_E_CLASS;
331 RegisterClassID(hBaseKey, CLSID_VLCPlugin, 1, DllPath, DllPathLen);
332 RegisterClassID(hBaseKey, CLSID_VLCPlugin2, 2, DllPath, DllPathLen);
334 RegCloseKey(hBaseKey);
336 RegisterProgID(CLSID_VLCPlugin, 1);
337 RegisterProgID(CLSID_VLCPlugin2, 2);
339 /* default control */
340 RegisterDefaultProgID(CLSID_VLCPlugin2, 2);
342 // indicate which component categories we support
344 if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
345 NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
346 CATID implCategories[] = {
348 CATID_PersistsToPropertyBag,
349 CATID_SafeForInitializing,
350 CATID_SafeForScripting,
353 pcr->RegisterClassImplCategories(CLSID_VLCPlugin,
354 sizeof(implCategories)/sizeof(CATID), implCategories);
355 pcr->RegisterClassImplCategories(CLSID_VLCPlugin2,
356 sizeof(implCategories)/sizeof(CATID), implCategories);
360 // register type lib into the registry
363 #ifdef BUILD_LOCALSERVER
364 // replace .exe by .tlb
365 strcpy(DllPath+DllPathLen-4, ".tlb");
369 size_t typeLibPathLen = MultiByteToWideChar(CP_ACP, 0, DllPath, -1, NULL, 0);
370 if( typeLibPathLen > 0 )
372 LPOLESTR typeLibPath = (LPOLESTR)CoTaskMemAlloc(typeLibPathLen*sizeof(wchar_t));
373 MultiByteToWideChar(CP_ACP, 0, DllPath, DllPathLen, typeLibPath, typeLibPathLen);
374 if( FAILED(LoadTypeLibEx(typeLibPath, REGKIND_REGISTER, &typeLib)) )
375 #ifndef BUILD_LOCALSERVER
376 return SELFREG_E_TYPELIB;
379 CoTaskMemFree((void *)typeLibPath);
382 if( FAILED(LoadTypeLibEx((LPOLESTR)DllPath, REGKIND_REGISTER, &typeLib)) )
383 return SELFREG_E_TYPELIB;
390 #ifdef BUILD_LOCALSERVER
393 ** easier to debug an application than a DLL on cygwin GDB :)
397 STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
401 if( FAILED(OleInitialize(NULL)) )
403 cerr << "cannot initialize OLE" << endl;
409 if( FAILED(DllRegisterServer()) )
411 cerr << "cannot register Local Server" << endl;
415 IUnknown *classProc = NULL;
417 if( FAILED(DllGetClassObject(CLSID_VLCPlugin, IID_IUnknown, (LPVOID *)&classProc)) )
420 DWORD dwRegisterClassObject;
422 if( FAILED(CoRegisterClassObject(CLSID_VLCPlugin, classProc,
423 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegisterClassObject)) )
426 DWORD dwRegisterActiveObject;
428 if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin,
429 ACTIVEOBJECT_WEAK, &dwRegisterActiveObject)) )
432 classProc->Release();
435 * Polling messages from event queue
437 while( S_FALSE == DllCanUnloadNow() )
439 while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
441 if( msg.message == WM_QUIT )
442 break; // Leave the PeekMessage while() loop
444 /*if(TranslateAccelerator(ghwndApp, ghAccel, &msg))
447 TranslateMessage(&msg);
448 DispatchMessage(&msg);
451 if(msg.message == WM_QUIT)
452 break; // Leave the for() loop
457 if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject, NULL)) )
458 CoRevokeClassObject(dwRegisterClassObject);
460 // Reached on WM_QUIT message
462 return ((int) msg.wParam);
467 STDAPI_(BOOL) DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved )
471 case DLL_PROCESS_ATTACH:
472 h_instance = (HINSTANCE)hModule;