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 *****************************************************************************/
37 #define COMPANY_STR "VideoLAN"
38 #define PROGRAM_STR "VLCPlugin"
39 #define DESCRIPTION "VideoLAN VLC ActiveX Plugin"
41 #define THREADING_MODEL "Apartment"
42 #define MISC_STATUS "131473"
44 #define PROGID_STR COMPANY_STR"."PROGRAM_STR
46 #define GUID_STRLEN 39
49 ** MingW headers & libs do not declare those
51 static DEFINE_GUID(_CATID_InternetAware, 0x0DE86A58, 0x2BAA, 0x11CF, 0xA2, 0x29, 0x00,0xAA,0x00,0x3D,0x73,0x52);
52 static DEFINE_GUID(_CATID_SafeForInitializing, 0x7DD95802, 0x9882, 0x11CF, 0x9F, 0xA9, 0x00,0xAA,0x00,0x6C,0x42,0xC4);
53 static DEFINE_GUID(_CATID_SafeForScripting, 0x7DD95801, 0x9882, 0x11CF, 0x9F, 0xA9, 0x00,0xAA,0x00,0x6C,0x42,0xC4);
55 static LONG i_class_ref= 0;
56 static HINSTANCE h_instance= 0;
58 HMODULE DllGetModule()
63 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
65 HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
69 if( (CLSID_VLCPlugin == rclsid )
70 || ( CLSID_VLCPlugin2 == rclsid) )
72 VLCPluginClass *plugin = new VLCPluginClass(&i_class_ref, h_instance, rclsid);
73 hr = plugin->QueryInterface(riid, ppv);
79 STDAPI DllCanUnloadNow(VOID)
81 return (0 == i_class_ref) ? S_OK: S_FALSE;
84 static inline HKEY keyCreate(HKEY parentKey, LPCTSTR keyName)
87 if( ERROR_SUCCESS == RegCreateKeyEx(parentKey, keyName, 0, NULL,
88 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &childKey, NULL) )
95 static inline HKEY keySet(HKEY hKey, LPCTSTR valueName, const void *s, size_t len, DWORD dwType = REG_SZ)
99 RegSetValueEx(hKey, valueName, 0, dwType,
100 (const BYTE*)s, len);
105 static inline HKEY keySetDef(HKEY hKey, const void *s, size_t len, DWORD dwType = REG_SZ)
107 return keySet(hKey, NULL, s, len, dwType);
110 static inline HKEY keySetDef(HKEY hKey, LPCTSTR s)
112 return keySetDef(hKey, s, sizeof(TCHAR)*(_tcslen(s)+1), REG_SZ);
115 static inline HKEY keyClose(HKEY hKey)
124 static void UnregisterProgID(REFCLSID rclsid, unsigned int version)
126 OLECHAR szCLSID[GUID_STRLEN];
128 StringFromGUID2(rclsid, szCLSID, GUID_STRLEN);
130 TCHAR progId[sizeof(PROGID_STR)+16];
131 _stprintf(progId, TEXT("%s.%u"), TEXT(PROGID_STR), version);
133 SHDeleteKey(HKEY_CLASSES_ROOT, progId);
136 if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_WRITE, &hClsIDKey) )
138 SHDeleteKey(hClsIDKey, szCLSID);
139 RegCloseKey(hClsIDKey);
143 STDAPI DllUnregisterServer(VOID)
145 // unregister type lib from the registry
146 UnRegisterTypeLib(LIBID_AXVLC, 1, 0, LOCALE_NEUTRAL, SYS_WIN32);
148 // remove component categories we supports
150 if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
151 NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
152 CATID implCategories[] = {
154 CATID_PersistsToPropertyBag,
155 _CATID_InternetAware,
156 _CATID_SafeForInitializing,
157 _CATID_SafeForScripting,
160 pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin,
161 sizeof(implCategories)/sizeof(CATID), implCategories);
162 pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin2,
163 sizeof(implCategories)/sizeof(CATID), implCategories);
167 SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
169 UnregisterProgID(CLSID_VLCPlugin, 2);
170 UnregisterProgID(CLSID_VLCPlugin2, 1);
175 static HRESULT RegisterClassID(HKEY hParent, REFCLSID rclsid, unsigned int version, BOOL isDefault, LPCTSTR path, size_t pathLen)
177 TCHAR progId[sizeof(PROGID_STR)+16];
178 _stprintf(progId, TEXT("%s.%u"), TEXT(PROGID_STR), version);
180 TCHAR description[sizeof(DESCRIPTION)+16];
181 _stprintf(description, TEXT("%s v%u"), TEXT(DESCRIPTION), version);
185 OLECHAR szCLSID[GUID_STRLEN];
187 StringFromGUID2(rclsid, szCLSID, GUID_STRLEN);
189 HKEY hProgKey = keyCreate(HKEY_CLASSES_ROOT, progId);
190 if( NULL != hProgKey )
193 keySetDef(hProgKey, description);
195 keyClose(keySetDef(keyCreate(hProgKey, TEXT("CLSID")),
199 //hSubKey = keyClose(keyCreate(hBaseKey, "Insertable"));
201 RegCloseKey(hProgKey);
205 hProgKey = keyCreate(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
206 if( NULL != hProgKey )
209 keySetDef(hProgKey, description);
211 keyClose(keySetDef(keyCreate(hProgKey, TEXT("CLSID")),
215 keyClose(keySetDef(keyCreate(hProgKey, TEXT("CurVer")),
219 hClassKey = keyCreate(hParent, szCLSID);
221 if( NULL != hClassKey )
224 keySetDef(hClassKey, description);
227 keyClose(keyCreate(hClassKey, TEXT("Control")));
229 // Insertable key value
230 //keyClose(keyCreate(hClassKey, TEXT("Insertable")));
232 // ToolboxBitmap32 key value
234 TCHAR iconPath[pathLen+3];
235 memcpy(iconPath, path, sizeof(TCHAR)*pathLen);
236 _tcscpy(iconPath+pathLen, TEXT(",1"));
237 keyClose(keySetDef(keyCreate(hClassKey,
238 TEXT("ToolboxBitmap32")),
239 iconPath, sizeof(iconPath)));
242 #ifdef BUILD_LOCALSERVER
243 // LocalServer32 key value
244 keyClose(keySetDef(keyCreate(hClassKey,
245 TEXT("LocalServer32"), path, sizeof(TCHAR)*(pathLen+1))));
247 // InprocServer32 key value
249 HKEY hSubKey = keySetDef(keyCreate(hClassKey,
250 TEXT("InprocServer32")),
251 path, sizeof(TCHAR)*(pathLen+1));
253 TEXT("ThreadingModel"),
254 TEXT(THREADING_MODEL), sizeof(TEXT(THREADING_MODEL)));
259 // MiscStatus key value
260 keyClose(keySetDef(keyCreate(hClassKey,
261 TEXT("MiscStatus\\1")),
262 TEXT(MISC_STATUS), sizeof(TEXT(MISC_STATUS))));
264 // Programmable key value
265 keyClose(keyCreate(hClassKey, TEXT("Programmable")));
268 keyClose(keySetDef(keyCreate(hClassKey,
272 // VersionIndependentProgID key value
273 keyClose(keySetDef(keyCreate(hClassKey,
274 TEXT("VersionIndependentProgID")),
275 TEXT(PROGID_STR), sizeof(TEXT(PROGID_STR))));
278 keyClose(keySetDef(keyCreate(hClassKey,
283 OLECHAR szLIBID[GUID_STRLEN];
285 StringFromGUID2(LIBID_AXVLC, szLIBID, GUID_STRLEN);
287 keyClose(keySetDef(keyCreate(hClassKey,
289 szLIBID, sizeof(szLIBID)));
291 RegCloseKey(hClassKey);
296 STDAPI DllRegisterServer(VOID)
298 DllUnregisterServer();
300 TCHAR DllPath[MAX_PATH];
301 DWORD DllPathLen=GetModuleFileName(h_instance, DllPath, MAX_PATH) ;
302 if( 0 == DllPathLen )
307 if( ERROR_SUCCESS != RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_CREATE_SUB_KEY, &hBaseKey) )
308 return SELFREG_E_CLASS;
310 RegisterClassID(hBaseKey, CLSID_VLCPlugin, 1, FALSE, DllPath, DllPathLen);
311 RegisterClassID(hBaseKey, CLSID_VLCPlugin2, 2, TRUE, DllPath, DllPathLen);
313 RegCloseKey(hBaseKey);
315 // indicate which component categories we support
317 if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
318 NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
319 CATID implCategories[] = {
321 CATID_PersistsToPropertyBag,
322 _CATID_InternetAware,
323 _CATID_SafeForInitializing,
324 _CATID_SafeForScripting,
327 pcr->RegisterClassImplCategories(CLSID_VLCPlugin,
328 sizeof(implCategories)/sizeof(CATID), implCategories);
329 pcr->RegisterClassImplCategories(CLSID_VLCPlugin2,
330 sizeof(implCategories)/sizeof(CATID), implCategories);
334 #ifdef BUILD_LOCALSERVER
335 // replace .exe by .tlb
336 _tcscpy(DllPath+DllPathLen-4, TEXT(".tlb"));
339 // register type lib into the registry
342 HRESULT result = LoadTypeLibEx(DllPath, REGKIND_REGISTER, &typeLib);
343 if( SUCCEEDED(result) )
349 #ifdef BUILD_LOCALSERVER
352 ** easier to debug an application than a DLL on cygwin GDB :)
356 STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
360 if( FAILED(OleInitialize(NULL)) )
362 cerr << "cannot initialize OLE" << endl;
368 if( FAILED(DllRegisterServer()) )
370 cerr << "cannot register Local Server" << endl;
374 IUnknown *classProc = NULL;
376 if( FAILED(DllGetClassObject(CLSID_VLCPlugin, IID_IUnknown, (LPVOID *)&classProc)) )
379 DWORD dwRegisterClassObject;
380 DWORD dwRegisterClassObject2;
382 if( FAILED(CoRegisterClassObject(CLSID_VLCPlugin, classProc,
383 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegisterClassObject)) )
386 DWORD dwRegisterActiveObject;
388 if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin,
389 ACTIVEOBJECT_WEAK, &dwRegisterActiveObject)) )
392 if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin2,
393 ACTIVEOBJECT_WEAK, &dwRegisterActiveObject2)) )
396 classProc->Release();
399 * Polling messages from event queue
401 while( S_FALSE == DllCanUnloadNow() )
403 while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
405 if( msg.message == WM_QUIT )
406 break; // break out PeekMessage loop
408 /*if(TranslateAccelerator(ghwndApp, ghAccel, &msg))
411 TranslateMessage(&msg);
412 DispatchMessage(&msg);
415 if(msg.message == WM_QUIT)
416 break; // break out main loop
421 if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject, NULL)) )
422 CoRevokeClassObject(dwRegisterClassObject);
424 if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject2, NULL)) )
425 CoRevokeClassObject(dwRegisterClassObject2);
427 // Reached on WM_QUIT message
429 return ((int) msg.wParam);
434 STDAPI_(BOOL) DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved )
438 case DLL_PROCESS_ATTACH:
439 h_instance = (HINSTANCE)hModule;