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 *****************************************************************************/
36 #define COMPANY_STR "VideoLAN"
37 #define PROGRAM_STR "VLCPlugin"
38 #define DESCRIPTION "VideoLAN VLC ActiveX Plugin"
40 #define THREADING_MODEL "Apartment"
41 #define MISC_STATUS "131473"
43 #define PROGID_STR COMPANY_STR"."PROGRAM_STR
45 #define GUID_STRLEN 39
48 ** MingW headers & libs do not declare those
50 static DEFINE_GUID(_CATID_InternetAware, 0x0DE86A58, 0x2BAA, 0x11CF, 0xA2, 0x29, 0x00,0xAA,0x00,0x3D,0x73,0x52);
51 static DEFINE_GUID(_CATID_SafeForInitializing, 0x7DD95802, 0x9882, 0x11CF, 0x9F, 0xA9, 0x00,0xAA,0x00,0x6C,0x42,0xC4);
52 static DEFINE_GUID(_CATID_SafeForScripting, 0x7DD95801, 0x9882, 0x11CF, 0x9F, 0xA9, 0x00,0xAA,0x00,0x6C,0x42,0xC4);
54 static LONG i_class_ref= 0;
55 static HINSTANCE h_instance= 0;
57 HMODULE DllGetModule()
62 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
64 HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
68 if( (CLSID_VLCPlugin == rclsid )
69 || ( CLSID_VLCPlugin2 == rclsid) )
71 VLCPluginClass *plugin = new VLCPluginClass(&i_class_ref, h_instance, rclsid);
72 hr = plugin->QueryInterface(riid, ppv);
78 STDAPI DllCanUnloadNow(VOID)
80 return (0 == i_class_ref) ? S_OK: S_FALSE;
83 static inline HKEY keyCreate(HKEY parentKey, LPCSTR keyName)
86 if( ERROR_SUCCESS == RegCreateKeyExA(parentKey, keyName, 0, NULL,
87 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &childKey, NULL) )
94 static inline HKEY keySet(HKEY hKey, LPCSTR valueName, const void *s, size_t len)
98 RegSetValueExA(hKey, valueName, 0, REG_SZ,
104 static inline HKEY keySetDef(HKEY hKey, const void *s, size_t len)
106 return keySet(hKey, NULL, s, len);
109 static inline HKEY keySetDef(HKEY hKey, LPCSTR s)
111 return keySetDef(hKey, s, strlen(s)+1);
114 static inline HKEY keyClose(HKEY hKey)
123 static HRESULT UnregisterProgID(REFCLSID rclsid, unsigned int version)
125 LPCSTR psz_CLSID = CStrFromGUID(rclsid);
127 if( NULL == psz_CLSID )
128 return E_OUTOFMEMORY;
130 char progId[sizeof(PROGID_STR)+16];
131 sprintf(progId, "%s.%u", PROGID_STR, version);
133 SHDeleteKeyA(HKEY_CLASSES_ROOT, progId);
136 if( ERROR_SUCCESS == RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_WRITE, &hClsIDKey) )
138 SHDeleteKey(hClsIDKey, psz_CLSID);
139 RegCloseKey(hClsIDKey);
141 CoTaskMemFree((void *)psz_CLSID);
144 STDAPI DllUnregisterServer(VOID)
146 // unregister type lib from the registry
147 UnRegisterTypeLib(LIBID_AXVLC, 1, 0, LOCALE_NEUTRAL, SYS_WIN32);
149 // remove component categories we supports
151 if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
152 NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
153 CATID implCategories[] = {
155 CATID_PersistsToPropertyBag,
156 _CATID_InternetAware,
157 _CATID_SafeForInitializing,
158 _CATID_SafeForScripting,
161 pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin,
162 sizeof(implCategories)/sizeof(CATID), implCategories);
163 pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin2,
164 sizeof(implCategories)/sizeof(CATID), implCategories);
168 SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
170 UnregisterProgID(CLSID_VLCPlugin, 2);
171 UnregisterProgID(CLSID_VLCPlugin2, 1);
176 static HRESULT RegisterClassID(HKEY hParent, REFCLSID rclsid, unsigned int version, BOOL isDefault, const char *path, size_t pathLen)
178 char progId[sizeof(PROGID_STR)+16];
179 sprintf(progId, "%s.%u", PROGID_STR, version);
181 char description[sizeof(DESCRIPTION)+16];
182 sprintf(description, "%s v%u", DESCRIPTION, version);
186 LPCSTR psz_CLSID = CStrFromGUID(rclsid);
188 if( NULL == psz_CLSID )
189 return E_OUTOFMEMORY;
191 HKEY hProgKey = keyCreate(HKEY_CLASSES_ROOT, progId);
192 if( NULL != hProgKey )
195 keySetDef(hProgKey, description);
197 keyClose(keySetDef(keyCreate(hProgKey, "CLSID"),
201 //hSubKey = keyClose(keyCreate(hBaseKey, "Insertable"));
203 RegCloseKey(hProgKey);
207 hProgKey = keyCreate(HKEY_CLASSES_ROOT, PROGID_STR);
208 if( NULL != hProgKey )
211 keySetDef(hProgKey, description);
213 keyClose(keySetDef(keyCreate(hProgKey, "CLSID"),
217 keyClose(keySetDef(keyCreate(hProgKey, "CurVer"),
221 hClassKey = keyCreate(hParent, psz_CLSID);
222 CoTaskMemFree((void *)psz_CLSID);
224 if( NULL != hClassKey )
227 keySetDef(hClassKey, description);
230 keyClose(keyCreate(hClassKey, "Control"));
232 // Insertable key value
233 //keyClose(keyCreate(hClassKey, "Insertable"));
235 // ToolboxBitmap32 key value
237 char iconPath[pathLen+3];
238 memcpy(iconPath, path, pathLen);
239 strcpy(iconPath+pathLen, ",1");
240 keyClose(keySetDef(keyCreate(hClassKey,
242 iconPath, sizeof(iconPath)));
245 #ifdef BUILD_LOCALSERVER
246 // LocalServer32 key value
247 keyClose(keySetDef(keyCreate(hClassKey,
248 "LocalServer32", path, pathLen+1)));
250 // InprocServer32 key value
252 HKEY hSubKey = keySetDef(keyCreate(hClassKey,
257 THREADING_MODEL, sizeof(THREADING_MODEL));
262 // MiscStatus key value
263 keyClose(keySetDef(keyCreate(hClassKey,
265 MISC_STATUS, sizeof(MISC_STATUS)));
267 // Programmable key value
268 keyClose(keyCreate(hClassKey, "Programmable"));
271 keyClose(keySetDef(keyCreate(hClassKey,
275 // VersionIndependentProgID key value
276 keyClose(keySetDef(keyCreate(hClassKey,
277 "VersionIndependentProgID"),
278 PROGID_STR, sizeof(PROGID_STR)));
281 keyClose(keySetDef(keyCreate(hClassKey,
286 LPCSTR psz_LIBID = CStrFromGUID(LIBID_AXVLC);
287 if( NULL != psz_LIBID )
289 keyClose(keySetDef(keyCreate(hClassKey,
291 psz_LIBID, GUID_STRLEN));
292 CoTaskMemFree((void *)psz_LIBID);
294 RegCloseKey(hClassKey);
299 STDAPI DllRegisterServer(VOID)
301 DllUnregisterServer();
303 char DllPath[MAX_PATH];
304 DWORD DllPathLen=GetModuleFileNameA(h_instance, DllPath, sizeof(DllPath)) ;
305 if( 0 == DllPathLen )
310 if( ERROR_SUCCESS != RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_CREATE_SUB_KEY, &hBaseKey) )
311 return SELFREG_E_CLASS;
313 RegisterClassID(hBaseKey, CLSID_VLCPlugin, 1, FALSE, DllPath, DllPathLen);
314 RegisterClassID(hBaseKey, CLSID_VLCPlugin2, 2, TRUE, DllPath, DllPathLen);
316 RegCloseKey(hBaseKey);
318 // indicate which component categories we support
320 if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
321 NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
322 CATID implCategories[] = {
324 CATID_PersistsToPropertyBag,
325 _CATID_InternetAware,
326 _CATID_SafeForInitializing,
327 _CATID_SafeForScripting,
330 pcr->RegisterClassImplCategories(CLSID_VLCPlugin,
331 sizeof(implCategories)/sizeof(CATID), implCategories);
332 pcr->RegisterClassImplCategories(CLSID_VLCPlugin2,
333 sizeof(implCategories)/sizeof(CATID), implCategories);
337 // register type lib into the registry
340 #ifdef BUILD_LOCALSERVER
341 // replace .exe by .tlb
342 strcpy(DllPath+DllPathLen-4, ".tlb");
346 size_t typeLibPathLen = MultiByteToWideChar(CP_ACP, 0, DllPath, -1, NULL, 0);
347 if( typeLibPathLen > 0 )
349 LPOLESTR typeLibPath = (LPOLESTR)CoTaskMemAlloc(typeLibPathLen*sizeof(wchar_t));
350 MultiByteToWideChar(CP_ACP, 0, DllPath, DllPathLen, typeLibPath, typeLibPathLen);
351 if( FAILED(LoadTypeLibEx(typeLibPath, REGKIND_REGISTER, &typeLib)) )
352 #ifndef BUILD_LOCALSERVER
353 return SELFREG_E_TYPELIB;
356 CoTaskMemFree((void *)typeLibPath);
359 if( FAILED(LoadTypeLibEx((LPOLESTR)DllPath, REGKIND_REGISTER, &typeLib)) )
360 return SELFREG_E_TYPELIB;
367 #ifdef BUILD_LOCALSERVER
370 ** easier to debug an application than a DLL on cygwin GDB :)
374 STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
378 if( FAILED(OleInitialize(NULL)) )
380 cerr << "cannot initialize OLE" << endl;
386 if( FAILED(DllRegisterServer()) )
388 cerr << "cannot register Local Server" << endl;
392 IUnknown *classProc = NULL;
394 if( FAILED(DllGetClassObject(CLSID_VLCPlugin, IID_IUnknown, (LPVOID *)&classProc)) )
397 DWORD dwRegisterClassObject;
398 DWORD dwRegisterClassObject2;
400 if( FAILED(CoRegisterClassObject(CLSID_VLCPlugin, classProc,
401 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegisterClassObject)) )
404 DWORD dwRegisterActiveObject;
406 if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin,
407 ACTIVEOBJECT_WEAK, &dwRegisterActiveObject)) )
410 if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin2,
411 ACTIVEOBJECT_WEAK, &dwRegisterActiveObject2)) )
414 classProc->Release();
417 * Polling messages from event queue
419 while( S_FALSE == DllCanUnloadNow() )
421 while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
423 if( msg.message == WM_QUIT )
424 break; // break out PeekMessage loop
426 /*if(TranslateAccelerator(ghwndApp, ghAccel, &msg))
429 TranslateMessage(&msg);
430 DispatchMessage(&msg);
433 if(msg.message == WM_QUIT)
434 break; // break out main loop
439 if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject, NULL)) )
440 CoRevokeClassObject(dwRegisterClassObject);
442 if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject2, NULL)) )
443 CoRevokeClassObject(dwRegisterClassObject2);
445 // Reached on WM_QUIT message
447 return ((int) msg.wParam);
452 STDAPI_(BOOL) DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved )
456 case DLL_PROCESS_ATTACH:
457 h_instance = (HINSTANCE)hModule;