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 HMODULE DllGetModule()
59 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
61 HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
65 if( (CLSID_VLCPlugin == rclsid )
66 || ( CLSID_VLCPlugin2 == rclsid) )
68 VLCPluginClass *plugin = new VLCPluginClass(&i_class_ref, h_instance, rclsid);
69 hr = plugin->QueryInterface(riid, ppv);
75 STDAPI DllCanUnloadNow(VOID)
77 return (0 == i_class_ref) ? S_OK: S_FALSE;
80 static inline HKEY keyCreate(HKEY parentKey, LPCSTR keyName)
83 if( ERROR_SUCCESS == RegCreateKeyExA(parentKey, keyName, 0, NULL,
84 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &childKey, NULL) )
91 static inline HKEY keySet(HKEY hKey, LPCSTR valueName, const void *s, size_t len)
95 RegSetValueExA(hKey, valueName, 0, REG_SZ,
101 static inline HKEY keySetDef(HKEY hKey, const void *s, size_t len)
103 return keySet(hKey, NULL, s, len);
106 static inline HKEY keySetDef(HKEY hKey, LPCSTR s)
108 return keySetDef(hKey, s, strlen(s)+1);
111 static inline HKEY keyClose(HKEY hKey)
120 static HRESULT UnregisterProgID(REFCLSID rclsid, unsigned int version)
122 LPCSTR psz_CLSID = CStrFromGUID(rclsid);
124 if( NULL == psz_CLSID )
125 return E_OUTOFMEMORY;
127 char progId[sizeof(PROGID_STR)+16];
128 sprintf(progId, "%s.%u", PROGID_STR, version);
130 SHDeleteKeyA(HKEY_CLASSES_ROOT, progId);
133 if( ERROR_SUCCESS == RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_WRITE, &hClsIDKey) )
135 SHDeleteKey(hClsIDKey, psz_CLSID);
136 RegCloseKey(hClsIDKey);
138 CoTaskMemFree((void *)psz_CLSID);
141 STDAPI DllUnregisterServer(VOID)
143 // unregister type lib from the registry
144 UnRegisterTypeLib(LIBID_AXVLC, 1, 0, LOCALE_NEUTRAL, SYS_WIN32);
146 // remove component categories we supports
148 if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
149 NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
150 CATID implCategories[] = {
152 CATID_PersistsToPropertyBag,
153 CATID_SafeForInitializing,
154 CATID_SafeForScripting,
157 pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin,
158 sizeof(implCategories)/sizeof(CATID), implCategories);
159 pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin2,
160 sizeof(implCategories)/sizeof(CATID), implCategories);
164 SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
166 UnregisterProgID(CLSID_VLCPlugin, 2);
167 UnregisterProgID(CLSID_VLCPlugin2, 1);
172 static HRESULT RegisterClassID(HKEY hParent, REFCLSID rclsid, unsigned int version, BOOL isDefault, const char *path, size_t pathLen)
174 char progId[sizeof(PROGID_STR)+16];
175 sprintf(progId, "%s.%u", PROGID_STR, version);
177 char description[sizeof(DESCRIPTION)+16];
178 sprintf(description, "%s v%u", DESCRIPTION, version);
182 LPCSTR psz_CLSID = CStrFromGUID(rclsid);
184 if( NULL == psz_CLSID )
185 return E_OUTOFMEMORY;
187 HKEY hProgKey = keyCreate(HKEY_CLASSES_ROOT, progId);
188 if( NULL != hProgKey )
191 keySetDef(hProgKey, description);
193 keyClose(keySetDef(keyCreate(hProgKey, "CLSID"),
197 //hSubKey = keyClose(keyCreate(hBaseKey, "Insertable"));
199 RegCloseKey(hProgKey);
203 hProgKey = keyCreate(HKEY_CLASSES_ROOT, PROGID_STR);
204 if( NULL != hProgKey )
207 keySetDef(hProgKey, description);
209 keyClose(keySetDef(keyCreate(hProgKey, "CLSID"),
213 keyClose(keySetDef(keyCreate(hProgKey, "CurVer"),
217 hClassKey = keyCreate(hParent, psz_CLSID);
218 CoTaskMemFree((void *)psz_CLSID);
220 if( NULL != hClassKey )
223 keySetDef(hClassKey, description);
226 keyClose(keyCreate(hClassKey, "Control"));
228 // Insertable key value
229 //keyClose(keyCreate(hClassKey, "Insertable"));
231 // ToolboxBitmap32 key value
233 char iconPath[pathLen+3];
234 memcpy(iconPath, path, pathLen);
235 strcpy(iconPath+pathLen, ",1");
236 keyClose(keySetDef(keyCreate(hClassKey,
238 iconPath, sizeof(iconPath)));
241 #ifdef BUILD_LOCALSERVER
242 // LocalServer32 key value
243 keyClose(keySetDef(keyCreate(hClassKey,
244 "LocalServer32", path, pathLen+1)));
246 // InprocServer32 key value
248 HKEY hSubKey = keySetDef(keyCreate(hClassKey,
253 THREADING_MODEL, sizeof(THREADING_MODEL));
258 // MiscStatus key value
259 keyClose(keySetDef(keyCreate(hClassKey,
261 MISC_STATUS, sizeof(MISC_STATUS)));
263 // Programmable key value
264 keyClose(keyCreate(hClassKey, "Programmable"));
267 keyClose(keySetDef(keyCreate(hClassKey,
271 // VersionIndependentProgID key value
272 keyClose(keySetDef(keyCreate(hClassKey,
273 "VersionIndependentProgID"),
274 PROGID_STR, sizeof(PROGID_STR)));
277 keyClose(keySetDef(keyCreate(hClassKey,
282 LPCSTR psz_LIBID = CStrFromGUID(LIBID_AXVLC);
283 if( NULL != psz_LIBID )
285 keyClose(keySetDef(keyCreate(hClassKey,
287 psz_LIBID, GUID_STRLEN));
288 CoTaskMemFree((void *)psz_LIBID);
290 RegCloseKey(hClassKey);
295 STDAPI DllRegisterServer(VOID)
297 DllUnregisterServer();
299 char DllPath[MAX_PATH];
300 DWORD DllPathLen=GetModuleFileNameA(h_instance, DllPath, sizeof(DllPath)) ;
301 if( 0 == DllPathLen )
306 if( ERROR_SUCCESS != RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_CREATE_SUB_KEY, &hBaseKey) )
307 return SELFREG_E_CLASS;
309 RegisterClassID(hBaseKey, CLSID_VLCPlugin, 1, FALSE, DllPath, DllPathLen);
310 RegisterClassID(hBaseKey, CLSID_VLCPlugin2, 2, TRUE, DllPath, DllPathLen);
312 RegCloseKey(hBaseKey);
314 // indicate which component categories we support
316 if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
317 NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
318 CATID implCategories[] = {
320 CATID_PersistsToPropertyBag,
321 CATID_SafeForInitializing,
322 CATID_SafeForScripting,
325 pcr->RegisterClassImplCategories(CLSID_VLCPlugin,
326 sizeof(implCategories)/sizeof(CATID), implCategories);
327 pcr->RegisterClassImplCategories(CLSID_VLCPlugin2,
328 sizeof(implCategories)/sizeof(CATID), implCategories);
332 // register type lib into the registry
335 #ifdef BUILD_LOCALSERVER
336 // replace .exe by .tlb
337 strcpy(DllPath+DllPathLen-4, ".tlb");
341 size_t typeLibPathLen = MultiByteToWideChar(CP_ACP, 0, DllPath, -1, NULL, 0);
342 if( typeLibPathLen > 0 )
344 LPOLESTR typeLibPath = (LPOLESTR)CoTaskMemAlloc(typeLibPathLen*sizeof(wchar_t));
345 MultiByteToWideChar(CP_ACP, 0, DllPath, DllPathLen, typeLibPath, typeLibPathLen);
346 if( FAILED(LoadTypeLibEx(typeLibPath, REGKIND_REGISTER, &typeLib)) )
347 #ifndef BUILD_LOCALSERVER
348 return SELFREG_E_TYPELIB;
351 CoTaskMemFree((void *)typeLibPath);
354 if( FAILED(LoadTypeLibEx((LPOLESTR)DllPath, REGKIND_REGISTER, &typeLib)) )
355 return SELFREG_E_TYPELIB;
362 #ifdef BUILD_LOCALSERVER
365 ** easier to debug an application than a DLL on cygwin GDB :)
369 STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
373 if( FAILED(OleInitialize(NULL)) )
375 cerr << "cannot initialize OLE" << endl;
381 if( FAILED(DllRegisterServer()) )
383 cerr << "cannot register Local Server" << endl;
387 IUnknown *classProc = NULL;
389 if( FAILED(DllGetClassObject(CLSID_VLCPlugin, IID_IUnknown, (LPVOID *)&classProc)) )
392 DWORD dwRegisterClassObject;
393 DWORD dwRegisterClassObject2;
395 if( FAILED(CoRegisterClassObject(CLSID_VLCPlugin, classProc,
396 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegisterClassObject)) )
399 DWORD dwRegisterActiveObject;
401 if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin,
402 ACTIVEOBJECT_WEAK, &dwRegisterActiveObject)) )
405 if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin2,
406 ACTIVEOBJECT_WEAK, &dwRegisterActiveObject2)) )
409 classProc->Release();
412 * Polling messages from event queue
414 while( S_FALSE == DllCanUnloadNow() )
416 while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
418 if( msg.message == WM_QUIT )
419 break; // break out PeekMessage loop
421 /*if(TranslateAccelerator(ghwndApp, ghAccel, &msg))
424 TranslateMessage(&msg);
425 DispatchMessage(&msg);
428 if(msg.message == WM_QUIT)
429 break; // break out main loop
434 if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject, NULL)) )
435 CoRevokeClassObject(dwRegisterClassObject);
437 if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject2, NULL)) )
438 CoRevokeClassObject(dwRegisterClassObject2);
440 // Reached on WM_QUIT message
442 return ((int) msg.wParam);
447 STDAPI_(BOOL) DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved )
451 case DLL_PROCESS_ATTACH:
452 h_instance = (HINSTANCE)hModule;