1 /*****************************************************************************
2 * main.cpp: ActiveX control for VLC
3 *****************************************************************************
4 * Copyright (C) 2005 VideoLAN
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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
21 *****************************************************************************/
31 #define THREADING_MODEL "Both"
32 #define COMPANY_STR "VideoLAN"
33 #define PROGRAM_STR "VLCPlugin"
34 #define VERSION_MAJOR_STR "1"
35 #define VERSION_MINOR_STR "0"
36 #define DESCRIPTION "VideoLAN VLC ActiveX Plugin"
38 #define PROGID_STR COMPANY_STR"."PROGRAM_STR
39 #define VERS_PROGID_STR COMPANY_STR"."PROGRAM_STR"."VERSION_MAJOR_STR
40 #define VERSION_STR VERSION_MAJOR_STR"."VERSION_MINOR_STR
42 #define GUID_STRLEN 39
45 ** MingW headers do not declare those
47 extern const CATID CATID_SafeForInitializing;
48 extern const CATID CATID_SafeForScripting;
50 static LONG i_class_ref= 0;
51 static HINSTANCE h_instance= 0;
53 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
55 HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
59 if( CLSID_VLCPlugin == rclsid )
61 VLCPluginClass *plugin = new VLCPluginClass(&i_class_ref, h_instance);
62 hr = plugin->QueryInterface(riid, ppv);
68 STDAPI DllCanUnloadNow(VOID)
70 return (0 == i_class_ref) ? S_OK: S_FALSE;
73 static LPCTSTR TStrFromGUID(REFGUID clsid) {
76 if( FAILED(StringFromIID(clsid, &oleStr)) )
79 //check whether TCHAR and OLECHAR are both either ANSI or UNICODE
80 if( sizeof(TCHAR) == sizeof(OLECHAR) )
81 return (LPCTSTR)oleStr;
83 LPTSTR pct_CLSID = NULL;
85 size_t len = WideCharToMultiByte(CP_ACP, 0, oleStr, -1, NULL, 0, NULL, NULL);
88 pct_CLSID = (char *)CoTaskMemAlloc(len);
89 WideCharToMultiByte(CP_ACP, 0, oleStr, -1, pct_CLSID, len, NULL, NULL);
92 size_t len = MutiByteToWideChar(CP_ACP, 0, oleStr, -1, NULL, 0);
95 clsidStr = (wchar_t *)CoTaskMemAlloc(len*sizeof(wchar_t));
96 WideCharToMultiByte(CP_ACP, 0, oleStr, -1, pct_CLSID, len);
99 CoTaskMemFree(oleStr);
103 static HKEY keyCreate(HKEY parentKey, LPCTSTR keyName)
106 if( ERROR_SUCCESS == RegCreateKeyEx(parentKey, keyName, 0, NULL,
107 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &childKey, NULL) )
114 STDAPI DllUnregisterServer(VOID)
116 // unregister type lib from the registry
117 UnRegisterTypeLib(LIBID_AXVLC, 1, 0, LOCALE_NEUTRAL, SYS_WIN32);
119 // remove component categories we supports
121 if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
122 NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
123 CATID implCategories[] = {
125 CATID_PersistsToPropertyBag,
126 CATID_SafeForInitializing,
127 CATID_SafeForScripting,
130 pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin,
131 sizeof(implCategories)/sizeof(CATID), implCategories);
135 SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(VERS_PROGID_STR));
136 SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
138 LPCTSTR psz_CLSID = TStrFromGUID(CLSID_VLCPlugin);
140 if( NULL == psz_CLSID )
141 return E_OUTOFMEMORY;
144 if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_WRITE, &hClsIDKey) )
146 SHDeleteKey(hClsIDKey, psz_CLSID);
147 RegCloseKey(hClsIDKey);
149 CoTaskMemFree((void *)psz_CLSID);
154 STDAPI DllRegisterServer(VOID)
156 DllUnregisterServer();
158 char DllPath[MAX_PATH];
159 DWORD DllPathLen= GetModuleFileName(h_instance, DllPath, sizeof(DllPath)) ;
160 if( 0 == DllPathLen )
163 LPCTSTR psz_CLSID = TStrFromGUID(CLSID_VLCPlugin);
165 if( NULL == psz_CLSID )
166 return E_OUTOFMEMORY;
170 if( ERROR_SUCCESS != RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_CREATE_SUB_KEY, &hBaseKey) )
173 HKEY hClassKey = keyCreate(hBaseKey, psz_CLSID);
174 if( NULL != hClassKey )
179 RegSetValueEx(hClassKey, NULL, 0, REG_SZ,
180 (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));
183 hSubKey = keyCreate(hClassKey, TEXT("Control"));
184 RegCloseKey(hSubKey);
186 // InprocServer32 key value
187 hSubKey = keyCreate(hClassKey, TEXT("InprocServer32"));
188 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
189 (const BYTE*)DllPath, DllPathLen);
190 RegSetValueEx(hSubKey, TEXT("ThreadingModel"), 0, REG_SZ,
191 (const BYTE*)THREADING_MODEL, sizeof(THREADING_MODEL));
192 RegCloseKey(hSubKey);
194 // MiscStatus key value
195 hSubKey = keyCreate(hClassKey, TEXT("MiscStatus\\1"));
196 RegSetValueEx(hSubKey, NULL, 0, REG_SZ, (const BYTE*)"131473", sizeof("131473"));
197 RegCloseKey(hSubKey);
199 // Programmable key value
200 hSubKey = keyCreate(hClassKey, TEXT("Programmable"));
201 RegCloseKey(hSubKey);
204 hSubKey = keyCreate(hClassKey, TEXT("ProgID"));
205 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
206 (const BYTE*)VERS_PROGID_STR, sizeof(VERS_PROGID_STR));
207 RegCloseKey(hSubKey);
209 // VersionIndependentProgID key value
210 hSubKey = keyCreate(hClassKey, TEXT("VersionIndependentProgID"));
211 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
212 (const BYTE*)PROGID_STR, sizeof(PROGID_STR));
213 RegCloseKey(hSubKey);
216 hSubKey = keyCreate(hClassKey, TEXT("Version"));
217 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
218 (const BYTE*)VERSION_STR, sizeof(VERSION_STR));
219 RegCloseKey(hSubKey);
222 LPCTSTR psz_LIBID = TStrFromGUID(LIBID_AXVLC);
223 if( NULL != psz_LIBID )
225 hSubKey = keyCreate(hClassKey, TEXT("TypeLib"));
226 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
227 (const BYTE*)psz_LIBID, sizeof(TCHAR)*GUID_STRLEN);
228 RegCloseKey(hSubKey);
230 RegCloseKey(hClassKey);
232 RegCloseKey(hBaseKey);
234 hBaseKey = keyCreate(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
235 if( NULL != hBaseKey )
238 RegSetValueEx(hBaseKey, NULL, 0, REG_SZ,
239 (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));
241 HKEY hSubKey = keyCreate(hBaseKey, TEXT("CLSID"));
242 if( NULL != hSubKey )
245 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
246 (const BYTE*)psz_CLSID, sizeof(TCHAR)*GUID_STRLEN);
248 RegCloseKey(hSubKey);
250 hSubKey = keyCreate(hBaseKey, TEXT("CurVer"));
251 if( NULL != hSubKey )
254 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
255 (const BYTE*)VERS_PROGID_STR, sizeof(VERS_PROGID_STR));
257 RegCloseKey(hSubKey);
259 RegCloseKey(hBaseKey);
262 hBaseKey = keyCreate(HKEY_CLASSES_ROOT, TEXT(VERS_PROGID_STR));
263 if( NULL != hBaseKey )
266 RegSetValueEx(hBaseKey, NULL, 0, REG_SZ,
267 (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));
269 HKEY hSubKey = keyCreate(hBaseKey, TEXT("CLSID"));
270 if( NULL != hSubKey )
273 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
274 (const BYTE*)psz_CLSID, sizeof(TCHAR)*GUID_STRLEN);
276 RegCloseKey(hSubKey);
278 RegCloseKey(hBaseKey);
281 // indicate which component categories we support
283 if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
284 NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
285 CATID implCategories[] = {
287 CATID_PersistsToPropertyBag,
288 CATID_SafeForInitializing,
289 CATID_SafeForScripting,
292 pcr->RegisterClassImplCategories(CLSID_VLCPlugin,
293 sizeof(implCategories)/sizeof(CATID), implCategories);
297 // register type lib into the registry
300 size_t typeLibPathLen = MultiByteToWideChar(CP_ACP, 0, DllPath, DllPathLen, NULL, 0);
301 if( typeLibPathLen > 0 )
303 LPOLESTR typeLibPath = (LPOLESTR)CoTaskMemAlloc(typeLibPathLen*sizeof(wchar_t));
304 MultiByteToWideChar(CP_ACP, 0, DllPath, DllPathLen, typeLibPath, typeLibPathLen);
305 if( SUCCEEDED(LoadTypeLibEx(typeLibPath, REGKIND_REGISTER, &typeLib)) )
307 CoTaskMemFree((void *)typeLibPath);
310 if( SUCCEEDED(LoadTypeLibEx((LPOLESTR)DllPath, REGKIND_REGISTER, &typeLib)) )
314 CoTaskMemFree((void *)psz_CLSID);
319 #ifdef BUILD_LOCALSERVER
322 ** easier to debug an application than a DLL on cygwin GDB :)
326 STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
330 if( FAILED(OleInitialize(NULL)) )
332 cerr << "cannot initialize OLE" << endl;
336 IUnknown *classProc = NULL;
338 if( FAILED(DllGetClassObject(CLSID_VLCPlugin, IID_IUnknown, (LPVOID *)&classProc)) )
341 DWORD dwRegisterClassObject;
343 if( FAILED(CoRegisterClassObject(CLSID_VLCPlugin, classProc,
344 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegisterClassObject)) )
347 DWORD dwRegisterActiveObject;
349 if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin,
350 ACTIVEOBJECT_WEAK, &dwRegisterActiveObject)) )
353 classProc->Release();
356 * Polling messages from event queue
358 while( S_FALSE == DllCanUnloadNow() )
360 while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
362 if( msg.message == WM_QUIT )
363 break; // Leave the PeekMessage while() loop
365 /*if(TranslateAccelerator(ghwndApp, ghAccel, &msg))
368 TranslateMessage(&msg);
369 DispatchMessage(&msg);
372 if(msg.message == WM_QUIT)
373 break; // Leave the for() loop
378 if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject, NULL)) )
379 CoRevokeClassObject(dwRegisterClassObject);
381 // Reached on WM_QUIT message
383 return ((int) msg.wParam);
388 STDAPI_(BOOL) DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved )
392 case DLL_PROCESS_ATTACH:
393 h_instance = (HINSTANCE)hModule;