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 *****************************************************************************/
31 #define COMPANY_STR "VideoLAN"
32 #define PROGRAM_STR "VLCPlugin"
33 #define VERSION_MAJOR_STR "1"
34 #define VERSION_MINOR_STR "0"
35 #define DESCRIPTION "VideoLAN VLC ActiveX Plugin"
37 #define THREADING_MODEL "Apartment"
38 #define MISC_STATUS "131473"
40 #define PROGID_STR COMPANY_STR"."PROGRAM_STR
41 #define VERS_PROGID_STR COMPANY_STR"."PROGRAM_STR"."VERSION_MAJOR_STR
42 #define VERSION_STR VERSION_MAJOR_STR"."VERSION_MINOR_STR
44 #define GUID_STRLEN 39
47 ** MingW headers do not declare those
49 extern const CATID CATID_SafeForInitializing;
50 extern const CATID CATID_SafeForScripting;
52 static LONG i_class_ref= 0;
53 static HINSTANCE h_instance= 0;
55 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
57 HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
61 if( CLSID_VLCPlugin == rclsid )
63 VLCPluginClass *plugin = new VLCPluginClass(&i_class_ref, h_instance);
64 hr = plugin->QueryInterface(riid, ppv);
70 STDAPI DllCanUnloadNow(VOID)
72 return (0 == i_class_ref) ? S_OK: S_FALSE;
75 static LPCTSTR TStrFromGUID(REFGUID clsid)
79 if( FAILED(StringFromIID(clsid, &oleStr)) )
82 //check whether TCHAR and OLECHAR are both either ANSI or UNICODE
83 if( sizeof(TCHAR) == sizeof(OLECHAR) )
84 return (LPCTSTR)oleStr;
86 LPTSTR pct_CLSID = NULL;
88 size_t len = WideCharToMultiByte(CP_ACP, 0, oleStr, -1, NULL, 0, NULL, NULL);
91 pct_CLSID = (char *)CoTaskMemAlloc(len);
92 WideCharToMultiByte(CP_ACP, 0, oleStr, -1, pct_CLSID, len, NULL, NULL);
95 size_t len = MutiByteToWideChar(CP_ACP, 0, oleStr, -1, NULL, 0);
98 clsidStr = (wchar_t *)CoTaskMemAlloc(len*sizeof(wchar_t));
99 MultiByteToWideChar(CP_ACP, 0, oleStr, -1, pct_CLSID, len);
102 CoTaskMemFree(oleStr);
106 static HKEY keyCreate(HKEY parentKey, LPCTSTR keyName)
109 if( ERROR_SUCCESS == RegCreateKeyEx(parentKey, keyName, 0, NULL,
110 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &childKey, NULL) )
117 STDAPI DllUnregisterServer(VOID)
119 // unregister type lib from the registry
120 UnRegisterTypeLib(LIBID_AXVLC, 1, 0, LOCALE_NEUTRAL, SYS_WIN32);
122 // remove component categories we supports
124 if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
125 NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
126 CATID implCategories[] = {
128 CATID_PersistsToPropertyBag,
129 CATID_SafeForInitializing,
130 CATID_SafeForScripting,
133 pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin,
134 sizeof(implCategories)/sizeof(CATID), implCategories);
138 SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(VERS_PROGID_STR));
139 SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
141 LPCTSTR psz_CLSID = TStrFromGUID(CLSID_VLCPlugin);
143 if( NULL == psz_CLSID )
144 return E_OUTOFMEMORY;
147 if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_WRITE, &hClsIDKey) )
149 SHDeleteKey(hClsIDKey, psz_CLSID);
150 RegCloseKey(hClsIDKey);
152 CoTaskMemFree((void *)psz_CLSID);
157 STDAPI DllRegisterServer(VOID)
159 DllUnregisterServer();
161 char DllPath[MAX_PATH];
162 DWORD DllPathLen= GetModuleFileName(h_instance, DllPath, sizeof(DllPath)) ;
163 if( 0 == DllPathLen )
166 LPCTSTR psz_CLSID = TStrFromGUID(CLSID_VLCPlugin);
168 if( NULL == psz_CLSID )
169 return E_OUTOFMEMORY;
173 if( ERROR_SUCCESS != RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_CREATE_SUB_KEY, &hBaseKey) )
174 return SELFREG_E_CLASS;
176 HKEY hClassKey = keyCreate(hBaseKey, psz_CLSID);
177 if( NULL != hClassKey )
182 RegSetValueEx(hClassKey, NULL, 0, REG_SZ,
183 (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));
186 hSubKey = keyCreate(hClassKey, TEXT("Control"));
187 RegCloseKey(hSubKey);
189 // Insertable key value
190 //hSubKey = keyCreate(hClassKey, TEXT("Insertable"));
191 //RegCloseKey(hSubKey);
193 // ToolboxBitmap32 key value
194 hSubKey = keyCreate(hClassKey, TEXT("ToolboxBitmap32"));
195 strcpy(DllPath+DllPathLen, ",1");
196 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
197 (const BYTE*)DllPath, DllPathLen+2);
198 DllPath[DllPathLen] = '\0';
199 RegCloseKey(hSubKey);
201 #ifdef BUILD_LOCALSERVER
202 // LocalServer32 key value
203 hSubKey = keyCreate(hClassKey, TEXT("LocalServer32"));
204 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
205 (const BYTE*)DllPath, DllPathLen);
206 RegCloseKey(hSubKey);
208 // InprocServer32 key value
209 hSubKey = keyCreate(hClassKey, TEXT("InprocServer32"));
210 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
211 (const BYTE*)DllPath, DllPathLen);
212 RegSetValueEx(hSubKey, TEXT("ThreadingModel"), 0, REG_SZ,
213 (const BYTE*)THREADING_MODEL, sizeof(THREADING_MODEL));
214 RegCloseKey(hSubKey);
217 // MiscStatus key value
218 hSubKey = keyCreate(hClassKey, TEXT("MiscStatus\\1"));
219 RegSetValueEx(hSubKey, NULL, 0, REG_SZ, (const BYTE*)MISC_STATUS, sizeof(MISC_STATUS));
220 RegCloseKey(hSubKey);
222 // Programmable key value
223 hSubKey = keyCreate(hClassKey, TEXT("Programmable"));
224 RegCloseKey(hSubKey);
227 hSubKey = keyCreate(hClassKey, TEXT("ProgID"));
228 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
229 (const BYTE*)VERS_PROGID_STR, sizeof(VERS_PROGID_STR));
230 RegCloseKey(hSubKey);
232 // VersionIndependentProgID key value
233 hSubKey = keyCreate(hClassKey, TEXT("VersionIndependentProgID"));
234 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
235 (const BYTE*)PROGID_STR, sizeof(PROGID_STR));
236 RegCloseKey(hSubKey);
239 hSubKey = keyCreate(hClassKey, TEXT("Version"));
240 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
241 (const BYTE*)VERSION_STR, sizeof(VERSION_STR));
242 RegCloseKey(hSubKey);
245 LPCTSTR psz_LIBID = TStrFromGUID(LIBID_AXVLC);
246 if( NULL != psz_LIBID )
248 hSubKey = keyCreate(hClassKey, TEXT("TypeLib"));
249 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
250 (const BYTE*)psz_LIBID, sizeof(TCHAR)*GUID_STRLEN);
251 RegCloseKey(hSubKey);
253 RegCloseKey(hClassKey);
255 RegCloseKey(hBaseKey);
257 hBaseKey = keyCreate(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
258 if( NULL != hBaseKey )
261 RegSetValueEx(hBaseKey, NULL, 0, REG_SZ,
262 (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));
264 HKEY hSubKey = keyCreate(hBaseKey, TEXT("CLSID"));
265 if( NULL != hSubKey )
268 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
269 (const BYTE*)psz_CLSID, sizeof(TCHAR)*GUID_STRLEN);
271 RegCloseKey(hSubKey);
273 hSubKey = keyCreate(hBaseKey, TEXT("CurVer"));
274 if( NULL != hSubKey )
277 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
278 (const BYTE*)VERS_PROGID_STR, sizeof(VERS_PROGID_STR));
280 RegCloseKey(hSubKey);
282 RegCloseKey(hBaseKey);
285 hBaseKey = keyCreate(HKEY_CLASSES_ROOT, TEXT(VERS_PROGID_STR));
286 if( NULL != hBaseKey )
289 RegSetValueEx(hBaseKey, NULL, 0, REG_SZ,
290 (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));
292 HKEY hSubKey = keyCreate(hBaseKey, TEXT("CLSID"));
293 if( NULL != hSubKey )
296 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
297 (const BYTE*)psz_CLSID, sizeof(TCHAR)*GUID_STRLEN);
299 RegCloseKey(hSubKey);
301 //hSubKey = keyCreate(hBaseKey, TEXT("Insertable"));
302 //RegCloseKey(hSubKey);
304 RegCloseKey(hBaseKey);
307 // indicate which component categories we support
309 if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
310 NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
311 CATID implCategories[] = {
313 CATID_PersistsToPropertyBag,
314 CATID_SafeForInitializing,
315 CATID_SafeForScripting,
318 pcr->RegisterClassImplCategories(CLSID_VLCPlugin,
319 sizeof(implCategories)/sizeof(CATID), implCategories);
323 // register type lib into the registry
326 #ifdef BUILD_LOCALSERVER
327 // replace .exe by .tlb
328 strcpy(DllPath+DllPathLen-4, ".tlb");
332 size_t typeLibPathLen = MultiByteToWideChar(CP_ACP, 0, DllPath, -1, NULL, 0);
333 if( typeLibPathLen > 0 )
335 LPOLESTR typeLibPath = (LPOLESTR)CoTaskMemAlloc(typeLibPathLen*sizeof(wchar_t));
336 MultiByteToWideChar(CP_ACP, 0, DllPath, DllPathLen, typeLibPath, typeLibPathLen);
337 if( FAILED(LoadTypeLibEx(typeLibPath, REGKIND_REGISTER, &typeLib)) )
338 #ifndef BUILD_LOCALSERVER
339 return SELFREG_E_TYPELIB;
342 CoTaskMemFree((void *)typeLibPath);
345 if( FAILED(LoadTypeLibEx((LPOLESTR)DllPath, REGKIND_REGISTER, &typeLib)) )
346 return SELFREG_E_TYPELIB;
350 CoTaskMemFree((void *)psz_CLSID);
355 #ifdef BUILD_LOCALSERVER
358 ** easier to debug an application than a DLL on cygwin GDB :)
362 STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
366 if( FAILED(OleInitialize(NULL)) )
368 cerr << "cannot initialize OLE" << endl;
374 if( FAILED(DllRegisterServer()) )
376 cerr << "cannot register Local Server" << endl;
380 IUnknown *classProc = NULL;
382 if( FAILED(DllGetClassObject(CLSID_VLCPlugin, IID_IUnknown, (LPVOID *)&classProc)) )
385 DWORD dwRegisterClassObject;
387 if( FAILED(CoRegisterClassObject(CLSID_VLCPlugin, classProc,
388 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegisterClassObject)) )
391 DWORD dwRegisterActiveObject;
393 if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin,
394 ACTIVEOBJECT_WEAK, &dwRegisterActiveObject)) )
397 classProc->Release();
400 * Polling messages from event queue
402 while( S_FALSE == DllCanUnloadNow() )
404 while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
406 if( msg.message == WM_QUIT )
407 break; // Leave the PeekMessage while() loop
409 /*if(TranslateAccelerator(ghwndApp, ghAccel, &msg))
412 TranslateMessage(&msg);
413 DispatchMessage(&msg);
416 if(msg.message == WM_QUIT)
417 break; // Leave the for() loop
422 if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject, NULL)) )
423 CoRevokeClassObject(dwRegisterClassObject);
425 // Reached on WM_QUIT message
427 return ((int) msg.wParam);
432 STDAPI_(BOOL) DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved )
436 case DLL_PROCESS_ATTACH:
437 h_instance = (HINSTANCE)hModule;